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  }