Fluffy State Bridge: Fetch portal client nodeId on startup and sort offers by distance from nodeId (#2570)

* Fetch portal client nodeId on startup and sort offers by distance from nodeId.

* Fix logging.

* Improve error handling at startup.
This commit is contained in:
web3-developer 2024-08-19 20:49:07 +08:00 committed by GitHub
parent 9826557184
commit 60c9b2c00d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 11 deletions

View File

@ -2,4 +2,3 @@
-d:"libp2p_pki_schemes=secp256k1" -d:"libp2p_pki_schemes=secp256k1"
-d:"chronicles_sinks=textlines[dynamic],json[dynamic]" -d:"chronicles_sinks=textlines[dynamic],json[dynamic]"
-d:"chronicles_sinks=textlines[dynamic]"

View File

@ -1,2 +1 @@
-d:"chronicles_sinks=textlines[dynamic],json[dynamic]" -d:"chronicles_sinks=textlines[dynamic],json[dynamic]"
-d:"chronicles_sinks=textlines[dynamic]"

View File

@ -8,7 +8,7 @@
{.push raises: [].} {.push raises: [].}
import import
std/sequtils, std/[sequtils, algorithm],
chronicles, chronicles,
chronos, chronos,
stint, stint,
@ -231,7 +231,7 @@ proc runBackfillBuildBlockOffersLoop(
db.putLastPersistedBlockNumber(blockData.blockNumber) db.putLastPersistedBlockNumber(blockData.blockNumber)
proc collectOffer( proc collectOffer(
offersMap: TableRef[seq[byte], seq[byte]], offersMap: OrderedTableRef[seq[byte], seq[byte]],
offerWithKey: offerWithKey:
AccountTrieOfferWithKey | ContractTrieOfferWithKey | ContractCodeOfferWithKey, AccountTrieOfferWithKey | ContractTrieOfferWithKey | ContractCodeOfferWithKey,
) {.inline.} = ) {.inline.} =
@ -239,7 +239,7 @@ proc collectOffer(
offersMap[keyBytes] = offerWithKey.offer.encode() offersMap[keyBytes] = offerWithKey.offer.encode()
proc recursiveCollectOffer( proc recursiveCollectOffer(
offersMap: TableRef[seq[byte], seq[byte]], offersMap: OrderedTableRef[seq[byte], seq[byte]],
offerWithKey: AccountTrieOfferWithKey | ContractTrieOfferWithKey, offerWithKey: AccountTrieOfferWithKey | ContractTrieOfferWithKey,
) = ) =
offersMap.collectOffer(offerWithKey) offersMap.collectOffer(offerWithKey)
@ -254,6 +254,7 @@ proc recursiveCollectOffer(
proc runBackfillGossipBlockOffersLoop( proc runBackfillGossipBlockOffersLoop(
blockOffersQueue: AsyncQueue[BlockOffersRef], blockOffersQueue: AsyncQueue[BlockOffersRef],
portalClient: RpcClient, portalClient: RpcClient,
portalNodeId: NodeId,
verifyGossip: bool, verifyGossip: bool,
workerId: int, workerId: int,
) {.async: (raises: [CancelledError]).} = ) {.async: (raises: [CancelledError]).} =
@ -264,7 +265,7 @@ proc runBackfillGossipBlockOffersLoop(
while true: while true:
# A table of offer key, value pairs is used to filter out duplicates so # A table of offer key, value pairs is used to filter out duplicates so
# that we don't gossip the same offer multiple times. # that we don't gossip the same offer multiple times.
let offersMap = newTable[seq[byte], seq[byte]]() let offersMap = newOrderedTable[seq[byte], seq[byte]]()
for offerWithKey in blockOffers.accountTrieOffers: for offerWithKey in blockOffers.accountTrieOffers:
offersMap.recursiveCollectOffer(offerWithKey) offersMap.recursiveCollectOffer(offerWithKey)
@ -273,6 +274,20 @@ proc runBackfillGossipBlockOffersLoop(
for offerWithKey in blockOffers.contractCodeOffers: for offerWithKey in blockOffers.contractCodeOffers:
offersMap.collectOffer(offerWithKey) offersMap.collectOffer(offerWithKey)
# We need to use a closure here because nodeId is required to calculate the
# distance of each content id from the node
proc offersMapCmp(x, y: (seq[byte], seq[byte])): int =
let
xId = ContentKeyByteList.init(x[0]).toContentId()
yId = ContentKeyByteList.init(y[0]).toContentId()
xDistance = portalNodeId xor xId
yDistance = portalNodeId xor yId
if xDistance >= yDistance: 1 else: -1
# Sort the offers based on the distance from the node so that we will gossip
# content that is closest to the node first
offersMap.sort(offersMapCmp)
var retryGossip = false var retryGossip = false
for k, v in offersMap: for k, v in offersMap:
try: try:
@ -337,14 +352,22 @@ proc runBackfillMetricsLoop(
proc runState*(config: PortalBridgeConf) = proc runState*(config: PortalBridgeConf) =
let let
portalClient = newRpcClientConnect(config.portalRpcUrl) portalClient = newRpcClientConnect(config.portalRpcUrl)
web3Client = newRpcClientConnect(config.web3UrlState) portalNodeId =
db = DatabaseRef.init(config.stateDir.string).get() try:
defer: (waitFor portalClient.portal_stateNodeInfo()).nodeId
db.close() except CatchableError as e:
fatal "Failed to connect to portal client", error = $e.msg
quit QuitFailure
info "Connected to portal client with nodeId", nodeId = portalNodeId
let web3Client = newRpcClientConnect(config.web3UrlState)
if web3Client of RpcHttpClient: if web3Client of RpcHttpClient:
warn "Using a WebSocket connection to the JSON-RPC API is recommended to improve performance" warn "Using a WebSocket connection to the JSON-RPC API is recommended to improve performance"
let db = DatabaseRef.init(config.stateDir.string).get()
defer:
db.close()
let maybeLastPersistedBlock = db.getLastPersistedBlockNumber() let maybeLastPersistedBlock = db.getLastPersistedBlockNumber()
if maybeLastPersistedBlock.isSome(): if maybeLastPersistedBlock.isSome():
info "Last persisted block found in the database: ", info "Last persisted block found in the database: ",
@ -376,7 +399,7 @@ proc runState*(config: PortalBridgeConf) =
for workerId in 1 .. config.gossipWorkersCount.int: for workerId in 1 .. config.gossipWorkersCount.int:
asyncSpawn runBackfillGossipBlockOffersLoop( asyncSpawn runBackfillGossipBlockOffersLoop(
blockOffersQueue, portalClient, config.verifyGossip, workerId blockOffersQueue, portalClient, portalNodeId, config.verifyGossip, workerId
) )
asyncSpawn runBackfillMetricsLoop(blockDataQueue, blockOffersQueue) asyncSpawn runBackfillMetricsLoop(blockDataQueue, blockOffersQueue)