Fluffy state bridge updates (#2683)

* Use Json decode when handling portal rpc client error.

* Remove preimages cache.

* Support disabling state gossip in order to just build state.
This commit is contained in:
bhartnett 2024-10-03 10:57:19 +08:00 committed by GitHub
parent a03bb56bec
commit 9192aa13ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 70 additions and 66 deletions

View File

@ -6,7 +6,7 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
std/strutils,
json_serialization,
chronos,
stew/byteutils,
results,
@ -29,17 +29,26 @@ type
InvalidContentValue
ContentValidationFailed
ErrorResponse = object
code*: int
message*: string
proc init*(T: type PortalRpcClient, rpcClient: RpcClient): T =
T(rpcClient)
func toPortalRpcError(e: ref CatchableError): PortalRpcError =
# TODO: Update this to parse the error message json
if e.msg.contains("-39001"):
let error =
try:
Json.decode(e.msg, ErrorResponse)
except SerializationError as e:
raiseAssert(e.msg)
if error.code == -39001:
ContentNotFound
elif e.msg.contains("-32602"):
elif error.code == -32602:
InvalidContentKey
else:
raiseAssert(e.msg) # Shouldn't happen
raiseAssert(e.msg)
proc historyLocalContent(
client: PortalRpcClient, contentKey: string

View File

@ -146,11 +146,19 @@ type
.}: uint64
verifyStateProofs* {.
desc: "Verify state proofs before gossiping them into the portal network",
desc:
"Verify state proofs before gossiping them into the portal network (Slow: Only used for testing).",
defaultValue: false,
name: "verify-state-proofs"
.}: bool
enableGossip* {.
desc:
"Enable gossipping the state into the portal network. Disable to only build the state without gossiping it.",
defaultValue: true,
name: "enable-gossip"
.}: bool
gossipGenesis* {.
desc:
"Enable gossip of the genesis state into the portal network when starting from block 1",

View File

@ -136,6 +136,7 @@ proc runBackfillBuildBlockOffersLoop(
blockDataQueue: AsyncQueue[BlockData],
blockOffersQueue: AsyncQueue[BlockOffersRef],
verifyStateProofs: bool,
enableGossip: bool,
gossipGenesis: bool,
) {.async: (raises: [CancelledError]).} =
info "Starting state backfill build block offers loop"
@ -163,7 +164,7 @@ proc runBackfillBuildBlockOffersLoop(
raiseAssert(e.msg) # Should never happen
ws.applyGenesisAccounts(genesisAccounts)
if gossipGenesis:
if enableGossip and gossipGenesis:
let genesisBlockHash =
hash32"d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
@ -213,6 +214,7 @@ proc runBackfillBuildBlockOffersLoop(
if verifyStateProofs:
worldState.verifyProofs(blockData.parentStateRoot, blockData.stateRoot)
if enableGossip:
var builder = OffersBuilder.init(worldState, blockData.blockHash)
builder.buildBlockOffers()
@ -350,12 +352,20 @@ proc runBackfillMetricsLoop(
while true:
await sleepAsync(30.seconds)
if blockDataQueue.len() > 0:
info "Block data queue metrics: ",
nextBlockNumber = blockDataQueue[0].blockNumber,
blockDataQueueLen = blockDataQueue.len()
else:
info "Block data queue metrics: ", blockDataQueueLen = blockDataQueue.len()
if blockOffersQueue.len() > 0:
info "Block offers queue metrics: ",
nextBlockNumber = blockOffersQueue[0].blockNumber,
blockOffersQueueLen = blockOffersQueue.len()
else:
info "Block offers queue metrics: ", blockOffersQueueLen = blockOffersQueue.len()
proc runState*(config: PortalBridgeConf) =
let
@ -402,7 +412,8 @@ proc runState*(config: PortalBridgeConf) =
db, blockDataQueue, web3Client, config.startBlockNumber
)
asyncSpawn runBackfillBuildBlockOffersLoop(
db, blockDataQueue, blockOffersQueue, config.verifyStateProofs, config.gossipGenesis
db, blockDataQueue, blockOffersQueue, config.verifyStateProofs, config.enableGossip,
config.gossipGenesis,
)
for workerId in 1 .. config.gossipWorkersCount.int:

View File

@ -22,35 +22,33 @@ type AccountState* = ref object
code: seq[byte]
codeUpdated: bool
proc init(T: type AccountState, account = newAccount()): T {.inline.} =
proc init(T: type AccountState, account = newAccount()): T =
T(account: account, codeUpdated: false)
proc getBalance*(accState: AccountState): UInt256 {.inline.} =
template getBalance*(accState: AccountState): UInt256 =
accState.account.balance
proc getNonce*(accState: AccountState): AccountNonce {.inline.} =
template getNonce*(accState: AccountState): AccountNonce =
accState.account.nonce
proc setBalance*(accState: var AccountState, balance: UInt256) {.inline.} =
accState.account.balance = balance
template setBalance*(accState: var AccountState, bal: UInt256) =
accState.account.balance = bal
proc addBalance*(accState: var AccountState, balance: UInt256) {.inline.} =
accState.account.balance += balance
template addBalance*(accState: var AccountState, bal: UInt256) =
accState.account.balance += bal
proc setNonce*(accState: var AccountState, nonce: AccountNonce) {.inline.} =
accState.account.nonce = nonce
template setNonce*(accState: var AccountState, nce: AccountNonce) =
accState.account.nonce = nce
proc setStorage*(
accState: var AccountState, slotKey: UInt256, slotValue: UInt256
) {.inline.} =
template setStorage*(accState: var AccountState, slotKey: UInt256, slotValue: UInt256) =
accState.storageUpdates[slotKey] = slotValue
proc deleteStorage*(accState: var AccountState, slotKey: UInt256) {.inline.} =
template deleteStorage*(accState: var AccountState, slotKey: UInt256) =
# setting to zero has the effect of deleting the slot
accState.setStorage(slotKey, 0.u256)
proc setCode*(accState: var AccountState, code: seq[byte]) =
accState.code = code
template setCode*(accState: var AccountState, bytecode: seq[byte]) =
accState.code = bytecode
accState.codeUpdated = true
# World State definition
@ -65,7 +63,6 @@ type
storageTries: TableRef[AddressHash, HexaryTrie]
storageDb: TrieDatabaseRef
bytecodeDb: TrieDatabaseRef # maps AddressHash -> seq[byte]
preimagesDb: TrieDatabaseRef # maps AddressHash -> EthAddress
proc init*(
T: type WorldStateRef, db: DatabaseRef, accountsTrieRoot: KeccakHash = emptyRlpHash
@ -80,35 +77,17 @@ proc init*(
storageTries: newTable[AddressHash, HexaryTrie](),
storageDb: db.getStorageBackend(),
bytecodeDb: db.getBytecodeBackend(),
preimagesDb: db.getPreimagesBackend(),
)
proc stateRoot*(state: WorldStateRef): KeccakHash {.inline.} =
template stateRoot*(state: WorldStateRef): KeccakHash =
state.accountsTrie.rootHash()
proc toAccountKey*(address: EthAddress): AddressHash {.inline.} =
template toAccountKey*(address: EthAddress): AddressHash =
keccakHash(address)
proc toStorageKey*(slotKey: UInt256): SlotKeyHash {.inline.} =
template toStorageKey*(slotKey: UInt256): SlotKeyHash =
keccakHash(toBytesBE(slotKey))
proc getAccountPreimage(state: WorldStateRef, accountKey: AddressHash): EthAddress =
doAssert(
state.preimagesDb.contains(rlp.encode(accountKey)),
"No account preimage with address hash: " & $accountKey,
)
let addressBytes = state.preimagesDb.get(rlp.encode(accountKey))
try:
rlp.decode(addressBytes, EthAddress)
except RlpError as e:
raiseAssert(e.msg) # Should never happen
proc setAccountPreimage(
state: WorldStateRef, accountKey: AddressHash, address: EthAddress
) =
state.preimagesDb.put(rlp.encode(accountKey), rlp.encode(address))
proc getAccount(state: WorldStateRef, accountKey: AddressHash): AccountState =
try:
if state.accountsTrie.contains(accountKey.data):
@ -119,12 +98,11 @@ proc getAccount(state: WorldStateRef, accountKey: AddressHash): AccountState =
except RlpError as e:
raiseAssert(e.msg) # should never happen unless the database is corrupted
proc getAccount*(state: WorldStateRef, address: EthAddress): AccountState {.inline.} =
template getAccount*(state: WorldStateRef, address: EthAddress): AccountState =
state.getAccount(toAccountKey(address))
proc setAccount*(state: WorldStateRef, address: EthAddress, accState: AccountState) =
let accountKey = toAccountKey(address)
state.setAccountPreimage(accountKey, address)
try:
if not state.storageTries.contains(accountKey):
@ -198,12 +176,10 @@ iterator updatedStorageProofs*(
except RlpError as e:
raiseAssert(e.msg) # should never happen unless the database is corrupted
proc getUpdatedBytecode*(
state: WorldStateRef, accountKey: AddressHash
): seq[byte] {.inline.} =
template getUpdatedBytecode*(state: WorldStateRef, accountKey: AddressHash): seq[byte] =
state.db.getBytecodeUpdatedCache().get(accountKey.data)
# Slow: Used for testing only
# Slow: Only used for testing
proc verifyProofs*(
state: WorldStateRef, preStateRoot: KeccakHash, expectedStateRoot: KeccakHash
) =