Skip to content

Commit

Permalink
Test and fix proof
Browse files Browse the repository at this point in the history
  • Loading branch information
Philogy committed Oct 15, 2022
1 parent f245f17 commit 0b52966
Show file tree
Hide file tree
Showing 8 changed files with 4,819 additions and 119 deletions.
18 changes: 18 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
env: {
commonjs: true,
es2021: true,
node: true,
},
extends: 'eslint:recommended',
overrides: [],
parserOptions: {
ecmaVersion: 'latest',
},
rules: {
indent: ['error', 2],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'never'],
},
}
130 changes: 70 additions & 60 deletions out/Auction.sol/Auction.json

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions out/AuctionFactory.sol/AuctionFactory.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
"author": "philogy <philippe@dumo.net>",
"license": "MIT",
"devDependencies": {
"@alch/alchemy-web3": "^1.4.6",
"dotenv": "^16.0.3",
"eslint": "^8.25.0",
"eslint-plugin-prettier": "^4.2.1",
"eth-proof": "^2.1.6",
"ethers": "^5.7.1",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.24"
}
Expand Down
85 changes: 85 additions & 0 deletions script/test-get-proof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const { createAlchemyWeb3 } = require('@alch/alchemy-web3')
const { GetProof } = require('eth-proof')
const ethers = require('ethers')
require('dotenv').config()

const getBlockHeader = (blockData) => {
const retData = {};
[
'hash',
'parentHash',
'sha3Uncles',
'miner',
'stateRoot',
'transactionsRoot',
'receiptsRoot',
'logsBloom',
'difficulty',
'number',
'gasLimit',
'gasUsed',
'timestamp',
'extraData',
'mixHash',
'nonce',
'totalDifficulty',
'baseFeePerGas',
].forEach((key) => (retData[key] = blockData[key]))
return retData
}

const bufToHex = (b) => '0x' + b.toString('hex')

const expandAddrToKey = (addr) =>
'0x' +
Array.from(ethers.utils.solidityKeccak256(['address'], [addr]).slice(2))
.map((char) => `0${char}`)
.join('')

const getAccMPTProof = (
{ accountProof: rawAccountProof },
{ stateRoot },
addr
) => {
const hexProofNodes = Array.from(rawAccountProof).map((bufs) =>
bufs.map(bufToHex)
)

return {
expectedRoot: stateRoot,
key: expandAddrToKey(addr),
proof: hexProofNodes.map((node) => ethers.utils.RLP.encode(node)),
keyIndex: 0,
proofIndex: 0,
expectedValue: hexProofNodes[hexProofNodes.length - 1][1],
}
}

async function main() {
const web3 = createAlchemyWeb3(process.env.GOERLI_RPC)

const block = await web3.eth.getBlockNumber()
console.log('block: ', block)
const directBlock = await web3.eth.getBlock(block)
const blockHeader = getBlockHeader(directBlock)
console.log('directBlock: ', directBlock)
console.log('blockHeader: ', blockHeader)
const account = '0x97aEabe66E1e126358DF8b977D0F615A62173448'
// const ethProof = await web3.eth.getProof(account, [], block)

const getProof = new GetProof(process.env.GOERLI_RPC)

const accountProof = getAccMPTProof(
await getProof.accountProof(account, blockHeader.hash),
blockHeader,
account
)
console.log('accountProof: ', accountProof)
}

main()
.then(() => process.exit(0))
.catch((err) => {
console.error('err:', err)
process.exit(1)
})
33 changes: 32 additions & 1 deletion src/mpt/VerifyMPTBalance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,44 @@ library VerifyMPTBalance {
uint256 internal constant _EMPTY_CODE_HASH =
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

function expandAddrToKey(address _addr)
internal
pure
returns (bytes memory key)
{
assembly {
mstore(0x00, _addr)
let hashedAddr := keccak256(0x0c, 0x14)

// alloc bytes
key := mload(0x40)
mstore(0x40, add(key, 0x60))

// store length
mstore(key, 0x40)

// add zeros
let keyOffset := add(key, 0x20)
// prettier-ignore
for { let i := 0x40 } i { } {
i := sub(i, 1)
mstore8(add(keyOffset, i), and(hashedAddr, 0xf))
hashedAddr := shr(4, hashedAddr)
}
}
}

function isValidEmptyAccountBalanceProof(
EthereumDecoder.BlockHeader memory _header,
MPT.MerkleProof memory _accountDataProof,
uint256 _balance,
address
address _addr
) internal pure returns (bool) {
if (_header.stateRoot != _accountDataProof.expectedRoot) return false;
if (
keccak256(_accountDataProof.key) !=
keccak256(expandAddrToKey(_addr))
) return false;

bytes[] memory accountTuple = new bytes[](4);
accountTuple[0] = RLPEncode.encodeUint(_EMPTY_NONCE);
Expand Down
123 changes: 123 additions & 0 deletions test/Proof.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.15;

import {Test} from "forge-std/Test.sol";
import {EthereumDecoder} from "../src/mpt/EthereumDecoder.sol";
import {MPT} from "../src/mpt/MPT.sol";
import {VerifyMPTBalance} from "../src/mpt/VerifyMPTBalance.sol";

/// @author philogy <https://github.com/philogy>
contract ProofTest is Test {
using EthereumDecoder for EthereumDecoder.BlockHeader;

EthereumDecoder.BlockHeader internal header =
EthereumDecoder.BlockHeader({
hash: 0x23a970d715e3883c99a3c7fd722003441c47b6d0270555966e2a274eb4fa8904,
parentHash: 0x2d6bd03a05ea51f87df40ade91ce04635e3afb5be170ce038f65db10449bedf0,
sha3Uncles: 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347,
miner: 0x000095E79eAC4d76aab57cB2c1f091d553b36ca0,
stateRoot: 0xfc4185e02ffb0dc966e52b23cbf0adc68ab141ddbc39eafcdebc96ca2fb6d91d,
transactionsRoot: 0x927e030351124ca1cd2bad9ae7b39f4c488ac57097b5a9ef401938d5aeff218c,
receiptsRoot: 0x598f147f735e74bc531d1d9a5e8577d2b78ad1eca561d01a9f66d1dc8b783306,
logsBloom: hex"106004006000400144000008a140084188404900008100520203000048400114044144400a040200c028412040c00041082200120010104108140e842224005008414004c63400811a200a0801588020020180010264902100110314004c0c00400430000200008542a0091a0088080000000010041a070000025092808420081000810c844000140066080980100000002144822821006c042384601407004442230005480802000800250609000220a2002402000482404200242224212880126170120800091104884000811282500100002406830012d841004288206000b91001c0210202000c0020080000400140581208100002510048000082200101",
difficulty: 0,
number: 7775555,
gasLimit: 30000000,
gasUsed: 12414225,
timestamp: 1665863808,
extraData: "",
mixHash: 0xdadfbce9b3ad7a17a8391cc7fe4ed1d577c355ba63928c9cc3c0afc1c2114529,
nonce: 0x0000000000000000,
totalDifficulty: 10790000,
baseFeePerGas: 8
});

MPT.MerkleProof internal mptProof;

function setUp() public {
bytes[] memory proofEls = new bytes[](7);

proofEls[
0
] = hex"f90211a034ce757c58ac04fb9127a5ee76c2aed061b998ca17a2a059d0599c8f995c6f1ca035844dc3a95893884479820f751760ae8a8094bde61aaa21421cb610b1ac055ca0403882b9f08f33a6b84382dc078a4f28ca5e7465aaa5a7213ea2f699a68ebd25a040584ddbb95b8a03776414c09cc51af13b67956123dcda6ac1e3c4fff83070b7a0415c9c2970ea112db01f631833dd005868244b04ee3460cc3a78cdadbd57bb40a0ebb111aeaf6ac129d9a350f42238fb4af5b0999c3a1fbc0f6afaaa1614d4ae17a09abac1e0b2a63738762f75717e220e719bf26647f11cfaf586019d90cc8421aca0dd4f0e7d7311b3dfda15c5eef1b80fa70b74c5df2399bca75de06edf71e3d9d1a072d872004cbab07516dc68caa2e1f696cbc4ea160453d3a35e8c481874162c9fa0b121ef426eee03f56301c50b2d75f7587e9c963e5525b8fd74e329a4562acbd1a006445165ae62c704776544438c1d97bfa41b429ad76a5be407066d435218b6c3a00d73986dd4a897c3dae253d379ed25bad3effaba4fdc93c47b7c71bc82af77c4a046b280c9b225276ffcc8436b25d1211dc5531f5418e7be4a8a660aa3875b8c5ea0dcb86b968c90d277bd1e7f18dbf40895237bd1c55ca1b4ff0782ffa637ba7613a07e0b70e2a498abc560ba82a03d271af3289e43e32a747c44746b24990083b084a06a70c1c26edfa30cd7b7baaeabd717d741bb5dc444e4ff88d579aae0e1c7d51180";
proofEls[
1
] = hex"f90211a0d0f35b92541d8bfeb38ed6d79898e7170db982462643e5b6ae97eed69aa69beea07da2701474a5cbf3b09616dbb7a79206551d5ffaf148e8dd14c08540cbdbf41ea0cf0287a575e7a277ccd230b3e8432de89e0c2975c64bc7d3c67a289ee8c1fea8a08327c886168307d3ab3f9da046c8b62762a8c0e8293fdcaaedffc2eb13980278a0ca967d1288f4425584a2544df685660cf0f8b7ef88f3bf0ec8955d981d62bbfaa02ce51c7b4f617855fd1cadd9c592b0bd78cbccd95731f5569b457fb55d6f4032a0989235a08096577aa19cddf78a323b8c5204b908da4ba4dcdce6915490b6de50a0b39eccd77d2708dbeef2f6648554e3b9ea79d3c2a2b77b96715f48a0a9242512a0547c19bb5e26e109512966cecc5028a81c276610a91c2188fc9e574bba94bf52a0e99845a381bb5c5a1c10cfaa88697fc2d979dc8011048ab346162d017e0288f5a0dcde4a961e54af2d5b2e08f1c1a291757f6322f4923d1fa68bdecc12c7ce6375a07ca2171d20dec82f7bbcc0e1aa69b6a388cbc90d486c20d41941b763948eea13a0cc82741fe4a9e07ef7b680bee6548ec39345002fd15644bff5a9cd7d2f9a4558a0fa5b3e2714b60e66c70c02c262dba347010828063df65a99317e09a373a02e9aa0614bb3efeab9ce17e0430ef5d0129cd3d107997743649883353ecab7d715c32ba0f08fbab878f741119a3a1f0d5534480a60323a3cc0a37b7ab7ee909b0ae3da2a80";
proofEls[
2
] = hex"f90211a0793e27d7274f176d53c71f8bd217c762012a299ca1c0ea6645408aae455f1bbca0f031601ec5552e49e3acde043650543da29641512ce43d0a3d4715cede9d300fa0d16e597566b01cd316119f880e09de69aea8a64aa04d242e00047073485f5d32a0ebd775ca4a3d55271536afef6e5d711856b06bf8c71b31a139477e55f330d7baa0e99086786846a30575e039893d35654156e87eb0c13e2549c9883d7aca0e2cbca0b243bdde3d514510d1ce31e650c96a717da7e81e00f3c34c83c43332f29442cba09be1e650f0b3340c0c83749661e102a624c9d35072658e835c787f99d9d39daaa04ec0114c02ddb194fbdfe3323f4186939fd60fc0a18c8fde808293764cc2974aa039a81c34a6fd020d9a9025317e672d43e03879d2b8496561f1cec9851fe54bb2a05c704b9bedcbfb457fcae62716f66573741f88c1e708b254811a4c374b8abdc6a03c24e5a3628136daee9b1ebdcb6d1621cef511c21f74f1c1a7cc9be0dc2cf8e4a04de3aefdee7bca818d38d6bddd1846b43c245c9e4a5790780d49401dd315fdaaa0dc90ffd167d53fc783d697449fb4094f986ff7e37d7627d7394bc1eed448f513a0222bd7626768b31820212a2eff5d3e98f908a4c193e6cadf2d4f8104ee243187a04d725ef4da36280b6851c3c6821f2ab238c6f19ba71fb4cd1df0c2137e73e609a0be019cc697fe9ec2b4dd4ec744a5f8b4e19185eec0f963e3d40d37339bc99ec480";
proofEls[
3
] = hex"f90211a07e828f9c1fcc61dfd598056e532243cbf72803469bf4f340f8208210b21824b8a0af5cf1dcd8c74d2165df7fbdbb98d9a419983b85a96ba8737e492c516fc2713ba0081fc1637c165da5a5d113b3c91323e080bba84c1241413bd2abb925d55063f6a06d251958749b769bc37a3eaa65287505ae36fbd915794275ca16c4b21941fb48a091c1e83b5c4c3feff5b7dc2bf8b4f807055b9c0002bbeceb90782791e0200f47a03dc22356c2b945e505f2be3126f0f1dc2dd3365f60849a3fb7986572fb7f9bd9a03ca1fb3db7f5429a2406f0513e0d87ecd1fb778ea2d6b98d6462c1adc2199b5ca0842c88c4e5bb43387dfcc23a8fd78b0310e25d407577acb630f426cfb8bb1258a0fbbdbc71b709e7f4f6c063a54b1e7ce76b068bfcf5e8bc94759401cb6020dd20a00b186fca3aafbd7276561aa9058a31a9f5bb34cb145408e2cb3f66ed6a2183bda0599658d7328df29896d0ef74f752c03de9aeaba3a9e5a490f4b3c4eba7ca7e2da05284221fe17958e296ae9ab206db2edd17ce6a788bdf2304dd2c8adba94be123a01c600867d873431d8ec615f9221cc15c348a4e503257657ca8f9b263252fa06da0ceb57e955825f2ba9c5da40369a6892aeebb7aadeec8c156e4652d7757b4acaba0971f3cbeedf7840f4c02460a3c6991a4a341cd13e7cfcbaff99fff72157c597aa0bc78a5685c29088eb3d0800417e4cf937c63fbd75fb7299eb1268bb6b454ffb180";
proofEls[
4
] = hex"f90211a05d541aa7e47fc00e572c53abbcf416104601a44fb1c3845d86e7d3c441d6b76ba065a45f4690323cbbb2dbee8468bc943f7fcd90f8f51178b6c2ebd006ec1156b8a008afeee45d5de4170f0ffc82e72726b059fc1e1c1c114d3f68f52dd638bdc152a0d28a63e7073f314e008db9dbca37d7135461fdfc13bb07cbffb6373aa19b195da05f8e81d2f7c311b1c92be6bced5c71bc2bc2c2978a4eb59257348df03a68a2c9a0b7f2a376870ea13b20c1a0c64ba9277120a1190236382c1f874230309fcb99cda098aecaec115d7d16273d2a9060107d5a7f9e61e906b083cc2a3978109cb3853aa0372c5c195078d768fb77dcba3a80426946ffed285fb9728f2525d9b97ff469faa02b258eb30d5eea5036c148a824c527f9870a0f363546fc252d982ca4322e7335a064be8decb351194ac1b2d6107b4b109c8ac0e6b9f681b84d0de790801653d849a09122dcf5d3b9fb6006ac1dbff57d8a817e3ca0952d81d894bf5225aa8ec4526ea0bee3e6fcfe074e0ab5071e9e109ccb611d0e9d9348fc4cf5d99cba08fd15f348a0ce517e87dc004fba2471ca5d6502a938596117dbed47ae857a6b08f27b65e183a0305350fd90c360400d731802626c531c66ed0c612eaa746e37c5879769988094a049725fa0d29c845e1661321f4ca3ad103a2eba1806286ad25c9984b7eb1f9e8da061523402f671cb69048d103c75b7fecc1c2aae8452a9f327bd0bff29fb6980f880";
proofEls[
5
] = hex"f90151a07a829f019fd853740162f7b513761d00597ee484734ef9731503c6dc564a7dc0a07f17cb023b9bed242f15d8af8b23c5deb6f06933b84a6ad7fc9540c5443ef628a01d1dc3edf8dd0367ebbf282b2511ce910d4da9a37a3ef2e83f56d74e626753038080a0513d0abae59102a85831ad2854cd9c6b83e1426e12e358019c4854287316ae90a0f3fd7377624ed87f84d6f4de44f3cc91b2dbea5f66b854bdae72d5117599803c80808080a03fce35053ccd62728134dbfd40439a95361129eac41342aaef9bfefd41467645a0b2bd3b312973fbbd26f17737b1340d27f24defd38bf56a34ea98a81b6706bc77a0a7d9b4d1ed4fd4c2b54c35c68e9894934b85162ae7bb933cb93bef8570d7e7c3a023f5e34708956fdca37a549ae4cc710fef89467c7ec2f0e7842ffe9270f9a4b0a0a85f8df7935a519de77d830c689558cdc4404026f7f07bf2cbc916fd91d570ab80";
proofEls[
6
] = hex"f86f9e206f50412ffb302528d7234a5716abbf9a560eed7fc2b4e98e61d7004042b84ef84c8088016345785d8a0000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
mptProof = MPT.MerkleProof({
expectedRoot: 0xfc4185e02ffb0dc966e52b23cbf0adc68ab141ddbc39eafcdebc96ca2fb6d91d,
key: hex"0f010d03090f060f05000401020f0f0b0300020502080d070203040a050701060a0b0b0f090a0506000e0e0d070f0c020b040e09080e06010d07000004000402",
proof: proofEls,
keyIndex: 0,
proofIndex: 0,
expectedValue: hex"f84c8088016345785d8a0000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
});
}

function testHash() public {
assertEq(header.getBlockHash(), header.hash);
}

function testAccountProof() public {
assertFalse(
VerifyMPTBalance.isValidEmptyAccountBalanceProof(
header,
mptProof,
100000000000000000,
address(0)
)
);
assertFalse(
VerifyMPTBalance.isValidEmptyAccountBalanceProof(
header,
mptProof,
100000000000000001,
address(0)
)
);
assertFalse(
VerifyMPTBalance.isValidEmptyAccountBalanceProof(
header,
mptProof,
100000000000000001,
0x97aEabe66E1e126358DF8b977D0F615A62173448
)
);
assertTrue(
VerifyMPTBalance.isValidEmptyAccountBalanceProof(
header,
mptProof,
100000000000000000,
0x97aEabe66E1e126358DF8b977D0F615A62173448
)
);
}

function testExpand() public {
assertEq(
VerifyMPTBalance.expandAddrToKey(
0x97aEabe66E1e126358DF8b977D0F615A62173448
),
hex"0f010d03090f060f05000401020f0f0b0300020502080d070203040a050701060a0b0b0f090a0506000e0e0d070f0c020b040e09080e06010d07000004000402"
);
}

function run() public {
setUp();
testAccountProof();
}
}
Loading

0 comments on commit 0b52966

Please sign in to comment.