diff --git a/core/state/dump.go b/core/state/dump.go index 0218e723ef..00aeb4f173 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -28,6 +28,14 @@ import ( "github.com/XinFinOrg/XDPoSChain/trie" ) +// DumpCollector interface which the state trie calls during iteration +type DumpCollector interface { + // OnRoot is called with the state root + OnRoot(common.Hash) + // OnAccount is called once for each account in the trie + OnAccount(common.Address, DumpAccount) +} + // DumpAccount represents an account in the state. type DumpAccount struct { Balance string `json:"balance"` @@ -46,9 +54,14 @@ type Dump struct { Accounts map[common.Address]DumpAccount `json:"accounts"` } -// iterativeDump is a 'collector'-implementation which dump output line-by-line iteratively. -type iterativeDump struct { - *json.Encoder +// OnRoot implements DumpCollector interface +func (d *Dump) OnRoot(root common.Hash) { + d.Root = fmt.Sprintf("%x", root) +} + +// OnAccount implements DumpCollector interface +func (d *Dump) OnAccount(addr common.Address, account DumpAccount) { + d.Accounts[addr] = account } // IteratorDump is an implementation for iterating over data. @@ -58,28 +71,23 @@ type IteratorDump struct { Next []byte `json:"next,omitempty"` // nil if no more accounts } -// Collector interface which the state trie calls during iteration -type collector interface { - onRoot(common.Hash) - onAccount(common.Address, DumpAccount) -} - -func (d *Dump) onRoot(root common.Hash) { +// OnRoot implements DumpCollector interface +func (d *IteratorDump) OnRoot(root common.Hash) { d.Root = fmt.Sprintf("%x", root) } -func (d *Dump) onAccount(addr common.Address, account DumpAccount) { - d.Accounts[addr] = account -} -func (d *IteratorDump) onRoot(root common.Hash) { - d.Root = fmt.Sprintf("%x", root) -} - -func (d *IteratorDump) onAccount(addr common.Address, account DumpAccount) { +// OnAccount implements DumpCollector interface +func (d *IteratorDump) OnAccount(addr common.Address, account DumpAccount) { d.Accounts[addr] = account } -func (d iterativeDump) onAccount(addr common.Address, account DumpAccount) { +// iterativeDump is a DumpCollector-implementation which dumps output line-by-line iteratively. +type iterativeDump struct { + *json.Encoder +} + +// OnAccount implements DumpCollector interface +func (d iterativeDump) OnAccount(addr common.Address, account DumpAccount) { dumpAccount := &DumpAccount{ Balance: account.Balance, Nonce: account.Nonce, @@ -96,15 +104,16 @@ func (d iterativeDump) onAccount(addr common.Address, account DumpAccount) { d.Encode(dumpAccount) } -func (d iterativeDump) onRoot(root common.Hash) { +// OnRoot implements DumpCollector interface +func (d iterativeDump) OnRoot(root common.Hash) { d.Encode(struct { Root common.Hash `json:"root"` }{root}) } -func (s *StateDB) dump(c collector, excludeCode, excludeStorage, excludeMissingPreimages bool, start []byte, maxResults int) (nextKey []byte) { +func (s *StateDB) DumpToCollector(c DumpCollector, excludeCode, excludeStorage, excludeMissingPreimages bool, start []byte, maxResults int) (nextKey []byte) { missingPreimages := 0 - c.onRoot(s.trie.Hash()) + c.OnRoot(s.trie.Hash()) var count int it := trie.NewIterator(s.trie.NodeIterator(start)) @@ -145,7 +154,7 @@ func (s *StateDB) dump(c collector, excludeCode, excludeStorage, excludeMissingP account.Storage[common.BytesToHash(s.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(content) } } - c.onAccount(addr, account) + c.OnAccount(addr, account) count++ if maxResults > 0 && count >= maxResults { if it.Next() { @@ -166,7 +175,7 @@ func (s *StateDB) RawDump(excludeCode, excludeStorage, excludeMissingPreimages b dump := &Dump{ Accounts: make(map[common.Address]DumpAccount), } - s.dump(dump, excludeCode, excludeStorage, excludeMissingPreimages, nil, 0) + s.DumpToCollector(dump, excludeCode, excludeStorage, excludeMissingPreimages, nil, 0) return *dump } @@ -175,14 +184,14 @@ func (s *StateDB) Dump(excludeCode, excludeStorage, excludeMissingPreimages bool dump := s.RawDump(excludeCode, excludeStorage, excludeMissingPreimages) json, err := json.MarshalIndent(dump, "", " ") if err != nil { - fmt.Println("dump err", err) + fmt.Println("Dump err", err) } return json } // IterativeDump dumps out accounts as json-objects, delimited by linebreaks on stdout func (s *StateDB) IterativeDump(excludeCode, excludeStorage, excludeMissingPreimages bool, output *json.Encoder) { - s.dump(iterativeDump{output}, excludeCode, excludeStorage, excludeMissingPreimages, nil, 0) + s.DumpToCollector(iterativeDump{output}, excludeCode, excludeStorage, excludeMissingPreimages, nil, 0) } // IteratorDump dumps out a batch of accounts starts with the given start key @@ -190,6 +199,6 @@ func (s *StateDB) IteratorDump(excludeCode, excludeStorage, excludeMissingPreima iterator := &IteratorDump{ Accounts: make(map[common.Address]DumpAccount), } - iterator.Next = s.dump(iterator, excludeCode, excludeStorage, excludeMissingPreimages, start, maxResults) + iterator.Next = s.DumpToCollector(iterator, excludeCode, excludeStorage, excludeMissingPreimages, start, maxResults) return *iterator } diff --git a/core/state/state_test.go b/core/state/state_test.go index 4b312619d7..98d45231c2 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -57,7 +57,7 @@ func TestDump(t *testing.T) { s.state.updateStateObject(obj2) s.state.Commit(false) - // check that dump contains the state objects that are in trie + // check that DumpToCollector contains the state objects that are in trie got := string(s.state.Dump(false, false, true)) want := `{ "root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2", @@ -84,7 +84,7 @@ func TestDump(t *testing.T) { } }` if got != want { - t.Errorf("dump mismatch:\ngot: %s\nwant: %s\n", got, want) + t.Errorf("DumpToCollector mismatch:\ngot: %s\nwant: %s\n", got, want) } }