Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions core/vm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,91 @@ func TestPrecompileBlsInputSize(t *testing.T) {

func TestPrecompiledEcrecover(t *testing.T) { testJson("ecRecover", "01", t) }

func TestPrecompileJovianInputSizeLimits(t *testing.T) {
const (
maxTxGas = 16_000_000 // Target limit (actual params.MaxTxGas is 16,777,216)
txBaseGas = 21_000 // params.TxGas
preimageOracleGas = 100_000 // PreimageOracle.PRECOMPILE_CALL_RESERVED_GAS
calldataOverhead = 164 // Function selector + ABI params
calldataGasPerByte = 16 // params.TxDataNonZeroGasEIP2028
)

tests := []struct {
name string
precompileAddr string
maxInputSize uint64
inputElementSize int
expectedError string
}{
{
name: "bn256Pairing",
precompileAddr: "2f08",
maxInputSize: params.Bn256PairingMaxInputSizeJovian,
inputElementSize: 192,
expectedError: "bad elliptic curve pairing input size",
},
{
name: "BLS G1 MSM",
precompileAddr: "2f0b",
maxInputSize: params.Bls12381G1MulMaxInputSizeJovian,
inputElementSize: 160,
expectedError: "g1 msm input size exceeds maximum",
},
{
name: "BLS G2 MSM",
precompileAddr: "2f0d",
maxInputSize: params.Bls12381G2MulMaxInputSizeJovian,
inputElementSize: 288,
expectedError: "g2 msm input size exceeds maximum",
},
{
name: "BLS Pairing",
precompileAddr: "2f0e",
maxInputSize: params.Bls12381PairingMaxInputSizeJovian,
inputElementSize: 384,
expectedError: "pairing input size exceeds maximum",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
addr := common.HexToAddress(tt.precompileAddr)
precompile, ok := allPrecompiles[addr]
if !ok {
t.Fatalf("precompile %s not found in allPrecompiles", tt.precompileAddr)
}

t.Run("GasAtLimit", func(t *testing.T) {
inputSize := (int(tt.maxInputSize) / tt.inputElementSize) * tt.inputElementSize
input := make([]byte, inputSize)

precompileGas := precompile.RequiredGas(input)

calldataGas := uint64(calldataOverhead+inputSize) * calldataGasPerByte

totalGas := txBaseGas + preimageOracleGas + calldataGas + precompileGas

if totalGas >= maxTxGas {
t.Errorf("%s at Jovian limit (%d bytes) exceeds 16M gas: %d gas (over by %d)",
tt.name, inputSize, totalGas, totalGas-maxTxGas)
}

margin := maxTxGas - totalGas
t.Logf("✓ %s: %d bytes → %d gas (margin: %d gas)", tt.name, inputSize, totalGas, margin)
})

t.Run("AboveLimit", func(t *testing.T) {
big := make([]byte, tt.maxInputSize+1)
testPrecompiledFailure(tt.precompileAddr, precompiledFailureTest{
Input: common.Bytes2Hex(big),
ExpectedError: tt.expectedError,
Name: tt.name + "_jovian_input_too_big",
}, t)
})
})
}
}

func testJson(name, addr string, t *testing.T) {
tests, err := loadJson(name)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ const (
Bls12381G2MulMaxInputSizeIsthmus uint64 = 488448 // Maximum input size for BLS12-381 G2 multiple-scalar-multiply operation
Bls12381PairingMaxInputSizeIsthmus uint64 = 235008 // Maximum input size for BLS12-381 pairing check

// Jovian precompile limits ensure accelerated precompiles for fault proofs stay under the 16M gas
// transaction limit introduced in Fusaka (EIP-7825). Since accelerated precompiles execute on L1
// via PreimageOracle.loadPrecompilePreimagePart, the entire L1 transaction must stay under 16M gas:
// Total Gas = TxBaseGas (21K) + PreimageOracleGas (100K) + CalldataGas + PrecompileGas < 16M
Bn256PairingMaxInputSizeJovian uint64 = 81984 // bn256Pairing limit (427 pairs)
Bls12381G1MulMaxInputSizeJovian uint64 = 288960 // BLS12-381 G1 MSM limit (1,806 pairs)
Bls12381G2MulMaxInputSizeJovian uint64 = 278784 // BLS12-381 G2 MSM limit (968 pairs)
Expand Down