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:
parent
a03bb56bec
commit
9192aa13ed
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
) =
|
||||
|
|
Loading…
Reference in New Issue