Fluffy state network tests and logging improvements (#2402)
* Improve tests by waiting for content to get into db. * Improve state network logging.
This commit is contained in:
parent
bd2ca07da6
commit
09946c9958
|
@ -79,7 +79,7 @@ proc getAccountProof(
|
||||||
while nibblesIdx < nibbles.len():
|
while nibblesIdx < nibbles.len():
|
||||||
let
|
let
|
||||||
accountTrieNode = (await n.getAccountTrieNode(key)).valueOr:
|
accountTrieNode = (await n.getAccountTrieNode(key)).valueOr:
|
||||||
# log something here
|
warn "Failed to get account trie node when building account proof"
|
||||||
return Opt.none(TrieProof)
|
return Opt.none(TrieProof)
|
||||||
trieNode = accountTrieNode.node
|
trieNode = accountTrieNode.node
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ proc getStorageProof(
|
||||||
while nibblesIdx < nibbles.len():
|
while nibblesIdx < nibbles.len():
|
||||||
let
|
let
|
||||||
contractTrieNode = (await n.getContractTrieNode(key)).valueOr:
|
contractTrieNode = (await n.getContractTrieNode(key)).valueOr:
|
||||||
# log something here
|
warn "Failed to get contract trie node when building account proof"
|
||||||
return Opt.none(TrieProof)
|
return Opt.none(TrieProof)
|
||||||
trieNode = contractTrieNode.node
|
trieNode = contractTrieNode.node
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ proc getAccount(
|
||||||
warn "Failed to get account proof"
|
warn "Failed to get account proof"
|
||||||
return Opt.none(Account)
|
return Opt.none(Account)
|
||||||
account = accountProof.toAccount().valueOr:
|
account = accountProof.toAccount().valueOr:
|
||||||
warn "Failed to get account from accountProof"
|
error "Failed to get account from accountProof"
|
||||||
return Opt.none(Account)
|
return Opt.none(Account)
|
||||||
|
|
||||||
Opt.some(account)
|
Opt.some(account)
|
||||||
|
@ -165,7 +165,7 @@ proc getStorageAt*(
|
||||||
warn "Failed to get storage proof"
|
warn "Failed to get storage proof"
|
||||||
return Opt.none(UInt256)
|
return Opt.none(UInt256)
|
||||||
slotValue = storageProof.toSlot().valueOr:
|
slotValue = storageProof.toSlot().valueOr:
|
||||||
warn "Failed to get slot from storageProof"
|
error "Failed to get slot from storageProof"
|
||||||
return Opt.none(UInt256)
|
return Opt.none(UInt256)
|
||||||
|
|
||||||
Opt.some(slotValue)
|
Opt.some(slotValue)
|
||||||
|
|
|
@ -140,7 +140,7 @@ proc recursiveGossipOffer*(
|
||||||
key: AccountTrieNodeKey,
|
key: AccountTrieNodeKey,
|
||||||
offer: AccountTrieNodeOffer,
|
offer: AccountTrieNodeOffer,
|
||||||
) {.async: (raises: [CancelledError]).} =
|
) {.async: (raises: [CancelledError]).} =
|
||||||
asyncSpawn gossipOffer(p, srcNodeId, keyBytes, offerBytes, key, offer)
|
await gossipOffer(p, srcNodeId, keyBytes, offerBytes, key, offer)
|
||||||
|
|
||||||
# root node, recursive gossip is finished
|
# root node, recursive gossip is finished
|
||||||
if key.path.unpackNibbles().len() == 0:
|
if key.path.unpackNibbles().len() == 0:
|
||||||
|
@ -151,7 +151,7 @@ proc recursiveGossipOffer*(
|
||||||
(parentKey, parentOffer) = offer.withKey(key).getParent()
|
(parentKey, parentOffer) = offer.withKey(key).getParent()
|
||||||
parentKeyBytes = parentKey.toContentKey().encode()
|
parentKeyBytes = parentKey.toContentKey().encode()
|
||||||
|
|
||||||
asyncSpawn recursiveGossipOffer(
|
await recursiveGossipOffer(
|
||||||
p, srcNodeId, parentKeyBytes, parentOffer.encode(), parentKey, parentOffer
|
p, srcNodeId, parentKeyBytes, parentOffer.encode(), parentKey, parentOffer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ proc recursiveGossipOffer*(
|
||||||
key: ContractTrieNodeKey,
|
key: ContractTrieNodeKey,
|
||||||
offer: ContractTrieNodeOffer,
|
offer: ContractTrieNodeOffer,
|
||||||
) {.async: (raises: [CancelledError]).} =
|
) {.async: (raises: [CancelledError]).} =
|
||||||
asyncSpawn gossipOffer(p, srcNodeId, keyBytes, offerBytes, key, offer)
|
await gossipOffer(p, srcNodeId, keyBytes, offerBytes, key, offer)
|
||||||
|
|
||||||
# root node, recursive gossip is finished
|
# root node, recursive gossip is finished
|
||||||
if key.path.unpackNibbles().len() == 0:
|
if key.path.unpackNibbles().len() == 0:
|
||||||
|
@ -176,6 +176,6 @@ proc recursiveGossipOffer*(
|
||||||
(parentKey, parentOffer) = offer.withKey(key).getParent()
|
(parentKey, parentOffer) = offer.withKey(key).getParent()
|
||||||
parentKeyBytes = parentKey.toContentKey().encode()
|
parentKeyBytes = parentKey.toContentKey().encode()
|
||||||
|
|
||||||
asyncSpawn recursiveGossipOffer(
|
await recursiveGossipOffer(
|
||||||
p, srcNodeId, parentKeyBytes, parentOffer.encode(), parentKey, parentOffer
|
p, srcNodeId, parentKeyBytes, parentOffer.encode(), parentKey, parentOffer
|
||||||
)
|
)
|
||||||
|
|
|
@ -86,25 +86,26 @@ proc getContent(
|
||||||
let contentFromDB = n.contentDB.get(contentId)
|
let contentFromDB = n.contentDB.get(contentId)
|
||||||
if contentFromDB.isSome():
|
if contentFromDB.isSome():
|
||||||
let contentValue = V.decode(contentFromDB.get()).valueOr:
|
let contentValue = V.decode(contentFromDB.get()).valueOr:
|
||||||
error "Unable to decode account trie node content value from database"
|
error "Unable to decode state content value from database"
|
||||||
return Opt.none(V)
|
return Opt.none(V)
|
||||||
|
|
||||||
info "Fetched account trie node from database"
|
info "Fetched state content value from database"
|
||||||
return Opt.some(contentValue)
|
return Opt.some(contentValue)
|
||||||
|
|
||||||
let
|
let
|
||||||
contentLookupResult = (
|
contentLookupResult = (
|
||||||
await n.portalProtocol.contentLookup(contentKeyBytes, contentId)
|
await n.portalProtocol.contentLookup(contentKeyBytes, contentId)
|
||||||
).valueOr:
|
).valueOr:
|
||||||
|
warn "Failed fetching state content from the network"
|
||||||
return Opt.none(V)
|
return Opt.none(V)
|
||||||
contentValueBytes = contentLookupResult.content
|
contentValueBytes = contentLookupResult.content
|
||||||
|
|
||||||
let contentValue = V.decode(contentValueBytes).valueOr:
|
let contentValue = V.decode(contentValueBytes).valueOr:
|
||||||
error "Unable to decode account trie node content value from content lookup"
|
warn "Unable to decode state content value from content lookup"
|
||||||
return Opt.none(V)
|
return Opt.none(V)
|
||||||
|
|
||||||
validateRetrieval(key, contentValue).isOkOr:
|
validateRetrieval(key, contentValue).isOkOr:
|
||||||
error "Validation of retrieved content failed"
|
warn "Validation of retrieved state content failed"
|
||||||
return Opt.none(V)
|
return Opt.none(V)
|
||||||
|
|
||||||
n.portalProtocol.storeContent(contentKeyBytes, contentId, contentValueBytes)
|
n.portalProtocol.storeContent(contentKeyBytes, contentId, contentValueBytes)
|
||||||
|
@ -134,7 +135,7 @@ proc getStateRootByBlockHash*(
|
||||||
n: StateNetwork, hash: BlockHash
|
n: StateNetwork, hash: BlockHash
|
||||||
): Future[Opt[KeccakHash]] {.async: (raises: [CancelledError]).} =
|
): Future[Opt[KeccakHash]] {.async: (raises: [CancelledError]).} =
|
||||||
if n.historyNetwork.isNone():
|
if n.historyNetwork.isNone():
|
||||||
warn "History network is not available. Unable to get state root by block hash"
|
warn "History network is not available"
|
||||||
return Opt.none(KeccakHash)
|
return Opt.none(KeccakHash)
|
||||||
|
|
||||||
let header = (await n.historyNetwork.get().getVerifiedBlockHeader(hash)).valueOr:
|
let header = (await n.historyNetwork.get().getVerifiedBlockHeader(hash)).valueOr:
|
||||||
|
@ -174,7 +175,7 @@ proc processOffer*(
|
||||||
)
|
)
|
||||||
info "Offered content validated successfully", contentKeyBytes
|
info "Offered content validated successfully", contentKeyBytes
|
||||||
|
|
||||||
asyncSpawn gossipOffer(
|
await gossipOffer(
|
||||||
n.portalProtocol, maybeSrcNodeId, contentKeyBytes, contentValueBytes, contentKey,
|
n.portalProtocol, maybeSrcNodeId, contentKeyBytes, contentValueBytes, contentKey,
|
||||||
contentValue,
|
contentValue,
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,6 +33,7 @@ proc isValidNextNode(
|
||||||
|
|
||||||
nextNode.hashEquals(nextHash)
|
nextNode.hashEquals(nextHash)
|
||||||
|
|
||||||
|
# TODO: Refactor this function to improve maintainability
|
||||||
proc validateTrieProof*(
|
proc validateTrieProof*(
|
||||||
expectedRootHash: Opt[KeccakHash],
|
expectedRootHash: Opt[KeccakHash],
|
||||||
path: Nibbles,
|
path: Nibbles,
|
||||||
|
|
|
@ -167,7 +167,7 @@ proc stop*(sn: StateNode) {.async.} =
|
||||||
sn.stateNetwork.stop()
|
sn.stateNetwork.stop()
|
||||||
await sn.discoveryProtocol.closeWait()
|
await sn.discoveryProtocol.closeWait()
|
||||||
|
|
||||||
proc containsId*(sn: StateNode, contentId: ContentId): bool =
|
proc containsId*(sn: StateNode, contentId: ContentId): bool {.inline.} =
|
||||||
return sn.stateNetwork.contentDB.get(contentId).isSome()
|
return sn.stateNetwork.contentDB.get(contentId).isSome()
|
||||||
|
|
||||||
proc mockBlockHashToStateRoot*(
|
proc mockBlockHashToStateRoot*(
|
||||||
|
@ -187,3 +187,11 @@ proc mockBlockHashToStateRoot*(
|
||||||
sn.portalProtocol().storeContent(
|
sn.portalProtocol().storeContent(
|
||||||
contentKeyBytes, contentId, SSZ.encode(blockHeaderWithProof)
|
contentKeyBytes, contentId, SSZ.encode(blockHeaderWithProof)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
proc waitUntilContentAvailable*(sn: StateNode, contentId: ContentId) {.async.} =
|
||||||
|
var waitCount = 0
|
||||||
|
while not sn.containsId(contentId):
|
||||||
|
await sleepAsync(10.milliseconds)
|
||||||
|
inc waitCount
|
||||||
|
if waitCount > 1000:
|
||||||
|
break
|
||||||
|
|
|
@ -71,7 +71,9 @@ procSuite "State Endpoints":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for recursive gossip to complete
|
# wait for recursive gossip to complete
|
||||||
await sleepAsync(2000.milliseconds)
|
for node in testData.recursive_gossip:
|
||||||
|
let keyBytes = node.content_key.hexToSeqByte().ByteList
|
||||||
|
await stateNode2.waitUntilContentAvailable(toContentId(keyBytes))
|
||||||
|
|
||||||
let
|
let
|
||||||
address =
|
address =
|
||||||
|
@ -201,7 +203,9 @@ procSuite "State Endpoints":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for recursive gossip to complete
|
# wait for recursive gossip to complete
|
||||||
await sleepAsync(1000.milliseconds)
|
for node in testData.recursive_gossip:
|
||||||
|
let keyBytes = node.content_key.hexToSeqByte().ByteList
|
||||||
|
await stateNode2.waitUntilContentAvailable(toContentId(keyBytes))
|
||||||
|
|
||||||
let
|
let
|
||||||
address = EthAddress.fromHex("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
|
address = EthAddress.fromHex("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
|
||||||
|
@ -246,8 +250,8 @@ procSuite "State Endpoints":
|
||||||
contentValue,
|
contentValue,
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for recursive gossip to complete
|
# wait for gossip to complete
|
||||||
await sleepAsync(1000.milliseconds)
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
|
|
||||||
let
|
let
|
||||||
address = EthAddress.fromHex("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
|
address = EthAddress.fromHex("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
|
||||||
|
|
|
@ -76,9 +76,7 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for offer to be processed by state node 2
|
# wait for offer to be processed by state node 2
|
||||||
while not stateNode2.stateNetwork.contentQueue.empty():
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
await sleepAsync(1.milliseconds)
|
|
||||||
await sleepAsync(100.milliseconds)
|
|
||||||
|
|
||||||
# check that the offer was received by the second state instance
|
# check that the offer was received by the second state instance
|
||||||
let res1 =
|
let res1 =
|
||||||
|
@ -151,9 +149,7 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for offer to be processed by state node 2
|
# wait for offer to be processed by state node 2
|
||||||
while not stateNode2.stateNetwork.contentQueue.empty():
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
await sleepAsync(1.milliseconds)
|
|
||||||
await sleepAsync(100.milliseconds)
|
|
||||||
|
|
||||||
# check that the offer was received by the second state instance
|
# check that the offer was received by the second state instance
|
||||||
let res1 = await stateNode2.stateNetwork.getContractTrieNode(
|
let res1 = await stateNode2.stateNetwork.getContractTrieNode(
|
||||||
|
@ -216,9 +212,7 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for offer to be processed by state node 2
|
# wait for offer to be processed by state node 2
|
||||||
while not stateNode2.stateNetwork.contentQueue.empty():
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
await sleepAsync(1.milliseconds)
|
|
||||||
await sleepAsync(100.milliseconds)
|
|
||||||
|
|
||||||
# check that the offer was received by the second state instance
|
# check that the offer was received by the second state instance
|
||||||
let res1 =
|
let res1 =
|
||||||
|
@ -280,7 +274,9 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for recursive gossip to complete
|
# wait for recursive gossip to complete
|
||||||
await sleepAsync(1000.milliseconds)
|
for node in testData.recursive_gossip:
|
||||||
|
let keyBytes = node.content_key.hexToSeqByte().ByteList
|
||||||
|
await stateNode2.waitUntilContentAvailable(toContentId(keyBytes))
|
||||||
|
|
||||||
# check that all nodes were received by both state instances
|
# check that all nodes were received by both state instances
|
||||||
for kv in testData.recursive_gossip:
|
for kv in testData.recursive_gossip:
|
||||||
|
@ -357,7 +353,9 @@ procSuite "State Gossip - Gossip Offer":
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for recursive gossip to complete
|
# wait for recursive gossip to complete
|
||||||
await sleepAsync(1000.milliseconds)
|
for node in testData.recursive_gossip:
|
||||||
|
let keyBytes = node.content_key.hexToSeqByte().ByteList
|
||||||
|
await stateNode2.waitUntilContentAvailable(toContentId(keyBytes))
|
||||||
|
|
||||||
# check that all nodes were received by both state instances
|
# check that all nodes were received by both state instances
|
||||||
for kv in testData.recursive_gossip:
|
for kv in testData.recursive_gossip:
|
||||||
|
|
|
@ -271,9 +271,7 @@ procSuite "State Network - Offer Content":
|
||||||
check offerResult.isOk()
|
check offerResult.isOk()
|
||||||
|
|
||||||
# wait for offer to be processed by state node 2
|
# wait for offer to be processed by state node 2
|
||||||
while not stateNode2.stateNetwork.contentQueue.empty():
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
await sleepAsync(1.milliseconds)
|
|
||||||
await sleepAsync(100.milliseconds)
|
|
||||||
|
|
||||||
let getRes =
|
let getRes =
|
||||||
await stateNode2.stateNetwork.getAccountTrieNode(contentKey.accountTrieNodeKey)
|
await stateNode2.stateNetwork.getAccountTrieNode(contentKey.accountTrieNodeKey)
|
||||||
|
@ -322,9 +320,7 @@ procSuite "State Network - Offer Content":
|
||||||
check offerResult.isOk()
|
check offerResult.isOk()
|
||||||
|
|
||||||
# wait for offer to be processed by state node 2
|
# wait for offer to be processed by state node 2
|
||||||
while not stateNode2.stateNetwork.contentQueue.empty():
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
await sleepAsync(1.milliseconds)
|
|
||||||
await sleepAsync(100.milliseconds)
|
|
||||||
|
|
||||||
let getRes = await stateNode2.stateNetwork.getContractTrieNode(
|
let getRes = await stateNode2.stateNetwork.getContractTrieNode(
|
||||||
contentKey.contractTrieNodeKey
|
contentKey.contractTrieNodeKey
|
||||||
|
@ -374,9 +370,7 @@ procSuite "State Network - Offer Content":
|
||||||
check offerResult.isOk()
|
check offerResult.isOk()
|
||||||
|
|
||||||
# wait for offer to be processed by state node 2
|
# wait for offer to be processed by state node 2
|
||||||
while not stateNode2.stateNetwork.contentQueue.empty():
|
await stateNode2.waitUntilContentAvailable(contentId)
|
||||||
await sleepAsync(1.milliseconds)
|
|
||||||
await sleepAsync(100.milliseconds)
|
|
||||||
|
|
||||||
let getRes =
|
let getRes =
|
||||||
await stateNode2.stateNetwork.getContractCode(contentKey.contractCodeKey)
|
await stateNode2.stateNetwork.getContractCode(contentKey.contractCodeKey)
|
||||||
|
|
Loading…
Reference in New Issue