Skip to content

Commit

Permalink
op-program: Add missing unit tests for precompiles.
Browse files Browse the repository at this point in the history
  • Loading branch information
ajsutton committed Oct 9, 2024
1 parent fb62380 commit dfde961
Show file tree
Hide file tree
Showing 2 changed files with 329 additions and 25 deletions.
54 changes: 29 additions & 25 deletions op-program/client/l2/engineapi/precompiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileO
case ecrecoverPrecompileAddress:
return &ecrecoverOracle{Orig: orig, Oracle: precompileOracle}
case bn256PairingPrecompileAddress:
return &bn256PairingOracle{Orig: orig, Oracle: precompileOracle}
precompile := bn256PairingOracle{Orig: orig, Oracle: precompileOracle}
if rules.IsOptimismGranite {
return &bn256PairingOracleGranite{precompile}
}
return &precompile
case kzgPointEvaluationPrecompileAddress:
return &kzgPointEvaluationOracle{Orig: orig, Oracle: precompileOracle}
default:
Expand All @@ -68,6 +72,10 @@ func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileO
}
}

var (
errInvalidEcrecoverInput = errors.New("invalid ecrecover input")
)

type ecrecoverOracle struct {
Orig vm.PrecompiledContract
Oracle PrecompileOracle
Expand All @@ -86,8 +94,6 @@ func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) {

input = common.RightPadBytes(input, ecRecoverInputLength)
// "input" is (hash, v, r, s), each 32 bytes
// but for ecrecover we want (r, s, v)

r := new(big.Int).SetBytes(input[64:96])
s := new(big.Int).SetBytes(input[96:128])
v := input[63] - 27
Expand All @@ -96,17 +102,11 @@ func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) {
if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
return nil, nil
}
// We must make sure not to modify the 'input', so placing the 'v' along with
// the signature needs to be done on a new allocation
sig := make([]byte, 65)
copy(sig, input[64:128])
sig[64] = v
// v needs to be at the end for libsecp256k1

// Modification note: below replaces the crypto.Ecrecover call
result, ok := c.Oracle.Precompile(ecrecoverPrecompileAddress, input, c.RequiredGas(input))
if !ok {
return nil, errors.New("invalid ecrecover input")
return nil, errInvalidEcrecoverInput
}
return result, nil
}
Expand Down Expand Up @@ -138,6 +138,11 @@ var (

// errBadPairingInput is returned if the bn256 pairing input is invalid.
errBadPairingInput = errors.New("bad elliptic curve pairing size")

// errBadPairingInputSize is returned if the bn256 pairing input size is invalid.
errBadPairingInputSize = errors.New("bad elliptic curve pairing input size")

errInvalidBn256PairingCheck = errors.New("invalid bn256Pairing check")
)

func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) {
Expand All @@ -149,14 +154,25 @@ func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) {
// Assumes both L2 and the L1 oracle have an identical range of valid points
result, ok := b.Oracle.Precompile(bn256PairingPrecompileAddress, input, b.RequiredGas(input))
if !ok {
return nil, errors.New("invalid bn256Pairing check")
return nil, errInvalidBn256PairingCheck
}
if !bytes.Equal(result, true32Byte) && !bytes.Equal(result, false32Byte) {
panic("unexpected result from bn256Pairing check")
}
return result, nil
}

type bn256PairingOracleGranite struct {
bn256PairingOracle
}

func (b *bn256PairingOracleGranite) Run(input []byte) ([]byte, error) {
if len(input) > int(params.Bn256PairingMaxInputSizeGranite) {
return nil, errBadPairingInputSize
}
return b.bn256PairingOracle.Run(input)
}

// kzgPointEvaluationOracle implements the EIP-4844 point evaluation precompile,
// using the preimage-oracle to perform the evaluation.
type kzgPointEvaluationOracle struct {
Expand Down Expand Up @@ -189,30 +205,18 @@ func (b *kzgPointEvaluationOracle) Run(input []byte) ([]byte, error) {
if len(input) != blobVerifyInputLength {
return nil, errBlobVerifyInvalidInputLength
}
// Input is 32 byte versioned hash, 32 byte point, 32 byte claim, 48 byte commitment, 48 byte proof
// versioned hash: first 32 bytes
var versionedHash common.Hash
copy(versionedHash[:], input[:])

var (
point kzg4844.Point
claim kzg4844.Claim
)
// Evaluation point: next 32 bytes
copy(point[:], input[32:])
// Expected output: next 32 bytes
copy(claim[:], input[64:])

// input kzg point: next 48 bytes
// input kzg point
var commitment kzg4844.Commitment
copy(commitment[:], input[96:])
if eth.KZGToVersionedHash(commitment) != versionedHash {
return nil, errBlobVerifyMismatchedVersion
}

// Proof: next 48 bytes
var proof kzg4844.Proof
copy(proof[:], input[144:])

// Modification note: below replaces the kzg4844.VerifyProof call
result, ok := b.Oracle.Precompile(kzgPointEvaluationPrecompileAddress, input, b.RequiredGas(input))
if !ok {
Expand Down
Loading

0 comments on commit dfde961

Please sign in to comment.