Skip to content

Commit

Permalink
initial commit of MPT verify precompile
Browse files Browse the repository at this point in the history
decoding of arguments

end of precompile
  • Loading branch information
Kelvyne committed May 23, 2023
1 parent f7e10ee commit d1f2185
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 0 deletions.
70 changes: 70 additions & 0 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ import (
"errors"
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/blake2b"
"github.com/ethereum/go-ethereum/crypto/bls12381"
"github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/ripemd160"
)

Expand Down Expand Up @@ -88,6 +91,8 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{},

common.BytesToAddress([]byte{0x92}): &mptVerify{},
}

// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
Expand Down Expand Up @@ -155,6 +160,71 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uin
return output, suppliedGas, err
}

type mptVerify struct{}

func (c *mptVerify) RequiredGas(input []byte) uint64 {
return params.MptVerifyGas
}

type mappingKeyValue map[string][]byte

func (kv mappingKeyValue) Has(key []byte) (bool, error) {
_, has := kv[string(key)]
return has, nil
}

func (kv mappingKeyValue) Get(key []byte) ([]byte, error) {
v := kv[string(key)]
return v, nil
}

var (
errMptVerifyInvalidInput = errors.New("invalid mpt verify input")
)

func (c *mptVerify) Run(input []byte) ([]byte, error) {
// [root <32 bytes>, key <32 bytes>, proof <32 bytes length><n bytes arrays prefixed with length>]

if len(input) < 96 {
return nil, errMptVerifyInvalidInput
}

uint256Ty, _ := abi.NewType("uint256", "", nil)
bytesArrTy, _ := abi.NewType("bytes[]", "", nil)

arguments := abi.Arguments{
abi.Argument{ Name: "root", Type: uint256Ty },
abi.Argument{ Name: "key", Type: uint256Ty },
abi.Argument{ Name: "proof", Type: bytesArrTy },
}

r, err := arguments.Unpack(input)
if err != nil {
return nil, errMptVerifyInvalidInput
}

root, _ := r[0].(*big.Int)
key, _ := r[1].(*big.Int)
proof, _ := r[2].([][]byte)

proofKv := mappingKeyValue{}
for _, step := range proof {
hash := crypto.Keccak256(step)
proofKv[string(hash)] = step
}

v, err := trie.VerifyProof(common.BigToHash(root), key.Bytes(), proofKv)
if err != nil {
return nil, errMptVerifyInvalidInput
}

var rlpDecoded []byte
if err = rlp.DecodeBytes(v, &rlpDecoded); err != nil {
return nil, err
}
return rlpDecoded, nil
}

// ECRECOVER implemented as a native contract.
type ecrecover struct{}

Expand Down
3 changes: 3 additions & 0 deletions core/vm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{16}): &bls12381Pairing{},
common.BytesToAddress([]byte{17}): &bls12381MapG1{},
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
common.BytesToAddress([]byte{0x92}): &mptVerify{},
}

// EIP-152 test vectors
Expand Down Expand Up @@ -312,6 +313,8 @@ func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "1
func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "11", t) }
func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "12", t) }

func TestPrecompiledMPTVerify(t *testing.T) { testJson("mptVerify", "92", t) }

func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add", "0a", b) }
func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "0b", b) }
func BenchmarkPrecompiledBLS12381G1MultiExp(b *testing.B) { benchJson("blsG1MultiExp", "0c", b) }
Expand Down
9 changes: 9 additions & 0 deletions core/vm/testdata/precompiles/mptVerify.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"Input": "54b446bd21833f70b901b5500c46a0643f24711dc529f79127be65b43c5b1b108cd6980c531090b70571b4399f4b79395520acf3d7a0931cabac7c2fcce9a9c90000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000214f90211a0b42b47b521d706e31480e6cd5f824dc44e1c7e8de9de7dadd913b06aa23ea2a0a07a2d838706cfb15f2f38dfd344f9fbdc60a59e6af23f9bd321bfae350fc2c046a03a1c15cb1eb8784a598f21e6d82ad5dc3ec8bcbde7639a99277433b0dee771fea0706695332c7a676243785a01feef021ebb76b19773d5ed30030c744d11af6df1a037d752bb06883fe706e5552ebe6dc8f0a0662c0003b42b8f2e9aec3fd31c2298a0593bfd31724c754d8a77576479799d3e72983917dacf51958edffa9bcc840b53a0e2354713ec708dd66e855df9be9dda757f4354a4a2a408e02c08d115f8d4e302a0d0f6c256610945a677c1a09ce2c326f17133ceaefc47f9175160ca9aba6a3378a0ed1714788209444fd5ddf07f45e402942b3bf9dfeaa68240024caa3159693269a0f241952389ad968b92677794f3f5584f13fc1c830fdb2f2ccec9f3a7ef8e954aa09792be6cfba91d6d7df03fecea4bc5089f01e910e5846a97613f004b8b5a48d8a0ccc7945bbcde7caadeb89873630661d61e4ac2c1f34c88b22c2356dfd93a3bd5a04e74017f6f5489c99ee75c6e7d58009a9fb026b2db90f6b48a95f867640397d8a0b9fd9b3de227b5f97cd24dd3acdb5c5e5eaa69ad42641d12dcfee13c00fdf74aa00a70a96ee01d5dbdf8c6063bed5b18556c01e4bae4639ff3df4520906249c4e5a09a35323d3459176eb432599f03fcdb9762e8939106d9a9bdad219c3a897b9ba0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000214f90211a01aadf87ee3c9440c6d75c43d73d299449a14ef1110104630a101e40cecb05f4ea009761f32869ca0f45b801192221f041a9c07938e9859fab7568799b6739c8abaa0d56cb1c7282e29f40f7904fb2f111a9914468bfe4f1bc70d2ab297a3733bd9efa08f4e2ce659f15ddb9d2881228796d98b0c0bec1d2c76e4901e7bb7650bb32f6da0f22fee035a82145f03431b4401822106281e320f2d5c25814e72f3bc73f9b3aca0912c29c07e3904cb968cf1881e9cf1198b00677a16d9548a9b6aa3bc6deb66a8a048d9e4275f62c8dc8ad3878dbc973043d4294b6a2a5b190f96482ea9fc6552b5a035248335546e4ccb7d3f295d0087f394c65a11a7c2c50afa8d2d6f5d4afdcc6ba090f779d402f97a71b677cadfd3966a8be7066777770c1ba8190099b07fdfb787a05284f86a6b49f722a42dc998fae9b43d827e77ceba9fe6b48b241cfe86831f86a01229667a0e88ae137ab7f8d916d72290e43de375badc1aa099e0b54cea79abeaa0d82d7a065cdba6ca7102197f1e3d443c3d681dda3c472b5edb932a24cfe4dd3ba05fd3d864493348e8ded2bedcaf2370ef8294f654ac0548f0bc35590c9817ae5ba02542ad6f06bc399b511ad3753fea51714ad3b108b1216c8c34f983288846838fa07a1c3e0942b1b54b5cea0aefb65cc84cc1118e52b96b3f105bf3029208b3b644a084e1729821f2d8da50cb262eb2774b44a108a701864bed156bd657571e7065a4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000214f90211a075473be0d58abda4fb6f4b2762e31e21846a779f852139eb18552d99b519779fa0e02e84d721a56aa3168a8e0ea5499abeece6938f6695b1d8f8c413bec481898ea058b35f1446eb23616fc7015e1667a71e56a7076cdbe1d511a1cffe68ce739b75a02a1cb019734e950060876f2a479a34dcb0041d5c74bb534a5db07c94da1450fda0fbb8a46495c5e3ca60da812f72c0c393abf0adb661cfd54660340231278bef5aa086bafbf5dcb306ac2802c70c30bceeeaf6fce04896d183c64c77d2f51e083476a073c69f42e2c6299dc1cc222eb736afcd523b6e55a05323b4e1cfac20bf13bd97a0b0d1e3133965dd0d88acfd681b0d1f7fabb73cba5a4f56b00d1c6bd902527111a043b4447d5c2a1445126beed2164e399b4731fa77b501a34b6a1dd4e3d935765fa08d3ccc137261d9f4b9a52b4b3549050348838b96a7b7c2b8ce6693e0bac583a7a0129902a0313110646ec3d6492295ff2299b6b1f0dac575eb1ee5e9c95c37543ca02931d4eba8034557f6986c74a4b73f669c80906be7e1af3a1149531fe5f37c77a03f9b647ce59b955a11be83a17b2bc80ae4d6d8f27f97a9e5c6cfb266e824c118a0f959dbb66eb2d5fc969d68c48a984c26e98ca6e482cc77b346996ca78ea10233a0bf22593a349559f596fb67279703cf868c879ac938c428b9632ff5a5ffd32843a04753a0dcdd7388ff0e8d1f2bbd5ddf8ca27c34610304f0c3a1f25ced73cfd7f7800000000000000000000000000000000000000000000000000000000000000000000000000000000000000053f851808080808080a0e6dcb8c40f6aa6ad0785bed60833877cf27af634f43d101d56b7caba395133798080808080808080a041537058a23b3a6fabbfd41c335ba6b9379b91b3dd1307e57d15c761d87c9d4480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000053f851a00ca64bc995c32ad1f932d9a3b91b9fa03edd6c74ba2576206569d502a12414518080808080808080a0a5db5e6312ed508404d59b8361d895cf1e7d33c6756c8676ecc2cfb834e7e4f080808080808080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036f59e380c531090b70571b4399f4b79395520acf3d7a0931cabac7c2fcce9a9c99594502fce03af4bfd3dc991a6f7d0523cb920e1dbc800000000000000000000",
"Expected": "502fce03af4bfd3dc991a6f7d0523cb920e1dbc8",
"Name": "valid storage proof",
"Gas": 30000,
"NoBenchmark": false
}
]
3 changes: 3 additions & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ const (
Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation
Bls12381MapG2Gas uint64 = 110000 // Gas price for BLS12-381 mapping field element to G2 operation


MptVerifyGas uint64 = 30000

// The Refund Quotient is the cap on how much of the used gas can be refunded. Before EIP-3529,
// up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529
RefundQuotient uint64 = 2
Expand Down

0 comments on commit d1f2185

Please sign in to comment.