Skip to content

Commit

Permalink
feat: implement RIP-7212/EIP-7212 (#798)
Browse files Browse the repository at this point in the history
Implement RIP-7212/EIP-7212 according to reference implementation at ulerdogan#1

Co-authored-by: Péter Garamvölgyi <[email protected]>
  • Loading branch information
jonastheis and Thegaram authored Jun 6, 2024
1 parent d086022 commit c2d7bd8
Show file tree
Hide file tree
Showing 6 changed files with 5,571 additions and 0 deletions.
41 changes: 41 additions & 0 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/scroll-tech/go-ethereum/crypto/blake2b"
"github.com/scroll-tech/go-ethereum/crypto/bls12381"
"github.com/scroll-tech/go-ethereum/crypto/bn256"
"github.com/scroll-tech/go-ethereum/crypto/secp256r1"
"github.com/scroll-tech/go-ethereum/params"

//lint:ignore SA1019 Needed for precompile
Expand Down Expand Up @@ -139,6 +140,12 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
}

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

var (
PrecompiledAddressesBernoulli []common.Address
PrecompiledAddressesArchimedes []common.Address
Expand Down Expand Up @@ -1130,3 +1137,37 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
// Encode the G2 point to 256 bytes
return g.EncodePoint(r), nil
}

// 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([]byte{1}, 32), nil
} else {
// Signature is invalid
return nil, nil
}
}
16 changes: 16 additions & 0 deletions core/vm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{0x01, 0x00}): &p256Verify{},
}

// EIP-152 test vectors
Expand Down Expand Up @@ -397,3 +399,17 @@ 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)
}
Loading

0 comments on commit c2d7bd8

Please sign in to comment.