From b1020ccd07a7030c0d7785aae5fdd05bb8ab79eb Mon Sep 17 00:00:00 2001 From: Mikhail Wall Date: Tue, 24 Dec 2024 20:26:27 +0500 Subject: [PATCH] feat: added bls --- core/vm/contracts.go | 39 ++++++++++++++++++++++++++++++++++----- go.mod | 5 +++-- go.sum | 2 ++ params/protocol_params.go | 2 ++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index f54d5ab86e..395758a692 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -25,6 +25,7 @@ import ( "math" "math/big" + "github.com/cloudflare/circl/sign/bls" "github.com/consensys/gnark-crypto/ecc" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" @@ -98,6 +99,9 @@ var PrecompiledContractsBerlin = PrecompiledContracts{ common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{0x9}): &blake2F{}, + + // primev pre-compiles start at 0xf addresses + common.BytesToAddress([]byte{0xf0}): &bls12381SignatureVerification{}, } // PrecompiledContractsCancun contains the default set of pre-compiled Ethereum @@ -225,12 +229,9 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uin if suppliedGas < gasCost { return nil, 0, ErrOutOfGas } - if logger != nil && logger.OnGasChange != nil { - logger.OnGasChange(suppliedGas, suppliedGas-gasCost, tracing.GasChangeCallPrecompiledContract) - } - suppliedGas -= gasCost + gasLeft := suppliedGas - gasCost output, err := p.Run(input) - return output, suppliedGas, err + return output, gasLeft, err } // ecrecover implemented as a native contract. @@ -714,6 +715,34 @@ var ( errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup") ) +// bls12381SignatureVerification implements BLS signature verification precompile. +type bls12381SignatureVerification struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381SignatureVerification) RequiredGas(input []byte) uint64 { + return params.BlsSignVerifyGas +} + +func (c *bls12381SignatureVerification) Run(input []byte) ([]byte, error) { + // Input format: + // - pubkey (48 bytes) - G1 point + // - message (32 bytes) - Hash of the message + // - signature (96 bytes) - G2 point + if len(input) != 176 { + return nil, errBLS12381InvalidInputLength + } + + var pubKey bls.PublicKey[bls.G1] + if err := pubKey.UnmarshalBinary(input[:48]); err != nil { + return nil, err + } + + if !bls.Verify(&pubKey, input[48:80], input[80:]) { + return nil, nil + } + return input[:48], nil +} + // bls12381G1Add implements EIP-2537 G1Add precompile. type bls12381G1Add struct{} diff --git a/go.mod b/go.mod index 35018fbe08..869f3faa34 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/ethereum/go-ethereum -go 1.22 +go 1.22.0 -toolchain go1.22.0 +toolchain go1.23.0 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 @@ -93,6 +93,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.17.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cloudflare/circl v1.5.0 github.com/cockroachdb/errors v1.11.3 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect diff --git a/go.sum b/go.sum index ded07f4867..5317574e3b 100644 --- a/go.sum +++ b/go.sum @@ -107,6 +107,8 @@ github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86c github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= +github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudflare/cloudflare-go v0.79.0 h1:ErwCYDjFCYppDJlDJ/5WhsSmzegAUe2+K9qgFyQDg3M= github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= diff --git a/params/protocol_params.go b/params/protocol_params.go index b46e8d66b2..66f4e8bf7e 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -161,6 +161,8 @@ const ( Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation Bls12381MapG2Gas uint64 = 75000 // Gas price for BLS12-381 mapping field element to G2 operation + BlsSignVerifyGas uint64 = 150000 // Gas price for BLS12-381 signature verification + // 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