diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index b22d999e6c..0d1f760936 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -65,6 +65,8 @@ var allPrecompiles = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{16}): &bls12381Pairing{}, common.BytesToAddress([]byte{17}): &bls12381MapG1{}, common.BytesToAddress([]byte{18}): &bls12381MapG2{}, + common.BytesToAddress([]byte{0x50}): &MinaPoseidon{}, + common.BytesToAddress([]byte{0x51}): &MinaSigner{}, } // EIP-152 test vectors @@ -311,6 +313,7 @@ func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "10", t) } func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "11", t) } func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "12", t) } +func TestPrecompiledMinaPoseidon(t *testing.T) { testJson("minaPoseidon", "50", t) } func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add", "0a", b) } func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "0b", b) } @@ -321,6 +324,7 @@ func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2Mult func BenchmarkPrecompiledBLS12381Pairing(b *testing.B) { benchJson("blsPairing", "10", b) } func BenchmarkPrecompiledBLS12381MapG1(b *testing.B) { benchJson("blsMapG1", "11", b) } func BenchmarkPrecompiledBLS12381MapG2(b *testing.B) { benchJson("blsMapG2", "12", b) } +func BenchmarkPrecompiledMinaPoseidon(b *testing.B) { benchJson("minaPoseidon", "50", b) } // Failure tests func TestPrecompiledBLS12381G1AddFail(t *testing.T) { testJsonFail("blsG1Add", "0a", t) } @@ -332,6 +336,7 @@ func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2Mu func TestPrecompiledBLS12381PairingFail(t *testing.T) { testJsonFail("blsPairing", "10", t) } func TestPrecompiledBLS12381MapG1Fail(t *testing.T) { testJsonFail("blsMapG1", "11", t) } func TestPrecompiledBLS12381MapG2Fail(t *testing.T) { testJsonFail("blsMapG2", "12", t) } +func TestPrecompiledMinaPoseidonFail(t *testing.T) { testJsonFail("minaPoseidon", "50", t) } func loadJson(name string) ([]precompiledTest, error) { data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name)) diff --git a/core/vm/mina_contracts.go b/core/vm/mina_contracts.go index 113f3e951c..7154337f67 100644 --- a/core/vm/mina_contracts.go +++ b/core/vm/mina_contracts.go @@ -33,6 +33,7 @@ package vm import "C" import ( "bytes" + "errors" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/crypto" @@ -65,9 +66,14 @@ func (c *MinaPoseidon) RequiredGas(input []byte) uint64 { // 0x1f831f84 var poseidonHashSignature = crypto.Keccak256([]byte("poseidonHash(uint8,bytes32[])"))[:4] +var ( + errMinaPoseidonInvalidSignature = errors.New("invalid function signature") + errMinaPoseidonCallingRustLibFailed = errors.New("calling rust library failed") +) + func (c *MinaPoseidon) Run(input []byte) ([]byte, error) { if len(input) < 4 || !bytes.Equal(input[:4], poseidonHashSignature) { - return packErr("Invalid signature"), ErrExecutionReverted + return packErr("Invalid signature"), errMinaPoseidonInvalidSignature } calldata := input[4:] @@ -84,19 +90,22 @@ func (c *MinaPoseidon) Run(input []byte) ([]byte, error) { networkId := unpacked[0].(uint8) fields := unpacked[1].([][32]uint8) - if len(fields) == 0 { - return packErr("Unable to verify for 0 fields"), ErrExecutionReverted - } - output_buffer := [32]byte{} + var fields_ptr *C.uint8_t + if len(fields) == 0 { + fields_ptr = (*C.uint8_t)(nil) + } else { + fields_ptr = (*C.uint8_t)(&fields[0][0]) + } + if !C.poseidon( C.uint8_t(networkId), - (*C.uint8_t)(&fields[0][0]), + fields_ptr, C.uintptr_t(len(fields)), (*C.uint8_t)(&output_buffer[0]), ) { - return packErr("Calling Poseidon hash failed"), ErrExecutionReverted + return packErr("Calling Poseidon hash failed"), errMinaPoseidonCallingRustLibFailed } return output_buffer[:], nil diff --git a/core/vm/testdata/precompiles/fail-minaPoseidon.json b/core/vm/testdata/precompiles/fail-minaPoseidon.json new file mode 100644 index 0000000000..54f983b988 --- /dev/null +++ b/core/vm/testdata/precompiles/fail-minaPoseidon.json @@ -0,0 +1,22 @@ +[ + { + "Input": "aabbccdd", + "ExpectedError": "invalid function signature", + "Name": "mina_poseidon_invalid_signature" + }, + { + "Input": "1f831f84", + "ExpectedError": "abi: attempting to unmarshall an empty string while arguments are expected", + "Name": "mina_poseidon_invalid_calldata 1" + }, + { + "Input": "1f831f84aabbccdd", + "ExpectedError": "abi: cannot marshal in to go type: length insufficient 4 require 32", + "Name": "mina_poseidon_invalid_calldata 2" + }, + { + "Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ExpectedError": "calling rust library failed", + "Name": "mina_poseidon_invalid_field" + } +] diff --git a/core/vm/testdata/precompiles/minaPoseidon.json b/core/vm/testdata/precompiles/minaPoseidon.json new file mode 100644 index 0000000000..e812b8f92f --- /dev/null +++ b/core/vm/testdata/precompiles/minaPoseidon.json @@ -0,0 +1,44 @@ +[ + { + "Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000", + "Expected": "a8eb9ee0f30046308abbfa5d20af73c81bbdabc25b459785024d045228bead2f", + "Name": "vector 1", + "Gas": 1000, + "NoBenchmark": false + }, + { + "Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001f2eee8d8f6e5fb182c610cae6c5393fce69dc4d900e7b4923b074e54ad00fb36", + "Expected": "fb5992f65c07f9335995f43fd791d39012ad466717729e61045c297507054f3d", + "Name": "vector 2", + "Gas": 1000, + "NoBenchmark": false + }, + { + "Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002bd3f1c8f183ceedea15080edbe79d30bd7d613b86bf2ba12007091c60ae3933765e4f04ab87706bab06d13c7eee0a7807d0b8ce268b4ece6aab1e0508ec9c42f", + "Expected": "fe2436f2027620a11233318b55d0a117086f09674826d1b7ce08d48ad0736c33", + "Name": "vector 3", + "Gas": 1000, + "NoBenchmark": false + }, + { + "Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003f5ea61ce47773495363dc4f6a41c3e2da14b13d6dd173acf87c9ca7357fb2400f28573f49c658b4ba151e82ed0bd6aaab045311d1a72df58c21eed462bede01873cf45c39285f17ccea99e0daeb547430cf7921218fe3726010f608e682a841a", + "Expected": "9b1b94444a54af49a7623d1fe1ca72649f0a098daf5704925f024eb6ab0e4b3f", + "Name": "vector 4", + "Gas": 1000, + "NoBenchmark": false + }, + { + "Input": "1f831f840000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000044c28b87198e0012207f93cdbdaa35355ec8213fa97a60e62701f62602d4659200787a40fc046c4dd0ff3cad0e54006577fece871c774707494984f1c7d3347271504ffe48e4e6dfcc4ded439edd386cf271b69d94afae83079f3ee3e7c04d52d290b6506516fe7588b5100f8db2e871427c6d74e7a60ab656f43dd9bc687c312", + "Expected": "47ecd3bf2eed86dcf8d2cef3d7667104689dba4d9bcb54006e0c66f6ec8c5a16", + "Name": "vector 5", + "Gas": 1000, + "NoBenchmark": false + }, + { + "Input": "1f831f84000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005da99182b35f2cd9f8a137052c4262576377a16deb83652db459a74893a0cf73c9805573990c4028292c9db171cd2b97902f9fc494983f6f7e0a0c184bc55df1b90ff1001b9dab21358aad1f6b7906a56d0c039502c1590c3ef9921a8951e440988b56238a0eda34576db959fecd1c3790bb5311fdb231753243c5085974a5b37896a7727e511a4c30d99082bf3542623fb702afab0b62ebbf301ed51e38f6812", + "Expected": "09a2d55277908b7c8214f745b3605f0f9055dcd4c9b594cdd759292c34c3a20c", + "Name": "vector 6", + "Gas": 1000, + "NoBenchmark": false + } +]