@@ -57,76 +57,72 @@ func buildTrie(encodedProofNodes [][]byte, rootHash []byte) (t *trie.Trie, err e
57
57
ErrEmptyProof , rootHash )
58
58
}
59
59
60
- merkleValueToNode := make (map [string ]* node. Node , len (encodedProofNodes ))
60
+ merkleValueToEncoding := make (map [string ][] byte , len (encodedProofNodes ))
61
61
62
+ // This loop finds the root node and decodes it.
63
+ // The other nodes have their Merkle value (blake2b digest or the encoding itself)
64
+ // inserted into a map from merkle value to encoding. They are only decoded
65
+ // later if the root or one of its descendant node reference their Merkle value.
62
66
var root * node.Node
63
- for i , encodedProofNode := range encodedProofNodes {
64
- decodedNode , err := node .Decode (bytes .NewReader (encodedProofNode ))
65
- if err != nil {
66
- return nil , fmt .Errorf ("decoding node at index %d: %w (node encoded is 0x%x)" ,
67
- i , err , encodedProofNode )
68
- }
69
-
70
- decodedNode .Encoding = encodedProofNode
71
- // We compute the Merkle value of nodes treating them all
72
- // as non-root nodes, meaning nodes with encoding smaller
73
- // than 33 bytes will have their Merkle value set as their
74
- // encoding. The Blake2b hash of the encoding is computed
75
- // later if needed to compare with the root hash given to find
76
- // which node is the root node.
77
- const isRoot = false
78
- decodedNode .HashDigest , err = node .MerkleValue (encodedProofNode , isRoot )
79
- if err != nil {
80
- return nil , fmt .Errorf ("merkle value of node at index %d: %w" , i , err )
81
- }
82
-
83
- proofHash := common .BytesToHex (decodedNode .HashDigest )
84
- merkleValueToNode [proofHash ] = decodedNode
85
-
86
- if root != nil {
87
- // Root node already found in proof
88
- continue
89
- }
90
-
91
- possibleRootMerkleValue := decodedNode .HashDigest
92
- if len (possibleRootMerkleValue ) <= 32 {
93
- // If the root merkle value is smaller than 33 bytes, it means
94
- // it is the encoding of the node. However, the root node merkle
95
- // value is always the blake2b digest of the node, and not its own
96
- // encoding. Therefore, in this case we force the computation of the
97
- // blake2b digest of the node to check if it matches the root hash given.
98
- const isRoot = true
99
- possibleRootMerkleValue , err = node .MerkleValue (encodedProofNode , isRoot )
67
+ for _ , encodedProofNode := range encodedProofNodes {
68
+ var digest []byte
69
+ if root == nil {
70
+ // root node not found yet
71
+ digestHash , err := common .Blake2bHash (encodedProofNode )
100
72
if err != nil {
101
- return nil , fmt .Errorf ("merkle value of possible root node: %w" , err )
73
+ return nil , fmt .Errorf ("blake2b hash: %w" , err )
74
+ }
75
+ digest = digestHash [:]
76
+
77
+ if bytes .Equal (digest , rootHash ) {
78
+ root , err = node .Decode (bytes .NewReader (encodedProofNode ))
79
+ if err != nil {
80
+ return nil , fmt .Errorf ("decoding root node: %w" , err )
81
+ }
82
+ continue // no need to add root to map of hash to encoding
102
83
}
103
84
}
104
85
105
- if bytes .Equal (rootHash , possibleRootMerkleValue ) {
106
- decodedNode .HashDigest = rootHash
107
- root = decodedNode
86
+ var merkleValue []byte
87
+ if len (encodedProofNode ) <= 32 {
88
+ merkleValue = encodedProofNode
89
+ } else {
90
+ if digest == nil {
91
+ digestHash , err := common .Blake2bHash (encodedProofNode )
92
+ if err != nil {
93
+ return nil , fmt .Errorf ("blake2b hash: %w" , err )
94
+ }
95
+ digest = digestHash [:]
96
+ }
97
+ merkleValue = digest
108
98
}
99
+
100
+ merkleValueToEncoding [string (merkleValue )] = encodedProofNode
109
101
}
110
102
111
103
if root == nil {
112
- proofMerkleValues := make ([]string , 0 , len (merkleValueToNode ))
113
- for merkleValue := range merkleValueToNode {
114
- proofMerkleValues = append (proofMerkleValues , merkleValue )
104
+ proofMerkleValues := make ([]string , 0 , len (merkleValueToEncoding ))
105
+ for merkleValueString := range merkleValueToEncoding {
106
+ merkleValueHex := common .BytesToHex ([]byte (merkleValueString ))
107
+ proofMerkleValues = append (proofMerkleValues , merkleValueHex )
115
108
}
116
109
return nil , fmt .Errorf ("%w: for Merkle root hash 0x%x in proof Merkle value(s) %s" ,
117
110
ErrRootNodeNotFound , rootHash , strings .Join (proofMerkleValues , ", " ))
118
111
}
119
112
120
- loadProof (merkleValueToNode , root )
113
+ err = loadProof (merkleValueToEncoding , root )
114
+ if err != nil {
115
+ return nil , fmt .Errorf ("loading proof: %w" , err )
116
+ }
121
117
122
118
return trie .NewTrie (root ), nil
123
119
}
124
120
125
121
// loadProof is a recursive function that will create all the trie paths based
126
122
// on the map from node hash to node starting at the root.
127
- func loadProof (merkleValueToNode map [string ]* node. Node , n * node.Node ) {
123
+ func loadProof (merkleValueToEncoding map [string ][] byte , n * node.Node ) ( err error ) {
128
124
if n .Type () != node .Branch {
129
- return
125
+ return nil
130
126
}
131
127
132
128
branch := n
@@ -135,15 +131,38 @@ func loadProof(merkleValueToNode map[string]*node.Node, n *node.Node) {
135
131
continue
136
132
}
137
133
138
- merkleValueHex := common . BytesToHex ( child .HashDigest )
139
- node , ok := merkleValueToNode [ merkleValueHex ]
134
+ merkleValue := child .HashDigest
135
+ encoding , ok := merkleValueToEncoding [ string ( merkleValue ) ]
140
136
if ! ok {
137
+ inlinedChild := len (child .Value ) > 0 || child .HasChild ()
138
+ if ! inlinedChild {
139
+ // hash not found and the child is not inlined,
140
+ // so clear the child from the branch.
141
+ branch .Descendants -= 1 + child .Descendants
142
+ branch .Children [i ] = nil
143
+ if ! branch .HasChild () {
144
+ // Convert branch to a leaf if all its children are nil.
145
+ branch .Children = nil
146
+ }
147
+ }
141
148
continue
142
149
}
143
150
144
- branch .Children [i ] = node
145
- loadProof (merkleValueToNode , node )
151
+ child , err := node .Decode (bytes .NewReader (encoding ))
152
+ if err != nil {
153
+ return fmt .Errorf ("decoding child node for Merkle value 0x%x: %w" ,
154
+ merkleValue , err )
155
+ }
156
+
157
+ branch .Children [i ] = child
158
+ branch .Descendants += child .Descendants
159
+ err = loadProof (merkleValueToEncoding , child )
160
+ if err != nil {
161
+ return err // do not wrap error since this is recursive
162
+ }
146
163
}
164
+
165
+ return nil
147
166
}
148
167
149
168
func bytesToString (b []byte ) (s string ) {
0 commit comments