@@ -23,8 +23,11 @@ import (
2323 "github.com/ethereum/go-ethereum/common"
2424 "github.com/ethereum/go-ethereum/rlp"
2525 "github.com/ethereum/go-ethereum/trie"
26+ "io"
27+ "os"
2628)
2729
30+ // DumpAccount represents an account in the state
2831type DumpAccount struct {
2932 Balance string `json:"balance"`
3033 Nonce uint64 `json:"nonce"`
@@ -34,16 +37,76 @@ type DumpAccount struct {
3437 Storage map [string ]string `json:"storage"`
3538}
3639
40+ // For output in a collected format, as one large map
3741type Dump struct {
3842 Root string `json:"root"`
3943 Accounts map [string ]DumpAccount `json:"accounts"`
4044}
4145
42- func (self * StateDB ) RawDump () Dump {
43- dump := Dump {
44- Root : fmt .Sprintf ("%x" , self .trie .Hash ()),
46+ // DumpAccountFull is the same as DumpAccount but also with address, for standalone printing
47+ type DumpAccountFull struct {
48+ Address string `json:"address"`
49+ Balance string `json:"balance"`
50+ Nonce uint64 `json:"nonce"`
51+ Root string `json:"root"`
52+ CodeHash string `json:"codeHash"`
53+ Code string `json:"code"`
54+ Storage map [string ]string `json:"storage"`
55+ }
56+
57+ // For line-by-line json output
58+ type IterativeDump struct {
59+ encoder * json.Encoder
60+ }
61+
62+ // Collector interface which the state trie calls during iteration
63+ type collector interface {
64+ onRoot (common.Hash )
65+ onAccount (string , DumpAccount )
66+ }
67+
68+ func newCollectingDump () * Dump {
69+ return & Dump {
4570 Accounts : make (map [string ]DumpAccount ),
4671 }
72+ }
73+
74+ func newIterativeDump (w io.Writer ) * IterativeDump {
75+ return & IterativeDump {
76+ encoder : json .NewEncoder (w ),
77+ }
78+ }
79+
80+ func (self * Dump ) onRoot (root common.Hash ) {
81+ self .Root = fmt .Sprintf ("%x" , root )
82+ }
83+
84+ func (self * Dump ) onAccount (addr string , account DumpAccount ) {
85+ self .Accounts [addr ] = account
86+ }
87+
88+ func (self * IterativeDump ) onAccount (addr string , account DumpAccount ) {
89+ self .encoder .Encode (& DumpAccountFull {
90+ addr ,
91+ account .Balance ,
92+ account .Nonce ,
93+ account .Root ,
94+ account .CodeHash ,
95+ account .Code ,
96+ account .Storage ,
97+ })
98+ }
99+ func (self * IterativeDump ) onRoot (root common.Hash ) {
100+ self .encoder .Encode (struct {
101+ Root string `json:"root"`
102+ }{
103+ common .Bytes2Hex (root .Bytes ()),
104+ })
105+ }
106+
107+ func (self * StateDB ) performDump (c collector ) {
108+
109+ c .onRoot (self .trie .Hash ())
47110
48111 it := trie .NewIterator (self .trie .NodeIterator (nil ))
49112 for it .Next () {
@@ -66,16 +129,30 @@ func (self *StateDB) RawDump() Dump {
66129 for storageIt .Next () {
67130 account .Storage [common .Bytes2Hex (self .trie .GetKey (storageIt .Key ))] = common .Bytes2Hex (storageIt .Value )
68131 }
69- dump . Accounts [ common .Bytes2Hex (addr )] = account
132+ c . onAccount ( common .Bytes2Hex (addr ), account )
70133 }
71- return dump
72134}
73135
136+ // RawDump returns the entire state an a single large object
137+ func (self * StateDB ) RawDump () Dump {
138+
139+ dump := newCollectingDump ()
140+ self .performDump (dump )
141+ return * dump
142+ }
143+
144+ // Dump returns a JSON string representing the entire state as a single json-object
74145func (self * StateDB ) Dump () []byte {
75- json , err := json .MarshalIndent (self .RawDump (), "" , " " )
146+ dump := newCollectingDump ()
147+ self .performDump (dump )
148+ json , err := json .MarshalIndent (dump , "" , " " )
76149 if err != nil {
77150 fmt .Println ("dump err" , err )
78151 }
79-
80152 return json
81153}
154+
155+ // IterativeDump dumps out accounts as json-objects, delimited by linebreaks on stdout
156+ func (self * StateDB ) IterativeDump () {
157+ self .performDump (newIterativeDump (os .Stdout ))
158+ }
0 commit comments