github.com/koko1123/flow-go-1@v0.29.6/ledger/trie_encoder_test.go (about)

     1  package ledger_test
     2  
     3  import (
     4  	"encoding/binary"
     5  	"encoding/hex"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/koko1123/flow-go-1/ledger"
    11  	"github.com/koko1123/flow-go-1/ledger/common/hash"
    12  	"github.com/koko1123/flow-go-1/ledger/common/testutils"
    13  )
    14  
    15  // TestKeyPartSerialization tests encoding and decoding functionality of a ledger key part
    16  func TestKeyPartSerialization(t *testing.T) {
    17  	kp := testutils.KeyPartFixture(1, "key part 1")
    18  
    19  	encodedV0 := []byte{
    20  		0x00, 0x00, // version 0
    21  		0x02,       // type
    22  		0x00, 0x01, // key part type
    23  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
    24  	}
    25  
    26  	encodedV1 := []byte{
    27  		0x00, 0x01, // version 1
    28  		0x02,       // type
    29  		0x00, 0x01, // key part type
    30  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
    31  	}
    32  
    33  	t.Run("encoding", func(t *testing.T) {
    34  		encoded := ledger.EncodeKeyPart(&kp)
    35  		require.Equal(t, encodedV1, encoded)
    36  	})
    37  
    38  	t.Run("decoding", func(t *testing.T) {
    39  		// decode key part encoded in version 0
    40  		decodedkp, err := ledger.DecodeKeyPart(encodedV0)
    41  		require.NoError(t, err)
    42  		require.Equal(t, kp, *decodedkp)
    43  
    44  		// decode key part encoded in version 1
    45  		decodedkp, err = ledger.DecodeKeyPart(encodedV1)
    46  		require.NoError(t, err)
    47  		require.Equal(t, kp, *decodedkp)
    48  	})
    49  
    50  	t.Run("roundtrip", func(t *testing.T) {
    51  		encoded := ledger.EncodeKeyPart(&kp)
    52  		newkp, err := ledger.DecodeKeyPart(encoded)
    53  		require.NoError(t, err)
    54  		require.Equal(t, kp, *newkp)
    55  
    56  		// wrong type decoding
    57  		_, err = ledger.DecodeKey(encoded)
    58  		require.Error(t, err)
    59  
    60  		// test wrong version decoding
    61  		binary.BigEndian.PutUint16(encoded, ledger.PayloadVersion+1)
    62  		_, err = ledger.DecodeKeyPart(encoded)
    63  		require.Error(t, err)
    64  	})
    65  }
    66  
    67  // TestKeySerialization tests encoding and decoding functionality of a ledger key
    68  func TestKeySerialization(t *testing.T) {
    69  	kp1 := testutils.KeyPartFixture(1, "key part 1")
    70  	kp2 := testutils.KeyPartFixture(22, "key part 2")
    71  	k := ledger.NewKey([]ledger.KeyPart{kp1, kp2})
    72  
    73  	encodedV0 := []byte{
    74  		0x00, 0x00, // version 0
    75  		0x03,       // type
    76  		0x00, 0x02, // number of key parts
    77  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 1
    78  		0x00, 0x01, // key part type
    79  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
    80  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 2
    81  		0x00, 0x16, // key part type
    82  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value
    83  	}
    84  
    85  	encodedV1 := []byte{
    86  		0x00, 0x01, // version 1
    87  		0x03,       // type
    88  		0x00, 0x02, // number of key parts
    89  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 1
    90  		0x00, 0x01, // key part type
    91  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
    92  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 2
    93  		0x00, 0x16, // key part type
    94  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value
    95  	}
    96  
    97  	t.Run("encoding", func(t *testing.T) {
    98  		encoded := ledger.EncodeKey(&k)
    99  		require.Equal(t, encodedV1, encoded)
   100  	})
   101  
   102  	t.Run("decoding", func(t *testing.T) {
   103  		// decode key encoded in version 0
   104  		decodedk, err := ledger.DecodeKey(encodedV0)
   105  		require.NoError(t, err)
   106  		require.Equal(t, k, *decodedk)
   107  
   108  		// decode key encoded in version 1
   109  		decodedk, err = ledger.DecodeKey(encodedV1)
   110  		require.NoError(t, err)
   111  		require.Equal(t, k, *decodedk)
   112  	})
   113  
   114  	t.Run("roundtrip", func(t *testing.T) {
   115  		encoded := ledger.EncodeKey(&k)
   116  		newk, err := ledger.DecodeKey(encoded)
   117  		require.NoError(t, err)
   118  		require.Equal(t, k, *newk)
   119  	})
   120  }
   121  
   122  // TestValueSerialization tests encoding and decoding functionality of a ledger value
   123  func TestValueSerialization(t *testing.T) {
   124  	v := ledger.Value("value")
   125  
   126  	encodedV0 := []byte{
   127  		0x00, 0x01, // version 1
   128  		0x04,                         // type
   129  		0x76, 0x61, 0x6c, 0x75, 0x65, // value
   130  	}
   131  
   132  	encodedV1 := []byte{
   133  		0x00, 0x01, // version 1
   134  		0x04,                         // type
   135  		0x76, 0x61, 0x6c, 0x75, 0x65, // value
   136  	}
   137  
   138  	t.Run("encoding", func(t *testing.T) {
   139  		encoded := ledger.EncodeValue(v)
   140  		require.Equal(t, encodedV1, encoded)
   141  	})
   142  
   143  	t.Run("decoding", func(t *testing.T) {
   144  		// decode key encoded in version 0
   145  		decodedv, err := ledger.DecodeValue(encodedV0)
   146  		require.NoError(t, err)
   147  		require.Equal(t, v, decodedv)
   148  
   149  		// decode key encoded in version 1
   150  		decodedv, err = ledger.DecodeValue(encodedV1)
   151  		require.NoError(t, err)
   152  		require.Equal(t, v, decodedv)
   153  	})
   154  
   155  	t.Run("roundtrip", func(t *testing.T) {
   156  		encoded := ledger.EncodeValue(v)
   157  		newV, err := ledger.DecodeValue(encoded)
   158  		require.NoError(t, err)
   159  		require.Equal(t, v, newV)
   160  	})
   161  }
   162  
   163  // TestPayloadSerialization tests encoding and decoding functionality of a payload
   164  func TestPayloadSerialization(t *testing.T) {
   165  	kp1 := ledger.NewKeyPart(1, []byte("key part 1"))
   166  	kp2 := ledger.NewKeyPart(uint16(22), []byte("key part 2"))
   167  	k := ledger.NewKey([]ledger.KeyPart{kp1, kp2})
   168  	v := ledger.Value([]byte{'A'})
   169  	p := ledger.NewPayload(k, v)
   170  
   171  	encodedV0 := []byte{
   172  		0x00, 0x00, // version 0
   173  		0x06,                   // type
   174  		0x00, 0x00, 0x00, 0x22, // length of encoded key
   175  		0x00, 0x02, // number of key parts
   176  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 1
   177  		0x00, 0x01, // key part type
   178  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
   179  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 2
   180  		0x00, 0x16, // key part type
   181  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value
   182  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // length of encoded value
   183  		0x41, // value
   184  	}
   185  
   186  	encodedV1 := []byte{
   187  		0x00, 0x01, // version 1
   188  		0x06,                   // type
   189  		0x00, 0x00, 0x00, 0x22, // length of encoded key
   190  		0x00, 0x02, // number of key parts
   191  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 1
   192  		0x00, 0x01, // key part type
   193  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
   194  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 2
   195  		0x00, 0x16, // key part type
   196  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value
   197  		0x00, 0x00, 0x00, 0x01, // length of encoded value
   198  		0x41, // value
   199  	}
   200  
   201  	t.Run("encoding", func(t *testing.T) {
   202  		encoded := ledger.EncodePayload(p)
   203  		require.Equal(t, encodedV1, encoded)
   204  	})
   205  
   206  	t.Run("decoding", func(t *testing.T) {
   207  		// decode payload encoded in version 0
   208  		decodedp, err := ledger.DecodePayload(encodedV0)
   209  		require.NoError(t, err)
   210  		require.Equal(t, p, decodedp)
   211  
   212  		// decode payload encoded in version 1
   213  		decodedp, err = ledger.DecodePayload(encodedV1)
   214  		require.NoError(t, err)
   215  		require.Equal(t, p, decodedp)
   216  	})
   217  
   218  	t.Run("roundtrip", func(t *testing.T) {
   219  		encoded := ledger.EncodePayload(p)
   220  		newp, err := ledger.DecodePayload(encoded)
   221  		require.NoError(t, err)
   222  		require.Equal(t, p, newp)
   223  	})
   224  }
   225  
   226  // TestNilPayloadWithoutPrefixSerialization tests encoding and decoding
   227  // nil payload without prefix (version and type).
   228  func TestNilPayloadWithoutPrefixSerialization(t *testing.T) {
   229  
   230  	t.Run("encoding", func(t *testing.T) {
   231  		buf := []byte{1, 2, 3}
   232  
   233  		// Test encoded payload data length
   234  		encodedPayloadLen := ledger.EncodedPayloadLengthWithoutPrefix(nil, ledger.PayloadVersion)
   235  		require.Equal(t, 0, encodedPayloadLen)
   236  
   237  		// Encode payload and append to buffer
   238  		encoded := ledger.EncodeAndAppendPayloadWithoutPrefix(buf, nil, ledger.PayloadVersion)
   239  		// Test original input data isn't modified
   240  		require.Equal(t, buf, encoded)
   241  		// Test returned encoded data reuses input data
   242  		require.True(t, &buf[0] == &encoded[0])
   243  	})
   244  
   245  	t.Run("decoding", func(t *testing.T) {
   246  		// Decode and copy payload (excluding prefix)
   247  		newp, err := ledger.DecodePayloadWithoutPrefix([]byte{}, false, ledger.PayloadVersion)
   248  		require.NoError(t, err)
   249  		require.Nil(t, newp)
   250  
   251  		// Zerocopy option has no effect for nil payload, but test it anyway.
   252  		// Decode payload (excluding prefix) with zero copy
   253  		newp, err = ledger.DecodePayloadWithoutPrefix([]byte{}, true, ledger.PayloadVersion)
   254  		require.NoError(t, err)
   255  		require.Nil(t, newp)
   256  	})
   257  }
   258  
   259  // TestPayloadWithoutPrefixSerialization tests encoding and decoding payload without prefix (version and type).
   260  func TestPayloadWithoutPrefixSerialization(t *testing.T) {
   261  	kp1 := ledger.NewKeyPart(1, []byte("key part 1"))
   262  	kp2 := ledger.NewKeyPart(22, []byte("key part 2"))
   263  	k := ledger.NewKey([]ledger.KeyPart{kp1, kp2})
   264  	v := ledger.Value([]byte{'A'})
   265  	p := ledger.NewPayload(k, v)
   266  
   267  	encodedV0 := []byte{
   268  		0x00, 0x00, 0x00, 0x22, // length of encoded key
   269  		0x00, 0x02, // number of key parts
   270  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 0
   271  		0x00, 0x01, // key part type
   272  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
   273  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 1
   274  		0x00, 0x16, // key part type
   275  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value
   276  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // length of encoded value
   277  		0x41, // value
   278  	}
   279  
   280  	encodedV1 := []byte{
   281  		0x00, 0x00, 0x00, 0x22, // length of encoded key
   282  		0x00, 0x02, // number of key parts
   283  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 0
   284  		0x00, 0x01, // key part type
   285  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value
   286  		0x00, 0x00, 0x00, 0x0c, // length of encoded key part 1
   287  		0x00, 0x16, // key part type
   288  		0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value
   289  		0x00, 0x00, 0x00, 0x01, // length of encoded value
   290  		0x41, // value
   291  	}
   292  
   293  	t.Run("encoding", func(t *testing.T) {
   294  		// encode payload without prefix using version 0
   295  		encoded := ledger.EncodeAndAppendPayloadWithoutPrefix(nil, p, 0)
   296  		encodedPayloadLen := ledger.EncodedPayloadLengthWithoutPrefix(p, 0)
   297  		require.Equal(t, len(encodedV0), encodedPayloadLen)
   298  		require.Equal(t, encodedV0, encoded)
   299  
   300  		// encode payload without prefix using version 1
   301  		encoded = ledger.EncodeAndAppendPayloadWithoutPrefix(nil, p, 1)
   302  		encodedPayloadLen = ledger.EncodedPayloadLengthWithoutPrefix(p, 1)
   303  		require.Equal(t, len(encodedV1), encodedPayloadLen)
   304  		require.Equal(t, encodedV1, encoded)
   305  	})
   306  
   307  	t.Run("decoding", func(t *testing.T) {
   308  		// decode payload without prefix encoding in verison 0
   309  		decodedp, err := ledger.DecodePayloadWithoutPrefix(encodedV0, true, 0)
   310  		require.NoError(t, err)
   311  		require.Equal(t, p, decodedp)
   312  
   313  		// decode payload without prefix encoding in verison 1
   314  		decodedp, err = ledger.DecodePayloadWithoutPrefix(encodedV1, true, 1)
   315  		require.NoError(t, err)
   316  		require.Equal(t, p, decodedp)
   317  	})
   318  
   319  	const encodedPayloadSize = 43 // size of encoded payload p without prefix (version + type)
   320  
   321  	testCases := []struct {
   322  		name     string
   323  		bufCap   int
   324  		zeroCopy bool
   325  	}{
   326  		// full cap means no capacity for appending payload (new alloc)
   327  		{"full cap zerocopy", 0, true},
   328  		{"full cap", 0, false},
   329  		// small cap means not enough capacity for appending payload (new alloc)
   330  		{"small cap zerocopy", encodedPayloadSize - 1, true},
   331  		{"small cap", encodedPayloadSize - 1, false},
   332  		// exact cap means exact capacity for appending payload (no alloc)
   333  		{"exact cap zerocopy", encodedPayloadSize, true},
   334  		{"exact cap", encodedPayloadSize, false},
   335  		// large cap means extra capacity than is needed for appending payload (no alloc)
   336  		{"large cap zerocopy", encodedPayloadSize + 1, true},
   337  		{"large cap", encodedPayloadSize + 1, false},
   338  	}
   339  
   340  	bufPrefix := []byte{1, 2, 3}
   341  	bufPrefixLen := len(bufPrefix)
   342  
   343  	for _, tc := range testCases {
   344  
   345  		t.Run("roundtrip "+tc.name, func(t *testing.T) {
   346  			// Create a buffer of specified cap + prefix length
   347  			buffer := make([]byte, bufPrefixLen, bufPrefixLen+tc.bufCap)
   348  			copy(buffer, bufPrefix)
   349  
   350  			// Encode payload and append to buffer
   351  			encoded := ledger.EncodeAndAppendPayloadWithoutPrefix(buffer, p, ledger.PayloadVersion)
   352  			encodedPayloadLen := ledger.EncodedPayloadLengthWithoutPrefix(p, ledger.PayloadVersion)
   353  			// Test encoded data size
   354  			require.Equal(t, len(encoded), bufPrefixLen+encodedPayloadLen)
   355  			// Test if original input data is modified
   356  			require.Equal(t, bufPrefix, encoded[:bufPrefixLen])
   357  			// Test if input buffer is reused if it fits
   358  			if tc.bufCap >= encodedPayloadLen {
   359  				require.True(t, &buffer[0] == &encoded[0])
   360  			} else {
   361  				// new alloc
   362  				require.True(t, &buffer[0] != &encoded[0])
   363  			}
   364  
   365  			// Decode payload (excluding prefix)
   366  			decodedp, err := ledger.DecodePayloadWithoutPrefix(encoded[bufPrefixLen:], tc.zeroCopy, ledger.PayloadVersion)
   367  			require.NoError(t, err)
   368  			require.Equal(t, p, decodedp)
   369  
   370  			// Reset encoded payload
   371  			for i := 0; i < len(encoded); i++ {
   372  				encoded[i] = 0
   373  			}
   374  
   375  			if tc.zeroCopy {
   376  				// Test if decoded payload is changed after source data is modified
   377  				// because data is shared.
   378  				require.NotEqual(t, p, decodedp)
   379  			} else {
   380  				// Test if decoded payload is unchanged after source data is modified.
   381  				require.Equal(t, p, decodedp)
   382  			}
   383  		})
   384  	}
   385  }
   386  
   387  // TestTrieProofSerialization tests encoding and decoding functionality of a proof
   388  func TestTrieProofSerialization(t *testing.T) {
   389  
   390  	interim1Bytes, _ := hex.DecodeString("accb0399dd2b3a7a48618b2376f5e61d822e0c7736b044c364a05c2904a2f315")
   391  	interim2Bytes, _ := hex.DecodeString("f3fba426a2f01c342304e3ca7796c3980c62c625f7fd43105ad5afd92b165542")
   392  
   393  	var interim1, interim2 hash.Hash
   394  	copy(interim1[:], interim1Bytes)
   395  	copy(interim2[:], interim2Bytes)
   396  
   397  	p := &ledger.TrieProof{
   398  		Payload:   testutils.LightPayload8('A', 'A'),
   399  		Interims:  []hash.Hash{interim1, interim2},
   400  		Inclusion: true,
   401  		Flags:     []byte{byte(130), byte(0)},
   402  		Steps:     7,
   403  		Path:      testutils.PathByUint16(330),
   404  	}
   405  
   406  	encodedV0 := []byte{
   407  		0x00, 0x00, // version 0
   408  		0x07,       // type
   409  		0x80,       // inclusion
   410  		0x07,       // step
   411  		0x02,       // length of flag
   412  		0x82, 0x00, // flag
   413  		0x00, 0x20, // length of path
   414  		0x01, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   415  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   416  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   417  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // path
   418  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, // length of encoded payload
   419  		0x00, 0x00, 0x00, 0x09, // length of encoded payload key
   420  		0x00, 0x01, // number of payload key parts
   421  		0x00, 0x00, 0x00, 0x03, // length of encoded payload key part 0
   422  		0x00, 0x00, // payload key part type
   423  		0x41,                                           // payload key part value
   424  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // length of encoded payload value
   425  		0x41,        // payload value
   426  		0x02,        // number of interims
   427  		0x00, 0x020, // length of encoded interim
   428  		0xac, 0xcb, 0x03, 0x99, 0xdd, 0x2b, 0x3a, 0x7a,
   429  		0x48, 0x61, 0x8b, 0x23, 0x76, 0xf5, 0xe6, 0x1d,
   430  		0x82, 0x2e, 0x0c, 0x77, 0x36, 0xb0, 0x44, 0xc3,
   431  		0x64, 0xa0, 0x5c, 0x29, 0x04, 0xa2, 0xf3, 0x15, // interim
   432  		0x00, 0x020, // length of encoded interim
   433  		0xf3, 0xfb, 0xa4, 0x26, 0xa2, 0xf0, 0x1c, 0x34,
   434  		0x23, 0x04, 0xe3, 0xca, 0x77, 0x96, 0xc3, 0x98,
   435  		0x0c, 0x62, 0xc6, 0x25, 0xf7, 0xfd, 0x43, 0x10,
   436  		0x5a, 0xd5, 0xaf, 0xd9, 0x2b, 0x16, 0x55, 0x42, // interim
   437  	}
   438  
   439  	t.Run("encoding", func(t *testing.T) {
   440  		encoded := ledger.EncodeTrieProof(p)
   441  		require.Equal(t, encodedV0, encoded)
   442  	})
   443  
   444  	t.Run("decoding", func(t *testing.T) {
   445  		decodedp, err := ledger.DecodeTrieProof(encodedV0)
   446  		require.NoError(t, err)
   447  		require.True(t, decodedp.Equals(p))
   448  	})
   449  
   450  	t.Run("roundtrip", func(t *testing.T) {
   451  		p, _ := testutils.TrieProofFixture()
   452  		encoded := ledger.EncodeTrieProof(p)
   453  		newp, err := ledger.DecodeTrieProof(encoded)
   454  		require.NoError(t, err)
   455  		require.True(t, newp.Equals(p))
   456  	})
   457  }
   458  
   459  // TestBatchProofSerialization tests encoding and decoding functionality of a batch proof
   460  func TestBatchProofSerialization(t *testing.T) {
   461  	interim1Bytes, _ := hex.DecodeString("accb0399dd2b3a7a48618b2376f5e61d822e0c7736b044c364a05c2904a2f315")
   462  	interim2Bytes, _ := hex.DecodeString("f3fba426a2f01c342304e3ca7796c3980c62c625f7fd43105ad5afd92b165542")
   463  
   464  	var interim1, interim2 hash.Hash
   465  	copy(interim1[:], interim1Bytes)
   466  	copy(interim2[:], interim2Bytes)
   467  
   468  	p := &ledger.TrieProof{
   469  		Payload:   testutils.LightPayload8('A', 'A'),
   470  		Interims:  []hash.Hash{interim1, interim2},
   471  		Inclusion: true,
   472  		Flags:     []byte{byte(130), byte(0)},
   473  		Steps:     7,
   474  		Path:      testutils.PathByUint16(330),
   475  	}
   476  
   477  	bp := &ledger.TrieBatchProof{
   478  		Proofs: []*ledger.TrieProof{p, p},
   479  	}
   480  
   481  	encodedProofV0 := []byte{
   482  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, // length of encoded proof
   483  		0x80,       // inclusion
   484  		0x07,       // step
   485  		0x02,       // length of flag
   486  		0x82, 0x00, // flag
   487  		0x00, 0x20, // length of path
   488  		0x01, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   489  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   490  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   491  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // path
   492  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, // length of encoded payload
   493  		0x00, 0x00, 0x00, 0x09, // length of encoded payload key
   494  		0x00, 0x01, // number of payload key parts
   495  		0x00, 0x00, 0x00, 0x03, // length of encoded payload key part 0
   496  		0x00, 0x00, // payload key part type
   497  		0x41,                                           // payload key part value
   498  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // length of encoded payload value
   499  		0x41,        // payload value
   500  		0x02,        // number of interims
   501  		0x00, 0x020, // length of encoded interim
   502  		0xac, 0xcb, 0x03, 0x99, 0xdd, 0x2b, 0x3a, 0x7a,
   503  		0x48, 0x61, 0x8b, 0x23, 0x76, 0xf5, 0xe6, 0x1d,
   504  		0x82, 0x2e, 0x0c, 0x77, 0x36, 0xb0, 0x44, 0xc3,
   505  		0x64, 0xa0, 0x5c, 0x29, 0x04, 0xa2, 0xf3, 0x15, // interim
   506  		0x00, 0x020, // length of encoded interim
   507  		0xf3, 0xfb, 0xa4, 0x26, 0xa2, 0xf0, 0x1c, 0x34,
   508  		0x23, 0x04, 0xe3, 0xca, 0x77, 0x96, 0xc3, 0x98,
   509  		0x0c, 0x62, 0xc6, 0x25, 0xf7, 0xfd, 0x43, 0x10,
   510  		0x5a, 0xd5, 0xaf, 0xd9, 0x2b, 0x16, 0x55, 0x42, // interim
   511  	}
   512  
   513  	encodedBatchProofHead := []byte{
   514  		0x00, 0x00, // version 0
   515  		0x08,                   // type
   516  		0x00, 0x00, 0x00, 0x02, // number of proofs
   517  	}
   518  	encodedV0 := append([]byte{}, encodedBatchProofHead...)
   519  	encodedV0 = append(encodedV0, encodedProofV0...)
   520  	encodedV0 = append(encodedV0, encodedProofV0...)
   521  
   522  	t.Run("encoding", func(t *testing.T) {
   523  		encoded := ledger.EncodeTrieBatchProof(bp)
   524  		require.Equal(t, encodedV0, encoded)
   525  	})
   526  
   527  	t.Run("decoding", func(t *testing.T) {
   528  		decodedbp, err := ledger.DecodeTrieBatchProof(encodedV0)
   529  		require.NoError(t, err)
   530  		require.True(t, decodedbp.Equals(bp))
   531  	})
   532  
   533  	t.Run("roundtrip", func(t *testing.T) {
   534  		bp, _ = testutils.TrieBatchProofFixture()
   535  		encoded := ledger.EncodeTrieBatchProof(bp)
   536  		newbp, err := ledger.DecodeTrieBatchProof(encoded)
   537  		require.NoError(t, err)
   538  		require.True(t, newbp.Equals(bp))
   539  	})
   540  }
   541  
   542  // TestTrieUpdateSerialization tests encoding and decoding functionality of a trie update
   543  func TestTrieUpdateSerialization(t *testing.T) {
   544  
   545  	p1 := testutils.PathByUint16(1)
   546  	kp1 := ledger.NewKeyPart(uint16(1), []byte("key 1 part 1"))
   547  	kp2 := ledger.NewKeyPart(uint16(22), []byte("key 1 part 2"))
   548  	k1 := ledger.NewKey([]ledger.KeyPart{kp1, kp2})
   549  	pl1 := ledger.NewPayload(k1, []byte{'A'})
   550  
   551  	p2 := testutils.PathByUint16(2)
   552  	kp3 := ledger.NewKeyPart(uint16(1), []byte("key 2 part 1"))
   553  	k2 := ledger.NewKey([]ledger.KeyPart{kp3})
   554  	pl2 := ledger.NewPayload(k2, []byte{'B'})
   555  
   556  	tu := &ledger.TrieUpdate{
   557  		RootHash: testutils.RootHashFixture(),
   558  		Paths:    []ledger.Path{p1, p2},
   559  		Payloads: []*ledger.Payload{pl1, pl2},
   560  	}
   561  
   562  	encodedV0 := []byte{
   563  		0x00, 0x00, // version 0
   564  		0x0b,        // type
   565  		0x00, 0x020, // length of hash
   566  		0x6a, 0x7a, 0x56, 0x5a, 0xdd, 0x94, 0xfb, 0x36,
   567  		0x06, 0x9d, 0x79, 0xe8, 0x72, 0x5c, 0x22, 0x1c,
   568  		0xd1, 0xe5, 0x74, 0x07, 0x42, 0x50, 0x1e, 0xf0,
   569  		0x14, 0xea, 0x6d, 0xb9, 0x99, 0xfd, 0x98, 0xad, // root hash
   570  		0x00, 0x00, 0x00, 0x02, // number of paths
   571  		0x00, 0x20, // length of path
   572  		0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   573  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   574  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   575  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // path 1
   576  		0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   577  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   578  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   579  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // path 2
   580  		0x00, 0x00, 0x00, 0x33, // length of encoded payload
   581  		0x00, 0x00, 0x00, 0x26, // length of encoded key
   582  		0x00, 0x02, // number of key parts: 2
   583  		0x00, 0x00, 0x00, 0x0e, // length of encoded key part 0
   584  		0x00, 0x01, // key part type
   585  		0x6b, 0x65, 0x79, 0x20, 0x31, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value: key 1 part 1
   586  		0x00, 0x00, 0x00, 0x0e, // length of encoded key part 1
   587  		0x00, 0x16, // key part type
   588  		0x6b, 0x65, 0x79, 0x20, 0x31, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x32, // key part value: key 1 part 2
   589  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // length of encoded value
   590  		0x41,                   // value
   591  		0x00, 0x00, 0x00, 0x21, // length of encoded payload
   592  		0x00, 0x00, 0x00, 0x14, // length of encoded key
   593  		0x00, 0x01, // number of key parts
   594  		0x00, 0x00, 0x00, 0x0e, // length of encoded key part 0
   595  		0x00, 0x01, // key part type
   596  		0x6b, 0x65, 0x79, 0x20, 0x32, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x31, // key part value: key 2 part 1
   597  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // length of encoded value
   598  		0x42, // value
   599  	}
   600  
   601  	t.Run("encoding", func(t *testing.T) {
   602  		encoded := ledger.EncodeTrieUpdate(tu)
   603  		require.Equal(t, encodedV0, encoded)
   604  	})
   605  
   606  	t.Run("decoding", func(t *testing.T) {
   607  		decodedtu, err := ledger.DecodeTrieUpdate(encodedV0)
   608  		require.NoError(t, err)
   609  		require.True(t, decodedtu.Equals(tu))
   610  	})
   611  
   612  	t.Run("roundtrip", func(t *testing.T) {
   613  		encoded := ledger.EncodeTrieUpdate(tu)
   614  		decodedtu, err := ledger.DecodeTrieUpdate(encoded)
   615  		require.NoError(t, err)
   616  		require.True(t, decodedtu.Equals(tu))
   617  	})
   618  }