func (t *TreeMemoryCache) Update(cb func(TreeDatabaseTransaction) error) error {
	return t.underlyingStore.View(func(underlyingTx TreeDatabaseTransaction) error {
		t.lock.Lock()
		defer t.lock.Unlock()
		dirtyCopy := make(map[chainhash.Hash]Node)
		dirtyKVCopy := make(map[chainhash.Hash]chainhash.Hash)
		toRemoveCopy := make(map[chainhash.Hash]struct{})
		for k, v := range t.dirty {
			dirtyCopy[k] = v
		}
		for k, v := range t.dirtyKV {
			dirtyKVCopy[k] = v
		}
		for k := range t.toRemove {
			toRemoveCopy[k] = struct{}{}
		}
		tx := &TreeMemoryCacheTransaction{
			underlyingTransaction: underlyingTx,
			root:                  t.root,
			dirty:                 dirtyCopy,
			dirtyKV:               dirtyKVCopy,
			toRemove:              toRemoveCopy,
			update:                true,
		}
		err := cb(tx)
		if err != nil {
			return err
		}
		t.root = tx.root
		t.dirty = dirtyCopy
		t.dirtyKV = dirtyKVCopy
		t.toRemove = toRemoveCopy
		return nil
	})
}
Update creates an update transaction for the cache.
package csmt
import (
	"errors"
	"fmt"
	"sync"
	"github.com/phoreproject/synapse/chainhash"
	"github.com/phoreproject/synapse/primitives"
)
type TreeMemoryCache struct {
	underlyingStore TreeDatabase
	dirty           map[chainhash.Hash]Node
	dirtyKV         map[chainhash.Hash]chainhash.Hash
	toRemove        map[chainhash.Hash]struct{}
	root            chainhash.Hash
	lock *sync.RWMutex
}
func (t *TreeMemoryCache) Hash() (*chainhash.Hash, error) {
	t.lock.RLock()
	defer t.lock.RUnlock()
	return &t.root, nil
}
func NewTreeMemoryCache(underlyingDatabase TreeDatabase) (*TreeMemoryCache, error) {
	var preRoot chainhash.Hash
	err := underlyingDatabase.View(func(tx TreeDatabaseTransaction) error {
		root, err := tx.Root()
		if err != nil {
			return err
		}
		if root == nil {
			preRoot = primitives.EmptyTree
			return nil
		}
		preRoot = root.GetHash()
		return nil
	})
	if err != nil {
		return nil, err
	}
	return &TreeMemoryCache{
		underlyingStore: underlyingDatabase,
		root:            preRoot,
		dirty:           make(map[chainhash.Hash]Node),
		dirtyKV:         make(map[chainhash.Hash]chainhash.Hash),
		toRemove:        make(map[chainhash.Hash]struct{}),
		lock:            new(sync.RWMutex),
	}, nil
}