Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RIP-7212: Precompile for secp256r1 Curve Support, Reference Implementation #1

Draft
wants to merge 23 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
fb89b61
crypto/secp2561r1: add secp256r1 curve verifiers
ulerdogan May 8, 2023
a8c0a2e
core/vm: implement secp256r1 verifier precompiled
ulerdogan May 8, 2023
c0554c0
params: add new precompiled gas price
ulerdogan May 8, 2023
6c7028a
core/vm, params: rename precompiled to p256verify
ulerdogan May 16, 2023
d245194
core/vm: simplify the return values format
ulerdogan May 22, 2023
066a31f
crypto/secp25r1: fix reverse malleability issue
ulerdogan May 22, 2023
ec17e78
core/vm: fix testdata non-malleable for p256Verify
ulerdogan May 22, 2023
6bf9e70
all: merge branch master into ulerdogan-secp256r1
ulerdogan Jun 15, 2023
f5b6d7e
core/vm: update the eip number
ulerdogan Jun 22, 2023
2820903
core, crypto/secp256r1: fix error reverts tx error
ulerdogan Jun 22, 2023
1be1875
crypto/secp256r1: refactor by simplfying return
ulerdogan Aug 10, 2023
21f4932
core/vm: force the input length of p256verify
ulerdogan Sep 24, 2023
98f10b0
crypto/secp256r1: reject the reference pubKey coordinates
ulerdogan Sep 24, 2023
7e0bc92
Merge branch 'master' into ulerdogan-secp256r1
ulerdogan Sep 24, 2023
cec0b05
crypto/secp256r1: remove malleability check due to spec
ulerdogan Oct 7, 2023
99c44ae
core/vm: change the implementation address to 0x0b
ulerdogan Nov 30, 2023
b5ad1a7
Merge branch 'ethereum:master' into ulerdogan-secp256r1
ulerdogan Nov 30, 2023
b5a6bb0
core/vm: change the implementation address to 0x100
ulerdogan Dec 21, 2023
827716f
Merge branch 'ethereum:master' into ulerdogan-secp256r1
ulerdogan Jan 16, 2024
520d4f7
Add wycheproof test vector
yukaitu-cb Feb 8, 2024
384dbd6
Merge branch 'ulerdogan-secp256r1-test' into ulerdogan-secp256r1
ulerdogan Feb 8, 2024
9b0bc8a
Add missing test cases
danyalprout Apr 22, 2024
75062a6
remove redundant x/y check
danyalprout Apr 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 41 additions & 0 deletions core/vm/contracts.go
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/crypto/bls12381"
"github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/crypto/secp256r1"
"github.com/ethereum/go-ethereum/params"
"golang.org/x/crypto/ripemd160"
)
Expand Down Expand Up @@ -107,6 +108,12 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
}

// PrecompiledContractsP256Verify contains the precompiled Ethereum
// contract specified in EIP-7212. This is exported for testing purposes.
var PrecompiledContractsP256Verify = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}

// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
// contracts specified in EIP-2537. These are exported for testing purposes.
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
Expand Down Expand Up @@ -1135,3 +1142,37 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash {

return h
}

// P256VERIFY (secp256r1 signature verification)
// implemented as a native contract
type p256Verify struct{}

// RequiredGas returns the gas required to execute the precompiled contract
func (c *p256Verify) RequiredGas(input []byte) uint64 {
return params.P256VerifyGas
}

// Run executes the precompiled contract with given 160 bytes of param, returning the output and the used gas
func (c *p256Verify) Run(input []byte) ([]byte, error) {
// Required input length is 160 bytes
const p256VerifyInputLength = 160
// Check the input length
if len(input) != p256VerifyInputLength {
// Input length is invalid
return nil, nil
}

// Extract the hash, r, s, x, y from the input
hash := input[0:32]
r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96])
x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160])

// Verify the secp256r1 signature
if secp256r1.Verify(hash, r, s, x, y) {
// Signature is valid
return common.LeftPadBytes(common.Big1.Bytes(), 32), nil
} else {
// Signature is invalid
return nil, nil
}
}
14 changes: 14 additions & 0 deletions core/vm/contracts_test.go
Expand Up @@ -58,6 +58,8 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{9}): &blake2F{},
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},

common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},

common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{},
common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1Mul{},
common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G1MultiExp{},
Expand Down Expand Up @@ -395,3 +397,15 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
}
benchmarkPrecompiled("0f", testcase, b)
}

// Benchmarks the sample inputs from the P256VERIFY precompile.
func BenchmarkPrecompiledP256Verify(bench *testing.B) {
t := precompiledTest{
Input: "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e",
Expected: "0000000000000000000000000000000000000000000000000000000000000001",
Name: "p256Verify",
}
benchmarkPrecompiled("100", t, bench)
}

func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "100", t) }