More clean-up since eth types refactor (#2742)
This commit is contained in:
parent
f797d55c35
commit
b885f822d0
|
@ -10,6 +10,7 @@
|
|||
import
|
||||
chronos,
|
||||
testutils/unittests,
|
||||
stew/byteutils,
|
||||
json_rpc/rpcserver,
|
||||
json_rpc/clients/httpclient,
|
||||
stint,
|
||||
|
@ -67,6 +68,6 @@ procSuite "Discovery v5 JSON-RPC API":
|
|||
|
||||
check:
|
||||
nodeEnr == tc.localDiscovery.localNode.record.toURI()
|
||||
nodeId == "0x" & tc.localDiscovery.localNode.id.toHex()
|
||||
nodeId == tc.localDiscovery.localNode.id.toBytesBE().to0xHex()
|
||||
|
||||
waitFor tc.stop()
|
||||
|
|
|
@ -79,9 +79,9 @@ func asReceipt(receiptObject: ReceiptObject): Result[Receipt, string] =
|
|||
var logs: seq[Log]
|
||||
if receiptObject.logs.len > 0:
|
||||
for log in receiptObject.logs:
|
||||
var topics: seq[eth_types.Topic]
|
||||
var topics: seq[Topic]
|
||||
for topic in log.topics:
|
||||
topics.add(eth_types.Topic(topic))
|
||||
topics.add(Topic(topic))
|
||||
|
||||
logs.add(Log(address: log.address, data: log.data, topics: topics))
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import
|
|||
chronos,
|
||||
json_rpc/rpcclient,
|
||||
stew/byteutils,
|
||||
eth/keys,
|
||||
eth/common/keys,
|
||||
./utp_test_rpc_client
|
||||
|
||||
proc generateBytesHex(rng: var HmacDrbgContext, length: int): string =
|
||||
|
|
|
@ -17,7 +17,7 @@ import
|
|||
eth/p2p/discoveryv5/protocol,
|
||||
eth/p2p/discoveryv5/enr,
|
||||
eth/utp/[utp_discv5_protocol, utp_router],
|
||||
eth/keys,
|
||||
eth/common/keys,
|
||||
../../rpc/rpc_discovery_api,
|
||||
./utp_rpc_types
|
||||
|
||||
|
@ -46,7 +46,7 @@ proc writeValue*(w: var JsonWriter[JrpcConv], v: Record) {.gcsafe, raises: [IOEr
|
|||
proc readValue*(
|
||||
r: var JsonReader[JrpcConv], val: var Record
|
||||
) {.gcsafe, raises: [IOError, JsonReaderError].} =
|
||||
if not fromURI(val, r.parseString()):
|
||||
val = enr.Record.fromURI(r.parseString()).valueOr:
|
||||
r.raiseUnexpectedValue("Invalid ENR")
|
||||
|
||||
proc installUtpHandlers(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
{.push raises: [].}
|
||||
|
||||
import std/tables, web3/primitives, stew/keyed_queue, results, ./rpc/rpc_utils
|
||||
import eth/common/hashes, web3/primitives, stew/keyed_queue, results, ./rpc/rpc_utils
|
||||
|
||||
## Cache for payloads received through block gossip and validated by the
|
||||
## consensus light client.
|
||||
|
@ -15,15 +15,14 @@ import std/tables, web3/primitives, stew/keyed_queue, results, ./rpc/rpc_utils
|
|||
## oldest payload is deleted first.
|
||||
type BlockCache* = ref object
|
||||
max: int
|
||||
blocks: KeyedQueue[BlockHash, ExecutionData]
|
||||
blocks: KeyedQueue[Hash32, ExecutionData]
|
||||
|
||||
proc `==`(x, y: Quantity): bool {.borrow, noSideEffect.}
|
||||
|
||||
proc new*(T: type BlockCache, max: uint32): T =
|
||||
let maxAsInt = int(max)
|
||||
return BlockCache(
|
||||
max: maxAsInt, blocks: KeyedQueue[BlockHash, ExecutionData].init(maxAsInt)
|
||||
)
|
||||
return
|
||||
BlockCache(max: maxAsInt, blocks: KeyedQueue[Hash32, ExecutionData].init(maxAsInt))
|
||||
|
||||
func len*(self: BlockCache): int =
|
||||
return len(self.blocks)
|
||||
|
@ -54,5 +53,5 @@ proc getByNumber*(self: BlockCache, number: Quantity): Opt[ExecutionData] =
|
|||
|
||||
return payloadResult
|
||||
|
||||
proc getPayloadByHash*(self: BlockCache, hash: BlockHash): Opt[ExecutionData] =
|
||||
proc getPayloadByHash*(self: BlockCache, hash: Hash32): Opt[ExecutionData] =
|
||||
return self.blocks.eq(hash)
|
||||
|
|
|
@ -200,7 +200,7 @@ proc run*(
|
|||
try:
|
||||
headerCallback(cstring(Json.encode(forkyHeader)), 0)
|
||||
except SerializationError as e:
|
||||
notice "finalizedHeaderCallback exception"
|
||||
error "finalizedHeaderCallback exception", error = e.msg
|
||||
|
||||
proc onOptimisticHeader(
|
||||
lightClient: LightClient, optimisticHeader: ForkedLightClientHeader
|
||||
|
@ -212,7 +212,7 @@ proc run*(
|
|||
try:
|
||||
headerCallback(cstring(Json.encode(forkyHeader)), 1)
|
||||
except SerializationError as e:
|
||||
notice "optimisticHeaderCallback exception"
|
||||
error "optimisticHeaderCallback exception", error = e.msg
|
||||
|
||||
lightClient.onFinalizedHeader = onFinalizedHeader
|
||||
lightClient.onOptimisticHeader = onOptimisticHeader
|
||||
|
|
|
@ -8,15 +8,14 @@
|
|||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/[strutils, typetraits],
|
||||
std/strutils,
|
||||
stint,
|
||||
stew/byteutils,
|
||||
results,
|
||||
chronicles,
|
||||
json_rpc/[rpcproxy, rpcserver, rpcclient],
|
||||
eth/common/eth_types as etypes,
|
||||
web3,
|
||||
web3/[primitives, eth_api_types],
|
||||
eth/common/accounts,
|
||||
web3/[primitives, eth_api_types, eth_api],
|
||||
beacon_chain/el/el_manager,
|
||||
beacon_chain/networking/network_metadata,
|
||||
beacon_chain/spec/forks,
|
||||
|
@ -26,15 +25,9 @@ import
|
|||
|
||||
export forks
|
||||
|
||||
type
|
||||
FixedBytes[N: static int] = primitives.FixedBytes[N]
|
||||
Address = primitives.Address
|
||||
|
||||
logScope:
|
||||
topics = "verified_proxy"
|
||||
|
||||
proc `==`(x, y: Quantity): bool {.borrow, noSideEffect.}
|
||||
|
||||
type
|
||||
VerifiedRpcProxy* = ref object
|
||||
proxy: RpcProxy
|
||||
|
@ -63,7 +56,7 @@ func parseQuantityTag(blockTag: BlockTag): Result[QuantityTag, string] =
|
|||
else:
|
||||
return err("Unsupported blockTag: " & tag)
|
||||
else:
|
||||
let quantity = blockTag.number.Quantity
|
||||
let quantity = blockTag.number
|
||||
return ok(QuantityTag(kind: BlockNumber, blockNumber: quantity))
|
||||
|
||||
template checkPreconditions(proxy: VerifiedRpcProxy) =
|
||||
|
@ -197,7 +190,7 @@ proc installEthApiHandlers*(lcProxy: VerifiedRpcProxy) =
|
|||
|
||||
let account = accountResult.get()
|
||||
|
||||
if account.codeHash == etypes.EMPTY_CODE_HASH:
|
||||
if account.codeHash == EMPTY_CODE_HASH:
|
||||
# account does not have any code, return empty hex data
|
||||
return @[]
|
||||
|
||||
|
@ -233,7 +226,7 @@ proc installEthApiHandlers*(lcProxy: VerifiedRpcProxy) =
|
|||
return Opt.some(asBlockObject(executionPayload.get()))
|
||||
|
||||
lcProxy.proxy.rpc("eth_getBlockByHash") do(
|
||||
blockHash: BlockHash, fullTransactions: bool
|
||||
blockHash: Hash32, fullTransactions: bool
|
||||
) -> Opt[BlockObject]:
|
||||
let executionPayload = lcProxy.blockCache.getPayloadByHash(blockHash)
|
||||
|
||||
|
|
|
@ -8,24 +8,19 @@
|
|||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/typetraits,
|
||||
eth/common/eth_types as etypes,
|
||||
eth/rlp,
|
||||
nimcrypto/hash,
|
||||
eth/common/[base_rlp, headers_rlp, blocks, hashes],
|
||||
stint,
|
||||
web3,
|
||||
web3/eth_api_types,
|
||||
web3/engine_api_types,
|
||||
../../nimbus/db/core_db
|
||||
|
||||
type
|
||||
FixedBytes[N: static int] = primitives.FixedBytes[N]
|
||||
Address = primitives.Address
|
||||
export eth_api_types, engine_api_types
|
||||
|
||||
type ExecutionData* = object
|
||||
parentHash*: BlockHash
|
||||
parentHash*: Hash32
|
||||
feeRecipient*: Address
|
||||
stateRoot*: BlockHash
|
||||
receiptsRoot*: BlockHash
|
||||
stateRoot*: Hash32
|
||||
receiptsRoot*: Hash32
|
||||
logsBloom*: FixedBytes[256]
|
||||
prevRandao*: FixedBytes[32]
|
||||
blockNumber*: Quantity
|
||||
|
@ -34,7 +29,7 @@ type ExecutionData* = object
|
|||
timestamp*: Quantity
|
||||
extraData*: DynamicBytes[0, 32]
|
||||
baseFeePerGas*: UInt256
|
||||
blockHash*: BlockHash
|
||||
blockHash*: Hash32
|
||||
transactions*: seq[TypedTransaction]
|
||||
withdrawals*: seq[WithdrawalV1]
|
||||
|
||||
|
@ -77,15 +72,9 @@ proc asExecutionData*(payload: SomeExecutionPayload): ExecutionData =
|
|||
withdrawals: payload.withdrawals,
|
||||
)
|
||||
|
||||
func toFixedBytes(d: MDigest[256]): FixedBytes[32] =
|
||||
FixedBytes[32](d.data)
|
||||
|
||||
template asEthHash(hash: BlockHash): etypes.Hash32 =
|
||||
etypes.Hash32(distinctBase(hash))
|
||||
|
||||
proc calculateTransactionData(
|
||||
items: openArray[TypedTransaction]
|
||||
): (etypes.Hash32, seq[TxOrHash], uint64) =
|
||||
): (Hash32, seq[TxOrHash], uint64) =
|
||||
## returns tuple composed of
|
||||
## - root of transactions trie
|
||||
## - list of transactions hashes
|
||||
|
@ -97,30 +86,30 @@ proc calculateTransactionData(
|
|||
let tx = distinctBase(t)
|
||||
txSize = txSize + uint64(len(tx))
|
||||
tr.merge(rlp.encode(uint64 i), tx).expect "merge data"
|
||||
txHashes.add(txOrHash keccakHash(tx))
|
||||
txHashes.add(txOrHash keccak256(tx))
|
||||
let rootHash = tr.state(updateOk = true).expect "hash"
|
||||
(rootHash, txHashes, txSize)
|
||||
|
||||
func blockHeaderSize(payload: ExecutionData, txRoot: etypes.Hash32): uint64 =
|
||||
let bh = etypes.BlockHeader(
|
||||
func blockHeaderSize(payload: ExecutionData, txRoot: Hash32): uint64 =
|
||||
let header = Header(
|
||||
parentHash: payload.parentHash,
|
||||
ommersHash: etypes.EMPTY_UNCLE_HASH,
|
||||
ommersHash: EMPTY_UNCLE_HASH,
|
||||
coinbase: payload.feeRecipient,
|
||||
stateRoot: payload.stateRoot,
|
||||
transactionsRoot: txRoot,
|
||||
receiptsRoot: payload.receiptsRoot,
|
||||
logsBloom: distinctBase(payload.logsBloom).to(Bloom),
|
||||
difficulty: default(etypes.DifficultyInt),
|
||||
number: payload.blockNumber.distinctBase,
|
||||
logsBloom: payload.logsBloom,
|
||||
difficulty: default(DifficultyInt),
|
||||
number: distinctBase(payload.blockNumber),
|
||||
gasLimit: distinctBase(payload.gasLimit),
|
||||
gasUsed: distinctBase(payload.gasUsed),
|
||||
timestamp: payload.timestamp.EthTime,
|
||||
extraData: bytes payload.extraData,
|
||||
extraData: payload.extraData.data,
|
||||
mixHash: payload.prevRandao,
|
||||
nonce: default(etypes.BlockNonce),
|
||||
nonce: default(Bytes8),
|
||||
baseFeePerGas: Opt.some payload.baseFeePerGas,
|
||||
)
|
||||
return uint64(len(rlp.encode(bh)))
|
||||
return uint64(len(rlp.encode(header)))
|
||||
|
||||
proc asBlockObject*(p: ExecutionData): BlockObject {.raises: [ValueError].} =
|
||||
# TODO: currently we always calculate txHashes as BlockObject does not have
|
||||
|
@ -130,10 +119,10 @@ proc asBlockObject*(p: ExecutionData): BlockObject {.raises: [ValueError].} =
|
|||
let headerSize = blockHeaderSize(p, txRoot)
|
||||
let blockSize = txSize + headerSize
|
||||
BlockObject(
|
||||
number: web3.BlockNumber p.blockNumber,
|
||||
number: p.blockNumber,
|
||||
hash: p.blockHash,
|
||||
parentHash: p.parentHash,
|
||||
sha3Uncles: etypes.EMPTY_UNCLE_HASH,
|
||||
sha3Uncles: EMPTY_UNCLE_HASH,
|
||||
logsBloom: p.logsBloom,
|
||||
transactionsRoot: txRoot,
|
||||
stateRoot: p.stateRoot,
|
||||
|
@ -144,7 +133,7 @@ proc asBlockObject*(p: ExecutionData): BlockObject {.raises: [ValueError].} =
|
|||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
nonce: Opt.some(default(FixedBytes[8])),
|
||||
nonce: Opt.some(default(Bytes8)),
|
||||
size: Quantity(blockSize),
|
||||
# TODO: It does not matter what we put here after merge blocks.
|
||||
# Other projects like `helios` return `0`, data providers like alchemy return
|
||||
|
|
|
@ -8,82 +8,51 @@
|
|||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/[sequtils, typetraits, options],
|
||||
std/sequtils,
|
||||
stint,
|
||||
results,
|
||||
nimcrypto/hash,
|
||||
eth/common/eth_types as etypes,
|
||||
eth/common/eth_types_rlp,
|
||||
eth/rlp,
|
||||
eth/trie/[hexary, hexary_proof_verification],
|
||||
eth/common/[base_rlp, accounts_rlp, hashes_rlp],
|
||||
eth/trie/[hexary_proof_verification],
|
||||
web3/eth_api_types
|
||||
|
||||
export results
|
||||
|
||||
type
|
||||
FixedBytes[N: static int] = primitives.FixedBytes[N]
|
||||
Address = primitives.Address
|
||||
|
||||
func toMDigest(arg: primitives.FixedBytes[32]): MDigest[256] =
|
||||
MDigest[256](data: distinctBase(arg))
|
||||
|
||||
func emptyAccount(): etypes.Account =
|
||||
return etypes.Account(
|
||||
nonce: uint64(0),
|
||||
balance: UInt256.zero,
|
||||
storageRoot: etypes.EMPTY_ROOT_HASH,
|
||||
codeHash: etypes.EMPTY_CODE_HASH,
|
||||
)
|
||||
|
||||
proc isValidProof(
|
||||
branch: seq[seq[byte]], rootHash: KeccakHash, key, value: seq[byte]
|
||||
): bool =
|
||||
try:
|
||||
# TODO: Investigate if this handles proof of non-existence.
|
||||
# Probably not as bool is not expressive enough to say if proof is valid,
|
||||
# but key actually does not exists in MPT
|
||||
return isValidBranch(branch, rootHash, key, value)
|
||||
except RlpError:
|
||||
return false
|
||||
export results, stint, hashes_rlp, accounts_rlp, eth_api_types
|
||||
|
||||
proc getAccountFromProof*(
|
||||
stateRoot: Hash32,
|
||||
accountAddress: Address,
|
||||
accountBalance: UInt256,
|
||||
accountNonce: Quantity,
|
||||
accountCodeHash: CodeHash,
|
||||
accountStorageRootHash: StorageHash,
|
||||
accountCodeHash: Hash32,
|
||||
accountStorageRoot: Hash32,
|
||||
mptNodes: seq[RlpEncodedBytes],
|
||||
): Result[etypes.Account, string] =
|
||||
): Result[Account, string] =
|
||||
let
|
||||
mptNodesBytes = mptNodes.mapIt(distinctBase(it))
|
||||
keccakStateRootHash = Hash32(stateRoot)
|
||||
acc = etypes.Account(
|
||||
acc = Account(
|
||||
nonce: distinctBase(accountNonce),
|
||||
balance: accountBalance,
|
||||
storageRoot: Hash32(accountStorageRootHash),
|
||||
codeHash: Hash32(accountCodeHash),
|
||||
storageRoot: accountStorageRoot,
|
||||
codeHash: accountCodeHash,
|
||||
)
|
||||
accountEncoded = rlp.encode(acc)
|
||||
accountKey = toSeq(keccakHash(distinctBase(accountAddress)).data)
|
||||
accountKey = toSeq(keccak256((accountAddress.data)).data)
|
||||
|
||||
let proofResult =
|
||||
verifyMptProof(mptNodesBytes, keccakStateRootHash, accountKey, accountEncoded)
|
||||
let proofResult = verifyMptProof(mptNodesBytes, stateRoot, accountKey, accountEncoded)
|
||||
|
||||
case proofResult.kind
|
||||
of MissingKey:
|
||||
return ok(emptyAccount())
|
||||
return ok(EMPTY_ACCOUNT)
|
||||
of ValidProof:
|
||||
return ok(acc)
|
||||
of InvalidProof:
|
||||
return err(proofResult.errorMsg)
|
||||
|
||||
proc getStorageData(
|
||||
account: etypes.Account, storageProof: StorageProof
|
||||
account: Account, storageProof: StorageProof
|
||||
): Result[UInt256, string] =
|
||||
let
|
||||
storageMptNodes = storageProof.proof.mapIt(distinctBase(it))
|
||||
key = toSeq(keccakHash(toBytesBE(storageProof.key)).data)
|
||||
key = toSeq(keccak256(toBytesBE(storageProof.key)).data)
|
||||
encodedValue = rlp.encode(storageProof.value)
|
||||
proofResult =
|
||||
verifyMptProof(storageMptNodes, account.storageRoot, key, encodedValue)
|
||||
|
@ -105,7 +74,7 @@ proc getStorageData*(
|
|||
proof.storageHash, proof.accountProof,
|
||||
)
|
||||
|
||||
if account.storageRoot == etypes.EMPTY_ROOT_HASH:
|
||||
if account.storageRoot == EMPTY_ROOT_HASH:
|
||||
# valid account with empty storage, in that case getStorageAt
|
||||
# return 0 value
|
||||
return ok(u256(0))
|
||||
|
@ -113,15 +82,15 @@ proc getStorageData*(
|
|||
if len(proof.storageProof) != 1:
|
||||
return err("no storage proof for requested slot")
|
||||
|
||||
let sproof = proof.storageProof[0]
|
||||
let storageProof = proof.storageProof[0]
|
||||
|
||||
if len(sproof.proof) == 0:
|
||||
if len(storageProof.proof) == 0:
|
||||
return err("empty mpt proof for account with not empty storage")
|
||||
|
||||
if sproof.key != requestedSlot:
|
||||
if storageProof.key != requestedSlot:
|
||||
return err("received proof for invalid slot")
|
||||
|
||||
return getStorageData(account, sproof)
|
||||
getStorageData(account, storageProof)
|
||||
|
||||
func isValidCode*(account: etypes.Account, code: openArray[byte]): bool =
|
||||
return account.codeHash == keccakHash(code)
|
||||
func isValidCode*(account: Account, code: openArray[byte]): bool =
|
||||
account.codeHash == keccak256(code)
|
||||
|
|
Loading…
Reference in New Issue