From 35131b6d559b43a1ad0caadceaf9f4ee75d64580 Mon Sep 17 00:00:00 2001 From: Daniel Sobol Date: Mon, 12 Feb 2024 15:39:01 +0300 Subject: [PATCH] nibble encoding update (#2021) * nibble encoding update * portal-spec-tests update --- fluffy/network/state/state_content.nim | 43 +++++++++++-------- .../test_state_content_keys.nim | 13 +++--- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/fluffy/network/state/state_content.nim b/fluffy/network/state/state_content.nim index 3abeef595..ae15773e3 100644 --- a/fluffy/network/state/state_content.nim +++ b/fluffy/network/state/state_content.nim @@ -19,7 +19,7 @@ import export ssz_serialization, common_types, hash, results const - MAX_PACKED_NIBBLES_LEN = 32 + MAX_PACKED_NIBBLES_LEN = 33 MAX_UNPACKED_NIBBLES_LEN = 64 MAX_TRIE_NODE_LEN = 1024 @@ -44,10 +44,7 @@ type contractTrieNode = 0x21 contractCode = 0x22 - NibblePair* = byte - Nibbles* = object - isOddLength*: bool - packedNibbles*: List[NibblePair, MAX_PACKED_NIBBLES_LEN] + Nibbles* = List[byte, MAX_PACKED_NIBBLES_LEN] TrieNode* = List[byte, MAX_TRIE_NODE_LEN] TrieProof* = List[TrieNode, MAX_TRIE_PROOF_LEN] @@ -130,41 +127,53 @@ func toContentId*(contentKey: ContentKey): ContentId = func packNibbles*(nibbles: seq[byte]): Nibbles = doAssert(nibbles.len() <= MAX_UNPACKED_NIBBLES_LEN, "Can't pack more than 64 nibbles") + + if nibbles.len() == 0: + return Nibbles(@[byte(0x00)]) let isOddLength = (nibbles.len() %% 2 == 1) outputLength = (nibbles.len() + 1) div 2 var - output = newSeq[NibblePair]() + output = newSeq[byte]() highNibble = not isOddLength currentByte: byte = 0 - for nibble in nibbles: + if isOddLength: + currentByte = 0x10 + + if not isOddLength: + output.add(0x00) + + for i, nibble in nibbles: if highNibble: currentByte = nibble shl 4 else: - output.add(NibblePair(currentByte or nibble)) + output.add(currentByte or nibble) currentByte = 0 highNibble = not highNibble - Nibbles(isOddLength: isOddLength, packedNibbles: Nibbles.packedNibbles.init(output)) + Nibbles(output) func unpackNibbles*(nibbles: Nibbles): seq[byte] = - doAssert(nibbles.packedNibbles.len() <= MAX_PACKED_NIBBLES_LEN, "Can't unpack more than 32 nibbles") + doAssert(nibbles.len() <= MAX_PACKED_NIBBLES_LEN, "Can't unpack more than 32 nibbles") var output = newSeq[byte]() - for pair in nibbles.packedNibbles: + for i, pair in nibbles: + if i == 0 and pair == 0x00: + continue + let first = (pair and 0xF0) shr 4 second = pair and 0x0F - - output.add(first) - output.add(second) - - if nibbles.isOddLength: - output.delete(0) + + if i == 0 and first == 0x01: + output.add(second) + else: + output.add(first) + output.add(second) output diff --git a/fluffy/tests/state_network_tests/test_state_content_keys.nim b/fluffy/tests/state_network_tests/test_state_content_keys.nim index 87d67e6bb..5fd6144eb 100644 --- a/fluffy/tests/state_network_tests/test_state_content_keys.nim +++ b/fluffy/tests/state_network_tests/test_state_content_keys.nim @@ -13,7 +13,7 @@ import suite "State Content Keys": - const evenNibles = "00050000008679e8ed" + const evenNibles = "008679e8ed" test "Encode/decode even nibbles": const nibbles: seq[byte] = @[8, 6, 7, 9, 14, 8, 14, 13] @@ -26,20 +26,20 @@ suite "State Content Keys": check encoded.toHex() == evenNibles check unpackedNibbles == nibbles - const oddNibbles = "0105000000018679e8ed" + const oddNibbles = "138679e8ed" test "Encode/decode odd nibbles": const - nibbles: seq[byte] = @[1, 8, 6, 7, 9, 14, 8, 14, 13] + nibbles: seq[byte] = @[3, 8, 6, 7, 9, 14, 8, 14, 13] packedNibbles = packNibbles(nibbles) unpackedNibbles = unpackNibbles(packedNibbles) let encoded = SSZ.encode(packedNibbles) - + check encoded.toHex() == oddNibbles check unpackedNibbles == nibbles - const accountTrieNodeKeyEncoded = "20240000006225fcc63b22b80301d9f2582014e450e91f9b329b7cc87ad16894722fff529600050000008679e8ed" + const accountTrieNodeKeyEncoded = "20240000006225fcc63b22b80301d9f2582014e450e91f9b329b7cc87ad16894722fff5296008679e8ed" test "Encode/decode AccountTrieNodeKey": const nibbles: seq[byte] = @[8, 6, 7, 9, 14, 8, 14, 13] @@ -58,13 +58,12 @@ suite "State Content Keys": decoded.contentType == accountTrieNode decoded.accountTrieNodeKey == AccountTrieNodeKey(path: packedNibbles, nodeHash: nodeHash) - const contractTrieNodeKeyEncoded = "21c02aaa39b223fe8d0a0e5c4f27ead9083c756cc238000000eb43d68008d216e753fef198cf51077f5a89f406d9c244119d1643f0f2b190110005000000405787" + const contractTrieNodeKeyEncoded = "21c02aaa39b223fe8d0a0e5c4f27ead9083c756cc238000000eb43d68008d216e753fef198cf51077f5a89f406d9c244119d1643f0f2b1901100405787" test "Encode/decode ContractTrieNodeKey": const nibbles: seq[byte] = @[4, 0, 5, 7, 8, 7] packedNibbles = packNibbles(nibbles) address = Address.fromHex("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") - isOddLength = false nodeHash = NodeHash.fromHex("eb43d68008d216e753fef198cf51077f5a89f406d9c244119d1643f0f2b19011") let