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 {
L1Head common.Hash
AgreedPrestate common.Hash
Claim common.Hash
ClaimTimestamp uint64
GameTimestamp uint64
}
type ConfigSource interface {
......@@ -112,6 +112,6 @@ func BootstrapInterop(r oracleClient) *BootInfoInterop {
L1Head: l1Head,
AgreedPrestate: agreedPrestate,
Claim: claim,
ClaimTimestamp: claimTimestamp,
GameTimestamp: claimTimestamp,
}
}
......@@ -20,14 +20,14 @@ func TestInteropBootstrap_SimpleValues(t *testing.T) {
L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482,
GameTimestamp: 49829482,
}
mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle)
require.Equal(t, expected.L1Head, actual.L1Head)
require.Equal(t, expected.AgreedPrestate, actual.AgreedPrestate)
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) {
......@@ -36,7 +36,7 @@ func TestInteropBootstrap_RollupConfigBuiltIn(t *testing.T) {
L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482,
GameTimestamp: 49829482,
}
mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle)
......@@ -52,7 +52,7 @@ func TestInteropBootstrap_RollupConfigCustom(t *testing.T) {
L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482,
GameTimestamp: 49829482,
}
mockOracle := newMockInteropBootstrapOracle(source, true)
mockOracle.rollupCfgs = []*rollup.Config{config1, config2}
......@@ -72,7 +72,7 @@ func TestInteropBootstrap_ChainConfigBuiltIn(t *testing.T) {
L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482,
GameTimestamp: 49829482,
}
mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle)
......@@ -88,7 +88,7 @@ func TestInteropBootstrap_ChainConfigCustom(t *testing.T) {
L1Head: common.Hash{0xaa},
AgreedPrestate: common.Hash{0xbb},
Claim: common.Hash{0xcc},
ClaimTimestamp: 49829482,
GameTimestamp: 49829482,
}
mockOracle := newMockInteropBootstrapOracle(expected, true)
mockOracle.chainCfgs = []*params.ChainConfig{config1, config2}
......@@ -109,7 +109,7 @@ func newMockInteropBootstrapOracle(b *BootInfoInterop, custom bool) *mockInterop
l1Head: b.L1Head,
l2OutputRoot: b.AgreedPrestate,
l2Claim: b.Claim,
l2ClaimBlockNumber: b.ClaimTimestamp,
l2ClaimBlockNumber: b.GameTimestamp,
},
custom: custom,
}
......
......@@ -63,6 +63,16 @@ func stateTransition(logger log.Logger, bootInfo *boot.BootInfoInterop, l1Preima
if err != nil {
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
if transitionState.Step < uint64(len(superRoot.Chains)) {
block, err := deriveOptimisticBlock(logger, bootInfo, l1PreimageOracle, l2PreimageOracle, superRoot, transitionState, tasks)
......
......@@ -67,7 +67,7 @@ func TestDeriveBlockForFirstChainFromSuperchainRoot(t *testing.T) {
}
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) {
......@@ -93,7 +93,7 @@ func TestDeriveBlockForSecondChainFromTransitionState(t *testing.T) {
}
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) {
......@@ -114,13 +114,39 @@ func TestNoOpStep(t *testing.T) {
expectedIntermediateRoot.Step = 3
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{
AgreedPrestate: agreedPrestate,
ClaimTimestamp: agreedSuperRoot.Timestamp + 1,
GameTimestamp: gameTimestamp,
Claim: expectedClaim,
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