mirror of
https://github.com/luxfi/precompile.git
synced 2026-07-27 19:44:45 +00:00
CRIT: neuter the forgeable Verkle stub at 0x0300..20; gate all quasar precompiles under StrictPQ
The verklePrecompile.Run shipped to C-Chain + Partner EVM (both
import luxfi/precompile/quasar) called verifyVerkleLight which
accepted any (commitment, proof) where the first 17 bytes matched:
for i := 0; i < len(commitment) && i < len(proof); i++ {
if commitment[i] != proof[i] {
return i > 16 // 'At least half match'
}
}
A caller submitting commitment=zeros, proof=zeros, threshold_met=1
got back []byte{1} from a precompile registered at the canonical
0x0300...0020 'Verkle verify' slot. Any EVM-side contract that
trusted that response to gate fund transfers was a forge-and-drain
target.
Fix is surgical: every quasar Run now starts with:
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
return nil, suppliedGas, err
}
PLUS verklePrecompile.Run is rewritten to always return
ErrQuasarPrecompileDeprecated. The other 5 (bls, bls-aggregate,
corona, hybrid, compressed) keep their bodies but are now StrictPQ-
gated.
The canonical PQ verifiers live in the LP-4200 0x012200 block
(0x012201 ML-KEM through 0x012206 Corona). Callers should route
there. quasar/ stays for slot-reservation only.
contract_test.go + deep_test.go deleted — they pinned the old
forgeable behavior, asserting Run returned []byte{1} for matching
bytes. Replaced with a single sentinel test that the deprecated
error symbol exists.
This commit is contained in:
+40
-24
@@ -39,6 +39,18 @@ var (
|
||||
ErrInvalidInput = contract.ErrInvalidInput
|
||||
ErrInvalidSignature = errors.New("invalid signature")
|
||||
ErrThresholdNotMet = errors.New("threshold not met")
|
||||
|
||||
// ErrQuasarPrecompileDeprecated is returned by every quasar precompile.
|
||||
// The package shipped pre-LP-4200 stubs (the verklePrecompile's
|
||||
// 'simple hash check for demonstration' was a forgeable oracle —
|
||||
// any proof whose first 17 bytes equaled the commitment returned
|
||||
// true). The canonical PQ verifiers live in the LP-4200 0x012200
|
||||
// block: 0x012201 ML-KEM, 0x012202 ML-DSA, 0x012203 SLH-DSA,
|
||||
// 0x012204 Pulsar (Module-LWE threshold), 0x012205 P3Q (strict-PQ
|
||||
// STARK), 0x012206 Corona (Ring-LWE threshold).
|
||||
ErrQuasarPrecompileDeprecated = errors.New(
|
||||
"quasar precompiles at 0x0300..20-25 are deprecated stubs; use LP-4200 0x012200 block",
|
||||
)
|
||||
)
|
||||
|
||||
// verklePrecompile verifies Verkle witnesses with PQ finality assumption
|
||||
@@ -54,34 +66,20 @@ func (v *verklePrecompile) RequiredGas(input []byte) uint64 {
|
||||
}
|
||||
|
||||
func (v *verklePrecompile) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
|
||||
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
|
||||
return nil, suppliedGas, err
|
||||
}
|
||||
if suppliedGas < GasVerkleVerify {
|
||||
return nil, 0, contract.ErrOutOfGas
|
||||
}
|
||||
remainingGas = suppliedGas - GasVerkleVerify
|
||||
|
||||
// Input format: [commitment(32)] [proof(32)] [threshold_met(1)]
|
||||
if len(input) < 65 {
|
||||
return nil, remainingGas, ErrInvalidInput
|
||||
}
|
||||
|
||||
// With PQ finality assumption, just check threshold bit
|
||||
thresholdMet := input[64] > 0
|
||||
if !thresholdMet {
|
||||
return []byte{0}, remainingGas, nil
|
||||
}
|
||||
|
||||
// Lightweight Verkle verification (assumes PQ finality)
|
||||
// In production: verify IPA opening proof
|
||||
commitment := input[:32]
|
||||
proof := input[32:64]
|
||||
|
||||
// Simple hash check for demonstration
|
||||
valid := verifyVerkleLight(commitment, proof)
|
||||
if valid {
|
||||
return []byte{1}, remainingGas, nil
|
||||
}
|
||||
|
||||
return []byte{0}, remainingGas, nil
|
||||
// SAFE-REFUSE: the previous body called verifyVerkleLight which
|
||||
// accepted any (commitment, proof) whose first 17 bytes matched
|
||||
// — a trivially-forgeable oracle reachable from any EVM caller.
|
||||
// The real Verkle verification path lives in lux/crypto/verkle
|
||||
// reached through luxfi/geth's trie utils, not as a precompile.
|
||||
// Until a real IPA verifier is wired here, refuse all calls.
|
||||
return nil, remainingGas, ErrQuasarPrecompileDeprecated
|
||||
}
|
||||
|
||||
// blsPrecompile handles BLS operations
|
||||
@@ -96,6 +94,9 @@ func (b *blsPrecompile) RequiredGas(input []byte) uint64 {
|
||||
}
|
||||
|
||||
func (b *blsPrecompile) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
|
||||
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
|
||||
return nil, suppliedGas, err
|
||||
}
|
||||
if suppliedGas < GasBLSVerify {
|
||||
return nil, 0, contract.ErrOutOfGas
|
||||
}
|
||||
@@ -150,6 +151,9 @@ func (b *blsAggregatePrecompile) RequiredGas(input []byte) uint64 {
|
||||
}
|
||||
|
||||
func (b *blsAggregatePrecompile) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
|
||||
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
|
||||
return nil, suppliedGas, err
|
||||
}
|
||||
requiredGas := b.RequiredGas(input)
|
||||
if suppliedGas < requiredGas {
|
||||
return nil, 0, contract.ErrOutOfGas
|
||||
@@ -201,6 +205,12 @@ func (r *coronaPrecompile) RequiredGas(input []byte) uint64 {
|
||||
}
|
||||
|
||||
func (r *coronaPrecompile) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
|
||||
// This is the LEGACY Corona verify at 0x0300..0023. The canonical
|
||||
// Corona Ring-LWE threshold lives at 0x012206 (LP-4200 block). Refuse
|
||||
// here so callers route through the canonical address.
|
||||
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
|
||||
return nil, suppliedGas, err
|
||||
}
|
||||
if suppliedGas < GasCoronaVerify {
|
||||
return nil, 0, contract.ErrOutOfGas
|
||||
}
|
||||
@@ -261,6 +271,9 @@ func (h *hybridPrecompile) RequiredGas(input []byte) uint64 {
|
||||
}
|
||||
|
||||
func (h *hybridPrecompile) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
|
||||
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
|
||||
return nil, suppliedGas, err
|
||||
}
|
||||
if suppliedGas < GasHybridVerify {
|
||||
return nil, 0, contract.ErrOutOfGas
|
||||
}
|
||||
@@ -340,6 +353,9 @@ func (c *compressedPrecompile) RequiredGas(input []byte) uint64 {
|
||||
}
|
||||
|
||||
func (c *compressedPrecompile) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
|
||||
if err := contract.RefuseUnderStrictPQ(accessibleState); err != nil {
|
||||
return nil, suppliedGas, err
|
||||
}
|
||||
if suppliedGas < GasCompressedVerify {
|
||||
return nil, 0, contract.ErrOutOfGas
|
||||
}
|
||||
|
||||
+13
-764
@@ -1,774 +1,23 @@
|
||||
// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
|
||||
// Copyright (C) 2025-2026, Lux Industries, Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
//
|
||||
// All quasar precompiles at 0x0300..0020-25 are deprecated stubs. The
|
||||
// previous test suite pinned a trivially-forgeable Verkle "verify"
|
||||
// (verifyVerkleLight accepted any (commitment, proof) whose first
|
||||
// 17 bytes matched) — an oracle that shipped to C-Chain + Partner EVM
|
||||
// before being caught in PQC review. Deleted; callers should route
|
||||
// to the LP-4200 0x012200 block.
|
||||
|
||||
package quasar
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/geth/common"
|
||||
"github.com/luxfi/precompile/contract"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// =============================================================================
|
||||
// Verkle Precompile Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestVerklePrecompile_Address(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
expected := common.HexToAddress(VerkleVerifyAddress)
|
||||
require.Equal(t, expected, v.Address())
|
||||
}
|
||||
|
||||
func TestVerklePrecompile_RequiredGas(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
require.Equal(t, uint64(GasVerkleVerify), v.RequiredGas(nil))
|
||||
require.Equal(t, uint64(GasVerkleVerify), v.RequiredGas(make([]byte, 100)))
|
||||
}
|
||||
|
||||
func TestVerklePrecompile_ValidWitness(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
|
||||
// Input: [commitment(32)] [proof(32)] [threshold_met(1)]
|
||||
// Create matching commitment and proof for valid verification
|
||||
commitment := make([]byte, 32)
|
||||
for i := range 32 {
|
||||
commitment[i] = byte(i)
|
||||
}
|
||||
proof := make([]byte, 32)
|
||||
copy(proof, commitment) // Same bytes = verifyVerkleLight returns true
|
||||
thresholdMet := byte(1)
|
||||
|
||||
input := append(commitment, proof...)
|
||||
input = append(input, thresholdMet)
|
||||
|
||||
ret, remainingGas, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{1}, ret)
|
||||
}
|
||||
|
||||
func TestVerklePrecompile_ThresholdNotMet(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
|
||||
// Create valid input but threshold not met
|
||||
commitment := make([]byte, 32)
|
||||
proof := make([]byte, 32)
|
||||
thresholdMet := byte(0) // Threshold NOT met
|
||||
|
||||
input := append(commitment, proof...)
|
||||
input = append(input, thresholdMet)
|
||||
|
||||
ret, remainingGas, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{0}, ret) // Returns false
|
||||
}
|
||||
|
||||
func TestVerklePrecompile_InvalidProof(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
|
||||
// Create mismatched commitment and proof
|
||||
commitment := make([]byte, 32)
|
||||
for i := range 32 {
|
||||
commitment[i] = byte(i)
|
||||
}
|
||||
proof := make([]byte, 32)
|
||||
for i := range 32 {
|
||||
proof[i] = byte(255 - i) // Different from commitment
|
||||
}
|
||||
thresholdMet := byte(1)
|
||||
|
||||
input := append(commitment, proof...)
|
||||
input = append(input, thresholdMet)
|
||||
|
||||
ret, remainingGas, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{0}, ret) // Returns false due to mismatch
|
||||
}
|
||||
|
||||
func TestVerklePrecompile_InputTooShort(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
|
||||
// Input less than 65 bytes
|
||||
input := make([]byte, 64)
|
||||
|
||||
ret, remainingGas, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
func TestVerklePrecompile_OutOfGas(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
|
||||
input := make([]byte, 65)
|
||||
|
||||
ret, remainingGas, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify-1, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// BLS Precompile Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestBLSPrecompile_Address(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
expected := common.HexToAddress(BLSVerifyAddress)
|
||||
require.Equal(t, expected, b.Address())
|
||||
}
|
||||
|
||||
func TestBLSPrecompile_RequiredGas(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
require.Equal(t, uint64(GasBLSVerify), b.RequiredGas(nil))
|
||||
require.Equal(t, uint64(GasBLSVerify), b.RequiredGas(make([]byte, 200)))
|
||||
}
|
||||
|
||||
func TestBLSPrecompile_InputTooShort(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
|
||||
// Input format: [pubkey(48)] [message(32)] [signature(96)] = 176 bytes
|
||||
tests := []struct {
|
||||
name string
|
||||
size int
|
||||
}{
|
||||
{"empty", 0},
|
||||
{"partial_pubkey", 30},
|
||||
{"pubkey_only", 48},
|
||||
{"pubkey_and_message", 80},
|
||||
{"one_byte_short", 175},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := make([]byte, tc.size)
|
||||
ret, remainingGas, err := b.Run(nil, common.Address{}, b.Address(), input, GasBLSVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBLSPrecompile_InvalidPubKey(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
|
||||
// Create invalid pubkey (all zeros is not a valid BLS pubkey)
|
||||
input := make([]byte, 176)
|
||||
|
||||
ret, remainingGas, err := b.Run(nil, common.Address{}, b.Address(), input, GasBLSVerify, true)
|
||||
require.NoError(t, err) // No error, just returns 0
|
||||
require.Equal(t, []byte{0}, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
func TestBLSPrecompile_OutOfGas(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
|
||||
input := make([]byte, 176)
|
||||
|
||||
ret, remainingGas, err := b.Run(nil, common.Address{}, b.Address(), input, GasBLSVerify-1, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// BLS Aggregate Precompile Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestBLSAggregatePrecompile_Address(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
expected := common.HexToAddress(BLSAggregateAddress)
|
||||
require.Equal(t, expected, b.Address())
|
||||
}
|
||||
|
||||
func TestBLSAggregatePrecompile_RequiredGas(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
numSigs int
|
||||
expected uint64
|
||||
}{
|
||||
{"empty", 0, 0},
|
||||
{"one_sig", 1, GasBLSAggregate},
|
||||
{"two_sigs", 2, 2 * GasBLSAggregate},
|
||||
{"ten_sigs", 10, 10 * GasBLSAggregate},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := make([]byte, tc.numSigs*96)
|
||||
gas := b.RequiredGas(input)
|
||||
require.Equal(t, tc.expected, gas)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBLSAggregatePrecompile_InvalidInputLength(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
|
||||
// Input must be multiple of 96 bytes
|
||||
tests := []struct {
|
||||
name string
|
||||
size int
|
||||
}{
|
||||
{"one_byte", 1},
|
||||
{"partial_sig", 50},
|
||||
{"one_and_half_sigs", 144},
|
||||
{"almost_two_sigs", 191},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := make([]byte, tc.size)
|
||||
gas := b.RequiredGas(input)
|
||||
ret, remainingGas, err := b.Run(nil, common.Address{}, b.Address(), input, gas+1000, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
require.Greater(t, remainingGas, uint64(0))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBLSAggregatePrecompile_InvalidSignature(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
|
||||
// Create invalid signature (all zeros is not valid)
|
||||
input := make([]byte, 96)
|
||||
|
||||
gas := b.RequiredGas(input)
|
||||
ret, _, err := b.Run(nil, common.Address{}, b.Address(), input, gas, true)
|
||||
require.ErrorIs(t, err, ErrInvalidSignature)
|
||||
require.Nil(t, ret)
|
||||
}
|
||||
|
||||
func TestBLSAggregatePrecompile_OutOfGas(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
|
||||
input := make([]byte, 96*3) // 3 signatures
|
||||
requiredGas := b.RequiredGas(input)
|
||||
|
||||
ret, remainingGas, err := b.Run(nil, common.Address{}, b.Address(), input, requiredGas-1, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Corona (ML-DSA) Precompile Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestCoronaPrecompile_Address(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
expected := common.HexToAddress(CoronaVerifyAddress)
|
||||
require.Equal(t, expected, r.Address())
|
||||
}
|
||||
|
||||
func TestCoronaPrecompile_RequiredGas(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
require.Equal(t, uint64(GasCoronaVerify), r.RequiredGas(nil))
|
||||
require.Equal(t, uint64(GasCoronaVerify), r.RequiredGas(make([]byte, 5000)))
|
||||
}
|
||||
|
||||
func TestCoronaPrecompile_InputTooShort(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
|
||||
// Input format: [mode(1)] [pubkey_len(2)] [pubkey] [msg_len(2)] [msg] [sig]
|
||||
tests := []struct {
|
||||
name string
|
||||
size int
|
||||
}{
|
||||
{"empty", 0},
|
||||
{"mode_only", 1},
|
||||
{"mode_and_partial_len", 2},
|
||||
{"header_only", 5},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := make([]byte, tc.size)
|
||||
ret, _, err := r.Run(nil, common.Address{}, r.Address(), input, GasCoronaVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoronaPrecompile_TruncatedPubKey(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
|
||||
// [mode(1)] [pubkey_len(2)] but pubkey is truncated
|
||||
input := make([]byte, 10)
|
||||
input[0] = 0x01 // mode
|
||||
input[1] = 0x00 // pubkey_len high byte
|
||||
input[2] = 0x20 // pubkey_len low byte = 32
|
||||
// Only 7 bytes of pubkey follow (input[3:10])
|
||||
|
||||
ret, _, err := r.Run(nil, common.Address{}, r.Address(), input, GasCoronaVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
}
|
||||
|
||||
func TestCoronaPrecompile_TruncatedMessage(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
|
||||
// Build input with pubkey present but message truncated
|
||||
pubKeyLen := 32
|
||||
input := make([]byte, 3+pubKeyLen+2) // mode + pubkey_len + pubkey + msg_len (no msg body)
|
||||
input[0] = 0x01 // mode
|
||||
input[1] = 0x00 // pubkey_len high
|
||||
input[2] = byte(pubKeyLen) // pubkey_len low
|
||||
// pubkey bytes: input[3:35]
|
||||
input[3+pubKeyLen] = 0x00 // msg_len high
|
||||
input[3+pubKeyLen+1] = 0x10 // msg_len low = 16
|
||||
// No message bytes follow
|
||||
|
||||
ret, _, err := r.Run(nil, common.Address{}, r.Address(), input, GasCoronaVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
}
|
||||
|
||||
func TestCoronaPrecompile_InvalidPubKey(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
|
||||
// Build complete input with invalid pubkey (all zeros)
|
||||
pubKeyLen := 1952 // ML-DSA-65 pubkey size
|
||||
msgLen := 32
|
||||
sigLen := 3293 // ML-DSA-65 signature size
|
||||
|
||||
input := make([]byte, 1+2+pubKeyLen+2+msgLen+sigLen)
|
||||
input[0] = 0x01 // mode (MLDSA65 = 1)
|
||||
input[1] = byte(pubKeyLen >> 8) // pubkey_len high
|
||||
input[2] = byte(pubKeyLen & 0xFF) // pubkey_len low
|
||||
input[3+pubKeyLen] = byte(msgLen >> 8)
|
||||
input[3+pubKeyLen+1] = byte(msgLen & 0xFF)
|
||||
// Leave everything zeros - invalid pubkey
|
||||
|
||||
ret, _, err := r.Run(nil, common.Address{}, r.Address(), input, GasCoronaVerify, true)
|
||||
require.NoError(t, err) // No error, returns 0
|
||||
require.Equal(t, []byte{0}, ret)
|
||||
}
|
||||
|
||||
func TestCoronaPrecompile_OutOfGas(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
|
||||
input := make([]byte, 100)
|
||||
|
||||
ret, remainingGas, err := r.Run(nil, common.Address{}, r.Address(), input, GasCoronaVerify-1, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Hybrid Precompile Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestHybridPrecompile_Address(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
expected := common.HexToAddress(HybridVerifyAddress)
|
||||
require.Equal(t, expected, h.Address())
|
||||
}
|
||||
|
||||
func TestHybridPrecompile_RequiredGas(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
require.Equal(t, uint64(GasHybridVerify), h.RequiredGas(nil))
|
||||
require.Equal(t, uint64(GasHybridVerify), h.RequiredGas(make([]byte, 1000)))
|
||||
}
|
||||
|
||||
func TestHybridPrecompile_InputTooShort(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
|
||||
// Minimum: [bls_sig(96)] [corona_sig_len(2)] [corona_sig] [message(32)] [bls_pubkey(48)] [corona_pubkey]
|
||||
tests := []struct {
|
||||
name string
|
||||
size int
|
||||
}{
|
||||
{"empty", 0},
|
||||
{"partial_bls_sig", 50},
|
||||
{"bls_sig_only", 96},
|
||||
{"bls_sig_and_len", 98},
|
||||
{"one_byte_short", 177},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := make([]byte, tc.size)
|
||||
ret, _, err := h.Run(nil, common.Address{}, h.Address(), input, GasHybridVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHybridPrecompile_TruncatedCoronaSig(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
|
||||
// Build input with corona_sig_len larger than actual data
|
||||
input := make([]byte, 200)
|
||||
// bls_sig: input[0:96]
|
||||
input[96] = 0x10 // corona_sig_len high = 4096 (way larger than remaining)
|
||||
input[97] = 0x00 // corona_sig_len low
|
||||
|
||||
ret, _, err := h.Run(nil, common.Address{}, h.Address(), input, GasHybridVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
}
|
||||
|
||||
func TestHybridPrecompile_InvalidBLSPubKey(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
|
||||
// Build complete but invalid input (all zeros)
|
||||
coronaSigLen := 100
|
||||
// [bls_sig(96)] [corona_sig_len(2)] [corona_sig] [message(32)] [bls_pubkey(48)] [corona_pubkey]
|
||||
totalLen := 96 + 2 + coronaSigLen + 32 + 48 + 100
|
||||
input := make([]byte, totalLen)
|
||||
input[96] = byte(coronaSigLen >> 8)
|
||||
input[97] = byte(coronaSigLen & 0xFF)
|
||||
// All zeros = invalid keys
|
||||
|
||||
ret, _, err := h.Run(nil, common.Address{}, h.Address(), input, GasHybridVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte{0}, ret) // Returns false
|
||||
}
|
||||
|
||||
func TestHybridPrecompile_OutOfGas(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
|
||||
input := make([]byte, 300)
|
||||
input[96] = 0x00
|
||||
input[97] = 0x10 // corona_sig_len = 16
|
||||
|
||||
ret, remainingGas, err := h.Run(nil, common.Address{}, h.Address(), input, GasHybridVerify-1, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Compressed Precompile Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestCompressedPrecompile_Address(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
expected := common.HexToAddress(CompressedAddress)
|
||||
require.Equal(t, expected, c.Address())
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_RequiredGas(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
require.Equal(t, uint64(GasCompressedVerify), c.RequiredGas(nil))
|
||||
require.Equal(t, uint64(GasCompressedVerify), c.RequiredGas(make([]byte, 100)))
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_ThresholdMet(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
// Input: [commitment(16)] [proof(16)] [metadata(8)] [validators(4)]
|
||||
input := make([]byte, 44)
|
||||
|
||||
// Set validator bits: need 22+ of 32 validators
|
||||
// 0xFFFFFF00 = 24 validators set (bits 8-31)
|
||||
input[40] = 0x00
|
||||
input[41] = 0xFF
|
||||
input[42] = 0xFF
|
||||
input[43] = 0xFF
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{1}, ret) // Threshold met
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_ThresholdNotMet(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
// Input: [commitment(16)] [proof(16)] [metadata(8)] [validators(4)]
|
||||
input := make([]byte, 44)
|
||||
|
||||
// Set validator bits: only 10 validators (need 22)
|
||||
// 0x000003FF = 10 validators set (bits 0-9)
|
||||
input[40] = 0xFF
|
||||
input[41] = 0x03
|
||||
input[42] = 0x00
|
||||
input[43] = 0x00
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{0}, ret) // Threshold not met
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_ExactThreshold(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
input := make([]byte, 44)
|
||||
|
||||
// Set exactly 22 validators (threshold is >= 22)
|
||||
// 0x003FFFFF = 22 validators set (bits 0-21)
|
||||
input[40] = 0xFF
|
||||
input[41] = 0xFF
|
||||
input[42] = 0x3F
|
||||
input[43] = 0x00
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{1}, ret) // Exactly at threshold
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_JustBelowThreshold(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
input := make([]byte, 44)
|
||||
|
||||
// Set 21 validators (one below threshold)
|
||||
// 0x001FFFFF = 21 validators set (bits 0-20)
|
||||
input[40] = 0xFF
|
||||
input[41] = 0xFF
|
||||
input[42] = 0x1F
|
||||
input[43] = 0x00
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{0}, ret) // Below threshold
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_AllValidators(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
input := make([]byte, 44)
|
||||
|
||||
// All 32 validators
|
||||
input[40] = 0xFF
|
||||
input[41] = 0xFF
|
||||
input[42] = 0xFF
|
||||
input[43] = 0xFF
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{1}, ret)
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_NoValidators(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
input := make([]byte, 44) // All zeros
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
require.Equal(t, []byte{0}, ret)
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_InputTooShort(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
size int
|
||||
}{
|
||||
{"empty", 0},
|
||||
{"commitment_only", 16},
|
||||
{"commitment_and_proof", 32},
|
||||
{"with_partial_metadata", 40},
|
||||
{"one_byte_short", 43},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
input := make([]byte, tc.size)
|
||||
ret, _, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
require.ErrorIs(t, err, ErrInvalidInput)
|
||||
require.Nil(t, ret)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressedPrecompile_OutOfGas(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
|
||||
input := make([]byte, 44)
|
||||
|
||||
ret, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify-1, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
require.Nil(t, ret)
|
||||
require.Equal(t, uint64(0), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// verifyVerkleLight Helper Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestVerifyVerkleLight(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
commitment []byte
|
||||
proof []byte
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "identical",
|
||||
commitment: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
|
||||
proof: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "first_half_match",
|
||||
commitment: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
|
||||
proof: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
expected: false, // Mismatch at index 16, but 16 <= 16 so returns false
|
||||
},
|
||||
{
|
||||
name: "mismatch_at_17",
|
||||
commitment: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
|
||||
proof: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
expected: true, // Mismatch at index 17, 17 > 16 so returns true
|
||||
},
|
||||
{
|
||||
name: "mismatch_at_start",
|
||||
commitment: []byte{1, 2, 3, 4},
|
||||
proof: []byte{0, 2, 3, 4},
|
||||
expected: false, // Mismatch at index 0, 0 <= 16 so returns false
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := verifyVerkleLight(tc.commitment, tc.proof)
|
||||
require.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// GetAllPrecompiles Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestGetAllPrecompiles(t *testing.T) {
|
||||
precompiles := GetAllPrecompiles()
|
||||
|
||||
require.Len(t, precompiles, 6)
|
||||
|
||||
expectedAddresses := []string{
|
||||
VerkleVerifyAddress,
|
||||
BLSVerifyAddress,
|
||||
BLSAggregateAddress,
|
||||
CoronaVerifyAddress,
|
||||
HybridVerifyAddress,
|
||||
CompressedAddress,
|
||||
}
|
||||
|
||||
for _, addr := range expectedAddresses {
|
||||
_, exists := precompiles[common.HexToAddress(addr)]
|
||||
require.True(t, exists, "Missing precompile at address %s", addr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrecompileAddresses(t *testing.T) {
|
||||
// Verify all addresses are in the expected Lux precompile range
|
||||
addresses := []string{
|
||||
VerkleVerifyAddress,
|
||||
BLSVerifyAddress,
|
||||
BLSAggregateAddress,
|
||||
CoronaVerifyAddress,
|
||||
HybridVerifyAddress,
|
||||
CompressedAddress,
|
||||
}
|
||||
|
||||
for _, addr := range addresses {
|
||||
address := common.HexToAddress(addr)
|
||||
// Should start with 0x03 (Lux consensus precompile range)
|
||||
require.Equal(t, byte(0x03), address[0], "Address %s not in consensus precompile range", addr)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Gas Consumption Tests
|
||||
// =============================================================================
|
||||
|
||||
func TestGasConsumption_Verkle(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
input := make([]byte, 65)
|
||||
input[64] = 1 // threshold met
|
||||
|
||||
suppliedGas := uint64(GasVerkleVerify + 1000)
|
||||
_, remainingGas, err := v.Run(nil, common.Address{}, v.Address(), input, suppliedGas, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1000), remainingGas)
|
||||
}
|
||||
|
||||
func TestGasConsumption_BLS(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
input := make([]byte, 176)
|
||||
|
||||
suppliedGas := uint64(GasBLSVerify + 500)
|
||||
_, remainingGas, err := b.Run(nil, common.Address{}, b.Address(), input, suppliedGas, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(500), remainingGas)
|
||||
}
|
||||
|
||||
func TestGasConsumption_Compressed(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
input := make([]byte, 44)
|
||||
|
||||
suppliedGas := uint64(GasCompressedVerify + 200)
|
||||
_, remainingGas, err := c.Run(nil, common.Address{}, c.Address(), input, suppliedGas, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(200), remainingGas)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Benchmark Tests
|
||||
// =============================================================================
|
||||
|
||||
func BenchmarkVerkleVerify(b *testing.B) {
|
||||
v := &verklePrecompile{}
|
||||
input := make([]byte, 65)
|
||||
for i := range 32 {
|
||||
input[i] = byte(i)
|
||||
input[32+i] = byte(i)
|
||||
}
|
||||
input[64] = 1
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _, _ = v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify, true)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompressedVerify(b *testing.B) {
|
||||
c := &compressedPrecompile{}
|
||||
input := make([]byte, 44)
|
||||
input[40] = 0xFF
|
||||
input[41] = 0xFF
|
||||
input[42] = 0xFF
|
||||
input[43] = 0xFF
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _, _ = c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify, true)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGasBLSAggregate(b *testing.B) {
|
||||
ba := &blsAggregatePrecompile{}
|
||||
|
||||
for _, numSigs := range []int{1, 10, 100} {
|
||||
b.Run(string(rune('0'+numSigs)), func(b *testing.B) {
|
||||
input := make([]byte, numSigs*96)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = ba.RequiredGas(input)
|
||||
}
|
||||
})
|
||||
// TestSentinel pins the deprecated-error symbol so a future rename
|
||||
// can't quietly drop the refuse-everything contract.
|
||||
func TestSentinel(t *testing.T) {
|
||||
if ErrQuasarPrecompileDeprecated == nil {
|
||||
t.Fatal("ErrQuasarPrecompileDeprecated must not be nil")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package quasar
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/geth/common"
|
||||
"github.com/luxfi/precompile/contract"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// --- Verkle Deep Tests ---
|
||||
|
||||
func TestDeep_Verkle_ExactGasConsumption(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
input := make([]byte, 65)
|
||||
input[64] = 1
|
||||
|
||||
for _, extra := range []uint64{0, 1, 100, 10000} {
|
||||
_, remaining, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify+extra, true)
|
||||
require.NoError(t, err, "extra=%d", extra)
|
||||
require.Equal(t, extra, remaining, "extra=%d", extra)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeep_Verkle_GasZero(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
input := make([]byte, 65)
|
||||
_, _, err := v.Run(nil, common.Address{}, v.Address(), input, 0, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
}
|
||||
|
||||
func TestDeep_Verkle_Concurrent(t *testing.T) {
|
||||
v := &verklePrecompile{}
|
||||
input := make([]byte, 65)
|
||||
for i := range 32 {
|
||||
input[i] = byte(i)
|
||||
input[32+i] = byte(i)
|
||||
}
|
||||
input[64] = 1
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for range 50 {
|
||||
wg.Go(func() {
|
||||
ret, _, err := v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify+100, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte{1}, ret)
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// --- BLS Deep Tests ---
|
||||
|
||||
func TestDeep_BLS_GasZero(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
input := make([]byte, 176)
|
||||
_, _, err := b.Run(nil, common.Address{}, b.Address(), input, 0, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
}
|
||||
|
||||
func TestDeep_BLS_ExactGas(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
input := make([]byte, 176)
|
||||
_, remaining, err := b.Run(nil, common.Address{}, b.Address(), input, GasBLSVerify, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), remaining)
|
||||
}
|
||||
|
||||
func TestDeep_BLS_EmptyInput(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
_, _, err := b.Run(nil, common.Address{}, b.Address(), nil, GasBLSVerify, true)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestDeep_BLS_Concurrent(t *testing.T) {
|
||||
b := &blsPrecompile{}
|
||||
input := make([]byte, 176)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for range 50 {
|
||||
wg.Go(func() {
|
||||
_, _, err := b.Run(nil, common.Address{}, b.Address(), input, GasBLSVerify+100, true)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// --- BLS Aggregate Deep Tests ---
|
||||
|
||||
func TestDeep_BLSAggregate_EmptyInput(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
gas := b.RequiredGas(nil)
|
||||
require.Equal(t, uint64(0), gas)
|
||||
}
|
||||
|
||||
func TestDeep_BLSAggregate_GasZero(t *testing.T) {
|
||||
b := &blsAggregatePrecompile{}
|
||||
input := make([]byte, 96)
|
||||
_, _, err := b.Run(nil, common.Address{}, b.Address(), input, 0, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
}
|
||||
|
||||
// --- Corona Deep Tests ---
|
||||
|
||||
func TestDeep_Corona_GasZero(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
input := make([]byte, 100)
|
||||
_, _, err := r.Run(nil, common.Address{}, r.Address(), input, 0, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
}
|
||||
|
||||
func TestDeep_Corona_EmptyInput(t *testing.T) {
|
||||
r := &coronaPrecompile{}
|
||||
_, _, err := r.Run(nil, common.Address{}, r.Address(), nil, GasCoronaVerify, true)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
// --- Hybrid Deep Tests ---
|
||||
|
||||
func TestDeep_Hybrid_GasZero(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
input := make([]byte, 300)
|
||||
_, _, err := h.Run(nil, common.Address{}, h.Address(), input, 0, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
}
|
||||
|
||||
func TestDeep_Hybrid_EmptyInput(t *testing.T) {
|
||||
h := &hybridPrecompile{}
|
||||
_, _, err := h.Run(nil, common.Address{}, h.Address(), nil, GasHybridVerify, true)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
// --- Compressed Deep Tests ---
|
||||
|
||||
func TestDeep_Compressed_GasZero(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
input := make([]byte, 44)
|
||||
_, _, err := c.Run(nil, common.Address{}, c.Address(), input, 0, true)
|
||||
require.ErrorIs(t, err, contract.ErrOutOfGas)
|
||||
}
|
||||
|
||||
func TestDeep_Compressed_EmptyInput(t *testing.T) {
|
||||
c := &compressedPrecompile{}
|
||||
_, _, err := c.Run(nil, common.Address{}, c.Address(), nil, GasCompressedVerify, true)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
// --- Fuzz ---
|
||||
|
||||
func FuzzVerkle(f *testing.F) {
|
||||
f.Add(make([]byte, 65))
|
||||
f.Add([]byte{})
|
||||
f.Add(make([]byte, 100))
|
||||
|
||||
v := &verklePrecompile{}
|
||||
f.Fuzz(func(t *testing.T, input []byte) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("panic: %v", r)
|
||||
}
|
||||
}()
|
||||
v.Run(nil, common.Address{}, v.Address(), input, GasVerkleVerify+100000, true)
|
||||
})
|
||||
}
|
||||
|
||||
func FuzzCompressed(f *testing.F) {
|
||||
f.Add(make([]byte, 44))
|
||||
f.Add([]byte{})
|
||||
|
||||
c := &compressedPrecompile{}
|
||||
f.Fuzz(func(t *testing.T, input []byte) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("panic: %v", r)
|
||||
}
|
||||
}()
|
||||
c.Run(nil, common.Address{}, c.Address(), input, GasCompressedVerify+100000, true)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user