@@ -38,10 +38,20 @@ import (
3838//
3939// # Header
4040// The header records metadata, including:
41- // - the history version
41+ //
42+ // - the history version (1 byte)
43+ // - the parent state root (32 bytes)
44+ // - the current state root (32 bytes)
45+ // - block number (8 bytes)
46+ //
4247// - a lexicographically sorted list of trie IDs
4348// - the corresponding offsets into the key and value sections for each trie data chunk
4449//
50+ // Although some fields (e.g., parent state root, block number) are duplicated
51+ // between the state history and the trienode history, these two histories
52+ // operate independently. To ensure each remains self-contained and self-descriptive,
53+ // we have chosen to maintain these duplicate fields.
54+ //
4555// # Key section
4656// The key section stores trie node keys (paths) in a compressed format.
4757// It also contains relative offsets into the value section for resolving
@@ -60,7 +70,7 @@ import (
6070// Header section:
6171//
6272// +----------+------------------+---------------------+---------------------+-------+------------------+---------------------+---------------------|
63- // | ver (1B) | TrieID(32 bytes) | key offset(4 bytes) | val offset(4 bytes) | ... | TrieID(32 bytes) | key offset(4 bytes) | val offset(4 bytes) |
73+ // | metadata | TrieID(32 bytes) | key offset(4 bytes) | val offset(4 bytes) | ... | TrieID(32 bytes) | key offset(4 bytes) | val offset(4 bytes) |
6474// +----------+------------------+---------------------+---------------------+-------+------------------+---------------------+---------------------|
6575//
6676//
@@ -103,30 +113,45 @@ import (
103113// NOTE: All fixed-length integer are big-endian.
104114
105115const (
106- trienodeHistoryV0 = uint8 (0 ) // initial version of node history structure
107- trienodeHistoryVersion = trienodeHistoryV0 // the default node history version
108- trienodeVersionSize = 1 // the size of version tag in the history
109- trienodeTrieHeaderSize = 8 + common .HashLength // the size of a single trie header in history
110- trienodeDataBlockRestartLen = 16 // The restart interval length of trie node block
116+ trienodeHistoryV0 = uint8 (0 ) // initial version of node history structure
117+ trienodeHistoryVersion = trienodeHistoryV0 // the default node history version
118+ trienodeMetadataSize = 1 + 2 * common . HashLength + 8 // the size of metadata in the history
119+ trienodeTrieHeaderSize = 8 + common .HashLength // the size of a single trie header in history
120+ trienodeDataBlockRestartLen = 16 // The restart interval length of trie node block
111121)
112122
123+ // trienodeMetadata describes the meta data of trienode history.
124+ type trienodeMetadata struct {
125+ version uint8 // version tag of history object
126+ parent common.Hash // prev-state root before the state transition
127+ root common.Hash // post-state root after the state transition
128+ block uint64 // associated block number
129+ }
130+
113131// trienodeHistory represents a set of trie node changes resulting from a state
114132// transition across the main account trie and all associated storage tries.
115133type trienodeHistory struct {
134+ meta * trienodeMetadata // Metadata of the history
116135 owners []common.Hash // List of trie identifier sorted lexicographically
117136 nodeList map [common.Hash ][]string // Set of node paths sorted lexicographically
118137 nodes map [common.Hash ]map [string ][]byte // Set of original value of trie nodes before state transition
119138}
120139
121140// newTrienodeHistory constructs a trienode history with the provided trie nodes.
122- func newTrienodeHistory (nodes map [common.Hash ]map [string ][]byte ) * trienodeHistory {
141+ func newTrienodeHistory (root common. Hash , parent common. Hash , block uint64 , nodes map [common.Hash ]map [string ][]byte ) * trienodeHistory {
123142 nodeList := make (map [common.Hash ][]string )
124143 for owner , subset := range nodes {
125144 keys := sort .StringSlice (slices .Collect (maps .Keys (subset )))
126145 keys .Sort ()
127146 nodeList [owner ] = keys
128147 }
129148 return & trienodeHistory {
149+ meta : & trienodeMetadata {
150+ version : trienodeHistoryVersion ,
151+ parent : parent ,
152+ root : root ,
153+ block : block ,
154+ },
130155 owners : slices .SortedFunc (maps .Keys (nodes ), common .Hash .Cmp ),
131156 nodeList : nodeList ,
132157 nodes : nodes ,
@@ -174,7 +199,10 @@ func (h *trienodeHistory) encode() ([]byte, []byte, []byte, error) {
174199 keySection bytes.Buffer
175200 valueSection bytes.Buffer
176201 )
177- binary .Write (& headerSection , binary .BigEndian , trienodeHistoryVersion ) // 1 byte
202+ binary .Write (& headerSection , binary .BigEndian , h .meta .version ) // 1 byte
203+ headerSection .Write (h .meta .parent .Bytes ()) // 32 bytes
204+ headerSection .Write (h .meta .root .Bytes ()) // 32 bytes
205+ binary .Write (& headerSection , binary .BigEndian , h .meta .block ) // 8 byte
178206
179207 for _ , owner := range h .owners {
180208 // Fill the header section with offsets at key and value section
@@ -246,17 +274,21 @@ func (h *trienodeHistory) encode() ([]byte, []byte, []byte, error) {
246274
247275// decodeHeader resolves the metadata from the header section. An error
248276// should be returned if the header section is corrupted.
249- func decodeHeader (data []byte ) ([]common.Hash , []uint32 , []uint32 , error ) {
250- if len (data ) < trienodeVersionSize {
251- return nil , nil , nil , fmt .Errorf ("trienode history is too small, index size: %d" , len (data ))
277+ func decodeHeader (data []byte ) (* trienodeMetadata , []common.Hash , []uint32 , []uint32 , error ) {
278+ if len (data ) < trienodeMetadataSize {
279+ return nil , nil , nil , nil , fmt .Errorf ("trienode history is too small, index size: %d" , len (data ))
252280 }
253281 version := data [0 ]
254282 if version != trienodeHistoryVersion {
255- return nil , nil , nil , fmt .Errorf ("unregonized trienode history version: %d" , version )
283+ return nil , nil , nil , nil , fmt .Errorf ("unregonized trienode history version: %d" , version )
256284 }
257- size := len (data ) - trienodeVersionSize
285+ parent := common .BytesToHash (data [1 : common .HashLength + 1 ]) // 32 bytes
286+ root := common .BytesToHash (data [common .HashLength + 1 : common .HashLength * 2 + 1 ]) // 32 bytes
287+ block := binary .BigEndian .Uint64 (data [common .HashLength * 2 + 1 : trienodeMetadataSize ]) // 8 bytes
288+
289+ size := len (data ) - trienodeMetadataSize
258290 if size % trienodeTrieHeaderSize != 0 {
259- return nil , nil , nil , fmt .Errorf ("truncated trienode history data, size %d" , len (data ))
291+ return nil , nil , nil , nil , fmt .Errorf ("truncated trienode history data, size %d" , len (data ))
260292 }
261293 count := size / trienodeTrieHeaderSize
262294
@@ -266,17 +298,17 @@ func decodeHeader(data []byte) ([]common.Hash, []uint32, []uint32, error) {
266298 valOffsets = make ([]uint32 , 0 , count )
267299 )
268300 for i := 0 ; i < count ; i ++ {
269- n := trienodeVersionSize + trienodeTrieHeaderSize * i
301+ n := trienodeMetadataSize + trienodeTrieHeaderSize * i
270302 owner := common .BytesToHash (data [n : n + common .HashLength ])
271303 if i != 0 && bytes .Compare (owner .Bytes (), owners [i - 1 ].Bytes ()) <= 0 {
272- return nil , nil , nil , fmt .Errorf ("trienode owners are out of order, prev: %v, cur: %v" , owners [i - 1 ], owner )
304+ return nil , nil , nil , nil , fmt .Errorf ("trienode owners are out of order, prev: %v, cur: %v" , owners [i - 1 ], owner )
273305 }
274306 owners = append (owners , owner )
275307
276308 // Decode the offset to the key section
277309 keyOffset := binary .BigEndian .Uint32 (data [n + common .HashLength : n + common .HashLength + 4 ])
278310 if i != 0 && keyOffset <= keyOffsets [i - 1 ] {
279- return nil , nil , nil , fmt .Errorf ("key offset is out of order, prev: %v, cur: %v" , keyOffsets [i - 1 ], keyOffset )
311+ return nil , nil , nil , nil , fmt .Errorf ("key offset is out of order, prev: %v, cur: %v" , keyOffsets [i - 1 ], keyOffset )
280312 }
281313 keyOffsets = append (keyOffsets , keyOffset )
282314
@@ -285,11 +317,16 @@ func decodeHeader(data []byte) ([]common.Hash, []uint32, []uint32, error) {
285317 // a trie deletion).
286318 valOffset := binary .BigEndian .Uint32 (data [n + common .HashLength + 4 : n + common .HashLength + 8 ])
287319 if i != 0 && valOffset < valOffsets [i - 1 ] {
288- return nil , nil , nil , fmt .Errorf ("value offset is out of order, prev: %v, cur: %v" , valOffsets [i - 1 ], valOffset )
320+ return nil , nil , nil , nil , fmt .Errorf ("value offset is out of order, prev: %v, cur: %v" , valOffsets [i - 1 ], valOffset )
289321 }
290322 valOffsets = append (valOffsets , valOffset )
291323 }
292- return owners , keyOffsets , valOffsets , nil
324+ return & trienodeMetadata {
325+ version : version ,
326+ parent : parent ,
327+ root : root ,
328+ block : block ,
329+ }, owners , keyOffsets , valOffsets , nil
293330}
294331
295332func decodeSingle (keySection []byte , onValue func ([]byte , int , int ) error ) ([]string , error ) {
@@ -425,10 +462,11 @@ func decodeSingleWithValue(keySection []byte, valueSection []byte) ([]string, ma
425462
426463// decode deserializes the contained trie nodes from the provided bytes.
427464func (h * trienodeHistory ) decode (header []byte , keySection []byte , valueSection []byte ) error {
428- owners , keyOffsets , valueOffsets , err := decodeHeader (header )
465+ metadata , owners , keyOffsets , valueOffsets , err := decodeHeader (header )
429466 if err != nil {
430467 return err
431468 }
469+ h .meta = metadata
432470 h .owners = owners
433471 h .nodeList = make (map [common.Hash ][]string )
434472 h .nodes = make (map [common.Hash ]map [string ][]byte )
@@ -562,13 +600,13 @@ func newTrienodeHistoryReader(id uint64, reader ethdb.AncientReader) (*trienodeH
562600 return r , nil
563601}
564602
565- // decodeHeader decodes the metadata of trienode history from the header section .
603+ // decodeHeader decodes the header section of trienode history.
566604func (r * trienodeHistoryReader ) decodeHeader () error {
567605 header , err := rawdb .ReadTrienodeHistoryHeader (r .reader , r .id )
568606 if err != nil {
569607 return err
570608 }
571- owners , keyOffsets , valOffsets , err := decodeHeader (header )
609+ _ , owners , keyOffsets , valOffsets , err := decodeHeader (header )
572610 if err != nil {
573611 return err
574612 }
@@ -626,7 +664,7 @@ func (r *trienodeHistoryReader) read(owner common.Hash, path string) ([]byte, er
626664// nolint:unused
627665func writeTrienodeHistory (writer ethdb.AncientWriter , dl * diffLayer ) error {
628666 start := time .Now ()
629- h := newTrienodeHistory (dl .nodes .nodeOrigin )
667+ h := newTrienodeHistory (dl .rootHash (), dl . parent . rootHash (), dl . block , dl . nodes .nodeOrigin )
630668 header , keySection , valueSection , err := h .encode ()
631669 if err != nil {
632670 return err
@@ -649,6 +687,20 @@ func writeTrienodeHistory(writer ethdb.AncientWriter, dl *diffLayer) error {
649687 return nil
650688}
651689
690+ // readTrienodeMetadata resolves the metadata of the specified trienode history.
691+ // nolint:unused
692+ func readTrienodeMetadata (reader ethdb.AncientReader , id uint64 ) (* trienodeMetadata , error ) {
693+ header , err := rawdb .ReadTrienodeHistoryHeader (reader , id )
694+ if err != nil {
695+ return nil , err
696+ }
697+ metadata , _ , _ , _ , err := decodeHeader (header )
698+ if err != nil {
699+ return nil , err
700+ }
701+ return metadata , nil
702+ }
703+
652704// readTrienodeHistory resolves a single trienode history object with specific id.
653705func readTrienodeHistory (reader ethdb.AncientReader , id uint64 ) (* trienodeHistory , error ) {
654706 header , keySection , valueSection , err := rawdb .ReadTrienodeHistory (reader , id )
0 commit comments