Commit 92fc0d8f authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-program: Add missing unit tests for precompiles. (#12381)

parent 4dfd6ae5
...@@ -59,7 +59,11 @@ func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileO ...@@ -59,7 +59,11 @@ func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileO
case ecrecoverPrecompileAddress: case ecrecoverPrecompileAddress:
return &ecrecoverOracle{Orig: orig, Oracle: precompileOracle} return &ecrecoverOracle{Orig: orig, Oracle: precompileOracle}
case bn256PairingPrecompileAddress: case bn256PairingPrecompileAddress:
return &bn256PairingOracle{Orig: orig, Oracle: precompileOracle} precompile := bn256PairingOracle{Orig: orig, Oracle: precompileOracle}
if rules.IsOptimismGranite {
return &bn256PairingOracleGranite{precompile}
}
return &precompile
case kzgPointEvaluationPrecompileAddress: case kzgPointEvaluationPrecompileAddress:
return &kzgPointEvaluationOracle{Orig: orig, Oracle: precompileOracle} return &kzgPointEvaluationOracle{Orig: orig, Oracle: precompileOracle}
default: default:
...@@ -68,6 +72,10 @@ func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileO ...@@ -68,6 +72,10 @@ func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileO
} }
} }
var (
errInvalidEcrecoverInput = errors.New("invalid ecrecover input")
)
type ecrecoverOracle struct { type ecrecoverOracle struct {
Orig vm.PrecompiledContract Orig vm.PrecompiledContract
Oracle PrecompileOracle Oracle PrecompileOracle
...@@ -86,8 +94,6 @@ func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) { ...@@ -86,8 +94,6 @@ func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) {
input = common.RightPadBytes(input, ecRecoverInputLength) input = common.RightPadBytes(input, ecRecoverInputLength)
// "input" is (hash, v, r, s), each 32 bytes // "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]) r := new(big.Int).SetBytes(input[64:96])
s := new(big.Int).SetBytes(input[96:128]) s := new(big.Int).SetBytes(input[96:128])
v := input[63] - 27 v := input[63] - 27
...@@ -96,17 +102,11 @@ func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) { ...@@ -96,17 +102,11 @@ func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) {
if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) { if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
return nil, nil 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 // Modification note: below replaces the crypto.Ecrecover call
result, ok := c.Oracle.Precompile(ecrecoverPrecompileAddress, input, c.RequiredGas(input)) result, ok := c.Oracle.Precompile(ecrecoverPrecompileAddress, input, c.RequiredGas(input))
if !ok { if !ok {
return nil, errors.New("invalid ecrecover input") return nil, errInvalidEcrecoverInput
} }
return result, nil return result, nil
} }
...@@ -138,6 +138,11 @@ var ( ...@@ -138,6 +138,11 @@ var (
// errBadPairingInput is returned if the bn256 pairing input is invalid. // errBadPairingInput is returned if the bn256 pairing input is invalid.
errBadPairingInput = errors.New("bad elliptic curve pairing size") 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) { func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) {
...@@ -149,7 +154,7 @@ func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) { ...@@ -149,7 +154,7 @@ func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) {
// Assumes both L2 and the L1 oracle have an identical range of valid points // Assumes both L2 and the L1 oracle have an identical range of valid points
result, ok := b.Oracle.Precompile(bn256PairingPrecompileAddress, input, b.RequiredGas(input)) result, ok := b.Oracle.Precompile(bn256PairingPrecompileAddress, input, b.RequiredGas(input))
if !ok { if !ok {
return nil, errors.New("invalid bn256Pairing check") return nil, errInvalidBn256PairingCheck
} }
if !bytes.Equal(result, true32Byte) && !bytes.Equal(result, false32Byte) { if !bytes.Equal(result, true32Byte) && !bytes.Equal(result, false32Byte) {
panic("unexpected result from bn256Pairing check") panic("unexpected result from bn256Pairing check")
...@@ -157,6 +162,17 @@ func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) { ...@@ -157,6 +162,17 @@ func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) {
return result, nil 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, // kzgPointEvaluationOracle implements the EIP-4844 point evaluation precompile,
// using the preimage-oracle to perform the evaluation. // using the preimage-oracle to perform the evaluation.
type kzgPointEvaluationOracle struct { type kzgPointEvaluationOracle struct {
...@@ -189,30 +205,18 @@ func (b *kzgPointEvaluationOracle) Run(input []byte) ([]byte, error) { ...@@ -189,30 +205,18 @@ func (b *kzgPointEvaluationOracle) Run(input []byte) ([]byte, error) {
if len(input) != blobVerifyInputLength { if len(input) != blobVerifyInputLength {
return nil, errBlobVerifyInvalidInputLength 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 // versioned hash: first 32 bytes
var versionedHash common.Hash var versionedHash common.Hash
copy(versionedHash[:], input[:]) copy(versionedHash[:], input[:])
var ( // input kzg point
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
var commitment kzg4844.Commitment var commitment kzg4844.Commitment
copy(commitment[:], input[96:]) copy(commitment[:], input[96:])
if eth.KZGToVersionedHash(commitment) != versionedHash { if eth.KZGToVersionedHash(commitment) != versionedHash {
return nil, errBlobVerifyMismatchedVersion return nil, errBlobVerifyMismatchedVersion
} }
// Proof: next 48 bytes
var proof kzg4844.Proof
copy(proof[:], input[144:])
// Modification note: below replaces the kzg4844.VerifyProof call // Modification note: below replaces the kzg4844.VerifyProof call
result, ok := b.Oracle.Precompile(kzgPointEvaluationPrecompileAddress, input, b.RequiredGas(input)) result, ok := b.Oracle.Precompile(kzgPointEvaluationPrecompileAddress, input, b.RequiredGas(input))
if !ok { if !ok {
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment