@@ -26,6 +26,7 @@ import (
2626 "github.com/ethereum/go-ethereum/crypto"
2727 "github.com/ethereum/go-ethereum/ethdb"
2828 "github.com/ethereum/go-ethereum/ethdb/memorydb"
29+ "github.com/ethereum/go-ethereum/rlp"
2930 "github.com/ethereum/go-ethereum/trie"
3031)
3132
@@ -44,7 +45,7 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
4445 state , _ := New (common.Hash {}, db , nil )
4546
4647 // Fill it with some arbitrary data
47- accounts := []* testAccount {}
48+ var accounts []* testAccount
4849 for i := byte (0 ); i < 96 ; i ++ {
4950 obj := state .GetOrNewStateObject (common .BytesToAddress ([]byte {i }))
5051 acc := & testAccount {address : common .BytesToAddress ([]byte {i })}
@@ -59,6 +60,11 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
5960 obj .SetCode (crypto .Keccak256Hash ([]byte {i , i , i , i , i }), []byte {i , i , i , i , i })
6061 acc .code = []byte {i , i , i , i , i }
6162 }
63+ if i % 5 == 0 {
64+ for j := byte (0 ); j < 5 ; j ++ {
65+ obj .SetState (db , crypto .Keccak256Hash ([]byte {i , i , i , i , i , j , j }), crypto .Keccak256Hash ([]byte {i , i , i , i , i , j , j }))
66+ }
67+ }
6268 state .updateStateObject (obj )
6369 accounts = append (accounts , acc )
6470 }
@@ -126,52 +132,109 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
126132// Tests that an empty state is not scheduled for syncing.
127133func TestEmptyStateSync (t * testing.T ) {
128134 empty := common .HexToHash ("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" )
129- if req := NewStateSync (empty , rawdb .NewMemoryDatabase (), trie .NewSyncBloom (1 , memorydb .New ())).Missing (1 ); len (req ) != 0 {
130- t .Errorf ("content requested for empty state: %v" , req )
135+ sync := NewStateSync (empty , rawdb .NewMemoryDatabase (), trie .NewSyncBloom (1 , memorydb .New ()))
136+ if nodes , paths , codes := sync .Missing (1 ); len (nodes ) != 0 || len (paths ) != 0 || len (codes ) != 0 {
137+ t .Errorf (" content requested for empty state: %v, %v, %v" , nodes , paths , codes )
131138 }
132139}
133140
134141// Tests that given a root hash, a state can sync iteratively on a single thread,
135142// requesting retrieval tasks and returning all of them in one go.
136- func TestIterativeStateSyncIndividual (t * testing.T ) { testIterativeStateSync (t , 1 , false ) }
137- func TestIterativeStateSyncBatched (t * testing.T ) { testIterativeStateSync (t , 100 , false ) }
138- func TestIterativeStateSyncIndividualFromDisk (t * testing.T ) { testIterativeStateSync (t , 1 , true ) }
139- func TestIterativeStateSyncBatchedFromDisk (t * testing.T ) { testIterativeStateSync (t , 100 , true ) }
143+ func TestIterativeStateSyncIndividual (t * testing.T ) {
144+ testIterativeStateSync (t , 1 , false , false )
145+ }
146+ func TestIterativeStateSyncBatched (t * testing.T ) {
147+ testIterativeStateSync (t , 100 , false , false )
148+ }
149+ func TestIterativeStateSyncIndividualFromDisk (t * testing.T ) {
150+ testIterativeStateSync (t , 1 , true , false )
151+ }
152+ func TestIterativeStateSyncBatchedFromDisk (t * testing.T ) {
153+ testIterativeStateSync (t , 100 , true , false )
154+ }
155+ func TestIterativeStateSyncIndividualByPath (t * testing.T ) {
156+ testIterativeStateSync (t , 1 , false , true )
157+ }
158+ func TestIterativeStateSyncBatchedByPath (t * testing.T ) {
159+ testIterativeStateSync (t , 100 , false , true )
160+ }
140161
141- func testIterativeStateSync (t * testing.T , count int , commit bool ) {
162+ func testIterativeStateSync (t * testing.T , count int , commit bool , bypath bool ) {
142163 // Create a random state to copy
143164 srcDb , srcRoot , srcAccounts := makeTestState ()
144165 if commit {
145166 srcDb .TrieDB ().Commit (srcRoot , false , nil )
146167 }
168+ srcTrie , _ := trie .New (srcRoot , srcDb .TrieDB ())
169+
147170 // Create a destination state and sync with the scheduler
148171 dstDb := rawdb .NewMemoryDatabase ()
149172 sched := NewStateSync (srcRoot , dstDb , trie .NewSyncBloom (1 , dstDb ))
150173
151- queue := append ([]common.Hash {}, sched .Missing (count )... )
152- for len (queue ) > 0 {
153- results := make ([]trie.SyncResult , len (queue ))
154- for i , hash := range queue {
174+ nodes , paths , codes := sched .Missing (count )
175+ var (
176+ hashQueue []common.Hash
177+ pathQueue []trie.SyncPath
178+ )
179+ if ! bypath {
180+ hashQueue = append (append (hashQueue [:0 ], nodes ... ), codes ... )
181+ } else {
182+ hashQueue = append (hashQueue [:0 ], codes ... )
183+ pathQueue = append (pathQueue [:0 ], paths ... )
184+ }
185+ for len (hashQueue )+ len (pathQueue ) > 0 {
186+ results := make ([]trie.SyncResult , len (hashQueue )+ len (pathQueue ))
187+ for i , hash := range hashQueue {
155188 data , err := srcDb .TrieDB ().Node (hash )
156189 if err != nil {
157190 data , err = srcDb .ContractCode (common.Hash {}, hash )
158191 }
159192 if err != nil {
160- t .Fatalf ("failed to retrieve node data for %x" , hash )
193+ t .Fatalf ("failed to retrieve node data for hash %x" , hash )
161194 }
162195 results [i ] = trie.SyncResult {Hash : hash , Data : data }
163196 }
197+ for i , path := range pathQueue {
198+ if len (path ) == 1 {
199+ data , _ , err := srcTrie .TryGetNode (path [0 ])
200+ if err != nil {
201+ t .Fatalf ("failed to retrieve node data for path %x: %v" , path , err )
202+ }
203+ results [len (hashQueue )+ i ] = trie.SyncResult {Hash : crypto .Keccak256Hash (data ), Data : data }
204+ } else {
205+ var acc Account
206+ if err := rlp .DecodeBytes (srcTrie .Get (path [0 ]), & acc ); err != nil {
207+ t .Fatalf ("failed to decode account on path %x: %v" , path , err )
208+ }
209+ stTrie , err := trie .New (acc .Root , srcDb .TrieDB ())
210+ if err != nil {
211+ t .Fatalf ("failed to retriev storage trie for path %x: %v" , path , err )
212+ }
213+ data , _ , err := stTrie .TryGetNode (path [1 ])
214+ if err != nil {
215+ t .Fatalf ("failed to retrieve node data for path %x: %v" , path , err )
216+ }
217+ results [len (hashQueue )+ i ] = trie.SyncResult {Hash : crypto .Keccak256Hash (data ), Data : data }
218+ }
219+ }
164220 for _ , result := range results {
165221 if err := sched .Process (result ); err != nil {
166- t .Fatalf ("failed to process result %v" , err )
222+ t .Errorf ("failed to process result %v" , err )
167223 }
168224 }
169225 batch := dstDb .NewBatch ()
170226 if err := sched .Commit (batch ); err != nil {
171227 t .Fatalf ("failed to commit data: %v" , err )
172228 }
173229 batch .Write ()
174- queue = append (queue [:0 ], sched .Missing (count )... )
230+
231+ nodes , paths , codes = sched .Missing (count )
232+ if ! bypath {
233+ hashQueue = append (append (hashQueue [:0 ], nodes ... ), codes ... )
234+ } else {
235+ hashQueue = append (hashQueue [:0 ], codes ... )
236+ pathQueue = append (pathQueue [:0 ], paths ... )
237+ }
175238 }
176239 // Cross check that the two states are in sync
177240 checkStateAccounts (t , dstDb , srcRoot , srcAccounts )
@@ -187,7 +250,9 @@ func TestIterativeDelayedStateSync(t *testing.T) {
187250 dstDb := rawdb .NewMemoryDatabase ()
188251 sched := NewStateSync (srcRoot , dstDb , trie .NewSyncBloom (1 , dstDb ))
189252
190- queue := append ([]common.Hash {}, sched .Missing (0 )... )
253+ nodes , _ , codes := sched .Missing (0 )
254+ queue := append (append ([]common.Hash {}, nodes ... ), codes ... )
255+
191256 for len (queue ) > 0 {
192257 // Sync only half of the scheduled nodes
193258 results := make ([]trie.SyncResult , len (queue )/ 2 + 1 )
@@ -211,7 +276,9 @@ func TestIterativeDelayedStateSync(t *testing.T) {
211276 t .Fatalf ("failed to commit data: %v" , err )
212277 }
213278 batch .Write ()
214- queue = append (queue [len (results ):], sched .Missing (0 )... )
279+
280+ nodes , _ , codes = sched .Missing (0 )
281+ queue = append (append (queue [len (results ):], nodes ... ), codes ... )
215282 }
216283 // Cross check that the two states are in sync
217284 checkStateAccounts (t , dstDb , srcRoot , srcAccounts )
@@ -232,7 +299,8 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
232299 sched := NewStateSync (srcRoot , dstDb , trie .NewSyncBloom (1 , dstDb ))
233300
234301 queue := make (map [common.Hash ]struct {})
235- for _ , hash := range sched .Missing (count ) {
302+ nodes , _ , codes := sched .Missing (count )
303+ for _ , hash := range append (nodes , codes ... ) {
236304 queue [hash ] = struct {}{}
237305 }
238306 for len (queue ) > 0 {
@@ -259,8 +327,10 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
259327 t .Fatalf ("failed to commit data: %v" , err )
260328 }
261329 batch .Write ()
330+
262331 queue = make (map [common.Hash ]struct {})
263- for _ , hash := range sched .Missing (count ) {
332+ nodes , _ , codes = sched .Missing (count )
333+ for _ , hash := range append (nodes , codes ... ) {
264334 queue [hash ] = struct {}{}
265335 }
266336 }
@@ -279,7 +349,8 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
279349 sched := NewStateSync (srcRoot , dstDb , trie .NewSyncBloom (1 , dstDb ))
280350
281351 queue := make (map [common.Hash ]struct {})
282- for _ , hash := range sched .Missing (0 ) {
352+ nodes , _ , codes := sched .Missing (0 )
353+ for _ , hash := range append (nodes , codes ... ) {
283354 queue [hash ] = struct {}{}
284355 }
285356 for len (queue ) > 0 {
@@ -312,7 +383,11 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
312383 t .Fatalf ("failed to commit data: %v" , err )
313384 }
314385 batch .Write ()
315- for _ , hash := range sched .Missing (0 ) {
386+ for _ , result := range results {
387+ delete (queue , result .Hash )
388+ }
389+ nodes , _ , codes = sched .Missing (0 )
390+ for _ , hash := range append (nodes , codes ... ) {
316391 queue [hash ] = struct {}{}
317392 }
318393 }
@@ -341,8 +416,11 @@ func TestIncompleteStateSync(t *testing.T) {
341416 dstDb := rawdb .NewMemoryDatabase ()
342417 sched := NewStateSync (srcRoot , dstDb , trie .NewSyncBloom (1 , dstDb ))
343418
344- added := []common.Hash {}
345- queue := append ([]common.Hash {}, sched .Missing (1 )... )
419+ var added []common.Hash
420+
421+ nodes , _ , codes := sched .Missing (1 )
422+ queue := append (append ([]common.Hash {}, nodes ... ), codes ... )
423+
346424 for len (queue ) > 0 {
347425 // Fetch a batch of state nodes
348426 results := make ([]trie.SyncResult , len (queue ))
@@ -382,7 +460,8 @@ func TestIncompleteStateSync(t *testing.T) {
382460 }
383461 }
384462 // Fetch the next batch to retrieve
385- queue = append (queue [:0 ], sched .Missing (1 )... )
463+ nodes , _ , codes = sched .Missing (1 )
464+ queue = append (append (queue [:0 ], nodes ... ), codes ... )
386465 }
387466 // Sanity check that removing any node from the database is detected
388467 for _ , node := range added [1 :] {
0 commit comments