Commit 6574c458 authored by Inphi's avatar Inphi Committed by GitHub

Fix KZG Precompile Oracle (#9577)

* op-e2e: Fix flaky TestOutputCannonStepWithKZGPointEvaluation test

* fault-proofs: Fix on-chain KZG precompile oracle

* fix for flakes in CI

and add nil check when logging oracleKey
parent df80b5d3
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"math/big" "math/big"
"os" "os"
"path" "path"
"strings"
"testing" "testing"
"time" "time"
...@@ -42,20 +41,25 @@ func MarkdownTracer() vm.EVMLogger { ...@@ -42,20 +41,25 @@ func MarkdownTracer() vm.EVMLogger {
} }
type MIPSEVM struct { type MIPSEVM struct {
env *vm.EVM env *vm.EVM
evmState *state.StateDB evmState *state.StateDB
addrs *Addresses addrs *Addresses
localOracle PreimageOracle
} }
func NewMIPSEVM(contracts *Contracts, addrs *Addresses) *MIPSEVM { func NewMIPSEVM(contracts *Contracts, addrs *Addresses) *MIPSEVM {
env, evmState := NewEVMEnv(contracts, addrs) env, evmState := NewEVMEnv(contracts, addrs)
return &MIPSEVM{env, evmState, addrs} return &MIPSEVM{env, evmState, addrs, nil}
} }
func (m *MIPSEVM) SetTracer(tracer vm.EVMLogger) { func (m *MIPSEVM) SetTracer(tracer vm.EVMLogger) {
m.env.Config.Tracer = tracer m.env.Config.Tracer = tracer
} }
func (m *MIPSEVM) SetLocalOracle(oracle PreimageOracle) {
m.localOracle = oracle
}
// Step is a pure function that computes the poststate from the VM state encoded in the StepWitness. // Step is a pure function that computes the poststate from the VM state encoded in the StepWitness.
func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte { func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte {
sender := common.Address{0x13, 0x37} sender := common.Address{0x13, 0x37}
...@@ -66,7 +70,7 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte { ...@@ -66,7 +70,7 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte {
if stepWitness.HasPreimage() { if stepWitness.HasPreimage() {
t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset) t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset)
poInput, err := encodePreimageOracleInput(t, stepWitness, LocalContext{}) poInput, err := encodePreimageOracleInput(t, stepWitness, LocalContext{}, m.localOracle)
require.NoError(t, err, "encode preimage oracle input") require.NoError(t, err, "encode preimage oracle input")
_, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, big.NewInt(0)) _, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, big.NewInt(0))
require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas) require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas)
...@@ -100,7 +104,7 @@ func encodeStepInput(t *testing.T, wit *StepWitness, localContext LocalContext) ...@@ -100,7 +104,7 @@ func encodeStepInput(t *testing.T, wit *StepWitness, localContext LocalContext)
return input return input
} }
func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext LocalContext) ([]byte, error) { func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext LocalContext, localOracle PreimageOracle) ([]byte, error) {
if wit.PreimageKey == ([32]byte{}) { if wit.PreimageKey == ([32]byte{}) {
return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof") return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof")
} }
...@@ -132,6 +136,18 @@ func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext Loca ...@@ -132,6 +136,18 @@ func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext Loca
wit.PreimageValue[8:]) wit.PreimageValue[8:])
require.NoError(t, err) require.NoError(t, err)
return input, nil return input, nil
case preimage.KZGPointEvaluationKeyType:
if localOracle == nil {
return nil, fmt.Errorf("local oracle is required for point evaluation preimages")
}
preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey())
input, err := preimageAbi.Pack(
"loadKZGPointEvaluationPreimagePart",
new(big.Int).SetUint64(uint64(wit.PreimageOffset)),
preimage,
)
require.NoError(t, err)
return input, nil
default: default:
return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle", return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle",
wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset) wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset)
...@@ -147,15 +163,13 @@ func TestEVM(t *testing.T) { ...@@ -147,15 +163,13 @@ func TestEVM(t *testing.T) {
for _, f := range testFiles { for _, f := range testFiles {
t.Run(f.Name(), func(t *testing.T) { t.Run(f.Name(), func(t *testing.T) {
var oracle PreimageOracle oracle := selectOracleFixture(t, f.Name())
if strings.HasPrefix(f.Name(), "oracle") {
oracle = staticOracle(t, []byte("hello world"))
}
// Short-circuit early for exit_group.bin // Short-circuit early for exit_group.bin
exitGroup := f.Name() == "exit_group.bin" exitGroup := f.Name() == "exit_group.bin"
evm := NewMIPSEVM(contracts, addrs) evm := NewMIPSEVM(contracts, addrs)
evm.SetTracer(tracer) evm.SetTracer(tracer)
evm.SetLocalOracle(oracle)
fn := path.Join("open_mips_tests/test/bin", f.Name()) fn := path.Join("open_mips_tests/test/bin", f.Name())
programMem, err := os.ReadFile(fn) programMem, err := os.ReadFile(fn)
......
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
# load hash at 0x30001000
# 0x47173285 a8d7341e 5e972fc6 77286384 f802f8ef 42a5ec5f 03bbfa25 4cb01fad = keccak("hello world")
# 0x06173285 a8d7341e 5e972fc6 77286384 f802f8ef 42a5ec5f 03bbfa25 4cb01fad = keccak("hello world").key (kzg)
test:
lui $s0, 0x3000
ori $s0, 0x1000
lui $t0, 0x0617
ori $t0, 0x3285
sw $t0, 0($s0)
lui $t0, 0xa8d7
ori $t0, 0x341e
sw $t0, 4($s0)
lui $t0, 0x5e97
ori $t0, 0x2fc6
sw $t0, 8($s0)
lui $t0, 0x7728
ori $t0, 0x6384
sw $t0, 0xc($s0)
lui $t0, 0xf802
ori $t0, 0xf8ef
sw $t0, 0x10($s0)
lui $t0, 0x42a5
ori $t0, 0xec5f
sw $t0, 0x14($s0)
lui $t0, 0x03bb
ori $t0, 0xfa25
sw $t0, 0x18($s0)
lui $t0, 0x4cb0
ori $t0, 0x1fad
sw $t0, 0x1c($s0)
# preimage request - write(fdPreimageWrite, preimageData, 32)
li $a0, 6
li $a1, 0x30001000
li $t0, 8
li $a2, 4
$writeloop:
li $v0, 4004
syscall
addiu $a1, $a1, 4
addiu $t0, $t0, -1
bnez $t0, $writeloop
nop
# preimage response to 0x30002000 - read(fdPreimageRead, addr, count)
# read preimage length
li $a0, 5
li $a1, 0x31000000
li $a2, 4
li $v0, 4003
syscall
li $a1, 0x31000004
li $v0, 4003
syscall
# read the 1 byte preimage data
li $a1, 0x31000008
li $v0, 4003
syscall
nop
# length at 0x31000000. We also check that the lower 32 bits are zero
lui $s1, 0x3100
lw $t0, 0($s1)
sltiu $t6, $t0, 1
li $s1, 0x31000004
lw $t0, 0($s1)
# len should be 1
li $t4, 1
subu $t5, $t0, $t4
sltiu $v0, $t5, 1
and $v0, $v0, $t6
# most likely broken. need to check pc for exact case
# save results
lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0
ori $s1, $0, 1 # Prepare the 'done' status
sw $v0, 8($s0) # Set the test result
sw $s1, 4($s0) # Set 'done'
$done:
jr $ra
nop
.end test
...@@ -31,10 +31,7 @@ func TestState(t *testing.T) { ...@@ -31,10 +31,7 @@ func TestState(t *testing.T) {
for _, f := range testFiles { for _, f := range testFiles {
t.Run(f.Name(), func(t *testing.T) { t.Run(f.Name(), func(t *testing.T) {
var oracle PreimageOracle oracle := selectOracleFixture(t, f.Name())
if strings.HasPrefix(f.Name(), "oracle") {
oracle = staticOracle(t, []byte("hello world"))
}
// Short-circuit early for exit_group.bin // Short-circuit early for exit_group.bin
exitGroup := f.Name() == "exit_group.bin" exitGroup := f.Name() == "exit_group.bin"
...@@ -269,3 +266,34 @@ func staticOracle(t *testing.T, preimageData []byte) *testOracle { ...@@ -269,3 +266,34 @@ func staticOracle(t *testing.T, preimageData []byte) *testOracle {
}, },
} }
} }
func staticPrecompileOracle(t *testing.T, preimageData []byte, result []byte) *testOracle {
return &testOracle{
hint: func(v []byte) {},
getPreimage: func(k [32]byte) []byte {
switch k[0] {
case byte(preimage.Keccak256KeyType):
if k != preimage.Keccak256Key(crypto.Keccak256Hash(preimageData)).PreimageKey() {
t.Fatalf("invalid preimage request for %x", k)
}
return preimageData
case byte(preimage.KZGPointEvaluationKeyType):
if k != preimage.KZGPointEvaluationKey(crypto.Keccak256Hash(preimageData)).PreimageKey() {
t.Fatalf("invalid preimage request for %x", k)
}
return result
}
panic("unreachable")
},
}
}
func selectOracleFixture(t *testing.T, programName string) PreimageOracle {
if strings.HasPrefix(programName, "oracle_kzg") {
return staticPrecompileOracle(t, []byte("hello world"), []byte{0x1})
} else if strings.HasPrefix(programName, "oracle") {
return staticOracle(t, []byte("hello world"))
} else {
return nil
}
}
This diff is collapsed.
This diff is collapsed.
...@@ -70,7 +70,15 @@ func (a *Agent) Act(ctx context.Context) error { ...@@ -70,7 +70,15 @@ func (a *Agent) Act(ctx context.Context) error {
if action.Type == types.ActionTypeStep { if action.Type == types.ActionTypeStep {
containsOracleData := action.OracleData != nil containsOracleData := action.OracleData != nil
isLocal := containsOracleData && action.OracleData.IsLocal isLocal := containsOracleData && action.OracleData.IsLocal
actionLog = actionLog.New("prestate", common.Bytes2Hex(action.PreState), "proof", common.Bytes2Hex(action.ProofData), "containsOracleData", containsOracleData, "isLocalPreimage", isLocal) actionLog = actionLog.New(
"prestate", common.Bytes2Hex(action.PreState),
"proof", common.Bytes2Hex(action.ProofData),
"containsOracleData", containsOracleData,
"isLocalPreimage", isLocal,
)
if action.OracleData != nil {
actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey))
}
} else { } else {
actionLog = actionLog.New("value", action.Value) actionLog = actionLog.New("value", action.Value)
} }
......
...@@ -20,25 +20,25 @@ import ( ...@@ -20,25 +20,25 @@ import (
) )
const ( const (
methodInitLPP = "initLPP" methodInitLPP = "initLPP"
methodAddLeavesLPP = "addLeavesLPP" methodAddLeavesLPP = "addLeavesLPP"
methodSqueezeLPP = "squeezeLPP" methodSqueezeLPP = "squeezeLPP"
methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart" methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart"
methodLoadSha256PreimagePart = "loadSha256PreimagePart" methodLoadSha256PreimagePart = "loadSha256PreimagePart"
methodLoadBlobPreimagePart = "loadBlobPreimagePart" methodLoadBlobPreimagePart = "loadBlobPreimagePart"
methodLoadKZGPointEvaluationPreimage = "loadKZGPointEvaluationPreimage" methodLoadKZGPointEvaluationPreimagePart = "loadKZGPointEvaluationPreimagePart"
methodProposalCount = "proposalCount" methodProposalCount = "proposalCount"
methodProposals = "proposals" methodProposals = "proposals"
methodProposalMetadata = "proposalMetadata" methodProposalMetadata = "proposalMetadata"
methodProposalBlocksLen = "proposalBlocksLen" methodProposalBlocksLen = "proposalBlocksLen"
methodProposalBlocks = "proposalBlocks" methodProposalBlocks = "proposalBlocks"
methodPreimagePartOk = "preimagePartOk" methodPreimagePartOk = "preimagePartOk"
methodMinProposalSize = "minProposalSize" methodMinProposalSize = "minProposalSize"
methodChallengeFirstLPP = "challengeFirstLPP" methodChallengeFirstLPP = "challengeFirstLPP"
methodChallengeLPP = "challengeLPP" methodChallengeLPP = "challengeLPP"
methodChallengePeriod = "challengePeriod" methodChallengePeriod = "challengePeriod"
methodGetTreeRootLPP = "getTreeRootLPP" methodGetTreeRootLPP = "getTreeRootLPP"
methodMinBondSizeLPP = "MIN_BOND_SIZE" methodMinBondSizeLPP = "MIN_BOND_SIZE"
) )
var ( var (
...@@ -108,7 +108,7 @@ func (c *PreimageOracleContract) AddGlobalDataTx(data *types.PreimageOracleData) ...@@ -108,7 +108,7 @@ func (c *PreimageOracleContract) AddGlobalDataTx(data *types.PreimageOracleData)
new(big.Int).SetUint64(uint64(data.OracleOffset))) new(big.Int).SetUint64(uint64(data.OracleOffset)))
return call.ToTxCandidate() return call.ToTxCandidate()
case preimage.KZGPointEvaluationKeyType: case preimage.KZGPointEvaluationKeyType:
call := c.contract.Call(methodLoadKZGPointEvaluationPreimage, data.GetPreimageWithoutSize()) call := c.contract.Call(methodLoadKZGPointEvaluationPreimagePart, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize())
return call.ToTxCandidate() return call.ToTxCandidate()
default: default:
return txmgr.TxCandidate{}, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, keyType) return txmgr.TxCandidate{}, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, keyType)
......
...@@ -74,8 +74,9 @@ func TestPreimageOracleContract_AddGlobalDataTx(t *testing.T) { ...@@ -74,8 +74,9 @@ func TestPreimageOracleContract_AddGlobalDataTx(t *testing.T) {
t.Run("KZGPointEvaluation", func(t *testing.T) { t.Run("KZGPointEvaluation", func(t *testing.T) {
stubRpc, oracle := setupPreimageOracleTest(t) stubRpc, oracle := setupPreimageOracleTest(t)
input := testutils.RandomData(rand.New(rand.NewSource(23)), 200) input := testutils.RandomData(rand.New(rand.NewSource(23)), 200)
data := types.NewPreimageOracleKZGPointEvaluationData(common.Hash{byte(preimage.KZGPointEvaluationKeyType), 0xcc}.Bytes(), input) data := types.NewPreimageOracleData(common.Hash{byte(preimage.KZGPointEvaluationKeyType), 0xcc}.Bytes(), input, uint32(545))
stubRpc.SetResponse(oracleAddr, methodLoadKZGPointEvaluationPreimage, batching.BlockLatest, []interface{}{ stubRpc.SetResponse(oracleAddr, methodLoadKZGPointEvaluationPreimagePart, batching.BlockLatest, []interface{}{
new(big.Int).SetUint64(uint64(data.OracleOffset)),
data.GetPreimageWithoutSize(), data.GetPreimageWithoutSize(),
}, nil) }, nil)
......
...@@ -109,7 +109,7 @@ func (l *preimageLoader) loadKZGPointEvaluationPreimage(proof *proofData) (*type ...@@ -109,7 +109,7 @@ func (l *preimageLoader) loadKZGPointEvaluationPreimage(proof *proofData) (*type
return nil, fmt.Errorf("failed to get key preimage: %w", err) return nil, fmt.Errorf("failed to get key preimage: %w", err)
} }
inputWithLength := lengthPrefixed(input) inputWithLength := lengthPrefixed(input)
return types.NewPreimageOracleKZGPointEvaluationData(proof.OracleKey, inputWithLength), nil return types.NewPreimageOracleData(proof.OracleKey, inputWithLength, proof.OracleOffset), nil
} }
func lengthPrefixed(data []byte) []byte { func lengthPrefixed(data []byte) []byte {
......
...@@ -172,7 +172,7 @@ func TestPreimageLoader_KZGPointEvaluationPreimage(t *testing.T) { ...@@ -172,7 +172,7 @@ func TestPreimageLoader_KZGPointEvaluationPreimage(t *testing.T) {
actual, err := loader.LoadPreimage(proof) actual, err := loader.LoadPreimage(proof)
require.NoError(t, err) require.NoError(t, err)
inputWithLength := lengthPrefixed(input) inputWithLength := lengthPrefixed(input)
expected := types.NewPreimageOracleKZGPointEvaluationData(proof.OracleKey, inputWithLength) expected := types.NewPreimageOracleData(proof.OracleKey, inputWithLength, proof.OracleOffset)
require.Equal(t, expected, actual) require.Equal(t, expected, actual)
}) })
} }
......
...@@ -79,15 +79,6 @@ func NewPreimageOracleBlobData(key []byte, data []byte, offset uint32, fieldInde ...@@ -79,15 +79,6 @@ func NewPreimageOracleBlobData(key []byte, data []byte, offset uint32, fieldInde
} }
} }
func NewPreimageOracleKZGPointEvaluationData(key []byte, input []byte) *PreimageOracleData {
return &PreimageOracleData{
IsLocal: false,
OracleKey: key,
oracleData: input,
OracleOffset: 0,
}
}
// StepCallData encapsulates the data needed to perform a step. // StepCallData encapsulates the data needed to perform a step.
type StepCallData struct { type StepCallData struct {
ClaimIndex uint64 ClaimIndex uint64
......
...@@ -582,7 +582,7 @@ func (g *OutputGameHelper) uploadPreimage(ctx context.Context, data *types.Preim ...@@ -582,7 +582,7 @@ func (g *OutputGameHelper) uploadPreimage(ctx context.Context, data *types.Preim
var tx *gethtypes.Transaction var tx *gethtypes.Transaction
switch data.OracleKey[0] { switch data.OracleKey[0] {
case byte(preimage.KZGPointEvaluationKeyType): case byte(preimage.KZGPointEvaluationKeyType):
tx, err = boundOracle.LoadKZGPointEvaluationPreimage(g.opts, data.GetPreimageWithoutSize()) tx, err = boundOracle.LoadKZGPointEvaluationPreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize())
default: default:
tx, err = boundOracle.LoadKeccak256PreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) tx, err = boundOracle.LoadKeccak256PreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize())
} }
......
...@@ -3,6 +3,7 @@ package faultproofs ...@@ -3,6 +3,7 @@ package faultproofs
import ( import (
"context" "context"
"fmt" "fmt"
"math/big"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
...@@ -13,6 +14,7 @@ import ( ...@@ -13,6 +14,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -298,7 +300,6 @@ func TestOutputCannonStepWithPreimage(t *testing.T) { ...@@ -298,7 +300,6 @@ func TestOutputCannonStepWithPreimage(t *testing.T) {
} }
func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) { func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) {
t.Skip("TODO: Fix flaky test")
op_e2e.InitParallel(t, op_e2e.UsesCannon) op_e2e.InitParallel(t, op_e2e.UsesCannon)
testPreimageStep := func(t *testing.T, preloadPreimage bool) { testPreimageStep := func(t *testing.T, preloadPreimage bool) {
...@@ -308,6 +309,12 @@ func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) { ...@@ -308,6 +309,12 @@ func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) {
sys, _ := startFaultDisputeSystem(t, withEcotone()) sys, _ := startFaultDisputeSystem(t, withEcotone())
t.Cleanup(sys.Close) t.Cleanup(sys.Close)
// NOTE: Flake prevention
// Ensure that the L1 origin including the point eval tx isn't on the genesis epoch.
safeBlock, err := sys.Clients["sequencer"].BlockByNumber(ctx, big.NewInt(int64(rpc.SafeBlockNumber)))
require.NoError(t, err)
require.NoError(t, wait.ForSafeBlock(ctx, sys.RollupClient("sequencer"), safeBlock.NumberU64()+3))
receipt := sendKZGPointEvaluationTx(t, sys, "sequencer", sys.Cfg.Secrets.Alice) receipt := sendKZGPointEvaluationTx(t, sys, "sequencer", sys.Cfg.Secrets.Alice)
precompileBlock := receipt.BlockNumber precompileBlock := receipt.BlockNumber
t.Logf("KZG Point Evaluation block number: %d", precompileBlock) t.Logf("KZG Point Evaluation block number: %d", precompileBlock)
......
...@@ -316,13 +316,18 @@ ...@@ -316,13 +316,18 @@
}, },
{ {
"inputs": [ "inputs": [
{
"internalType": "uint256",
"name": "_partOffset",
"type": "uint256"
},
{ {
"internalType": "bytes", "internalType": "bytes",
"name": "_input", "name": "_input",
"type": "bytes" "type": "bytes"
} }
], ],
"name": "loadKZGPointEvaluationPreimage", "name": "loadKZGPointEvaluationPreimagePart",
"outputs": [], "outputs": [],
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
......
...@@ -334,10 +334,11 @@ contract PreimageOracle is IPreimageOracle { ...@@ -334,10 +334,11 @@ contract PreimageOracle is IPreimageOracle {
} }
/// @inheritdoc IPreimageOracle /// @inheritdoc IPreimageOracle
function loadKZGPointEvaluationPreimage(bytes calldata _input) external { function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes calldata _input) external {
// Prior to Cancun activation, the blob preimage precompile is not available. // Prior to Cancun activation, the blob preimage precompile is not available.
if (block.timestamp < CANCUN_ACTIVATION) revert CancunNotActive(); if (block.timestamp < CANCUN_ACTIVATION) revert CancunNotActive();
bytes32 res;
bytes32 key; bytes32 key;
bytes32 part; bytes32 part;
assembly { assembly {
...@@ -353,7 +354,7 @@ contract PreimageOracle is IPreimageOracle { ...@@ -353,7 +354,7 @@ contract PreimageOracle is IPreimageOracle {
// Verify the KZG proof by calling the point evaluation precompile. // Verify the KZG proof by calling the point evaluation precompile.
// Capture the verification result // Capture the verification result
part := res :=
staticcall( staticcall(
gas(), // forward all gas gas(), // forward all gas
0x0A, // point evaluation precompile address 0x0A, // point evaluation precompile address
...@@ -362,13 +363,21 @@ contract PreimageOracle is IPreimageOracle { ...@@ -362,13 +363,21 @@ contract PreimageOracle is IPreimageOracle {
0x00, // output ptr 0x00, // output ptr
0x00 // output size 0x00 // output size
) )
// "part" will be 0 on error, and 1 on success, of the KZG Point-evaluation precompile call // "res" will be 0 on error, and 1 on success, of the KZG Point-evaluation precompile call
// We do have to shift it to the left-most byte of the bytes32 however, since we only read that byte. // We do have to shift it to the left-most byte of the bytes32 however, since we only read that byte.
part := shl(248, part) res := shl(248, res)
// Reuse the `ptr` to store the preimage part including size prefix.
// put size as big-endian uint64 at the start of pre-image
mstore(ptr, shl(192, 1))
ptr := add(ptr, 0x08)
mstore(ptr, res)
// compute part given ofset
part := mload(add(sub(ptr, 0x08), _partOffset))
} }
// the part offset is always 0 preimagePartOk[key][_partOffset] = true;
preimagePartOk[key][0] = true; preimageParts[key][_partOffset] = part;
preimageParts[key][0] = part; // size is always 1
preimageLengths[key] = 1; preimageLengths[key] = 1;
} }
......
...@@ -72,5 +72,5 @@ interface IPreimageOracle { ...@@ -72,5 +72,5 @@ interface IPreimageOracle {
/// @notice Prepares a point evaluation precompile result to be read by the keccak256 of its input. /// @notice Prepares a point evaluation precompile result to be read by the keccak256 of its input.
/// @param _input The point evaluation precompile input. /// @param _input The point evaluation precompile input.
function loadKZGPointEvaluationPreimage(bytes calldata _input) external; function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes calldata _input) external;
} }
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