Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle getting creationAtBlock for l3 bold #732

Merged
merged 3 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion assertions/confirmation.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (m *Manager) keepTryingAssertionConfirmation(ctx context.Context, assertion
if parentAssertionHasSecondChild {
return
}
confirmed, err := solimpl.TryConfirmingAssertion(ctx, creationInfo.AssertionHash, prevCreationInfo.ConfirmPeriodBlocks+creationInfo.CreationBlock, m.chain, m.times.avgBlockTime, option.None[protocol.EdgeId]())
confirmed, err := solimpl.TryConfirmingAssertion(ctx, creationInfo.AssertionHash, prevCreationInfo.ConfirmPeriodBlocks+creationInfo.CreationL1Block, m.chain, m.times.avgBlockTime, option.None[protocol.EdgeId]())
if err != nil {
if !strings.Contains(err.Error(), "PREV_NOT_LATEST_CONFIRMED") {
logLevel := log.Error
Expand Down
8 changes: 4 additions & 4 deletions assertions/poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,13 @@ func (m *Manager) waitToPostIfNeeded(
}
minPeriodBlocks := m.chain.MinAssertionPeriodBlocks()
for {
latestBlockNumber, err := m.chain.DesiredHeaderU64(ctx)
latestL1BlockNumber, err := m.chain.DesiredL1HeaderU64(ctx)
if err != nil {
return err
}
blocksSinceLast := uint64(0)
if parentCreationInfo.CreationBlock < latestBlockNumber {
blocksSinceLast = latestBlockNumber - parentCreationInfo.CreationBlock
if parentCreationInfo.CreationL1Block < latestL1BlockNumber {
blocksSinceLast = latestL1BlockNumber - parentCreationInfo.CreationL1Block
}
if blocksSinceLast >= minPeriodBlocks {
return nil
Expand All @@ -235,7 +235,7 @@ func (m *Manager) waitToPostIfNeeded(
log.Info(
fmt.Sprintf("Need to wait %d blocks before posting next assertion. Current block number: %d",
minPeriodBlocks-blocksSinceLast,
latestBlockNumber,
latestL1BlockNumber,
),
)
select {
Expand Down
8 changes: 5 additions & 3 deletions assertions/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ func (m *Manager) syncAssertions(ctx context.Context) {
}
m.assertionChainData.Unlock()

fromBlock := latestConfirmed.CreatedAtBlock()

fromBlock, err := m.chain.GetAssertionCreationL1Block(ctx, latestConfirmed.Id().Hash)
if err != nil {
return
}
filterer, err := retry.UntilSucceeds(ctx, func() (*rollupgen.RollupUserLogicFilterer, error) {
return rollupgen.NewRollupUserLogicFilterer(m.rollupAddr, m.backend)
})
Expand Down Expand Up @@ -512,7 +514,7 @@ func (m *Manager) saveAssertionToDB(ctx context.Context, creationInfo *protocol.
if err != nil {
return err
}
firstChildBlock, err := assertion.SecondChildCreationBlock(ctx, opts)
firstChildBlock, err := assertion.FirstChildCreationBlock(ctx, opts)
if err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions chain-abstraction/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ type AssertionCreatedInfo struct {
ChallengeManager common.Address
TransactionHash common.Hash
CreationBlock uint64
CreationL1Block uint64
}

func (i AssertionCreatedInfo) ExecutionHash() common.Hash {
Expand All @@ -147,13 +148,15 @@ type AssertionChain interface {
IsChallengeComplete(ctx context.Context, challengeParentAssertionHash AssertionHash) (bool, error)
Backend() ChainBackend
DesiredHeaderU64(ctx context.Context) (uint64, error)
DesiredL1HeaderU64(ctx context.Context) (uint64, error)
RollupAddress() common.Address
StakerAddress() common.Address
AssertionStatus(
ctx context.Context,
assertionHash AssertionHash,
) (AssertionStatus, error)
LatestConfirmed(ctx context.Context, opts *bind.CallOpts) (Assertion, error)
GetAssertionCreationL1Block(ctx context.Context, assertionHash common.Hash) (uint64, error)
ReadAssertionCreationInfo(
ctx context.Context, id AssertionHash,
) (*AssertionCreatedInfo, error)
Expand Down
1 change: 1 addition & 0 deletions chain-abstraction/sol-implementation/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ go_library(
"//solgen/go/rollupgen",
"//solgen/go/testgen",
"//state-commitments/history",
"//util",
"@com_github_ccoveille_go_safecast//:go-safecast",
"@com_github_ethereum_go_ethereum//:go-ethereum",
"@com_github_ethereum_go_ethereum//accounts/abi",
Expand Down
51 changes: 32 additions & 19 deletions chain-abstraction/sol-implementation/assertion_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/offchainlabs/bold/solgen/go/mocksgen"
"github.com/offchainlabs/bold/solgen/go/rollupgen"
"github.com/offchainlabs/bold/solgen/go/testgen"
"github.com/offchainlabs/bold/util"
)

var (
Expand Down Expand Up @@ -313,6 +314,14 @@ func (a *AssertionChain) DesiredHeaderU64(ctx context.Context) (uint64, error) {
return header.Number.Uint64(), nil
}

func (a *AssertionChain) DesiredL1HeaderU64(ctx context.Context) (uint64, error) {
header, err := a.DesiredHeaderU64(ctx)
if err != nil {
return 0, err
}
return util.CorrespondingL1BlockNumber(ctx, a.backend, header)
}

func (a *AssertionChain) GetAssertion(ctx context.Context, opts *bind.CallOpts, assertionHash protocol.AssertionHash) (protocol.Assertion, error) {
var b [32]byte
copy(b[:], assertionHash.Bytes())
Expand All @@ -327,15 +336,10 @@ func (a *AssertionChain) GetAssertion(ctx context.Context, opts *bind.CallOpts,
assertionHash,
)
}

assertionCreationBlock, err := a.GetAssertionCreationBlock(ctx, b)
if err != nil {
return nil, err
}
return &Assertion{
id: assertionHash,
chain: a,
createdAt: assertionCreationBlock,
createdAt: res.CreatedAtBlock,
}, nil
}

Expand Down Expand Up @@ -701,20 +705,20 @@ func TryConfirmingAssertion(
return true, nil
}
for {
var latestHeaderNumber uint64
latestHeaderNumber, err = chain.DesiredHeaderU64(ctx)
var latestL1HeaderNumber uint64
latestL1HeaderNumber, err = chain.DesiredL1HeaderU64(ctx)
if err != nil {
return false, err
}
confirmable := latestHeaderNumber >= confirmableAfterBlock
confirmable := latestL1HeaderNumber >= confirmableAfterBlock

// If the assertion is not yet confirmable, we can simply wait.
if !confirmable {
var blocksLeftForConfirmation int64
if latestHeaderNumber > confirmableAfterBlock {
if latestL1HeaderNumber > confirmableAfterBlock {
blocksLeftForConfirmation = 0
} else {
blocksLeftForConfirmation, err = safecast.ToInt64(confirmableAfterBlock - latestHeaderNumber)
blocksLeftForConfirmation, err = safecast.ToInt64(confirmableAfterBlock - latestL1HeaderNumber)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -889,14 +893,14 @@ func (a *AssertionChain) AssertionUnrivaledBlocks(ctx context.Context, assertion
if !wantNode.IsFirstChild {
return 0, nil
}
assertionCreationBlock, err := a.GetAssertionCreationBlock(ctx, b)
assertionCreationBlock, err := a.GetAssertionCreationL1Block(ctx, b)
if err != nil {
return 0, err
}
assertion := &Assertion{
id: assertionHash,
chain: a,
createdAt: assertionCreationBlock,
createdAt: wantNode.CreatedAtBlock,
}
prevId, err := assertion.PrevId(ctx)
if err != nil {
Expand All @@ -921,17 +925,21 @@ func (a *AssertionChain) AssertionUnrivaledBlocks(ctx context.Context, assertion
if err != nil {
return 0, err
}
l1BlockNum, err := util.CorrespondingL1BlockNumber(ctx, a.backend, num)
if err != nil {
return 0, err
}

// Should never happen.
if assertionCreationBlock > num {
if assertionCreationBlock > l1BlockNum {
return 0, fmt.Errorf(
"assertion creation block %d > latest block number %d for assertion hash %#x",
assertionCreationBlock,
num,
l1BlockNum,
assertionHash,
)
}
return num - assertionCreationBlock, nil
return l1BlockNum - assertionCreationBlock, nil
}
// Should never happen.
if prevNode.FirstChildBlock > prevNode.SecondChildBlock {
Expand All @@ -945,12 +953,12 @@ func (a *AssertionChain) AssertionUnrivaledBlocks(ctx context.Context, assertion
return prevNode.SecondChildBlock - prevNode.FirstChildBlock, nil
}

// GetAssertionCreationBlock returns parent chain block number when the assertion was created.
// GetAssertionCreationL1Block returns parent chain block number when the assertion was created.
// assertion.CreatedAtBlock is the block number when the assertion was created on L1.
// But in case of L3, we need to look up the block number when the assertion was created on L2.
// To do this, we use getAssertionCreationBlockForLogLookup which returns the block number when the assertion was created
// on parent chain be it L2 or L1.
func (a *AssertionChain) GetAssertionCreationBlock(ctx context.Context, assertionHash common.Hash) (uint64, error) {
func (a *AssertionChain) GetAssertionCreationL1Block(ctx context.Context, assertionHash common.Hash) (uint64, error) {
callOpts := a.GetCallOptsWithDesiredRpcHeadBlockNumber(&bind.CallOpts{Context: ctx})
createdAtBlock, err := a.userLogic.GetAssertionCreationBlockForLogLookup(callOpts, assertionHash)
if err != nil {
Expand Down Expand Up @@ -1009,7 +1017,7 @@ func (a *AssertionChain) ReadAssertionCreationInfo(
var b [32]byte
copy(b[:], id.Bytes())
var err error
assertionCreationBlock, err = a.GetAssertionCreationBlock(ctx, b)
assertionCreationBlock, err = a.GetAssertionCreationL1Block(ctx, b)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1037,6 +1045,10 @@ func (a *AssertionChain) ReadAssertionCreationInfo(
return nil, err
}
afterState := parsedLog.Assertion.AfterState
creationL1Block, err := a.GetAssertionCreationL1Block(ctx, parsedLog.AssertionHash)
if err != nil {
return nil, err
}
return &protocol.AssertionCreatedInfo{
ConfirmPeriodBlocks: parsedLog.ConfirmPeriodBlocks,
RequiredStake: parsedLog.RequiredStake,
Expand All @@ -1050,6 +1062,7 @@ func (a *AssertionChain) ReadAssertionCreationInfo(
ChallengeManager: parsedLog.ChallengeManager,
TransactionHash: ethLog.TxHash,
CreationBlock: ethLog.BlockNumber,
CreationL1Block: creationL1Block,
}, nil
}

Expand Down
26 changes: 15 additions & 11 deletions challenge-manager/chain-watcher/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func (w *Watcher) Start(ctx context.Context) {
// GetRoyalEdges returns all royal, tracked edges in the watcher by assertion
// hash.
func (w *Watcher) GetRoyalEdges(ctx context.Context) (map[protocol.AssertionHash][]*api.JsonTrackedRoyalEdge, error) {
blockNum, err := w.chain.DesiredHeaderU64(ctx)
l1BlockNum, err := w.chain.DesiredL1HeaderU64(ctx)
if err != nil {
return nil, err
}
Expand All @@ -309,12 +309,12 @@ func (w *Watcher) GetRoyalEdges(ctx context.Context) (map[protocol.AssertionHash
if err2 != nil {
return err2
}
unrivaled, err2 := t.honestEdgeTree.IsUnrivaledAtBlockNum(edge, blockNum)
unrivaled, err2 := t.honestEdgeTree.IsUnrivaledAtBlockNum(edge, l1BlockNum)
if err2 != nil {
return err2
}
hasRival := !unrivaled
timeUnrivaled, err2 := t.honestEdgeTree.TimeUnrivaled(ctx, edge, blockNum)
timeUnrivaled, err2 := t.honestEdgeTree.TimeUnrivaled(ctx, edge, l1BlockNum)
if err2 != nil {
return err2
}
Expand Down Expand Up @@ -392,11 +392,11 @@ func (w *Watcher) ComputeAncestors(
challengedAssertionHash,
)
}
blockHeaderNumber, err := w.chain.DesiredHeaderU64(ctx)
l1BlockHeaderNumber, err := w.chain.DesiredL1HeaderU64(ctx)
if err != nil {
return nil, err
}
return chal.honestEdgeTree.ComputeAncestors(ctx, edgeId, blockHeaderNumber)
return chal.honestEdgeTree.ComputeAncestors(ctx, edgeId, l1BlockHeaderNumber)
}

func (w *Watcher) ClosestEssentialAncestor(
Expand Down Expand Up @@ -427,7 +427,7 @@ func (w *Watcher) IsEssentialAncestorConfirmable(
challengedAssertionHash,
)
}
blockHeaderNumber, err := w.chain.DesiredHeaderU64(ctx)
blockL1HeaderNumber, err := w.chain.DesiredL1HeaderU64(ctx)
if err != nil {
return false, err
}
Expand All @@ -441,7 +441,7 @@ func (w *Watcher) IsEssentialAncestorConfirmable(
pathWeight, err := chal.honestEdgeTree.ComputePathWeight(ctx, challengetree.ComputePathWeightArgs{
Child: edge.Id(),
Ancestor: essentialAncestor.Id(),
BlockNum: blockHeaderNumber,
BlockNum: blockL1HeaderNumber,
})
if err != nil {
return false, err
Expand All @@ -459,15 +459,15 @@ func (w *Watcher) IsConfirmableEssentialEdge(
if !ok {
return false, nil, 0, fmt.Errorf("could not get challenge for top level assertion %#x", challengedAssertionHash)
}
blockHeaderNumber, err := w.chain.DesiredHeaderU64(ctx)
blockL1HeaderNumber, err := w.chain.DesiredL1HeaderU64(ctx)
if err != nil {
return false, nil, 0, err
}
confirmable, essentialPaths, timer, err := chal.honestEdgeTree.IsConfirmableEssentialEdge(
ctx,
challengetree.IsConfirmableArgs{
EssentialEdge: essentialEdgeId,
BlockNum: blockHeaderNumber,
BlockNum: blockL1HeaderNumber,
ConfirmationThreshold: confirmationThreshold,
},
)
Expand Down Expand Up @@ -926,7 +926,7 @@ func challengedAssertionConfirmableBlock(
info *protocol.AssertionCreatedInfo,
challengeGracePeriodBlocks uint64,
) uint64 {
confirmableAtBlock := info.CreationBlock + parentInfo.ConfirmPeriodBlocks
confirmableAtBlock := info.CreationL1Block + parentInfo.ConfirmPeriodBlocks
if winningEdgeConfirmationBlock+challengeGracePeriodBlocks > confirmableAtBlock {
confirmableAtBlock = winningEdgeConfirmationBlock + challengeGracePeriodBlocks
}
Expand All @@ -953,8 +953,12 @@ func (w *Watcher) getStartEndBlockNum(ctx context.Context) (filterRange, error)
if err != nil {
return filterRange{}, err
}
latestConfirmedAssertionCreationBlock, err := w.chain.GetAssertionCreationL1Block(ctx, latestConfirmedAssertion.Id().Hash)
if err != nil {
return filterRange{}, err
}
return filterRange{
startBlockNum: latestConfirmedAssertion.CreatedAtBlock(),
startBlockNum: latestConfirmedAssertionCreationBlock,
endBlockNum: latestDesiredBlockNum,
}, nil
}
Expand Down
8 changes: 5 additions & 3 deletions challenge-manager/chain-watcher/watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ func Test_challengedAssertionConfirmableBlock(t *testing.T) {
ConfirmPeriodBlocks: 50,
}
info := &protocol.AssertionCreatedInfo{
CreationBlock: 100,
CreationBlock: 100,
CreationL1Block: 100, // in case of l2 chain CreationL1Block is equal to CreationBlock
}
edgeConfirmationBlock := uint64(200)
gracePeriodBlocks := uint64(10)
Expand All @@ -52,11 +53,12 @@ func Test_challengedAssertionConfirmableBlock(t *testing.T) {
ConfirmPeriodBlocks: 50,
}
info := &protocol.AssertionCreatedInfo{
CreationBlock: 100,
CreationBlock: 100,
CreationL1Block: 100, // in case of l2 chain CreationL1Block is equal to CreationBlock
}
edgeConfirmationBlock := uint64(105)
gracePeriodBlocks := uint64(10)
want := parentInfo.ConfirmPeriodBlocks + info.CreationBlock
want := parentInfo.ConfirmPeriodBlocks + info.CreationL1Block
got := challengedAssertionConfirmableBlock(parentInfo, edgeConfirmationBlock, info, gracePeriodBlocks)
require.Equal(t, want, got)
})
Expand Down
1 change: 1 addition & 0 deletions testing/endtoend/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_test(
size = "large",
srcs = [
"e2e_crash_test.go",
"e2e_delegated_staking_test.go",
"e2e_test.go",
"helpers_test.go",
],
Expand Down
11 changes: 11 additions & 0 deletions testing/mocks/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ func (m *MockProtocol) GetCallOptsWithDesiredRpcHeadBlockNumber(opts *bind.CallO
return opts
}

func (m *MockProtocol) GetAssertionCreationL1Block(ctx context.Context, assertionHash common.Hash) (uint64, error) {
args := m.Called(ctx, assertionHash)
return args.Get(0).(uint64), args.Error(1)
}

func (m *MockProtocol) GetDesiredRpcHeadBlockNumber() rpc.BlockNumber {
return rpc.LatestBlockNumber
}
Expand All @@ -439,6 +444,12 @@ func (m *MockProtocol) DesiredHeaderU64(ctx context.Context) (uint64, error) {
return args.Get(0).(uint64), args.Error(1)
}

// Read-only methods.
func (m *MockProtocol) DesiredL1HeaderU64(ctx context.Context) (uint64, error) {
args := m.Called()
return args.Get(0).(uint64), args.Error(1)
}

func (m *MockProtocol) Backend() protocol.ChainBackend {
args := m.Called()
return args.Get(0).(protocol.ChainBackend)
Expand Down
Loading
Loading