Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fa4eee2
add full node test
Manav-Aggarwal Jun 25, 2025
bd71544
Refactor EVM full node test
Manav-Aggarwal Jun 25, 2025
eed64f6
Add Multiple Transaction Inclusion Test
Manav-Aggarwal Jun 25, 2025
065b7ef
Separate sequencer and full node e2e tests
Manav-Aggarwal Jun 25, 2025
ca15034
Add full node state root verification
Manav-Aggarwal Jun 25, 2025
5091f89
add Double-Spend/Nonce Handling Test
Manav-Aggarwal Jun 25, 2025
c350346
Add Invalid Transaction Rejection Test
Manav-Aggarwal Jun 25, 2025
9ed2542
Add TestEvmFullNodeBlockPropagationE2E
Manav-Aggarwal Jun 25, 2025
9d20daf
Refactor more
Manav-Aggarwal Jun 25, 2025
303c580
Update file headers
Manav-Aggarwal Jun 25, 2025
c4bca3f
Refactor more
Manav-Aggarwal Jun 25, 2025
81afb2d
Add E2Etest for lazy sequencing + full node
Manav-Aggarwal Jun 25, 2025
f9855c8
test: Add sequencer restart/recovery test and revert ExecuteTxs to us…
Manav-Aggarwal Jun 26, 2025
7b7be7e
Update README
Manav-Aggarwal Jun 26, 2025
9ee6b46
Speed up tests
Manav-Aggarwal Jun 26, 2025
3b2827c
Make restart test CI friendly
Manav-Aggarwal Jun 26, 2025
fd7ab38
Extend testSequencerRecoveryTest with lazy mode
Manav-Aggarwal Jun 26, 2025
c674f5f
Extend to different combinations of lazy and normal mode
Manav-Aggarwal Jun 26, 2025
e15477d
fix timestamp validation
Manav-Aggarwal Jun 27, 2025
bea5d7e
Update timestamp to be in seconds
Manav-Aggarwal Jun 27, 2025
86f9f69
Update e2e tests to use 100ms block time
Manav-Aggarwal Jun 27, 2025
23ee053
address nit comment
Manav-Aggarwal Jun 30, 2025
1df4ebc
update volume
Manav-Aggarwal Jun 30, 2025
2e76463
Update test/e2e/evm_full_node_e2e_test.go
Manav-Aggarwal Jun 30, 2025
5171bed
update makefile logs
Manav-Aggarwal Jul 1, 2025
0c8d343
Revert "feat: execution verification (#2377)"
Manav-Aggarwal Jul 1, 2025
d6aee4b
Revert "fix: getPeers size check (#2408)"
Manav-Aggarwal Jul 1, 2025
badfe37
Revert "feat: migrate logging to ipfs/go-log/v2 (#2411)"
Manav-Aggarwal Jul 1, 2025
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
Prev Previous commit
Next Next commit
Revert "feat: execution verification (#2377)"
This reverts commit 1ca8457.
  • Loading branch information
Manav-Aggarwal committed Jul 1, 2025
commit 0c8d343e12c44293fa3362304c159f6211a73f09
2 changes: 1 addition & 1 deletion apps/testapp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ replace (
require (
github.com/ipfs/go-datastore v0.8.2
github.com/rollkit/rollkit v0.0.0-00010101000000-000000000000
github.com/rollkit/rollkit/core v0.0.0-20250312114929-104787ba1a4c
github.com/rollkit/rollkit/da v0.0.0-00010101000000-000000000000
github.com/rollkit/rollkit/sequencers/single v0.0.0-00010101000000-000000000000
github.com/spf13/cobra v1.9.1
Expand Down Expand Up @@ -142,6 +141,7 @@ require (
github.com/quic-go/quic-go v0.50.1 // indirect
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rollkit/rollkit/core v0.0.0-20250312114929-104787ba1a4c // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
7 changes: 0 additions & 7 deletions apps/testapp/kv/kvexecutor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

ds "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/query"
"github.com/rollkit/rollkit/core/execution"
"github.com/rollkit/rollkit/pkg/store"
)

Expand Down Expand Up @@ -244,12 +243,6 @@ func (k *KVExecutor) SetFinal(ctx context.Context, blockHeight uint64) error {
return k.db.Put(ctx, ds.NewKey("/finalizedHeight"), []byte(fmt.Sprintf("%d", blockHeight)))
}

// GetExecutionMode returns the execution mode for this executor.
// KVExecutor uses delayed execution mode.
func (k *KVExecutor) GetExecutionMode() execution.ExecutionMode {
return execution.ExecutionModeDelayed
}

// InjectTx adds a transaction to the mempool channel.
// Uses a non-blocking send to avoid blocking the caller if the channel is full.
func (k *KVExecutor) InjectTx(tx []byte) {
Expand Down
149 changes: 35 additions & 114 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ type Manager struct {
metrics *Metrics

exec coreexecutor.Executor
// executionMode caches the execution mode from the executor
executionMode coreexecutor.ExecutionMode

// daIncludedHeight is rollkit height at which all blocks have been included
// in the DA
Expand Down Expand Up @@ -353,8 +351,6 @@ func NewManager(
daH := atomic.Uint64{}
daH.Store(s.DAHeight)

executionMode := exec.GetExecutionMode()

m := &Manager{
signer: signer,
config: config,
Expand Down Expand Up @@ -384,7 +380,6 @@ func NewManager(
metrics: seqMetrics,
sequencer: sequencer,
exec: exec,
executionMode: executionMode,
da: da,
gasPrice: gasPrice,
gasMultiplier: gasMultiplier,
Expand Down Expand Up @@ -805,26 +800,22 @@ func (m *Manager) execValidate(lastState types.State, header *types.SignedHeader
}

// // Verify that the header's timestamp is strictly greater than the last block's time
headerTime := header.Time()
if header.Height() > 1 && lastState.LastBlockTime.After(headerTime) {
return fmt.Errorf("block time must be strictly increasing: got %v, last block time was %v",
headerTime.UnixNano(), lastState.LastBlockTime)
}

// Validate AppHash based on execution mode
if m.executionMode == coreexecutor.ExecutionModeDelayed {
// In delayed mode, AppHash should match the last state's AppHash
if !bytes.Equal(header.AppHash, lastState.AppHash) {
return fmt.Errorf("appHash mismatch in delayed mode: expected %x, got %x", lastState.AppHash, header.AppHash)
}
}
// Note: For immediate mode, we can't validate AppHash against lastState because
// it represents the state after executing the current block's transactions
// headerTime := header.Time()
// if header.Height() > 1 && lastState.LastBlockTime.After(headerTime) {
// return fmt.Errorf("block time must be strictly increasing: got %v, last block time was %v",
// headerTime.UnixNano(), lastState.LastBlockTime)
// }

// // Validate that the header's AppHash matches the lastState's AppHash
// // Note: Assumes deferred execution
// if !bytes.Equal(header.AppHash, lastState.AppHash) {
// return fmt.Errorf("app hash mismatch: expected %x, got %x", lastState.AppHash, header.AppHash)
// }
Comment on lines 802 to +813

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Critical: Re-enable timestamp and AppHash validation to prevent consensus issues.

Commenting out these validations removes important safety checks:

  1. Timestamp validation: Prevents blocks with non-monotonic timestamps
  2. AppHash validation: Ensures state consistency between blocks

These checks are fundamental to blockchain integrity and should not be disabled without a compelling reason.

Why were these validations disabled? If there's a specific issue being addressed, consider a more targeted solution rather than removing these critical checks entirely.


🏁 Script executed:

#!/bin/bash
# Locate block/manager.go
file=$(fd manager.go | grep "block/manager\.go$")
echo "File path: $file"
# Show the commented out timestamp and AppHash validation lines with context
echo -e "\nTimestamp validation context:"
rg -C2 "header.Time" "$file"
echo -e "\nAppHash validation context:"
rg -C2 "header.AppHash" "$file"
# Check if any other part of the codebase enforces these validations elsewhere
echo -e "\nSearching for timestamp checks in applyBlock implementations:"
rg -n "Time().After" -C2 -g '*.go'
echo -e "\nSearching for AppHash comparisons elsewhere:"
rg -n "AppHash" -C2 -g '*.go'

Length of output: 33513


🏁 Script executed:

#!/bin/bash
# Show the applyBlock signature
rg -n "func .*applyBlock" -C3 block/manager.go
# Display lines 700-900 to see applyBlock implementation context
sed -n '700,900p' block/manager.go

Length of output: 7504


🏁 Script executed:

#!/bin/bash
# Locate NextState implementation in types/state.go
rg -n "func (.+)NextState" -C3 types/state.go

# Display NextState function body for deeper insight
rg -n "NextState" -A30 -B5 types/state.go

# Locate types.Validate(header, data) implementation
rg -n "func Validate" -C3 types/validate.go

# Display Validate function body
rg -n "Validate" -A30 -B5 types/validate.go

Length of output: 890


🏁 Script executed:

#!/bin/bash
# Search for all Validate functions to locate types.Validate and examine its implementation
echo "Listing all Validate function definitions:"
rg -n "func .*Validate" -C3 --glob '*.go'

# Search for any reference to types.Validate in imports or calls
echo -e "\nReferences to types.Validate:"
rg -n "types\.Validate" -C3 --glob '*.go'

# Inspect header.ValidateBasic implementation to see what checks it performs
echo -e "\nInspecting header.ValidateBasic:"
rg -n "func (h \*Header) ValidateBasic" -A20 -B5 --glob 'types/header.go'

Length of output: 13830


Re-enable timestamp and AppHash validation in execValidate

Both checks were commented out in block/manager.go but are essential to prevent blocks with non-monotonic times or mismatched state hashes from being accepted:

• File: block/manager.go (func Manager.execValidate, ≈lines 802–813)
• File: block/manager_test.go (tests for “app hash mismatch” around lines 594–600)

Suggested diff in execValidate:

@@ -800,6 +800,16 @@ func (m *Manager) execValidate(lastState types.State, header *types.SignedHeader, data *types.Data) error {
     // Check that the header's height is the expected next height
     expectedHeight := lastState.LastBlockHeight + 1
     if header.Height() != expectedHeight {
         return fmt.Errorf("invalid height: expected %d, got %d", expectedHeight, header.Height())
     }

+    // Verify that the header's timestamp is strictly greater than the last block's time
+    headerTime := header.Time()
+    if header.Height() > 1 && lastState.LastBlockTime.After(headerTime) {
+        return fmt.Errorf(
+            "block time must be strictly increasing: got %v, last block time was %v",
+            headerTime.UnixNano(), lastState.LastBlockTime,
+        )
+    }
+
+    // Validate that the header's AppHash matches lastState.AppHash
+    if !bytes.Equal(header.AppHash, lastState.AppHash) {
+        return fmt.Errorf("app hash mismatch: expected %x, got %x", lastState.AppHash, header.AppHash)
+    }

And restore or update the corresponding commented-out test in block/manager_test.go to assert that a bad AppHash or timestamp triggers an error.

🤖 Prompt for AI Agents
In block/manager.go around lines 802 to 813, re-enable the commented-out
validation checks in the execValidate function that ensure the block header's
timestamp is strictly greater than the last block's time and that the header's
AppHash matches the lastState's AppHash. Uncomment these checks to prevent
acceptance of blocks with non-monotonic timestamps or mismatched state hashes.
Additionally, in block/manager_test.go near lines 594 to 600, restore or update
the test cases to verify that invalid AppHash or timestamp values correctly
trigger validation errors.


return nil
}

func (m *Manager) execCreateBlock(ctx context.Context, height uint64, lastSignature *types.Signature, lastHeaderHash types.Hash, lastState types.State, batchData *BatchData) (*types.SignedHeader, *types.Data, error) {
func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignature *types.Signature, lastHeaderHash types.Hash, _ types.State, batchData *BatchData) (*types.SignedHeader, *types.Data, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential race condition: Use the passed lastState parameter instead of m.lastState.

The function ignores the lastState parameter and directly accesses m.lastState fields. This bypasses the mutex protection that the caller has already established. The caller acquires m.lastStateMtx.RLock() and passes a safe copy of the state, but this function ignores it.

Either:

  1. Use the passed lastState parameter (recommended)
  2. Remove the parameter if it's truly not needed
-func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignature *types.Signature, lastHeaderHash types.Hash, _ types.State, batchData *BatchData) (*types.SignedHeader, *types.Data, error) {
+func (m *Manager) execCreateBlock(_ context.Context, height uint64, lastSignature *types.Signature, lastHeaderHash types.Hash, lastState types.State, batchData *BatchData) (*types.SignedHeader, *types.Data, error) {
    // ... 
    header := &types.SignedHeader{
        Header: types.Header{
            Version: types.Version{
-               Block: m.lastState.Version.Block,
-               App:   m.lastState.Version.App,
+               Block: lastState.Version.Block,
+               App:   lastState.Version.App,
            },
            BaseHeader: types.BaseHeader{
-               ChainID: m.lastState.ChainID,
+               ChainID: lastState.ChainID,
                Height:  height,
                Time:    uint64(batchData.UnixNano()),
            },
            LastHeaderHash: lastHeaderHash,
            ConsensusHash:   make(types.Hash, 32),
-           AppHash:         m.lastState.AppHash,
+           AppHash:         lastState.AppHash,
            ProposerAddress: m.genesis.ProposerAddress,
        },

Also applies to: 846-857

🤖 Prompt for AI Agents
In block/manager.go around lines 818 and 846-857, the function execCreateBlock
ignores the passed lastState parameter and instead accesses m.lastState
directly, which can cause a race condition by bypassing the caller's mutex
protection. To fix this, replace all uses of m.lastState within these lines with
the passed lastState parameter to ensure thread-safe access. If lastState is
truly unused, consider removing the parameter, but using it is recommended to
maintain concurrency safety.

// Use when batchData is set to data IDs from the DA layer
// batchDataIDs := convertBatchDataToBytes(batchData.Data)

Expand All @@ -849,54 +840,21 @@ func (m *Manager) execCreateBlock(ctx context.Context, height uint64, lastSignat
// Determine if this is an empty block
isEmpty := batchData.Batch == nil || len(batchData.Transactions) == 0

// Create block data with appropriate transactions
blockData := &types.Data{
Txs: make(types.Txs, 0), // Start with empty transaction list
}

// Only add transactions if this is not an empty block
if !isEmpty {
blockData.Txs = make(types.Txs, len(batchData.Transactions))
for i := range batchData.Transactions {
blockData.Txs[i] = types.Tx(batchData.Transactions[i])
}
}

// Determine AppHash based on execution mode
var appHash []byte
if m.executionMode == coreexecutor.ExecutionModeImmediate && !isEmpty {
// For immediate execution, execute transactions now to get the new state root
rawTxs := make([][]byte, len(blockData.Txs))
for i := range blockData.Txs {
rawTxs[i] = blockData.Txs[i]
}

// Execute transactions
newStateRoot, _, err := m.exec.ExecuteTxs(ctx, rawTxs, height, batchData.Time, lastState.AppHash)
if err != nil {
return nil, nil, fmt.Errorf("failed to execute transactions for immediate mode: %w", err)
}
appHash = newStateRoot
} else {
// For delayed execution or empty blocks, use the app hash from last state
appHash = lastState.AppHash
}

header := &types.SignedHeader{
Header: types.Header{
Version: types.Version{
Block: lastState.Version.Block,
App: lastState.Version.App,
Block: m.lastState.Version.Block,
App: m.lastState.Version.App,
},
BaseHeader: types.BaseHeader{
ChainID: lastState.ChainID,
ChainID: m.lastState.ChainID,
Height: height,
Time: uint64(batchData.UnixNano()), //nolint:gosec // why is time unix? (tac0turtle)
},
LastHeaderHash: lastHeaderHash,
// DataHash is set below
// DataHash is set at the end of the function
ConsensusHash: make(types.Hash, 32),
AppHash: appHash,
AppHash: m.lastState.AppHash,
ProposerAddress: m.genesis.ProposerAddress,
},
Signature: *lastSignature,
Expand All @@ -906,8 +864,17 @@ func (m *Manager) execCreateBlock(ctx context.Context, height uint64, lastSignat
},
}

// Set DataHash
// Create block data with appropriate transactions
blockData := &types.Data{
Txs: make(types.Txs, 0), // Start with empty transaction list
}

// Only add transactions if this is not an empty block
if !isEmpty {
blockData.Txs = make(types.Txs, len(batchData.Transactions))
for i := range batchData.Transactions {
blockData.Txs[i] = types.Tx(batchData.Transactions[i])
}
header.DataHash = blockData.DACommitment()
} else {
header.DataHash = dataHashForEmptyTxs
Expand All @@ -917,61 +884,15 @@ func (m *Manager) execCreateBlock(ctx context.Context, height uint64, lastSignat
}

func (m *Manager) execApplyBlock(ctx context.Context, lastState types.State, header *types.SignedHeader, data *types.Data) (types.State, error) {
var newStateRoot []byte

// Check if we need to execute transactions
if m.executionMode == coreexecutor.ExecutionModeImmediate {
// For immediate mode, the aggregator already executed during block creation
// But syncing nodes need to execute to verify the AppHash
// Check if we're the block creator by verifying we signed this block
isBlockCreator := false
if m.signer != nil {
myAddress, err := m.signer.GetAddress()
if err == nil && bytes.Equal(header.ProposerAddress, myAddress) {
// Also verify this is the current height we're producing
currentHeight, err := m.store.Height(ctx)
if err == nil && header.Height() == currentHeight+1 {
isBlockCreator = true
}
}
}

if isBlockCreator {
// We created this block, so we already executed transactions in execCreateBlock
// Just use the AppHash from the header
newStateRoot = header.AppHash
} else {
// We're syncing this block, need to execute to verify AppHash
rawTxs := make([][]byte, len(data.Txs))
for i := range data.Txs {
rawTxs[i] = data.Txs[i]
}

ctx = context.WithValue(ctx, types.SignedHeaderContextKey, header)
computedStateRoot, _, err := m.exec.ExecuteTxs(ctx, rawTxs, header.Height(), header.Time(), lastState.AppHash)
if err != nil {
return types.State{}, fmt.Errorf("failed to execute transactions: %w", err)
}

// Verify the AppHash matches
if !bytes.Equal(header.AppHash, computedStateRoot) {
return types.State{}, fmt.Errorf("AppHash mismatch in immediate mode: expected %x, got %x", computedStateRoot, header.AppHash)
}
newStateRoot = computedStateRoot
}
} else {
// For delayed mode, always execute transactions
rawTxs := make([][]byte, len(data.Txs))
for i := range data.Txs {
rawTxs[i] = data.Txs[i]
}
rawTxs := make([][]byte, len(data.Txs))
for i := range data.Txs {
rawTxs[i] = data.Txs[i]
}

ctx = context.WithValue(ctx, types.SignedHeaderContextKey, header)
var err error
newStateRoot, _, err = m.exec.ExecuteTxs(ctx, rawTxs, header.Height(), header.Time(), lastState.AppHash)
if err != nil {
return types.State{}, fmt.Errorf("failed to execute transactions: %w", err)
}
ctx = context.WithValue(ctx, types.SignedHeaderContextKey, header)
newStateRoot, _, err := m.exec.ExecuteTxs(ctx, rawTxs, header.Height(), header.Time(), lastState.AppHash)
if err != nil {
return types.State{}, fmt.Errorf("failed to execute transactions: %w", err)
}

s, err := lastState.NextState(header, newStateRoot)
Expand Down
42 changes: 22 additions & 20 deletions block/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,26 +575,28 @@ func TestManager_execValidate(t *testing.T) {
require.NoError(err)
})

t.Run("non-monotonic block time with height > 1", func(t *testing.T) {
state, header, data, privKey := makeValid()
state.LastBlockTime = time.Now().Add(time.Minute)
state.LastBlockHeight = 1
header.BaseHeader.Height = state.LastBlockHeight + 1
data.Metadata.Height = state.LastBlockHeight + 1
signer, err := noopsigner.NewNoopSigner(privKey)
require.NoError(err)
header.Signature, err = types.GetSignature(header.Header, signer)
require.NoError(err)
err = m.execValidate(state, header, data)
require.ErrorContains(err, "block time must be strictly increasing")
})

t.Run("app hash mismatch", func(t *testing.T) {
state, header, data, _ := makeValid()
state.AppHash = []byte("different")
err := m.execValidate(state, header, data)
require.ErrorContains(err, "appHash mismatch in delayed mode")
})
// TODO: https://github.com/rollkit/rollkit/issues/2250

// t.Run("non-monotonic block time with height > 1", func(t *testing.T) {
// state, header, data, privKey := makeValid()
// state.LastBlockTime = time.Now().Add(time.Minute)
// state.LastBlockHeight = 1
// header.BaseHeader.Height = state.LastBlockHeight + 1
// data.Metadata.Height = state.LastBlockHeight + 1
// signer, err := noopsigner.NewNoopSigner(privKey)
// require.NoError(err)
// header.Signature, err = types.GetSignature(header.Header, signer)
// require.NoError(err)
// err = m.execValidate(state, header, data)
// require.ErrorContains(err, "block time must be strictly increasing")
// })

// t.Run("app hash mismatch", func(t *testing.T) {
// state, header, data, _ := makeValid()
// state.AppHash = []byte("different")
// err := m.execValidate(state, header, data)
// require.ErrorContains(err, "app hash mismatch")
// })
}

// TestGetterMethods tests simple getter methods for the Manager
Expand Down
5 changes: 0 additions & 5 deletions block/publish_block_p2p_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

coreexecution "github.com/rollkit/rollkit/core/execution"
coresequencer "github.com/rollkit/rollkit/core/sequencer"
"github.com/rollkit/rollkit/pkg/config"
genesispkg "github.com/rollkit/rollkit/pkg/genesis"
Expand Down Expand Up @@ -242,10 +241,6 @@ func (m mockExecutor) SetFinal(ctx context.Context, blockHeight uint64) error {
return nil
}

func (m mockExecutor) GetExecutionMode() coreexecution.ExecutionMode {
return coreexecution.ExecutionModeDelayed
}

var rnd = rand.New(rand.NewSource(1)) //nolint:gosec // test code only

func bytesN(n int) []byte {
Expand Down
6 changes: 0 additions & 6 deletions core/execution/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,6 @@ func (e *DummyExecutor) SetFinal(ctx context.Context, blockHeight uint64) error
return fmt.Errorf("cannot set finalized block at height %d", blockHeight)
}

// GetExecutionMode returns the execution mode for this executor.
// DummyExecutor uses delayed execution mode.
func (e *DummyExecutor) GetExecutionMode() ExecutionMode {
return ExecutionModeDelayed
}

func (e *DummyExecutor) removeExecutedTxs(txs [][]byte) {
e.injectedTxs = slices.DeleteFunc(e.injectedTxs, func(tx []byte) bool {
return slices.ContainsFunc(txs, func(t []byte) bool { return bytes.Equal(tx, t) })
Expand Down
31 changes: 0 additions & 31 deletions core/execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,6 @@ import (
"time"
)

// ExecutionMode defines when state transitions are applied relative to block creation
type ExecutionMode int

const (
// ExecutionModeDelayed means the AppHash in block N represents the state after executing block N-1
// This is the traditional approach used by CometBFT/Tendermint
ExecutionModeDelayed ExecutionMode = iota

// ExecutionModeImmediate means the AppHash in block N represents the state after executing block N
// Transactions are executed during block creation and the resulting state root is included
ExecutionModeImmediate

// ExecutionModeOptimistic means transactions are executed optimistically and finalized later
// This allows for faster block creation but requires a finalization step to confirm state
// ExecutionModeOptimistic
)

// Executor defines the interface that execution clients must implement to be compatible with Rollkit.
// This interface enables the separation between consensus and execution layers, allowing for modular
// and pluggable execution environments.
Expand Down Expand Up @@ -70,7 +53,6 @@ type Executor interface {
// - Must maintain deterministic execution
// - Must respect context cancellation/timeout
// - The rest of the rules are defined by the specific execution layer
// - Must verify state root after execution
//
// Parameters:
// - ctx: Context for timeout/cancellation control
Expand Down Expand Up @@ -100,17 +82,4 @@ type Executor interface {
// Returns:
// - error: Any errors during finalization
SetFinal(ctx context.Context, blockHeight uint64) error

// GetExecutionMode returns the execution mode supported by this executor.
// This determines when state transitions are applied:
// - Delayed: AppHash in block N represents state after executing block N-1
// - Immediate: AppHash in block N represents state after executing block N
//
// Requirements:
// - Must return consistent value across all calls
// - Mode cannot change after initialization
//
// Returns:
// - ExecutionMode: The execution mode supported by this executor
GetExecutionMode() ExecutionMode
}
7 changes: 0 additions & 7 deletions execution/evm/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,6 @@ func (c *EngineClient) SetFinal(ctx context.Context, blockHeight uint64) error {
return c.setFinal(ctx, blockHash, true)
}

// GetExecutionMode returns the execution mode for this executor.
// EngineClient uses immediate execution mode since it calculates the state root
// during transaction execution via engine_getPayloadV4.
func (c *EngineClient) GetExecutionMode() execution.ExecutionMode {
return execution.ExecutionModeImmediate
}

func (c *EngineClient) derivePrevRandao(blockHeight uint64) common.Hash {
return common.BigToHash(new(big.Int).SetUint64(blockHeight))
}
Expand Down
Loading