Skip to content

Commit

Permalink
Wait for a minimum amount of time since parent assertion was created …
Browse files Browse the repository at this point in the history
…to post a new assertion
  • Loading branch information
ganeshvanahalli committed Dec 9, 2024
1 parent d0a87de commit 1b1c34c
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 33 deletions.
30 changes: 22 additions & 8 deletions assertions/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,19 @@ var (
)

type timings struct {
pollInterval time.Duration
confInterval time.Duration
postInterval time.Duration
avgBlockTime time.Duration
pollInterval time.Duration
confInterval time.Duration
postInterval time.Duration
avgBlockTime time.Duration
minGapToParent time.Duration
}

var defaultTimings = timings{
pollInterval: time.Minute,
confInterval: time.Second * 10,
postInterval: time.Hour,
avgBlockTime: time.Second * 12,
pollInterval: time.Minute,
confInterval: time.Second * 10,
postInterval: time.Hour,
avgBlockTime: time.Second * 12,
minGapToParent: time.Minute * 10, // Correct default?
}

// The Manager struct is responsible for several tasks related to the assertion
Expand Down Expand Up @@ -167,6 +169,18 @@ func WithAverageBlockCreationTime(t time.Duration) Opt {
}
}

// WithMinimumGapToParentAssertion overrides the default minimum gap (in duration)
// to parent assertion creation time.
//
// The minimum gap to parent assertion is used by the assertion manager to wait
// until this much amount of duration is passed since the parent assertion was created
// before posting a new assertion.
func WithMinimumGapToParentAssertion(t time.Duration) Opt {
return func(m *Manager) {
m.times.minGapToParent = t
}
}

// NewManager creates a manager from the required dependencies.
func NewManager(
chain protocol.AssertionChain,
Expand Down
5 changes: 5 additions & 0 deletions assertions/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func TestSkipsProcessingAssertionFromEvilFork(t *testing.T) {
types.DefensiveMode,
assertions.WithPollingInterval(time.Millisecond*200),
assertions.WithAverageBlockCreationTime(time.Second),
assertions.WithMinimumGapToParentAssertion(0),
assertions.WithPostingDisabled(),
)
require.NoError(t, err)
Expand Down Expand Up @@ -305,6 +306,7 @@ func TestComplexAssertionForkScenario(t *testing.T) {
types.DefensiveMode,
assertions.WithPollingInterval(time.Millisecond*200),
assertions.WithAverageBlockCreationTime(time.Second),
assertions.WithMinimumGapToParentAssertion(0),
assertions.WithPostingDisabled(),
)
require.NoError(t, err)
Expand Down Expand Up @@ -376,6 +378,7 @@ func TestFastConfirmation(t *testing.T) {
types.ResolveMode,
assertions.WithPollingInterval(time.Millisecond*200),
assertions.WithAverageBlockCreationTime(time.Second),
assertions.WithMinimumGapToParentAssertion(0),
assertions.WithFastConfirmation(),
)
require.NoError(t, err)
Expand Down Expand Up @@ -448,6 +451,7 @@ func TestFastConfirmationWithSafe(t *testing.T) {
types.ResolveMode,
assertions.WithPollingInterval(time.Millisecond*200),
assertions.WithAverageBlockCreationTime(time.Second),
assertions.WithMinimumGapToParentAssertion(0),
assertions.WithDangerousReadyToPost(),
assertions.WithPostingDisabled(),
assertions.WithFastConfirmation(),
Expand Down Expand Up @@ -489,6 +493,7 @@ func TestFastConfirmationWithSafe(t *testing.T) {
types.ResolveMode,
assertions.WithPollingInterval(time.Millisecond*200),
assertions.WithAverageBlockCreationTime(time.Second),
assertions.WithMinimumGapToParentAssertion(0),
assertions.WithDangerousReadyToPost(),
assertions.WithPostingDisabled(),
assertions.WithFastConfirmation(),
Expand Down
61 changes: 36 additions & 25 deletions assertions/poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ package assertions
import (
"context"
"fmt"
"math/big"
"time"

"github.com/ccoveille/go-safecast"
"github.com/pkg/errors"

"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -37,36 +39,33 @@ func (m *Manager) postAssertionRoutine(ctx context.Context) {
exceedsMaxMempoolSizeEphemeralErrorHandler := ephemeral.NewEphemeralErrorHandler(10*time.Minute, "posting this transaction will exceed max mempool size", 0)

log.Info("Ready to post")
if _, err := m.PostAssertion(ctx); err != nil {
if !errors.Is(err, solimpl.ErrAlreadyExists) {
logLevel := log.Error
logLevel = exceedsMaxMempoolSizeEphemeralErrorHandler.LogLevel(err, logLevel)

logLevel("Could not submit latest assertion to L1", "err", err)
errorPostingAssertionCounter.Inc(1)
}
}
ticker := time.NewTicker(m.times.postInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
_, err := m.PostAssertion(ctx)
if err != nil {
switch {
case errors.Is(err, solimpl.ErrAlreadyExists):
case errors.Is(err, solimpl.ErrBatchNotYetFound):
log.Info("Waiting for more batches to post assertions about them onchain")
default:
logLevel := log.Error
logLevel = exceedsMaxMempoolSizeEphemeralErrorHandler.LogLevel(err, logLevel)

logLevel("Could not submit latest assertion", "err", err, "validatorName", m.validatorName)
errorPostingAssertionCounter.Inc(1)
_, err := m.PostAssertion(ctx)
if err != nil {
switch {
case errors.Is(err, solimpl.ErrAlreadyExists):
case errors.Is(err, solimpl.ErrBatchNotYetFound):
log.Info("Waiting for more batches to post assertions about them onchain")
default:
logLevel := log.Error
logLevel = exceedsMaxMempoolSizeEphemeralErrorHandler.LogLevel(err, logLevel)

logLevel("Could not submit latest assertion", "err", err, "validatorName", m.validatorName)
errorPostingAssertionCounter.Inc(1)

if ctx.Err() != nil {
return
}
} else {
exceedsMaxMempoolSizeEphemeralErrorHandler.Reset()
continue // We retry again in case of a non ctx error
}
} else {
exceedsMaxMempoolSizeEphemeralErrorHandler.Reset()
}

select {
case <-ticker.C:
case <-ctx.Done():
return
}
Expand Down Expand Up @@ -140,6 +139,18 @@ func (m *Manager) PostAssertionBasedOnParent(
) (protocol.Assertion, error),
) (option.Option[*protocol.AssertionCreatedInfo], error) {
none := option.None[*protocol.AssertionCreatedInfo]()
if m.times.minGapToParent != 0 {
parentCreationBlock, err := m.backend.HeaderByNumber(ctx, new(big.Int).SetUint64(parentCreationInfo.CreationBlock))
if err != nil {
return none, fmt.Errorf("error getting parent assertion creation block header: %w", err)
}
parentCreationTime, err := safecast.ToInt64(parentCreationBlock.Time)
if err != nil {
return none, fmt.Errorf("error casting parent assertion creation time to int64: %w", err)
}
targetTime := time.Unix(parentCreationTime, 0).Add(m.times.minGapToParent)
time.Sleep(time.Until(targetTime))
}
if !parentCreationInfo.InboxMaxCount.IsUint64() {
return none, errors.New("inbox max count not a uint64")
}
Expand Down
4 changes: 4 additions & 0 deletions assertions/poster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,17 @@ func TestPostAssertion(t *testing.T) {
stateManager, err := statemanager.NewForSimpleMachine(t, stateManagerOpts...)
require.NoError(t, err)

// Set MinimumGapToBlockCreationTime as 1 second to verify that a new assertion is only posted after 1 sec has passed
// from parent assertion creation. This will make the test run for ~19 seconds as the parent assertion time is
// ~18 seconds in the future
assertionManager, err := assertions.NewManager(
aliceChain,
stateManager,
"alice",
types.DefensiveMode,
assertions.WithPollingInterval(time.Millisecond*200),
assertions.WithAverageBlockCreationTime(time.Second),
assertions.WithMinimumGapToParentAssertion(time.Second),
)
require.NoError(t, err)

Expand Down
11 changes: 11 additions & 0 deletions challenge-manager/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type stackParams struct {
postInterval time.Duration
confInterval time.Duration
avgBlockTime time.Duration
minGapToParent time.Duration
trackChallengeParentAssertionHashes []protocol.AssertionHash
apiAddr string
apiDBPath string
Expand All @@ -44,6 +45,7 @@ var defaultStackParams = stackParams{
postInterval: time.Hour,
confInterval: time.Second * 10,
avgBlockTime: time.Second * 12,
minGapToParent: time.Minute * 10,
trackChallengeParentAssertionHashes: nil,
apiAddr: "",
apiDBPath: "",
Expand Down Expand Up @@ -100,6 +102,14 @@ func StackWithAverageBlockCreationTime(interval time.Duration) StackOpt {
}
}

// StackWithMinimumGapToParentAssertion sets the minimum gap to parent assertion creation time
// of the challenge manager.
func StackWithMinimumGapToParentAssertion(interval time.Duration) StackOpt {
return func(p *stackParams) {
p.minGapToParent = interval
}
}

// WithTrackChallengeParentAssertionHashes sets the track challenge parent
// assertion hashes of the challenge manager.
func StackWithTrackChallengeParentAssertionHashes(hashes []string) StackOpt {
Expand Down Expand Up @@ -211,6 +221,7 @@ func NewChallengeStack(
assertions.WithConfirmationInterval(params.confInterval),
assertions.WithPollingInterval(params.pollInterval),
assertions.WithPostingInterval(params.postInterval),
assertions.WithMinimumGapToParentAssertion(params.minGapToParent),
}
if apiDB != nil {
amOpts = append(amOpts, assertions.WithAPIDB(apiDB))
Expand Down
1 change: 1 addition & 0 deletions testing/endtoend/e2e_crash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func TestEndToEnd_HonestValidatorCrashes(t *testing.T) {
cm.StackWithPostingInterval(timeCfg.assertionPostingInterval),
cm.StackWithAverageBlockCreationTime(timeCfg.blockTime),
cm.StackWithConfirmationInterval(timeCfg.assertionConfirmationAttemptInterval),
cm.StackWithMinimumGapToParentAssertion(0),
cm.StackWithHeaderProvider(shp),
}

Expand Down
1 change: 1 addition & 0 deletions testing/endtoend/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ func runEndToEndTest(t *testing.T, cfg *e2eConfig) {
cm.StackWithPostingInterval(cfg.timings.assertionPostingInterval),
cm.StackWithAverageBlockCreationTime(cfg.timings.blockTime),
cm.StackWithConfirmationInterval(cfg.timings.assertionConfirmationAttemptInterval),
cm.StackWithMinimumGapToParentAssertion(0),
cm.StackWithHeaderProvider(shp),
}

Expand Down

0 comments on commit 1b1c34c

Please sign in to comment.