mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Add poseidon precompile
This commit is contained in:
parent
37b5a40ab8
commit
7c5c706016
4 changed files with 74 additions and 4 deletions
|
|
@ -104,11 +104,16 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
|
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var PrecompiledContractsMina = map[common.Address]PrecompiledContract{
|
||||||
|
common.BytesToAddress([]byte{0x50}): &MinaPoseidon{},
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
PrecompiledAddressesBerlin []common.Address
|
PrecompiledAddressesBerlin []common.Address
|
||||||
PrecompiledAddressesIstanbul []common.Address
|
PrecompiledAddressesIstanbul []common.Address
|
||||||
PrecompiledAddressesByzantium []common.Address
|
PrecompiledAddressesByzantium []common.Address
|
||||||
PrecompiledAddressesHomestead []common.Address
|
PrecompiledAddressesHomestead []common.Address
|
||||||
|
PrecompiledAddressesMina []common.Address
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
@ -124,19 +129,24 @@ func init() {
|
||||||
for k := range PrecompiledContractsBerlin {
|
for k := range PrecompiledContractsBerlin {
|
||||||
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
|
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
|
||||||
}
|
}
|
||||||
|
for k := range PrecompiledContractsMina {
|
||||||
|
PrecompiledAddressesMina = append(PrecompiledAddressesMina, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
||||||
func ActivePrecompiles(rules params.Rules) []common.Address {
|
func ActivePrecompiles(rules params.Rules) []common.Address {
|
||||||
|
result := PrecompiledAddressesMina
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case rules.IsBerlin:
|
case rules.IsBerlin:
|
||||||
return PrecompiledAddressesBerlin
|
return append(result, PrecompiledAddressesBerlin...)
|
||||||
case rules.IsIstanbul:
|
case rules.IsIstanbul:
|
||||||
return PrecompiledAddressesIstanbul
|
return append(result, PrecompiledAddressesIstanbul...)
|
||||||
case rules.IsByzantium:
|
case rules.IsByzantium:
|
||||||
return PrecompiledAddressesByzantium
|
return append(result, PrecompiledAddressesByzantium...)
|
||||||
default:
|
default:
|
||||||
return PrecompiledAddressesHomestead
|
return append(result, PrecompiledAddressesHomestead...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||||
|
if p, ok := PrecompiledContractsMina[addr]; ok {
|
||||||
|
return p, ok
|
||||||
|
}
|
||||||
|
|
||||||
var precompiles map[common.Address]PrecompiledContract
|
var precompiles map[common.Address]PrecompiledContract
|
||||||
switch {
|
switch {
|
||||||
case evm.chainRules.IsBerlin:
|
case evm.chainRules.IsBerlin:
|
||||||
|
|
@ -53,6 +57,7 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||||
default:
|
default:
|
||||||
precompiles = PrecompiledContractsHomestead
|
precompiles = PrecompiledContractsHomestead
|
||||||
}
|
}
|
||||||
|
|
||||||
p, ok := precompiles[addr]
|
p, ok := precompiles[addr]
|
||||||
return p, ok
|
return p, ok
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
core/vm/mina_contracts.go
Normal file
54
core/vm/mina_contracts.go
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
package vm
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: mina/target/release/libmina.a -ldl
|
||||||
|
#include "../../mina/target/mina.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MinaPoseidon struct{}
|
||||||
|
|
||||||
|
func (c *MinaPoseidon) RequiredGas(input []byte) uint64 {
|
||||||
|
return 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0x1f831f84
|
||||||
|
var minaPoseidonSignature = crypto.Keccak256([]byte("poseidonHash(uint8,bytes32[])"))[:4]
|
||||||
|
|
||||||
|
const networkIdIndex = 0
|
||||||
|
const fieldsHeadIndex = networkIdIndex + 32
|
||||||
|
|
||||||
|
func (c *MinaPoseidon) Run(input []byte) ([]byte, error) {
|
||||||
|
if !bytes.Equal(input[:4], minaPoseidonSignature) {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
calldata := input[4:]
|
||||||
|
|
||||||
|
networkId := new(big.Int).SetBytes(getData(calldata, networkIdIndex, 32)).Uint64()
|
||||||
|
|
||||||
|
lenIndex := new(big.Int).SetBytes(getData(calldata, fieldsHeadIndex, 32)).Uint64()
|
||||||
|
fieldsLen := new(big.Int).SetBytes(getData(calldata, lenIndex, 32)).Uint64()
|
||||||
|
|
||||||
|
dataIndex := lenIndex + 32
|
||||||
|
fields := calldata[dataIndex : dataIndex+fieldsLen*32]
|
||||||
|
|
||||||
|
output_buffer := [32]byte{}
|
||||||
|
|
||||||
|
if !C.poseidon_hash(
|
||||||
|
uint32(networkId),
|
||||||
|
(*C.uint8_t)(&fields[0]),
|
||||||
|
C.uintptr_t(fieldsLen),
|
||||||
|
(*C.uint8_t)(&output_buffer[0]),
|
||||||
|
) {
|
||||||
|
return nil, ErrExecutionReverted
|
||||||
|
}
|
||||||
|
|
||||||
|
return output_buffer[:], nil
|
||||||
|
}
|
||||||
1
mina/.gitignore
vendored
Normal file
1
mina/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/target
|
||||||
Loading…
Reference in a new issue