@@ -2,8 +2,11 @@ package claimtrie
22
33import (
44 "bytes"
5+ "fmt"
56 "path/filepath"
7+ "runtime"
68 "sort"
9+ "sync"
710
811 "github.com/pkg/errors"
912
@@ -80,12 +83,13 @@ func New(cfg config.Config) (*ClaimTrie, error) {
8083 if err != nil {
8184 return nil , errors .Wrap (err , "creating node base manager" )
8285 }
83- nodeManager := node .NewNormalizingManager (baseManager )
86+ normalizingManager := node .NewNormalizingManager (baseManager )
87+ nodeManager := & node.HashV2Manager {Manager : normalizingManager }
8488 cleanups = append (cleanups , nodeManager .Close )
8589
8690 var trie merkletrie.MerkleTrie
8791 if cfg .RamTrie {
88- trie = merkletrie .NewRamTrie (nodeManager )
92+ trie = merkletrie .NewRamTrie ()
8993 } else {
9094
9195 // Initialize repository for MerkleTrie. The cleanup is delegated to MerkleTrie.
@@ -95,7 +99,7 @@ func New(cfg config.Config) (*ClaimTrie, error) {
9599 return nil , errors .Wrap (err , "creating trie repo" )
96100 }
97101
98- persistentTrie := merkletrie .NewPersistentTrie (nodeManager , trieRepo )
102+ persistentTrie := merkletrie .NewPersistentTrie (trieRepo )
99103 cleanups = append (cleanups , persistentTrie .Close )
100104 trie = persistentTrie
101105 }
@@ -129,8 +133,11 @@ func New(cfg config.Config) (*ClaimTrie, error) {
129133 ct .Close ()
130134 return nil , errors .Wrap (err , "increment height to" )
131135 }
132- // TODO: pass in the interrupt signal here:
133- trie .SetRoot (hash , nil ) // keep this after IncrementHeightTo
136+ err = trie .SetRoot (hash ) // keep this after IncrementHeightTo
137+ if err == merkletrie .ErrFullRebuildRequired {
138+ // TODO: pass in the interrupt signal here:
139+ ct .runFullTrieRebuild (nil )
140+ }
134141
135142 if ! ct .MerkleHash ().IsEqual (hash ) {
136143 ct .Close ()
@@ -235,7 +242,7 @@ func (ct *ClaimTrie) AppendBlock() error {
235242 names = append (names , expirations ... )
236243 names = removeDuplicates (names )
237244
238- nhns := ct .nodeManager . MakeNameHashNext (names , false )
245+ nhns := ct .makeNameHashNext (names , false )
239246 for nhn := range nhns {
240247
241248 ct .merkleTrie .Update (nhn .Name , nhn .Hash , true )
@@ -260,26 +267,19 @@ func (ct *ClaimTrie) AppendBlock() error {
260267 ct .blockRepo .Set (ct .height , h )
261268
262269 if hitFork {
263- ct .merkleTrie .SetRoot (h , names ) // for clearing the memory entirely
270+ err = ct .merkleTrie .SetRoot (h ) // for clearing the memory entirely
264271 }
265272
266- return nil
273+ return errors . Wrap ( err , "merkle trie clear memory" )
267274}
268275
269276func (ct * ClaimTrie ) updateTrieForHashForkIfNecessary () bool {
270277 if ct .height != param .ActiveParams .AllClaimsInMerkleForkHeight {
271278 return false
272279 }
273280
274- node .LogOnce ("Marking all trie nodes as dirty for the hash fork..." )
275-
276- // invalidate all names because we have to recompute the hash on everything
277- pairs := ct .nodeManager .MakeNameHashNext (nil , true )
278- for pair := range pairs {
279- ct .merkleTrie .Update (pair .Name , pair .Hash , false )
280- }
281-
282- node .LogOnce ("Done. Now recomputing all hashes..." )
281+ node .LogOnce (fmt .Sprintf ("Rebuilding all trie nodes for the hash fork at %d..." , ct .height ))
282+ ct .runFullTrieRebuild (nil )
283283 return true
284284}
285285
@@ -322,14 +322,32 @@ func (ct *ClaimTrie) ResetHeight(height int32) error {
322322 if passedHashFork {
323323 names = nil // force them to reconsider all names
324324 }
325- ct .merkleTrie .SetRoot (hash , names )
325+ err = ct .merkleTrie .SetRoot (hash )
326+ if err == merkletrie .ErrFullRebuildRequired {
327+ ct .runFullTrieRebuild (names )
328+ }
326329
327330 if ! ct .MerkleHash ().IsEqual (hash ) {
328331 return errors .Errorf ("unable to restore the hash at height %d" , height )
329332 }
330333 return nil
331334}
332335
336+ func (ct * ClaimTrie ) runFullTrieRebuild (names [][]byte ) {
337+ var nhns chan NameHashNext
338+ if names == nil {
339+ node .LogOnce ("Building the entire claim trie in RAM..." )
340+
341+ nhns = ct .makeNameHashNext (nil , true )
342+ } else {
343+ nhns = ct .makeNameHashNext (names , false )
344+ }
345+
346+ for nhn := range nhns {
347+ ct .merkleTrie .Update (nhn .Name , nhn .Hash , false )
348+ }
349+ }
350+
333351// MerkleHash returns the Merkle Hash of the claimTrie.
334352func (ct * ClaimTrie ) MerkleHash () * chainhash.Hash {
335353 if ct .height >= param .ActiveParams .AllClaimsInMerkleForkHeight {
@@ -392,3 +410,53 @@ func (ct *ClaimTrie) FlushToDisk() {
392410 node .Warn ("During blockRepo flush: " + err .Error ())
393411 }
394412}
413+
414+ type NameHashNext struct {
415+ Name []byte
416+ Hash * chainhash.Hash
417+ Next int32
418+ }
419+
420+ func (ct * ClaimTrie ) makeNameHashNext (names [][]byte , all bool ) chan NameHashNext {
421+ inputs := make (chan []byte , 512 )
422+ outputs := make (chan NameHashNext , 512 )
423+
424+ var wg sync.WaitGroup
425+ computeHash := func () {
426+ for name := range inputs {
427+ hash , next := ct .nodeManager .Hash (name )
428+ outputs <- NameHashNext {name , hash , next }
429+ }
430+ wg .Done ()
431+ }
432+
433+ threads := int (0.8 * float32 (runtime .NumCPU ()))
434+ if threads < 1 {
435+ threads = 1
436+ }
437+ for threads >= 0 {
438+ threads --
439+ wg .Add (1 )
440+ go computeHash ()
441+ }
442+ go func () {
443+ if all {
444+ ct .nodeManager .IterateNames (func (name []byte ) bool {
445+ clone := make ([]byte , len (name ))
446+ copy (clone , name ) // iteration name buffer is reused on future loops
447+ inputs <- clone
448+ return true
449+ })
450+ } else {
451+ for _ , name := range names {
452+ inputs <- name
453+ }
454+ }
455+ close (inputs )
456+ }()
457+ go func () {
458+ wg .Wait ()
459+ close (outputs )
460+ }()
461+ return outputs
462+ }
0 commit comments