Add mpt proof verification to proxy (#1213)

* Add mpt proof verification to proxy
This commit is contained in:
KonradStaniec 2022-09-06 18:14:50 +02:00 committed by GitHub
parent 8d6ec3dd1a
commit 9d10f8fbae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 8 deletions

View File

@ -227,6 +227,10 @@ utp-test: | build deps
fluffy-test-portal-testnet: | build deps
$(ENV_SCRIPT) nim test_portal_testnet $(NIM_PARAMS) nimbus.nims
# builds and runs the lc proxy test suite
lc-proxy-test: | build deps
$(ENV_SCRIPT) nim testlcproxy $(NIM_PARAMS) nimbus.nims
# usual cleaning
clean: | clean-common
rm -rf build/{nimbus,fluffy,$(TOOLS_CSV),all_tests,db/test_kvstore_rocksdb,test_rpc,all_fluffy_tests,portalcli,*.dSYM}

View File

@ -1,4 +1,4 @@
# beacon_chain
# ligh client proxy
# Copyright (c) 2022 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
@ -14,7 +14,8 @@ import
web3,
web3/ethhexstrings,
beacon_chain/eth1/eth1_monitor,
beacon_chain/spec/forks
beacon_chain/spec/forks,
../validate_proof
export forks
@ -59,12 +60,25 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
# `latest` to actual block number as `latest` on proxy and on data provider
# can mean different blocks and ultimatly piece received piece of state
# must by validated against correct state root
let blockNumber = payload.get.blockNumber.uint64
let
executionPayload = payload.get
blockNumber = executionPayload.blockNumber.uint64
info "Forwarding get_Balance", executionBn = blockNumber
# TODO this could be realised by eth_getProof as it return also balance
# of the account
let b = await lcProxy.client.eth_getBalance(address, blockId(blockNumber))
let proof = await lcProxy.client.eth_getProof(address, @[], blockId(blockNumber))
return encodeQuantity(b)
let proofValid = isAccountProofValid(
executionPayload.stateRoot,
proof.address,
proof.balance,
proof.nonce,
proof.codeHash,
proof.storageHash,
proof.accountProof
)
if proofValid:
return encodeQuantity(proof.balance)
else:
raise newException(ValueError, "Data provided by data provider server is invalid")

View File

@ -0,0 +1,49 @@
# light client proxy
# Copyright (c) 2022 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.used.}
{.push raises: [Defect].}
import
unittest2,
stint,
stew/byteutils,
web3,
../validate_proof
suite "Merkle proof of inclusion validation":
test "Validate account proof":
# Valid inclusion proof for account 0xf36f155486299ecaff2d4f5160ed5114c1f66000
# at execution block 7533830 of goerli network
let
stateRoot = FixedBytes[32].fromHex("0x4cc43abefcb010e4176e82e44eadaa49a249d258867ba31f5c14d6099790a614")
codeHash = FixedBytes[32].fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
storageRoot = FixedBytes[32].fromHex("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
nonce = Quantity(uint64(71518))
balance = UInt256.fromHex("3d25780abb5f0a89b7da")
address = Address(hexToByteArray[20]("0xf36f155486299ecaff2d4f5160ed5114c1f66000"))
rlpNodes = @[
RlpEncodedBytes(hexToSeqByte("0xf90211a00314821db27eb679525687656632f7fc3cd4e196dd8740a4fbf3c484d33cc87da0b32d41dd34b46eb2ed19133871e1c927a2b922662d512b0281965f9b44eae8dca0967240ead870312be02e54d36e91305ab81a92f9623ed1aa99505be9d05d8336a07324a33b901419dd8ae772a7ecf8a634dfbca267c1d7a8ae330800e997428db3a006dfd8d1aa5e9ceb38f3942d127a341f2b223ae2c52ec8d30528676d464c3936a04e0251f3bc74fe3a136d5de07adf754bdbf50046c1c07ef2575a8375fa780a25a0b58b1c4d2cb7cb0d5d03799ea1b9590054ac1ca12b9751a36a97bd6e5928e2d4a098af6c3153e28c974884a15b1559f27496d56d2b7cdc4dfa02ad7787adcfedbda05ab08ebefdda99feb3cb89f5d70b612de898fb387ac21d8334beb7d763748c63a0ba15badc1bb92fc1170d87b36ca1b600355312376b14802f9bc1028c6a1046e0a0bb89f3c908e5681b12b35795850ca555c41957ba680d5f88e5f4002ac092025ea0577014557fe78cca16ba9d98b7c2d1a4f1f5deb467ac24f4481cc733ff28088ca0a34409628aa8722d2977aeeb1a06a8b6220afdd20d7df376ae19d1c87fdddbeda06c59547c3b6eaec3330be1a224be6df0df62ab7d48a8b9d3dd7faf4bcef18725a087328e8cd421248ab4d6a9652e02bd27affed5ce0c4c1b7813bf9e6603b951b2a0e83ecf40ab16b2c1499c0a4431dbd507078268e31eab9f4d8747b7bfaf74b6e880")),
RlpEncodedBytes(hexToSeqByte("0xf90211a0f8c7d5888d57dbc7c05198b347d48ccabae419b0240aa322b9ebc7eac04d6977a0b6190df5827a8de954713e947e6670f8424e3693ba43f514dbbc0e884b4a28a6a0708628ad543a7941dba0ddb1f1d4bf7844bba626a3a3aafd89b0385e72e57c56a08232da95725e034b1f3d9e9602765ad5e7598e7658ecad4db7c80993ca8cd82ea01ef4066c878575e664385f39ef77db1fb7a57a0a58e3b3c9b6cde5e310ddf399a02e845663f630667e0a3942b721a8dec00f01869afafcf668b0a7418cf4c89cc9a05f354987aac1183adabc4719a7b9c2607925f01d59d7334f391615b2bcbab59ea0090667b1bcf668a02a7e52c3abd65701f12ac6cebd8e2baafec3d5738c4f78bea07caa986367ce30ef3671ae12dbb31e273cdb8607bf4b4dca027eec19d68e1180a0b654499330b745fe687ff27aea175fc5ec1a170802de3422913b76742c46d29aa0f33e264f528eb4b18e558a81c5c44c8f626ed7da7a97db0f7f1f9dafc33d1793a030aa24216649d527b72e5d6e537ec39834828be1718d2454a83bbee7a4ff03e0a0b36d7321d4651737f7bf94e5a6c8e26f160a07d2c7dc572e64e2f3a332b34b9ea0c96767291f5bf5aa8849c96c9da108b2168f9268165916eb5e1fe25195a91afda011970351d8b437572eeda47c501b33c36601a2bc4f3f81aa6fc314300b8fb0f4a054558250264df1b4f7598c46ff847ee3cf880029377548d2f5dbe7ae9ea5ae6180")),
RlpEncodedBytes(hexToSeqByte("0xf90211a0645e0adf3fc44f24e122018134c8f3b354a9daf05489f9edea8421995af83d54a0f3aee49dabe2ee334de612dba0b5860b35373217f70860f1966fbf5ed87bd465a0959edf01ef89590429a1b024fd0f03c44a172725db0fbc2b06d3b48898756171a0b46320bd901a7c10859bb4855a558180fe03442d8f0ed5818aa0959ffac1cd52a0a137a658d13cc5cc1278f0e8f94d1c807183b81c248dd1d2d7d810d3888a84b5a0f472cc3565832a83d8f7196ecb582cb37ba5acce4e6d920854381101c6821dcfa0104bca973f514d8c49ea9ec29bd8e810f0126a8ee224a1d8dd38e841d9dffa64a0ade759bd4b3d4aee6afd2c6cc208d06cf61f18a3e368af4946d75270119b4417a065963fce379969fb0486089cae75302d029a5db1e11015e3ad74f0226f4e527ba0a3ee0d4db6e0a5c654ab98d3a52b06b1d5f91f481376ecbb1cb6be98221a8586a061426d1ccd902e701a6caaea223795d5f3e236aa55dce0460d2f045c6006fe3ca01619e291402e63179d5a0900bbce5604b32a1c0387611de2ddcb54ddee59f1aba0099661197942347bbe819915e9a5571ca39f0da8140f7bbf47a219a2914582ada0a7bcfa122de1249a971c58a59851a9a17d3818f4d8b6849c555ba822c5807b07a0e9d6d70a74952aaa417dac7af7ba0a730e296def339062a20e280f8149841d3aa0c5802c02299ecefe4d5881960cf7b18a1a7fa019c7a01d0ffa60ec22c68a96ec80")),
RlpEncodedBytes(hexToSeqByte("0xf90211a0b33390ffe04f59199aa089264474955e382577538040fc9f772ad6b5c4c06e27a0a5fd2d2fbdd68b6117370131fcf2c721d0da0cf2d8f01a3ddf4ad5420cf92446a008f32325d4430b4a920fbe9501fb3a62f9b39519505b69de14e182d9e9c28fdaa049b6c110a5f95b039130fbe7c369e5c76b56d66c11b3cb49d15676b832c71ef9a018119a73e40c92fc80133e021351b5633dccee7c2e2d242cd621d43b7ec806a5a083d32aebce2b54863f4440dd80ef970ab5866a4fee9ce50336b51d6d6c6c514ca01432f1eb3e4afc6fa493fd75823455a86dd921c67ca7e0f81518ab35e5696ebda027ac89ec60eac73922fef5e0ff3d53e3a04a4dce200a9f9db673b595f94cd63fa060cac64c1ac701ab6ebc752f9678c5543b856ac1755a9fa497d036d59a761d43a012f241474b3c69e648a58f2decb402e5613b38119f052bc76841860919dfbf02a0fe6141f40b1e2106b560f85c69e533c9f8474be39c74adbfb27352c39b606c29a0a826e7c1ea4203742b201b9c87244042bb07acf7c75d5e171d548c4675748d79a010b898bbcbab926031138c96b851ab6ece680d0a0ee4ed9f0d3630505aefed00a0207ca951540621936ecb946527d630e987e1dae1f6b299615d5163cbae74c229a0680537757d58834489d865435cb3947988a361bba8ee446304d6dfe665581a75a0613b58f9069a610ebffaa7b8086a97ea3991587790eb1f096b90b9526ccf9d5280")),
RlpEncodedBytes(hexToSeqByte("0xf90211a0f1b4b40950e332e3c246f6f6337bd559851b016d6b8eb7f40e31f01d63d5d003a02a77269847cfebd549834d7dac417f01b0f50d860e405305ec5988929b6c3339a0903f28b7912939efa6a807a4624702e28a6479583837b4e492aeae6a5d983a18a0638921e1fcf9bf9be37e6a648fa0ac7e1cc967abf4b975bb508515f9239260b2a015be428e82a9832418df65893858bb752f0aff3a380dd725854f64f5872b256ba09ea32765a32962713ba16c05bada54f7e4ac0e5da9fdc065f9c0deccecae61aba0a0c332c40ec2008c1d7e2176de631677317036c958991fa6a3773c9dabbd95fba06eaf67569e289f4f4c12486569b60325745a603d70fe836e28ed79abe608dd5fa0d09de843dd1de76e046a5de951db5330f03bc0b9df21d0a3ddb6a368f860cd09a063f9de11d14818fdfe6225306dbec74194c56a0f7b4c0cbb7c2200986d76d039a0a50fe5a0fac3e83bdaac397c0c4a32152e4ae756614961f2172492b42a576401a07119c9011c9eba49d196a878c6af0fe8204befccf6fb45ddce5ec0ebbe5d4c6da01d2ccefea315ac12691ce505e9bb828b731ce130b4108703f8ed7eedb2bcf1eba0e2fe8df21c00c13507e2b2870a213692ae455d4a6208f44e9bbd7d0a55b7cecba0ee91cbfa9b14ee3d2e958f0f6a383fa5da7dc667c0b93f6787b79861994d6f5fa089307ff3f6d958b9e5ef2e13ba5ceebaadcff82e99e92b6563acd0deef148e5c80")),
RlpEncodedBytes(hexToSeqByte("0xf90111a09725a5bda59d158e12856fd110eed37c2b2377833b01bbb730db1111658cb302a0acacf1fba3ed03da1672f5e12b06cc59a4e85eb8573bc64b30e598979963823f80808080808080a070555db94f94d4046ab94a7f99db7dc6caf8c1ddb9e083a8c807c99f96e0bf0ca0196f92289153376127494f86154dd26abf8273e443c4dc64d9d35ec974e63838a0969ef252c7141504f76fbb187f24e526035b3c649b18aa9d219ba9954c3312dda0bcb2b97af79709852e0f50edc795193938b18307e76f7dc87244c9dff11d5fe8a0bc7dcabe984dc42cef99f04a5c730b3c7e54f19014e6b18e5ee17add59c29b49a0d635c1be1b1ee4355531ffebdadd3cf470a0065c3a951063ef00fc60c5dece1d8080")),
RlpEncodedBytes(hexToSeqByte("0xf8749e2070b0cf62febcfb17abd5e2189b6e0029e0f9b9a1aabf0e670469d6ab74b853f8518301175e8a3d25780abb5f0a89b7daa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"))
]
check:
isAccountProofValid(
stateRoot,
address,
balance,
nonce,
codeHash,
storageRoot,
rlpNodes
)

View File

@ -0,0 +1,52 @@
# light client proxy
# Copyright (c) 2022 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [Defect].}
import
std/[sequtils, typetraits],
stint,
eth/common/eth_types as etypes,
eth/common/eth_types_rlp,
eth/rlp,
eth/trie/hexary,
web3/ethtypes
func toMDigest(arg: FixedBytes[32]): MDigest[256] =
MDigest[256](data: distinctBase(arg))
proc isAccountProofValid*(
stateRoot: FixedBytes[32],
accountAddress: Address,
accountBalance: UInt256,
accountNonce: Quantity,
accountCodeHash: CodeHash,
accountStorageRootHash: StorageHash,
mptNodes: seq[RlpEncodedBytes]
): bool =
let
mptNodesBytes = mptNodes.mapIt(distinctBase(it))
keccakStateRootHash = toMDigest(stateRoot)
acc = etypes.Account(
nonce: distinctBase(accountNonce),
balance: accountBalance,
storageRoot: toMDigest(accountStorageRootHash),
codeHash: toMDigest(accountCodeHash)
)
accountEncoded = rlp.encode(acc)
accountKey = toSeq(keccakHash(distinctBase(accountAddress)).data)
try:
return isValidBranch(
mptNodesBytes,
keccakStateRootHash,
accountKey,
accountEncoded
)
except RlpError:
return false

View File

@ -90,3 +90,6 @@ task testfluffy, "Run fluffy tests":
# Need the nimbus_db_backend in state network tests as we need a Hexary to
# start from, even though it only uses the MemoryDb.
test "fluffy/tests", "all_fluffy_tests", "-d:chronicles_log_level=ERROR -d:chronosStrictException -d:nimbus_db_backend=sqlite -d:PREFER_BLST_SHA256=false"
task testlcproxy, "Run light proxy tests":
test "lc_proxy/tests", "test_proof_validation", "-d:chronicles_log_level=ERROR -d:chronosStrictException -d:nimbus_db_backend=sqlite -d:PREFER_BLST_SHA256=false"

2
vendor/nimbus-eth2 vendored

@ -1 +1 @@
Subproject commit 59092e5b3bc38ed42995fc7276f7c4601b890988
Subproject commit d9ceb61dbd9e9763ba073b564eac7478e072f367