func (i *InMemoryTreeTX) SetRoot(n *Node) error {
	if !i.update {
		return errors.New("set root called on view transaction")
	}
	nodeHash := n.GetHash()
	if _, found := i.nodes[nodeHash]; !found {
		err := i.SetNode(n)
		if err != nil {
			return err
		}
	}
	i.root = nodeHash
	return nil
}
SetRoot sets the root of the tree.
package csmt
import (
	"bytes"
	"errors"
	"fmt"
	"github.com/phoreproject/synapse/chainhash"
	"github.com/phoreproject/synapse/primitives"
	"io"
	"sync"
)
type InMemoryTreeDB struct {
	root  chainhash.Hash
	nodes map[chainhash.Hash]Node
	store map[chainhash.Hash]chainhash.Hash
	updateLock *sync.RWMutex
}
func (t *InMemoryTreeDB) Hash() (*chainhash.Hash, error) {
	t.updateLock.RLock()
	defer t.updateLock.RUnlock()
	return &t.root, nil
}
func NewInMemoryTreeDB() *InMemoryTreeDB {
	return &InMemoryTreeDB{
		root:  primitives.EmptyTree,
		nodes: make(map[chainhash.Hash]Node),
		store: make(map[chainhash.Hash]chainhash.Hash),
		updateLock: new(sync.RWMutex),
	}
}
func (t *InMemoryTreeDB) Update(cb func(TreeDatabaseTransaction) error) error {
	t.updateLock.Lock()
	defer t.updateLock.Unlock()
	nodesCopy := make(map[chainhash.Hash]Node)
	storeCopy := make(map[chainhash.Hash]chainhash.Hash)
	for k, v := range t.nodes {
		nodesCopy[k] = v
	}
	for k, v := range t.store {
		storeCopy[k] = v
	}
	tx := &InMemoryTreeTX{
		root:   t.root,
		nodes:  nodesCopy,
		store:  storeCopy,
		update: true,
	}
	if err := cb(tx); err != nil {
		return err
	}
	t.nodes = nodesCopy
	t.store = storeCopy
	t.root = tx.root
	return nil
}
func (t *InMemoryTreeDB) View(cb func(TreeDatabaseTransaction) error) error {
	nodesCopy := make(map[chainhash.Hash]Node)
	storeCopy := make(map[chainhash.Hash]chainhash.Hash)
	t.updateLock.RLock()
	for k, v := range t.nodes {
		nodesCopy[k] = v
	}
	for k, v := range t.store {
		storeCopy[k] = v
	}
	t.updateLock.RUnlock()
	tx := &InMemoryTreeTX{
		root:   t.root,
		nodes:  t.nodes,
		store:  t.store,
		update: false,
	}
	return cb(tx)
}
type InMemoryTreeTX struct {
	root   chainhash.Hash
	nodes  map[chainhash.Hash]Node
	store  map[chainhash.Hash]chainhash.Hash
	update bool
}
func (i *InMemoryTreeTX) Hash() (*chainhash.Hash, error) {
	return &i.root, nil
}
func (i *InMemoryTreeTX) GetNode(nodeHash chainhash.Hash) (*Node, error) {
	if n, found := i.nodes[nodeHash]; found {
		return &n, nil
	} else {
		return nil, fmt.Errorf("could not find node with hash %s", nodeHash)
	}
}
func (i *InMemoryTreeTX) SetNode(n *Node) error {
	if !i.update {
		return errors.New("set node called on view transaction")
	}
	nodeHash := n.GetHash()
	i.nodes[nodeHash] = *n
	return nil
}
func (i *InMemoryTreeTX) DeleteNode(h chainhash.Hash) error {
	if !i.update {
		return errors.New("delete called on view transaction")
	}
	delete(i.nodes, h)
	return nil
}
func (i *InMemoryTreeTX) Root() (*Node, error) {
	if n, found := i.nodes[i.root]; found {
		return &n, nil
	} else {
		return nil, nil
	}
}