Skip to content

Commit 9413399

Browse files
committed
rlp, trie, triedb/pathdb: compress trienode hsitory
1 parent cfa3b96 commit 9413399

File tree

5 files changed

+669
-0
lines changed

5 files changed

+669
-0
lines changed

rlp/raw.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package rlp
1818

1919
import (
20+
"fmt"
2021
"io"
2122
"reflect"
2223
)
@@ -152,6 +153,35 @@ func CountValues(b []byte) (int, error) {
152153
return i, nil
153154
}
154155

156+
// SplitListValues extracts the raw elements from the list RLP-encoding blob.
157+
func SplitListValues(b []byte) ([][]byte, error) {
158+
b, _, err := SplitList(b)
159+
if err != nil {
160+
return nil, fmt.Errorf("decode error: %v", err)
161+
}
162+
var elements [][]byte
163+
for len(b) > 0 {
164+
_, tagsize, size, err := readKind(b)
165+
if err != nil {
166+
return nil, err
167+
}
168+
elements = append(elements, b[:tagsize+size])
169+
b = b[tagsize+size:]
170+
}
171+
return elements, nil
172+
}
173+
174+
// MergeListValues takes a list of raw elements and rlp-encodes them as list.
175+
func MergeListValues(elems [][]byte) ([]byte, error) {
176+
w := NewEncoderBuffer(nil)
177+
offset := w.List()
178+
for _, elem := range elems {
179+
w.Write(elem)
180+
}
181+
w.ListEnd(offset)
182+
return w.ToBytes(), nil
183+
}
184+
155185
func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) {
156186
if len(buf) == 0 {
157187
return 0, 0, 0, io.ErrUnexpectedEOF

trie/node.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package trie
1818

1919
import (
20+
"bytes"
2021
"fmt"
2122
"io"
2223
"strings"
@@ -242,6 +243,74 @@ func decodeRef(buf []byte) (node, []byte, error) {
242243
}
243244
}
244245

246+
// decodeNodeElements parses the RLP encoding of a trie node and returns all the
247+
// elements in raw byte format.
248+
//
249+
// For full node, it returns a slice of 17 elements;
250+
// For short node, it returns a slice of 2 elements;
251+
func decodeNodeElements(buf []byte) ([][]byte, error) {
252+
if len(buf) == 0 {
253+
return nil, io.ErrUnexpectedEOF
254+
}
255+
return rlp.SplitListValues(buf)
256+
}
257+
258+
// encodeNodeElements encodes the provided node elements into a rlp list.
259+
func encodeNodeElements(elements [][]byte) ([]byte, error) {
260+
if len(elements) != 2 && len(elements) != 17 {
261+
return nil, fmt.Errorf("invalid number of elements: %d", len(elements))
262+
}
263+
return rlp.MergeListValues(elements)
264+
}
265+
266+
// NodeDifference accepts two RLP-encoding nodes and figures out the difference
267+
// between them.
268+
//
269+
// An error is returned if any of the provided blob is nil, or the type of nodes
270+
// are different.
271+
func NodeDifference(oldvalue []byte, newvalue []byte) (int, []int, [][]byte, error) {
272+
oldElems, err := decodeNodeElements(oldvalue)
273+
if err != nil {
274+
return 0, nil, nil, err
275+
}
276+
newElems, err := decodeNodeElements(newvalue)
277+
if err != nil {
278+
return 0, nil, nil, err
279+
}
280+
if len(oldElems) != len(newElems) {
281+
return 0, nil, nil, fmt.Errorf("different node type, old elements: %d, new elements: %d", len(oldElems), len(newElems))
282+
}
283+
var (
284+
indices = make([]int, 0, len(oldElems))
285+
diff = make([][]byte, 0, len(oldElems))
286+
)
287+
for i := 0; i < len(oldElems); i++ {
288+
if !bytes.Equal(oldElems[i], newElems[i]) {
289+
indices = append(indices, i)
290+
diff = append(diff, oldElems[i])
291+
}
292+
}
293+
return len(oldElems), indices, diff, nil
294+
}
295+
296+
// ReassembleNode accepts a RLP-encoding node along with a set of mutations,
297+
// applying the modification diffs according to the indices and re-assemble.
298+
func ReassembleNode(blob []byte, mutations [][][]byte, indices [][]int) ([]byte, error) {
299+
if len(mutations) == 0 && len(indices) == 0 {
300+
return blob, nil
301+
}
302+
elements, err := decodeNodeElements(blob)
303+
if err != nil {
304+
return nil, err
305+
}
306+
for i := 0; i < len(mutations); i++ {
307+
for j, pos := range indices[i] {
308+
elements[pos] = mutations[i][j]
309+
}
310+
}
311+
return encodeNodeElements(elements)
312+
}
313+
245314
// wraps a decoding error with information about the path to the
246315
// invalid child node (for debugging encoding issues).
247316
type decodeError struct {

0 commit comments

Comments
 (0)