Fluffy state network fixes and improvements (#2576)
* Cleanup tests. * Improve offer sort function in state bridge. * Verify nibble prefix for leaf and extension nodes during lookup.
This commit is contained in:
parent
dbabe7e0a7
commit
507a9e71df
|
@ -50,7 +50,16 @@ proc getNextNodeHash(
|
||||||
)
|
)
|
||||||
|
|
||||||
# leaf or extension node
|
# leaf or extension node
|
||||||
let (_, isLeaf, prefix) = decodePrefix(trieNodeRlp.listElem(0))
|
let
|
||||||
|
(_, isLeaf, prefix) = decodePrefix(trieNodeRlp.listElem(0))
|
||||||
|
unpackedPrefix = prefix.unpackNibbles()
|
||||||
|
|
||||||
|
if unpackedPrefix != nibbles[nibbleIdx ..< nibbleIdx + unpackedPrefix.len()]:
|
||||||
|
# The nibbles don't match so we stop the search and don't increment
|
||||||
|
# the nibble index to indicate how many nibbles were consumed
|
||||||
|
return Opt.none((Nibbles, NodeHash))
|
||||||
|
|
||||||
|
nibbleIdx += prefix.unpackNibbles().len()
|
||||||
if isLeaf:
|
if isLeaf:
|
||||||
return Opt.none((Nibbles, NodeHash))
|
return Opt.none((Nibbles, NodeHash))
|
||||||
|
|
||||||
|
@ -59,7 +68,6 @@ proc getNextNodeHash(
|
||||||
if nextHashBytes.len() == 0:
|
if nextHashBytes.len() == 0:
|
||||||
return Opt.none((Nibbles, NodeHash))
|
return Opt.none((Nibbles, NodeHash))
|
||||||
|
|
||||||
nibbleIdx += prefix.unpackNibbles().len()
|
|
||||||
Opt.some(
|
Opt.some(
|
||||||
(nibbles[0 ..< nibbleIdx].packNibbles(), KeccakHash.fromBytes(nextHashBytes))
|
(nibbles[0 ..< nibbleIdx].packNibbles(), KeccakHash.fromBytes(nextHashBytes))
|
||||||
)
|
)
|
||||||
|
@ -91,7 +99,10 @@ proc getAccountProof(
|
||||||
|
|
||||||
key = AccountTrieNodeKey.init(nextPath, nextNodeHash)
|
key = AccountTrieNodeKey.init(nextPath, nextNodeHash)
|
||||||
|
|
||||||
Opt.some(proof)
|
if nibblesIdx < nibbles.len():
|
||||||
|
Opt.none(TrieProof)
|
||||||
|
else:
|
||||||
|
Opt.some(proof)
|
||||||
|
|
||||||
proc getStorageProof(
|
proc getStorageProof(
|
||||||
n: StateNetwork, storageRoot: KeccakHash, address: EthAddress, storageKey: UInt256
|
n: StateNetwork, storageRoot: KeccakHash, address: EthAddress, storageKey: UInt256
|
||||||
|
@ -119,7 +130,10 @@ proc getStorageProof(
|
||||||
|
|
||||||
key = ContractTrieNodeKey.init(addressHash, nextPath, nextNodeHash)
|
key = ContractTrieNodeKey.init(addressHash, nextPath, nextNodeHash)
|
||||||
|
|
||||||
Opt.some(proof)
|
if nibblesIdx < nibbles.len():
|
||||||
|
Opt.none(TrieProof)
|
||||||
|
else:
|
||||||
|
Opt.some(proof)
|
||||||
|
|
||||||
proc getAccount(
|
proc getAccount(
|
||||||
n: StateNetwork, blockHash: BlockHash, address: EthAddress
|
n: StateNetwork, blockHash: BlockHash, address: EthAddress
|
||||||
|
|
|
@ -61,12 +61,12 @@ func rlpDecodeContractTrieNode*(contractTrieNode: TrieNode): Result[UInt256, str
|
||||||
err(e.msg)
|
err(e.msg)
|
||||||
|
|
||||||
func toAccount*(accountProof: TrieProof): Result[Account, string] {.inline.} =
|
func toAccount*(accountProof: TrieProof): Result[Account, string] {.inline.} =
|
||||||
doAssert(accountProof.len() > 1)
|
doAssert(accountProof.len() > 0)
|
||||||
|
|
||||||
rlpDecodeAccountTrieNode(accountProof[^1])
|
rlpDecodeAccountTrieNode(accountProof[^1])
|
||||||
|
|
||||||
func toSlot*(storageProof: TrieProof): Result[UInt256, string] {.inline.} =
|
func toSlot*(storageProof: TrieProof): Result[UInt256, string] {.inline.} =
|
||||||
doAssert(storageProof.len() > 1)
|
doAssert(storageProof.len() > 0)
|
||||||
|
|
||||||
rlpDecodeContractTrieNode(storageProof[^1])
|
rlpDecodeContractTrieNode(storageProof[^1])
|
||||||
|
|
||||||
|
|
|
@ -77,20 +77,21 @@ proc getGenesisAlloc*(filePath: string): GenesisAlloc =
|
||||||
|
|
||||||
proc toState*(
|
proc toState*(
|
||||||
alloc: GenesisAlloc
|
alloc: GenesisAlloc
|
||||||
): (HexaryTrie, Table[EthAddress, HexaryTrie]) {.raises: [RlpError].} =
|
): (HexaryTrie, TableRef[EthAddress, HexaryTrie]) {.raises: [RlpError].} =
|
||||||
var accountTrie = initHexaryTrie(newMemoryDB())
|
var accountTrie = initHexaryTrie(newMemoryDB())
|
||||||
var storageStates = Table[EthAddress, HexaryTrie]()
|
let storageStates = TableRef[EthAddress, HexaryTrie]()
|
||||||
|
|
||||||
for address, genAccount in alloc:
|
for address, genAccount in alloc:
|
||||||
var storageRoot = EMPTY_ROOT_HASH
|
var
|
||||||
var codeHash = EMPTY_CODE_HASH
|
storageRoot = EMPTY_ROOT_HASH
|
||||||
|
codeHash = EMPTY_CODE_HASH
|
||||||
|
|
||||||
if genAccount.code.len() > 0:
|
if genAccount.code.len() > 0:
|
||||||
var storageTrie = initHexaryTrie(newMemoryDB())
|
var storageTrie = initHexaryTrie(newMemoryDB())
|
||||||
for slotKey, slotValue in genAccount.storage:
|
for slotKey, slotValue in genAccount.storage:
|
||||||
let key = keccakHash(toBytesBE(slotKey)).data
|
let key = keccakHash(toBytesBE(slotKey)).data
|
||||||
let value = rlp.encode(slotValue)
|
storageTrie.put(key, rlp.encode(slotValue))
|
||||||
storageTrie.put(key, value)
|
|
||||||
storageStates[address] = storageTrie
|
storageStates[address] = storageTrie
|
||||||
storageRoot = storageTrie.rootHash()
|
storageRoot = storageTrie.rootHash()
|
||||||
codeHash = keccakHash(genAccount.code)
|
codeHash = keccakHash(genAccount.code)
|
||||||
|
@ -101,9 +102,7 @@ proc toState*(
|
||||||
storageRoot: storageRoot,
|
storageRoot: storageRoot,
|
||||||
codeHash: codeHash,
|
codeHash: codeHash,
|
||||||
)
|
)
|
||||||
let key = keccakHash(address).data
|
accountTrie.put(keccakHash(address).data, rlp.encode(account))
|
||||||
let value = rlp.encode(account)
|
|
||||||
accountTrie.put(key, value)
|
|
||||||
|
|
||||||
(accountTrie, storageStates)
|
(accountTrie, storageStates)
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,6 @@ suite "State Endpoints - Genesis JSON Files":
|
||||||
let
|
let
|
||||||
storageProof = storageState.generateStorageProof(slotKey)
|
storageProof = storageState.generateStorageProof(slotKey)
|
||||||
leafNode = storageProof[^1]
|
leafNode = storageProof[^1]
|
||||||
slotKeyHash = keccakHash(toBytesBE(slotKey)).data
|
|
||||||
path = removeLeafKeyEndNibbles(
|
path = removeLeafKeyEndNibbles(
|
||||||
Nibbles.init(keccakHash(toBytesBE(slotKey)).data, true), leafNode
|
Nibbles.init(keccakHash(toBytesBE(slotKey)).data, true), leafNode
|
||||||
)
|
)
|
||||||
|
|
|
@ -54,7 +54,6 @@ procSuite "State Endpoints":
|
||||||
leafData = testData
|
leafData = testData
|
||||||
contentKeyBytes = leafData.content_key.hexToSeqByte().ContentKeyByteList
|
contentKeyBytes = leafData.content_key.hexToSeqByte().ContentKeyByteList
|
||||||
contentKey = ContentKey.decode(contentKeyBytes).get()
|
contentKey = ContentKey.decode(contentKeyBytes).get()
|
||||||
contentId = toContentId(contentKeyBytes)
|
|
||||||
contentValueBytes = leafData.content_value_offer.hexToSeqByte()
|
contentValueBytes = leafData.content_value_offer.hexToSeqByte()
|
||||||
contentValue = AccountTrieNodeOffer.decode(contentValueBytes).get()
|
contentValue = AccountTrieNodeOffer.decode(contentValueBytes).get()
|
||||||
|
|
||||||
|
@ -163,7 +162,6 @@ procSuite "State Endpoints":
|
||||||
leafData = testData
|
leafData = testData
|
||||||
contentKeyBytes = leafData.content_key.hexToSeqByte().ContentKeyByteList
|
contentKeyBytes = leafData.content_key.hexToSeqByte().ContentKeyByteList
|
||||||
contentKey = ContentKey.decode(contentKeyBytes).get()
|
contentKey = ContentKey.decode(contentKeyBytes).get()
|
||||||
contentId = toContentId(contentKeyBytes)
|
|
||||||
contentValueBytes = leafData.content_value_offer.hexToSeqByte()
|
contentValueBytes = leafData.content_value_offer.hexToSeqByte()
|
||||||
contentValue = AccountTrieNodeOffer.decode(contentValueBytes).get()
|
contentValue = AccountTrieNodeOffer.decode(contentValueBytes).get()
|
||||||
|
|
||||||
|
@ -192,7 +190,6 @@ procSuite "State Endpoints":
|
||||||
leafData = testData
|
leafData = testData
|
||||||
contentKeyBytes = leafData.content_key.hexToSeqByte().ContentKeyByteList
|
contentKeyBytes = leafData.content_key.hexToSeqByte().ContentKeyByteList
|
||||||
contentKey = ContentKey.decode(contentKeyBytes).get()
|
contentKey = ContentKey.decode(contentKeyBytes).get()
|
||||||
contentId = toContentId(contentKeyBytes)
|
|
||||||
contentValueBytes = leafData.content_value_offer.hexToSeqByte()
|
contentValueBytes = leafData.content_value_offer.hexToSeqByte()
|
||||||
contentValue = ContractTrieNodeOffer.decode(contentValueBytes).get()
|
contentValue = ContractTrieNodeOffer.decode(contentValueBytes).get()
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,6 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
parentContentKey = ContentKey.decode(parentContentKeyBytes).get()
|
parentContentKey = ContentKey.decode(parentContentKeyBytes).get()
|
||||||
parentContentId = toContentId(parentContentKeyBytes)
|
parentContentId = toContentId(parentContentKeyBytes)
|
||||||
parentContentValueBytes = parentTestData.content_value_offer.hexToSeqByte()
|
parentContentValueBytes = parentTestData.content_value_offer.hexToSeqByte()
|
||||||
parentContentValue = AccountTrieNodeOffer.decode(parentContentValueBytes).get()
|
|
||||||
|
|
||||||
# set valid state root
|
# set valid state root
|
||||||
stateNode1.mockBlockHashToStateRoot(contentValue.blockHash, stateRoot)
|
stateNode1.mockBlockHashToStateRoot(contentValue.blockHash, stateRoot)
|
||||||
|
@ -133,7 +132,6 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
parentContentKey = ContentKey.decode(parentContentKeyBytes).get()
|
parentContentKey = ContentKey.decode(parentContentKeyBytes).get()
|
||||||
parentContentId = toContentId(parentContentKeyBytes)
|
parentContentId = toContentId(parentContentKeyBytes)
|
||||||
parentContentValueBytes = parentTestData.content_value_offer.hexToSeqByte()
|
parentContentValueBytes = parentTestData.content_value_offer.hexToSeqByte()
|
||||||
parentContentValue = ContractTrieNodeOffer.decode(parentContentValueBytes).get()
|
|
||||||
|
|
||||||
# set valid state root
|
# set valid state root
|
||||||
stateNode1.mockBlockHashToStateRoot(contentValue.blockHash, stateRoot)
|
stateNode1.mockBlockHashToStateRoot(contentValue.blockHash, stateRoot)
|
||||||
|
|
|
@ -19,7 +19,7 @@ import
|
||||||
template checkValidProofsForExistingLeafs(
|
template checkValidProofsForExistingLeafs(
|
||||||
genAccounts: GenesisAlloc,
|
genAccounts: GenesisAlloc,
|
||||||
accountState: HexaryTrie,
|
accountState: HexaryTrie,
|
||||||
storageStates: Table[EthAddress, HexaryTrie],
|
storageStates: TableRef[EthAddress, HexaryTrie],
|
||||||
) =
|
) =
|
||||||
for address, account in genAccounts:
|
for address, account in genAccounts:
|
||||||
var acc = newAccount(account.nonce, account.balance)
|
var acc = newAccount(account.nonce, account.balance)
|
||||||
|
@ -74,7 +74,7 @@ template checkValidProofsForExistingLeafs(
|
||||||
template checkInvalidProofsWithBadValue(
|
template checkInvalidProofsWithBadValue(
|
||||||
genAccounts: GenesisAlloc,
|
genAccounts: GenesisAlloc,
|
||||||
accountState: HexaryTrie,
|
accountState: HexaryTrie,
|
||||||
storageStates: Table[EthAddress, HexaryTrie],
|
storageStates: TableRef[EthAddress, HexaryTrie],
|
||||||
) =
|
) =
|
||||||
for address, account in genAccounts:
|
for address, account in genAccounts:
|
||||||
var acc = newAccount(account.nonce, account.balance)
|
var acc = newAccount(account.nonce, account.balance)
|
||||||
|
|
|
@ -282,7 +282,13 @@ proc runBackfillGossipBlockOffersLoop(
|
||||||
yId = ContentKeyByteList.init(y[0]).toContentId()
|
yId = ContentKeyByteList.init(y[0]).toContentId()
|
||||||
xDistance = portalNodeId xor xId
|
xDistance = portalNodeId xor xId
|
||||||
yDistance = portalNodeId xor yId
|
yDistance = portalNodeId xor yId
|
||||||
if xDistance >= yDistance: 1 else: -1
|
|
||||||
|
if xDistance == yDistance:
|
||||||
|
0
|
||||||
|
elif xDistance > yDistance:
|
||||||
|
1
|
||||||
|
else:
|
||||||
|
-1
|
||||||
|
|
||||||
# Sort the offers based on the distance from the node so that we will gossip
|
# Sort the offers based on the distance from the node so that we will gossip
|
||||||
# content that is closest to the node first
|
# content that is closest to the node first
|
||||||
|
|
Loading…
Reference in New Issue