From 33ceaf34c61d07b0cd8551369807a384a374f3a6 Mon Sep 17 00:00:00 2001 From: romelukaku Date: Wed, 5 Oct 2022 22:58:09 +0700 Subject: [PATCH] use nonce instead of path in tree for nodekey --- mutable_tree.go | 6 +++--- node.go | 31 ++----------------------------- nodedb.go | 32 +++++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/mutable_tree.go b/mutable_tree.go index 0d5742d6f..aa04bd783 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -42,9 +42,9 @@ type MutableTree struct { mtx sync.Mutex } -func NewRootNodeKeyWithVersion2(version int64) []byte { - return nodeKeyFormat.Key(version, make([]byte, 9)) -} +// func NewRootNodeKeyWithVersion2(version int64) []byte { +// return nodeKeyFormat.Key(version, make([]byte, 9)) +// } // NewMutableTree returns a new tree with the specified cache size and datastore. func NewMutableTree(db dbm.DB, cacheSize int, skipFastStorageUpgrade bool) (*MutableTree, error) { diff --git a/node.go b/node.go index 667919f01..f897ee400 100644 --- a/node.go +++ b/node.go @@ -21,7 +21,6 @@ type Node struct { key []byte value []byte hash []byte - path Path nodeKey []byte leftChildNodeKey []byte rightChildNodeKey []byte @@ -138,20 +137,6 @@ func MakeNode(buf []byte) (*Node, error) { return node, nil } -func (node *Node) PathToRightChild() Path { - return Path{ - Depth: node.path.Depth + 1, - Directions: node.path.Directions | (1 << node.path.Depth), - } -} - -func (node *Node) PathToLeftChild() Path { - return Path{ - Depth: node.path.Depth + 1, - Directions: node.path.Directions, - } -} - func (node *Node) GetKey() []byte { return node.nodeKey } @@ -220,20 +205,8 @@ func (node *Node) has(t *ImmutableTree, key []byte) (has bool, err error) { return rightNode.has(t, key) } -func (node *Node) MakePathForLeftNode() { - node.leftNode.path = node.path.MakePathToLeftChild() -} - -func (node *Node) MakePathForRightNode() { - node.rightNode.path = node.path.MakePathToRightChild() -} - -func (node *Node) SetNodeKeyForNode() { - node.nodeKey = nodeKeyFormat.Key(node.version, node.path.Bytes()) -} - -func NodeKey(version int64, path Path) []byte { - return nodeKeyFormat.Key(version, path.Bytes()) +func (node *Node) SetNodeKeyForNode(savingOrder uint64) { + node.nodeKey = nodeKeyFormat.Key(savingOrder) } // Get a key under the node. diff --git a/nodedb.go b/nodedb.go index 8043c7661..90e7ef730 100644 --- a/nodedb.go +++ b/nodedb.go @@ -3,6 +3,7 @@ package iavl import ( "bytes" "crypto/sha256" + "encoding/binary" "fmt" "math" "sort" @@ -22,9 +23,10 @@ import ( const ( int64Size = 8 hashSize = sha256.Size - nodeKeySize = 18 + nodeKeySize = 9 genesisVersion = 1 storageVersionKey = "storage_version" + savingNonceKey = "saving_nonce" // We store latest saved version together with storage version delimited by the constant below. // This delimiter is valid only if fast storage is enabled (i.e. storageVersion >= fastStorageVersionValue). // The latest saved version is needed for protection against downgrade and re-upgrade. In such a case, it would @@ -40,7 +42,7 @@ const ( var ( // All node keys are prefixed with the byte 'n'. This ensures no collision is // possible with the other keys, and makes them easier to traverse. They are indexed by the node hash. - nodeKeyFormat = keyformat.NewKeyFormat('n', int64Size, int64Size+1) // n + nodeKeyFormat = keyformat.NewKeyFormat('n', int64Size) // n // Orphans are keyed in the database by their expected lifetime. // The first number represents the *last* version at which the orphan needs @@ -66,6 +68,8 @@ var ( // Root nodes are indexed separately by their version rootKeyFormat = keyformat.NewKeyFormat('r', int64Size) // r + + savingNonceFormat = keyformat.NewKeyFormat('s', 0) ) var errInvalidFastStorageVersion = fmt.Sprintf("Fast storage version must be in the format %s", fastStorageVersionDelimiter) @@ -80,6 +84,15 @@ type nodeDB struct { latestVersion int64 // Latest version of nodeDB. nodeCache cache.Cache // Cache for nodes in the regular tree that consists of key-value pairs at any version. fastNodeCache cache.Cache // Cache for nodes in the fast index that represents only key-value pairs at the latest version. + savingNonce uint64 +} + +func (ndb *nodeDB) incrementSavingNonce() { + ndb.savingNonce += 1 + savingNonceBz := make([]byte, 8) + binary.BigEndian.PutUint16(savingNonceBz, uint16(ndb.savingNonce)) + + ndb.db.Set(savingNonceFormat.Key(unsafeToBz(savingNonceKey)), savingNonceBz) } func newNodeDB(db dbm.DB, cacheSize int, opts *Options) *nodeDB { @@ -94,6 +107,15 @@ func newNodeDB(db dbm.DB, cacheSize int, opts *Options) *nodeDB { storeVersion = []byte(defaultStorageVersionValue) } + savingNonceBz, err := db.Get(savingNonceFormat.Key(unsafeToBz(savingNonceKey))) + + var savingNonce uint64 + if err != nil || savingNonceBz == nil { + savingNonce = 0 + } else { + savingNonce = binary.BigEndian.Uint64(savingNonceBz) + } + return &nodeDB{ db: db, batch: db.NewBatch(), @@ -103,6 +125,7 @@ func newNodeDB(db dbm.DB, cacheSize int, opts *Options) *nodeDB { fastNodeCache: cache.New(fastNodeCacheSize), versionReaders: make(map[int64]uint32, 8), storageVersion: string(storeVersion), + savingNonce: savingNonce, } } @@ -342,7 +365,6 @@ func (ndb *nodeDB) SaveBranch(node *Node) ([]byte, []byte, error) { var err error if node.leftNode != nil { - node.leftNode.path = node.PathToLeftChild() // fmt.Printf("%d %08b\n", node.leftNode.path.Depth, node.leftNode.path.Directions) node.leftHash, node.leftChildNodeKey, err = ndb.SaveBranch(node.leftNode) } @@ -352,12 +374,12 @@ func (ndb *nodeDB) SaveBranch(node *Node) ([]byte, []byte, error) { } if node.rightNode != nil { - node.rightNode.path = node.PathToRightChild() // fmt.Printf("%d %08b\n", node.rightNode.path.Depth, node.rightNode.path.Directions) node.rightHash, node.rightChildNodeKey, err = ndb.SaveBranch(node.rightNode) } - node.SetNodeKeyForNode() + node.SetNodeKeyForNode(ndb.savingNonce) + ndb.incrementSavingNonce() // fmt.Println(node.nodeKey) if err != nil { return nil, nil, err