github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/complete/mtrie/flattener/encoding_v3_test.go (about) 1 package flattener_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 10 "github.com/onflow/flow-go/ledger" 11 "github.com/onflow/flow-go/ledger/common/hash" 12 "github.com/onflow/flow-go/ledger/common/testutils" 13 "github.com/onflow/flow-go/ledger/complete/mtrie/flattener" 14 "github.com/onflow/flow-go/ledger/complete/mtrie/node" 15 ) 16 17 // This file contains node/trie decoding tests for checkpoint v3 and earlier versions. 18 // These tests are based on TestStorableNode and TestStorableTrie. 19 20 func TestNodeV3Decoding(t *testing.T) { 21 22 const leafNode1Index = 1 23 const leafNode2Index = 2 24 25 leafNode1 := node.NewNode(255, nil, nil, testutils.PathByUint8(0), testutils.LightPayload8('A', 'a'), hash.Hash([32]byte{1, 1, 1})) 26 leafNode2 := node.NewNode(255, nil, nil, testutils.PathByUint8(1), testutils.LightPayload8('B', 'b'), hash.Hash([32]byte{2, 2, 2})) 27 28 interimNode := node.NewNode(256, leafNode1, leafNode2, ledger.DummyPath, nil, hash.Hash([32]byte{3, 3, 3})) 29 30 encodedLeafNode1 := []byte{ 31 0x00, 0x00, // encoding version 32 0x00, 0xff, // height 33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LIndex 34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RIndex 35 0x00, 0x00, // max depth 36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // reg count 37 0x00, 0x20, // path data len 38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // path data 42 0x00, 0x00, 0x00, 0x19, // payload data len 43 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 44 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x41, 45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 46 0x61, // payload data 47 0x00, 0x20, // hashValue length 48 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hash value 52 } 53 54 encodedInterimNode := []byte{ 55 0x00, 0x00, // encoding version 56 0x01, 0x00, // height 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // LIndex 58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // RIndex 59 0x00, 0x01, // max depth 60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // reg count 61 0x00, 0x00, // path data len 62 0x00, 0x00, 0x00, 0x00, // payload data len 63 0x00, 0x20, // hashValue length 64 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hash value 68 } 69 70 t.Run("leaf node", func(t *testing.T) { 71 reader := bytes.NewReader(encodedLeafNode1) 72 newNode, regCount, regSize, err := flattener.ReadNodeFromCheckpointV3AndEarlier(reader, func(nodeIndex uint64) (*node.Node, uint64, uint64, error) { 73 return nil, 0, 0, fmt.Errorf("no call expected") 74 }) 75 require.NoError(t, err) 76 require.Equal(t, leafNode1, newNode) 77 require.Equal(t, uint64(1), regCount) 78 require.Equal(t, uint64(leafNode1.Payload().Size()), regSize) 79 }) 80 81 t.Run("interim node", func(t *testing.T) { 82 reader := bytes.NewReader(encodedInterimNode) 83 newNode, regCount, regSize, err := flattener.ReadNodeFromCheckpointV3AndEarlier(reader, func(nodeIndex uint64) (*node.Node, uint64, uint64, error) { 84 switch nodeIndex { 85 case leafNode1Index: 86 return leafNode1, 1, uint64(leafNode1.Payload().Size()), nil 87 case leafNode2Index: 88 return leafNode2, 1, uint64(leafNode2.Payload().Size()), nil 89 default: 90 return nil, 0, 0, fmt.Errorf("unexpected child node index %d ", nodeIndex) 91 } 92 }) 93 require.NoError(t, err) 94 require.Equal(t, interimNode, newNode) 95 require.Equal(t, uint64(2), regCount) 96 require.Equal(t, uint64(leafNode1.Payload().Size()+leafNode2.Payload().Size()), regSize) 97 }) 98 } 99 100 func TestTrieV3Decoding(t *testing.T) { 101 102 const rootNodeIndex = 21 103 const rootNodeRegCount = 5000 104 const rootNodeRegSize = 1000000 105 106 hashValue := hash.Hash([32]byte{2, 2, 2}) 107 rootNode := node.NewNode(256, nil, nil, ledger.DummyPath, nil, hashValue) 108 109 expected := []byte{ 110 0x00, 0x00, // encoding version 111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21, // RootIndex 112 0x00, 0x20, // hashValue length 113 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hash value 117 } 118 119 reader := bytes.NewReader(expected) 120 121 trie, err := flattener.ReadTrieFromCheckpointV3AndEarlier(reader, func(nodeIndex uint64) (*node.Node, uint64, uint64, error) { 122 switch nodeIndex { 123 case rootNodeIndex: 124 return rootNode, rootNodeRegCount, rootNodeRegSize, nil 125 default: 126 return nil, 0, 0, fmt.Errorf("unexpected root node index %d ", nodeIndex) 127 } 128 }) 129 require.NoError(t, err) 130 require.Equal(t, rootNode, trie.RootNode()) 131 require.Equal(t, uint64(rootNodeRegCount), trie.AllocatedRegCount()) 132 require.Equal(t, uint64(rootNodeRegSize), trie.AllocatedRegSize()) 133 }