Skip to content

Commit

Permalink
Merge branch 'main' into bold_fast_confirm
Browse files Browse the repository at this point in the history
  • Loading branch information
amsanghi authored Feb 13, 2025
2 parents 157cd7b + efdfb6e commit 88bcfdd
Show file tree
Hide file tree
Showing 11 changed files with 390 additions and 83 deletions.
10 changes: 10 additions & 0 deletions assertions/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ type Manager struct {
delegatedStaking bool
autoDeposit bool
autoAllowanceApproval bool
maxGetLogBlocks uint64
}

type assertionChainData struct {
Expand Down Expand Up @@ -192,6 +193,14 @@ func WithAverageBlockCreationTime(t time.Duration) Opt {
}
}

// WithMaxGetLogBlocks overrides the default maximum number of blocks to get
// logs for in a single call.
func WithMaxGetLogBlocks(n uint64) Opt {
return func(m *Manager) {
m.maxGetLogBlocks = n
}
}

// WithMinimumGapToParentAssertion overrides the default minimum gap (in duration)
// to parent assertion creation time.
//
Expand Down Expand Up @@ -238,6 +247,7 @@ func NewManager(
rivalHandler: nil, // Must be set after construction if mode > DefensiveMode
autoDeposit: true,
autoAllowanceApproval: true,
maxGetLogBlocks: 1000,
}
for _, o := range opts {
o(m)
Expand Down
2 changes: 2 additions & 0 deletions assertions/poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ func (m *Manager) PostAssertionBasedOnParent(
"latestStakedAssertionBatchCount", batchCount,
"latestStakedAssertionBlockHash", containers.Trunc(parentBlockHash[:]),
)
// If the chain is catching up, we wait for a bit and try again.
time.Sleep(m.times.avgBlockTime / 10)
return none, nil
}
return none, errors.Wrapf(err, "could not get execution state at batch count %d with parent block hash %v", batchCount, parentBlockHash)
Expand Down
38 changes: 23 additions & 15 deletions assertions/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,28 @@ func (m *Manager) syncAssertions(ctx context.Context) {
return
}
if fromBlock != toBlock {
filterOpts := &bind.FilterOpts{
Start: fromBlock,
End: &toBlock,
Context: ctx,
}
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
innerErr := m.processAllAssertionsInRange(ctx, filterer, filterOpts)
if innerErr != nil {
log.Error("Could not process assertions in range", "err", innerErr)
return false, innerErr
for startBlock := fromBlock; startBlock <= toBlock; startBlock = startBlock + m.maxGetLogBlocks {
endBlock := startBlock + m.maxGetLogBlocks
if endBlock > toBlock {
endBlock = toBlock
}
filterOpts := &bind.FilterOpts{
Start: startBlock,
End: &endBlock,
Context: ctx,
}
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
innerErr := m.processAllAssertionsInRange(ctx, filterer, filterOpts)
if innerErr != nil {
log.Error("Could not process assertions in range", "err", innerErr)
return false, innerErr
}
return true, nil
})
if err != nil {
log.Error("Could not check for assertion added event")
return
}
return true, nil
})
if err != nil {
log.Error("Could not check for assertion added event")
return
}
fromBlock = toBlock
}
Expand Down Expand Up @@ -279,6 +285,8 @@ func (m *Manager) findCanonicalAssertionBranch(
chainCatchingUpCounter.Inc(1)
log.Info("Chain still syncing "+
"will reattempt processing when caught up", "err", err)
// If the chain is catching up, we wait for a bit and try again.
time.Sleep(m.times.avgBlockTime / 10)
return false, l2stateprovider.ErrChainCatchingUp
case err != nil:
return false, err
Expand Down
12 changes: 2 additions & 10 deletions chain-abstraction/sol-implementation/assertion_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,19 +500,11 @@ func (a *AssertionChain) NewStake(
if err != nil {
return err
}
if !staked {
if staked {
return nil
}
latestConfirmed, err := a.LatestConfirmed(ctx, a.GetCallOptsWithDesiredRpcHeadBlockNumber(&bind.CallOpts{Context: ctx}))
if err != nil {
return err
}
info, err := a.ReadAssertionCreationInfo(ctx, latestConfirmed.Id())
if err != nil {
return err
}
_, err = a.transact(ctx, a.backend, func(opts *bind.TransactOpts) (*types.Transaction, error) {
return a.userLogic.RollupUserLogicTransactor.NewStake(opts, info.RequiredStake, a.withdrawalAddress)
return a.userLogic.RollupUserLogicTransactor.NewStake(opts, new(big.Int), a.withdrawalAddress)
})
return err
}
Expand Down
11 changes: 11 additions & 0 deletions chain-abstraction/sol-implementation/assertion_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ import (
"github.com/offchainlabs/bold/testing/setup"
)

func TestNewEmptyStake(t *testing.T) {
ctx := context.Background()
cfg, err := setup.ChainsWithEdgeChallengeManager()
require.NoError(t, err)
chain := cfg.Chains[0]
require.NoError(t, chain.NewStake(ctx))
isStaked, err := chain.IsStaked(ctx)
require.NoError(t, err)
require.True(t, isStaked)
}

func TestNewStakeOnNewAssertion(t *testing.T) {
ctx := context.Background()
cfg, err := setup.ChainsWithEdgeChallengeManager()
Expand Down
86 changes: 44 additions & 42 deletions challenge-manager/chain-watcher/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"context"
"fmt"
"math"
"math/big"
"sync/atomic"
"time"

Expand Down Expand Up @@ -88,7 +87,7 @@ type Watcher struct {
// Only track challenges for these parent assertion hashes.
// Track all if empty / nil.
trackChallengeParentAssertionHashes []protocol.AssertionHash
maxLookbackBlocks uint64
maxGetLogBlocks uint64
}

// New initializes a watcher service for frequently scanning the chain
Expand All @@ -101,7 +100,7 @@ func New(
assertionConfirmingInterval time.Duration,
averageTimeForBlockCreation time.Duration,
trackChallengeParentAssertionHashes []protocol.AssertionHash,
maxLookbackBlocks uint64,
maxGetLogBlocks uint64,
) (*Watcher, error) {
return &Watcher{
chain: chain,
Expand All @@ -117,7 +116,7 @@ func New(
averageTimeForBlockCreation: averageTimeForBlockCreation,
evilEdgesByLevel: threadsafe.NewMap(threadsafe.MapWithMetric[protocol.ChallengeLevel, *threadsafe.Set[protocol.EdgeId]]("evilEdgesByLevel")),
trackChallengeParentAssertionHashes: trackChallengeParentAssertionHashes,
maxLookbackBlocks: maxLookbackBlocks,
maxGetLogBlocks: maxGetLogBlocks,
}, nil
}

Expand Down Expand Up @@ -211,33 +210,39 @@ func (w *Watcher) Start(ctx context.Context) {
log.Error("Could not initialize edge challenge manager filterer", "err", err)
return
}
filterOpts := &bind.FilterOpts{
Start: fromBlock,
End: &toBlock,
Context: ctx,
}
for startBlock := fromBlock; startBlock <= toBlock; startBlock = startBlock + w.maxGetLogBlocks {
endBlock := startBlock + w.maxGetLogBlocks
if endBlock > toBlock {
endBlock = toBlock
}
filterOpts := &bind.FilterOpts{
Start: startBlock,
End: &endBlock,
Context: ctx,
}

// Checks for different events right away before we start polling.
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
return true, w.checkForEdgeAdded(ctx, filterer, filterOpts)
})
if err != nil {
log.Error("Could not check for edge added", "err", err)
return
}
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
return true, w.checkForEdgeConfirmedByOneStepProof(ctx, filterer, filterOpts)
})
if err != nil {
log.Error("Could not check for edge confirmed by osp", "err", err)
return
}
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
return true, w.checkForEdgeConfirmedByTime(ctx, filterer, filterOpts)
})
if err != nil {
log.Error("Could not check for edge confirmed by time", "err", err)
return
// Checks for different events right away before we start polling.
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
return true, w.checkForEdgeAdded(ctx, filterer, filterOpts)
})
if err != nil {
log.Error("Could not check for edge added", "err", err)
return
}
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
return true, w.checkForEdgeConfirmedByOneStepProof(ctx, filterer, filterOpts)
})
if err != nil {
log.Error("Could not check for edge confirmed by osp", "err", err)
return
}
_, err = retry.UntilSucceeds(ctx, func() (bool, error) {
return true, w.checkForEdgeConfirmedByTime(ctx, filterer, filterOpts)
})
if err != nil {
log.Error("Could not check for edge confirmed by time", "err", err)
return
}
}

fromBlock = toBlock
Expand Down Expand Up @@ -936,23 +941,20 @@ type filterRange struct {
// Gets the start and end block numbers for our filter queries, starting from
// the latest confirmed assertion's block number up to the latest block number.
func (w *Watcher) getStartEndBlockNum(ctx context.Context) (filterRange, error) {
desiredRPCBlock := w.chain.GetDesiredRpcHeadBlockNumber()
latestDesiredBlockHeader, err := w.chain.Backend().HeaderByNumber(ctx, big.NewInt(int64(desiredRPCBlock)))
latestConfirmedAssertion, err := retry.UntilSucceeds(ctx, func() (protocol.Assertion, error) {
return w.chain.LatestConfirmed(ctx, w.chain.GetCallOptsWithDesiredRpcHeadBlockNumber(&bind.CallOpts{Context: ctx}))
})
if err != nil {
return filterRange{}, err
}
if !latestDesiredBlockHeader.Number.IsUint64() {
return filterRange{}, errors.New("latest desired block number is not a uint64")
}
latestDesiredBlockNum := latestDesiredBlockHeader.Number.Uint64()
startBlock := latestDesiredBlockNum
if w.maxLookbackBlocks < startBlock {
startBlock = startBlock - w.maxLookbackBlocks
} else {
startBlock = 0
latestDesiredBlockNum, err := retry.UntilSucceeds(ctx, func() (uint64, error) {
return w.chain.DesiredHeaderU64(ctx)
})
if err != nil {
return filterRange{}, err
}
return filterRange{
startBlockNum: startBlock,
startBlockNum: latestConfirmedAssertion.CreatedAtBlock(),
endBlockNum: latestDesiredBlockNum,
}, nil
}
Expand Down
4 changes: 2 additions & 2 deletions challenge-manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func setupEdgeTrackersForBisection(
confInterval,
avgBlockTime,
nil,
100,
10,
)
require.NoError(t, err)
honestWatcher.SetEdgeManager(honestValidator)
Expand Down Expand Up @@ -219,7 +219,7 @@ func setupEdgeTrackersForBisection(
confInterval,
avgBlockTime,
nil,
100,
10,
)
require.NoError(t, err)
evilWatcher.SetEdgeManager(evilValidator)
Expand Down
22 changes: 9 additions & 13 deletions challenge-manager/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type stackParams struct {
headerProvider HeaderProvider
enableFastConfirmation bool
assertionManagerOverride *assertions.Manager
maxLookbackBlocks int64
maxGetLogBlocks int64
delegatedStaking bool
autoDeposit bool
autoAllowanceApproval bool
Expand All @@ -55,7 +55,7 @@ var defaultStackParams = stackParams{
headerProvider: nil,
enableFastConfirmation: false,
assertionManagerOverride: nil,
maxLookbackBlocks: blocksPerInterval(time.Second*12, 21*24*time.Hour), // Default to 3 weeks worth of blocks.
maxGetLogBlocks: 1000,
delegatedStaking: false,
autoDeposit: true,
autoAllowanceApproval: true,
Expand Down Expand Up @@ -150,11 +150,11 @@ func StackWithFastConfirmationEnabled() StackOpt {
}
}

// StackWithSyncMaxLookbackBlocks specifies the number of blocks behind the latest block
// to start syncing the chain watcher from.
func StackWithSyncMaxLookbackBlocks(maxLookback int64) StackOpt {
// StackWithSyncMaxGetLogBlocks specifies the max size chunks of blocks to use when using get logs rpc for
// when syncing the chain watcher.
func StackWithSyncMaxGetLogBlocks(maxGetLog int64) StackOpt {
return func(p *stackParams) {
p.maxLookbackBlocks = maxLookback
p.maxGetLogBlocks = maxGetLog
}
}

Expand Down Expand Up @@ -214,7 +214,7 @@ func NewChallengeStack(
}
provider.UpdateAPIDatabase(apiDB)
}
maxLookbackBlocks, err := safecast.ToUint64(params.maxLookbackBlocks)
maxGetLogBlocks, err := safecast.ToUint64(params.maxGetLogBlocks)
if err != nil {
return nil, err
}
Expand All @@ -228,7 +228,7 @@ func NewChallengeStack(
params.confInterval,
params.avgBlockTime,
params.trackChallengeParentAssertionHashes,
maxLookbackBlocks,
maxGetLogBlocks,
)
if err != nil {
return nil, err
Expand All @@ -254,6 +254,7 @@ func NewChallengeStack(
assertions.WithPollingInterval(params.pollInterval),
assertions.WithPostingInterval(params.postInterval),
assertions.WithMinimumGapToParentAssertion(params.minGapToParent),
assertions.WithMaxGetLogBlocks(maxGetLogBlocks),
}
if apiDB != nil {
amOpts = append(amOpts, assertions.WithAPIDB(apiDB))
Expand Down Expand Up @@ -297,8 +298,3 @@ func NewChallengeStack(
}
return New(chain, provider, watcher, asm, cmOpts...)
}

func blocksPerInterval(avgBlockTime time.Duration, interval time.Duration) int64 {
// Calculate the number of blocks as an integer division
return int64(interval / avgBlockTime)
}
Loading

0 comments on commit 88bcfdd

Please sign in to comment.