Commit 0a7d1a61 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-program: Stop derivation once the claimed timestamp is reached (#13812)

* op-program: Stop derivation once the claimed timestamp is reached

* op-program: Add comment and switch to a panic if agreed is already after claimed
parent 4252ddd3
...@@ -22,7 +22,7 @@ type BootInfoInterop struct { ...@@ -22,7 +22,7 @@ type BootInfoInterop struct {
L1Head common.Hash L1Head common.Hash
AgreedPrestate common.Hash AgreedPrestate common.Hash
Claim common.Hash Claim common.Hash
ClaimTimestamp uint64 GameTimestamp uint64
} }
type ConfigSource interface { type ConfigSource interface {
...@@ -112,6 +112,6 @@ func BootstrapInterop(r oracleClient) *BootInfoInterop { ...@@ -112,6 +112,6 @@ func BootstrapInterop(r oracleClient) *BootInfoInterop {
L1Head: l1Head, L1Head: l1Head,
AgreedPrestate: agreedPrestate, AgreedPrestate: agreedPrestate,
Claim: claim, Claim: claim,
ClaimTimestamp: claimTimestamp, GameTimestamp: claimTimestamp,
} }
} }
...@@ -20,14 +20,14 @@ func TestInteropBootstrap_SimpleValues(t *testing.T) { ...@@ -20,14 +20,14 @@ func TestInteropBootstrap_SimpleValues(t *testing.T) {
L1Head: common.Hash{0xaa}, L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb}, AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc}, Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482, GameTimestamp: 49829482,
} }
mockOracle := newMockInteropBootstrapOracle(expected, false) mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle) actual := BootstrapInterop(mockOracle)
require.Equal(t, expected.L1Head, actual.L1Head) require.Equal(t, expected.L1Head, actual.L1Head)
require.Equal(t, expected.AgreedPrestate, actual.AgreedPrestate) require.Equal(t, expected.AgreedPrestate, actual.AgreedPrestate)
require.Equal(t, expected.Claim, actual.Claim) require.Equal(t, expected.Claim, actual.Claim)
require.Equal(t, expected.ClaimTimestamp, actual.ClaimTimestamp) require.Equal(t, expected.GameTimestamp, actual.GameTimestamp)
} }
func TestInteropBootstrap_RollupConfigBuiltIn(t *testing.T) { func TestInteropBootstrap_RollupConfigBuiltIn(t *testing.T) {
...@@ -36,7 +36,7 @@ func TestInteropBootstrap_RollupConfigBuiltIn(t *testing.T) { ...@@ -36,7 +36,7 @@ func TestInteropBootstrap_RollupConfigBuiltIn(t *testing.T) {
L1Head: common.Hash{0xaa}, L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb}, AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc}, Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482, GameTimestamp: 49829482,
} }
mockOracle := newMockInteropBootstrapOracle(expected, false) mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle) actual := BootstrapInterop(mockOracle)
...@@ -52,7 +52,7 @@ func TestInteropBootstrap_RollupConfigCustom(t *testing.T) { ...@@ -52,7 +52,7 @@ func TestInteropBootstrap_RollupConfigCustom(t *testing.T) {
L1Head: common.Hash{0xaa}, L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb}, AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc}, Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482, GameTimestamp: 49829482,
} }
mockOracle := newMockInteropBootstrapOracle(source, true) mockOracle := newMockInteropBootstrapOracle(source, true)
mockOracle.rollupCfgs = []*rollup.Config{config1, config2} mockOracle.rollupCfgs = []*rollup.Config{config1, config2}
...@@ -72,7 +72,7 @@ func TestInteropBootstrap_ChainConfigBuiltIn(t *testing.T) { ...@@ -72,7 +72,7 @@ func TestInteropBootstrap_ChainConfigBuiltIn(t *testing.T) {
L1Head: common.Hash{0xaa}, L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb}, AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc}, Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482, GameTimestamp: 49829482,
} }
mockOracle := newMockInteropBootstrapOracle(expected, false) mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle) actual := BootstrapInterop(mockOracle)
...@@ -88,7 +88,7 @@ func TestInteropBootstrap_ChainConfigCustom(t *testing.T) { ...@@ -88,7 +88,7 @@ func TestInteropBootstrap_ChainConfigCustom(t *testing.T) {
L1Head: common.Hash{0xaa}, L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb}, AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc}, Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482, GameTimestamp: 49829482,
} }
mockOracle := newMockInteropBootstrapOracle(expected, true) mockOracle := newMockInteropBootstrapOracle(expected, true)
mockOracle.chainCfgs = []*params.ChainConfig{config1, config2} mockOracle.chainCfgs = []*params.ChainConfig{config1, config2}
...@@ -109,7 +109,7 @@ func newMockInteropBootstrapOracle(b *BootInfoInterop, custom bool) *mockInterop ...@@ -109,7 +109,7 @@ func newMockInteropBootstrapOracle(b *BootInfoInterop, custom bool) *mockInterop
l1Head: b.L1Head, l1Head: b.L1Head,
l2OutputRoot: b.AgreedPrestate, l2OutputRoot: b.AgreedPrestate,
l2Claim: b.Claim, l2Claim: b.Claim,
l2ClaimBlockNumber: b.ClaimTimestamp, l2ClaimBlockNumber: b.GameTimestamp,
}, },
custom: custom, custom: custom,
} }
......
...@@ -63,6 +63,16 @@ func stateTransition(logger log.Logger, bootInfo *boot.BootInfoInterop, l1Preima ...@@ -63,6 +63,16 @@ func stateTransition(logger log.Logger, bootInfo *boot.BootInfoInterop, l1Preima
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
// Strictly, the state transition ends when superRoot.Timestamp == bootInfo.GameTimestamp.
// Since the valid state transition ends at the game timestamp, there isn't any valid hash resulting from
// an agreed prestate and so the program panics to make it clear that the setup is invalid.
// The honest actor will never agree to a prestate where superRoot.Timestamp > bootInfo.GameTimestamp and so will
// be unaffected by this
if superRoot.Timestamp == bootInfo.GameTimestamp {
return bootInfo.AgreedPrestate, nil
} else if superRoot.Timestamp > bootInfo.GameTimestamp {
panic(fmt.Errorf("agreed prestate timestamp %v is after the game timestamp %v", superRoot.Timestamp, bootInfo.GameTimestamp))
}
expectedPendingProgress := transitionState.PendingProgress expectedPendingProgress := transitionState.PendingProgress
if transitionState.Step < uint64(len(superRoot.Chains)) { if transitionState.Step < uint64(len(superRoot.Chains)) {
block, err := deriveOptimisticBlock(logger, bootInfo, l1PreimageOracle, l2PreimageOracle, superRoot, transitionState, tasks) block, err := deriveOptimisticBlock(logger, bootInfo, l1PreimageOracle, l2PreimageOracle, superRoot, transitionState, tasks)
......
...@@ -67,7 +67,7 @@ func TestDeriveBlockForFirstChainFromSuperchainRoot(t *testing.T) { ...@@ -67,7 +67,7 @@ func TestDeriveBlockForFirstChainFromSuperchainRoot(t *testing.T) {
} }
expectedClaim := expectedIntermediateRoot.Hash() expectedClaim := expectedIntermediateRoot.Hash()
verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, agreedSuperRoot, outputRootHash, expectedClaim) verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, outputRootHash, agreedSuperRoot.Timestamp+100000, expectedClaim)
} }
func TestDeriveBlockForSecondChainFromTransitionState(t *testing.T) { func TestDeriveBlockForSecondChainFromTransitionState(t *testing.T) {
...@@ -93,7 +93,7 @@ func TestDeriveBlockForSecondChainFromTransitionState(t *testing.T) { ...@@ -93,7 +93,7 @@ func TestDeriveBlockForSecondChainFromTransitionState(t *testing.T) {
} }
expectedClaim := expectedIntermediateRoot.Hash() expectedClaim := expectedIntermediateRoot.Hash()
verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, agreedSuperRoot, outputRootHash, expectedClaim) verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, outputRootHash, agreedSuperRoot.Timestamp+100000, expectedClaim)
} }
func TestNoOpStep(t *testing.T) { func TestNoOpStep(t *testing.T) {
...@@ -114,13 +114,39 @@ func TestNoOpStep(t *testing.T) { ...@@ -114,13 +114,39 @@ func TestNoOpStep(t *testing.T) {
expectedIntermediateRoot.Step = 3 expectedIntermediateRoot.Step = 3
expectedClaim := expectedIntermediateRoot.Hash() expectedClaim := expectedIntermediateRoot.Hash()
verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, agreedSuperRoot, outputRootHash, expectedClaim) verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, outputRootHash, agreedSuperRoot.Timestamp+100000, expectedClaim)
} }
func verifyResult(t *testing.T, logger log.Logger, tasks stubTasks, configSource *staticConfigSource, l2PreimageOracle *test.StubBlockOracle, agreedSuperRoot *eth.SuperV1, agreedPrestate common.Hash, expectedClaim common.Hash) { func TestTraceExtensionOnceClaimedTimestampIsReached(t *testing.T) {
logger := testlog.Logger(t, log.LevelError)
configSource, agreedSuperRoot, tasksStub := setupTwoChains()
agreedPrestatehash := common.Hash(eth.SuperRoot(agreedSuperRoot))
l2PreimageOracle, _ := test.NewStubOracle(t)
l2PreimageOracle.TransitionStates[agreedPrestatehash] = &types.TransitionState{SuperRoot: agreedSuperRoot.Marshal()}
// We have reached the game's timestamp so should just trace extend the agreed claim
expectedClaim := agreedPrestatehash
verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, agreedPrestatehash, agreedSuperRoot.Timestamp, expectedClaim)
}
func TestPanicIfAgreedPrestateIsAfterGameTimestamp(t *testing.T) {
logger := testlog.Logger(t, log.LevelError)
configSource, agreedSuperRoot, tasksStub := setupTwoChains()
agreedPrestatehash := common.Hash(eth.SuperRoot(agreedSuperRoot))
l2PreimageOracle, _ := test.NewStubOracle(t)
l2PreimageOracle.TransitionStates[agreedPrestatehash] = &types.TransitionState{SuperRoot: agreedSuperRoot.Marshal()}
// We have reached the game's timestamp so should just trace extend the agreed claim
expectedClaim := agreedPrestatehash
require.PanicsWithError(t, fmt.Sprintf("agreed prestate timestamp %v is after the game timestamp %v", agreedSuperRoot.Timestamp, agreedSuperRoot.Timestamp-1), func() {
verifyResult(t, logger, tasksStub, configSource, l2PreimageOracle, agreedPrestatehash, agreedSuperRoot.Timestamp-1, expectedClaim)
})
}
func verifyResult(t *testing.T, logger log.Logger, tasks stubTasks, configSource *staticConfigSource, l2PreimageOracle *test.StubBlockOracle, agreedPrestate common.Hash, gameTimestamp uint64, expectedClaim common.Hash) {
bootInfo := &boot.BootInfoInterop{ bootInfo := &boot.BootInfoInterop{
AgreedPrestate: agreedPrestate, AgreedPrestate: agreedPrestate,
ClaimTimestamp: agreedSuperRoot.Timestamp + 1, GameTimestamp: gameTimestamp,
Claim: expectedClaim, Claim: expectedClaim,
Configs: configSource, Configs: configSource,
} }
......
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