• Inphi's avatar
    op-program: Generic precompile oracle (#9699) · 44201560
    Inphi authored
    * op-program: Generic precompile oracle
    
    The generic precompile oracle replaces the point evaluation precompile
    oracle. The new oracle can be used to retrieve the return data and
    status of any precompile, including bn256Pairing and ecrecover.
    
    * op-challenger: Use generic precompile oracle
    
    Replace the KZG point evaluation oracle with a generic precompile oracle
    
    * op-program: Simplify required gas logic.
    Use FromHex instead of Hex2Bytes
    
    * op-program: Set beacon URL when capturing and verifying sepolia chain data
    
    * op-program: Actually use the beacon URL
    
    * op-program: Use default l1-rpckind if not set rather than overriding to debug_geth
    
    * Use freshly generated sepolia test data
    
    * Use sepolia compatibility data
    
    * Fix spelling
    
    * update PreimageOracle.sol snapshot
    
    ---------
    Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>
    44201560
cache_test.go 3.92 KB
package l1

import (
	"math/rand"
	"testing"

	"github.com/ethereum-optimism/optimism/op-program/client/l1/test"
	"github.com/ethereum-optimism/optimism/op-service/eth"
	"github.com/ethereum-optimism/optimism/op-service/testutils"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/stretchr/testify/require"
)

// Should implement Oracle
var _ Oracle = (*CachingOracle)(nil)

func TestCachingOracle_HeaderByBlockHash(t *testing.T) {
	rng := rand.New(rand.NewSource(1))
	stub := test.NewStubOracle(t)
	oracle := NewCachingOracle(stub)
	block := testutils.RandomBlockInfo(rng)

	// Initial call retrieves from the stub
	stub.Blocks[block.Hash()] = block
	result := oracle.HeaderByBlockHash(block.Hash())
	require.Equal(t, block, result)

	// Later calls should retrieve from cache
	delete(stub.Blocks, block.Hash())
	result = oracle.HeaderByBlockHash(block.Hash())
	require.Equal(t, block, result)
}

func TestCachingOracle_TransactionsByBlockHash(t *testing.T) {
	rng := rand.New(rand.NewSource(1))
	stub := test.NewStubOracle(t)
	oracle := NewCachingOracle(stub)
	block, _ := testutils.RandomBlock(rng, 3)

	// Initial call retrieves from the stub
	stub.Blocks[block.Hash()] = eth.BlockToInfo(block)
	stub.Txs[block.Hash()] = block.Transactions()
	actualBlock, actualTxs := oracle.TransactionsByBlockHash(block.Hash())
	require.Equal(t, eth.BlockToInfo(block), actualBlock)
	require.Equal(t, block.Transactions(), actualTxs)

	// Later calls should retrieve from cache
	delete(stub.Blocks, block.Hash())
	delete(stub.Txs, block.Hash())
	actualBlock, actualTxs = oracle.TransactionsByBlockHash(block.Hash())
	require.Equal(t, eth.BlockToInfo(block), actualBlock)
	require.Equal(t, block.Transactions(), actualTxs)
}

func TestCachingOracle_ReceiptsByBlockHash(t *testing.T) {
	rng := rand.New(rand.NewSource(1))
	stub := test.NewStubOracle(t)
	oracle := NewCachingOracle(stub)
	block, rcpts := testutils.RandomBlock(rng, 3)

	// Initial call retrieves from the stub
	stub.Blocks[block.Hash()] = eth.BlockToInfo(block)
	stub.Rcpts[block.Hash()] = rcpts
	actualBlock, actualRcpts := oracle.ReceiptsByBlockHash(block.Hash())
	require.Equal(t, eth.BlockToInfo(block), actualBlock)
	require.EqualValues(t, rcpts, actualRcpts)

	// Later calls should retrieve from cache
	delete(stub.Blocks, block.Hash())
	delete(stub.Rcpts, block.Hash())
	actualBlock, actualRcpts = oracle.ReceiptsByBlockHash(block.Hash())
	require.Equal(t, eth.BlockToInfo(block), actualBlock)
	require.EqualValues(t, rcpts, actualRcpts)
}

func TestCachingOracle_GetBlobs(t *testing.T) {
	stub := test.NewStubOracle(t)
	oracle := NewCachingOracle(stub)

	l1BlockRef := eth.L1BlockRef{Time: 0}
	indexedBlobHash := eth.IndexedBlobHash{Hash: [32]byte{0xFA, 0xCA, 0xDE}, Index: 0}
	blob := eth.Blob{0xFF}

	// Initial call retrieves from the stub
	stub.Blobs[l1BlockRef] = make(map[eth.IndexedBlobHash]*eth.Blob)
	stub.Blobs[l1BlockRef][indexedBlobHash] = &blob
	actualBlob := oracle.GetBlob(l1BlockRef, indexedBlobHash)
	require.Equal(t, &blob, actualBlob)

	// Later calls should retrieve from cache
	delete(stub.Blobs[l1BlockRef], indexedBlobHash)
	actualBlob = oracle.GetBlob(l1BlockRef, indexedBlobHash)
	require.Equal(t, &blob, actualBlob)
}

func TestCachingOracle_Precompile(t *testing.T) {
	stub := test.NewStubOracle(t)
	oracle := NewCachingOracle(stub)

	input := []byte{0x01, 0x02, 0x03, 0x04}
	output := []byte{0x0a, 0x0b, 0x0c, 0x0d}
	addr := common.Address{0x1}

	// Initial call retrieves from the stub
	stub.PcmpResults[crypto.Keccak256Hash(append(addr.Bytes(), input...))] = output
	actualResult, actualStatus := oracle.Precompile(addr, input)
	require.True(t, actualStatus)
	require.EqualValues(t, output, actualResult)

	// Later calls should retrieve from cache
	delete(stub.PcmpResults, crypto.Keccak256Hash(append(addr.Bytes(), input...)))
	actualResult, actualStatus = oracle.Precompile(addr, input)
	require.True(t, actualStatus)
	require.EqualValues(t, output, actualResult)
}