github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/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/onflow/flow-go/ledger" 11 "github.com/onflow/flow-go/ledger/common/hash" 12 "github.com/onflow/flow-go/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 }