Skip to content

Commit

Permalink
update how root nodes are confirmed
Browse files Browse the repository at this point in the history
  • Loading branch information
rauljordan committed May 3, 2024
1 parent 43f4cee commit 1cfe2fd
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 84 deletions.
38 changes: 38 additions & 0 deletions challenge-manager/chain-watcher/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,44 @@ func (w *Watcher) ComputeAncestors(
return chal.honestEdgeTree.ComputeAncestors(ctx, edgeId, blockHeader.Number.Uint64())
}

func (w *Watcher) IsConfirmableEssentialNode(
ctx context.Context,
challengedAssertionHash protocol.AssertionHash,
essentialNodeId protocol.EdgeId,
confirmationThreshold uint64,
) (confirmable bool, essentialPaths []challengetree.EssentialPath, timer uint64, err error) {
chal, ok := w.challenges.TryGet(challengedAssertionHash)
if !ok {
err = fmt.Errorf(
"could not get challenge for top level assertion %#x",
challengedAssertionHash,
)
return
}
blockHeader, err := w.chain.Backend().HeaderByNumber(ctx, util.GetSafeBlockNumber())
if err != nil {
return
}
if !blockHeader.Number.IsUint64() {
err = errors.New("block number is not uint64")
return
}
essentialNode, ok := chal.honestEdgeTree.GetEdge(essentialNodeId)
if !ok {
err = fmt.Errorf("could not get essential node with id %#x", essentialNodeId.Hash)
return
}
confirmable, essentialPaths, timer, err = chal.honestEdgeTree.IsConfirmableEssentialNode(
ctx,
challengetree.IsConfirmableArgs{
EssentialNode: essentialNode.Id(),
BlockNum: blockHeader.Number.Uint64(),
ConfirmationThreshold: confirmationThreshold,
},
)
return
}

func (w *Watcher) ComputeRootInheritedTimer(
ctx context.Context,
challengedAssertionHash protocol.AssertionHash,
Expand Down
28 changes: 14 additions & 14 deletions challenge-manager/challenge-tree/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
"github.com/OffchainLabs/bold/containers/option"
)

type essentialPath []protocol.EdgeId
type EssentialPath []protocol.EdgeId

type isConfirmableArgs struct {
essentialNode protocol.EdgeId
confirmationThreshold uint64
blockNum uint64
type IsConfirmableArgs struct {
EssentialNode protocol.EdgeId
ConfirmationThreshold uint64
BlockNum uint64
}

// Find all the paths down from an essential node, and
Expand All @@ -32,16 +32,16 @@ type isConfirmableArgs struct {
// essential node is then confirmable.
func (ht *RoyalChallengeTree) IsConfirmableEssentialNode(
ctx context.Context,
args isConfirmableArgs,
) (bool, []essentialPath, uint64, error) {
essentialNode, ok := ht.edges.TryGet(args.essentialNode)
args IsConfirmableArgs,
) (bool, []EssentialPath, uint64, error) {
essentialNode, ok := ht.edges.TryGet(args.EssentialNode)
if !ok {
return false, nil, 0, fmt.Errorf("essential node not found")
}
essentialPaths, essentialTimers, err := ht.findEssentialPaths(
ctx,
essentialNode,
args.blockNum,
args.BlockNum,
)
if err != nil {
return false, nil, 0, err
Expand All @@ -66,7 +66,7 @@ func (ht *RoyalChallengeTree) IsConfirmableEssentialNode(
return false, nil, 0, fmt.Errorf("no path weights computed")
}
minWeight := pathWeights.Pop()
allEssentialPathsConfirmable := minWeight >= args.confirmationThreshold
allEssentialPathsConfirmable := minWeight >= args.ConfirmationThreshold
return allEssentialPathsConfirmable, essentialPaths, minWeight, nil
}

Expand All @@ -81,13 +81,13 @@ func (ht *RoyalChallengeTree) findEssentialPaths(
ctx context.Context,
essentialNode protocol.ReadOnlyEdge,
blockNum uint64,
) ([]essentialPath, []essentialLocalTimers, error) {
allPaths := make([]essentialPath, 0)
) ([]EssentialPath, []essentialLocalTimers, error) {
allPaths := make([]EssentialPath, 0)
allTimers := make([]essentialLocalTimers, 0)

type visited struct {
essentialNode protocol.ReadOnlyEdge
path essentialPath
path EssentialPath
localTimers essentialLocalTimers
}
stack := newStack[*visited]()
Expand All @@ -99,7 +99,7 @@ func (ht *RoyalChallengeTree) findEssentialPaths(

stack.push(&visited{
essentialNode: essentialNode,
path: essentialPath{essentialNode.Id()},
path: EssentialPath{essentialNode.Id()},
localTimers: essentialLocalTimers{localTimer},
})

Expand Down
20 changes: 10 additions & 10 deletions challenge-manager/challenge-tree/paths_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ func TestIsConfirmableEssentialNode(t *testing.T) {
// understand the setup of the challenge tree.
_, _, _, err := tree.IsConfirmableEssentialNode(
ctx,
isConfirmableArgs{
essentialNode: protocol.EdgeId{},
IsConfirmableArgs{
EssentialNode: protocol.EdgeId{},
},
)
require.ErrorContains(t, err, "essential node not found")
Expand All @@ -32,10 +32,10 @@ func TestIsConfirmableEssentialNode(t *testing.T) {
blockNum := uint64(10)
isConfirmable, _, minPathWeight, err := tree.IsConfirmableEssentialNode(
ctx,
isConfirmableArgs{
confirmationThreshold: 10,
essentialNode: essentialHonestRoot.Id(),
blockNum: blockNum,
IsConfirmableArgs{
ConfirmationThreshold: 10,
EssentialNode: essentialHonestRoot.Id(),
BlockNum: blockNum,
},
)
require.NoError(t, err)
Expand All @@ -47,10 +47,10 @@ func TestIsConfirmableEssentialNode(t *testing.T) {
blockNum = uint64(14)
isConfirmable, _, minPathWeight, err = tree.IsConfirmableEssentialNode(
ctx,
isConfirmableArgs{
confirmationThreshold: 10,
essentialNode: essentialHonestRoot.Id(),
blockNum: blockNum,
IsConfirmableArgs{
ConfirmationThreshold: 10,
EssentialNode: essentialHonestRoot.Id(),
BlockNum: blockNum,
},
)
require.NoError(t, err)
Expand Down
4 changes: 4 additions & 0 deletions challenge-manager/challenge-tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ func (ht *RoyalChallengeTree) GetEdges() *threadsafe.Map[protocol.EdgeId, protoc
return ht.edges
}

func (ht *RoyalChallengeTree) GetEdge(edgeId protocol.EdgeId) (protocol.SpecEdge, bool) {
return ht.edges.TryGet(edgeId)
}

func (ht *RoyalChallengeTree) HasRoyalEdge(edgeId protocol.EdgeId) bool {
return ht.edges.Has(edgeId)
}
Expand Down
81 changes: 21 additions & 60 deletions challenge-manager/edge-tracker/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

protocol "github.com/OffchainLabs/bold/chain-abstraction"
challengetree "github.com/OffchainLabs/bold/challenge-manager/challenge-tree"
"github.com/OffchainLabs/bold/containers"
"github.com/OffchainLabs/bold/containers/fsm"
"github.com/OffchainLabs/bold/containers/option"
Expand Down Expand Up @@ -49,10 +50,12 @@ type RoyalChallengeWriter interface {
AddVerifiedHonestEdge(
ctx context.Context, verifiedHonest protocol.VerifiedRoyalEdge,
) error
ComputeRootInheritedTimer(
IsConfirmableEssentialNode(
ctx context.Context,
challengedAssertionHash protocol.AssertionHash,
) (protocol.InheritedTimer, error)
essentialNodeId protocol.EdgeId,
confirmationThreshold uint64,
) (confirmable bool, essentialPaths []challengetree.EssentialPath, timer uint64, err error)
}

type ChallengeTracker interface {
Expand Down Expand Up @@ -426,18 +429,6 @@ func (et *Tracker) tryToConfirmEdge(ctx context.Context) (bool, error) {
return false, err
}
fields := et.uniqueTrackerLogFields()
start := time.Now()
computedTimer, err := et.chainWatcher.ComputeRootInheritedTimer(ctx, assertionHash)
if err != nil {
fields["error"] = err
srvlog.Error("Could not update time cache")
return false, errors.Wrap(err, "could not update edge inherited timer")
}
end := time.Since(start)
onchainTimer, err := et.edge.SafeHeadInheritedTimer(ctx)
if err != nil {
return false, errors.Wrap(err, "could not get edge onchain inherited timer")
}
manager, err := et.chain.SpecChallengeManager(ctx)
if err != nil {
return false, errors.Wrap(err, "could not get challenge manager")
Expand All @@ -446,53 +437,23 @@ func (et *Tracker) tryToConfirmEdge(ctx context.Context) (bool, error) {
if err != nil {
return false, errors.Wrap(err, "could not check the challenge period length")
}
localFields := log.Ctx{
"localTimer": computedTimer,
"onchainTimer": onchainTimer,
"confirmableAfter": chalPeriod,
"edgeId": fmt.Sprintf("%#x", et.edge.Id().Bytes()[:4]),
"took": end,
"fromBatch": et.associatedAssertionMetadata.FromBatch,
"toBatch": et.associatedAssertionMetadata.ToBatch,
"claimedAssertion": fmt.Sprintf("%#x", et.associatedAssertionMetadata.ClaimedAssertionHash[:4]),
}
srvlog.Info("Updated edge timer", localFields)
// Short circuit early if the edge is confirmable.
// We have a few things to check here:
// First, if the edge's onchain timer is greater than a challenge period, then we can
// immediately confirm by time by sending a transaction.
if onchainTimer >= protocol.InheritedTimer(chalPeriod) {
srvlog.Info("Onchain timer is greater than challenge period, now confirming edge by time", localFields)
if _, err := et.edge.ConfirmByTimer(ctx); err != nil {
return false, errors.Wrapf(
err,
"could not confirm by timer: got timer %d, chal period %d",
onchainTimer,
chalPeriod,
)
}
srvlog.Info("Confirmed edge by time", fields)
confirmedCounter.Inc(1)
return true, nil
start := time.Now()
isConfirmable, essentialPaths, timer, err := et.chainWatcher.IsConfirmableEssentialNode(
ctx,
assertionHash,
et.edge.Id(),
chalPeriod,
)
if err != nil {
fields["error"] = err
srvlog.Error("Could not check if essential node is confirmable")
return false, errors.Wrap(err, "not check if essential node is confirmable")
}
// Otherwise, if the locally cached timer is greater than a challenge period, it means
// we need to trigger a confirmation job that will propagate updates to the whole royal
// challenge tree onchain until the edge has an onchain timer >= a challenge period.
// We let our confirmer dependency take care of this confirmatin job.
if uint64(computedTimer) >= chalPeriod {
srvlog.Info("Local computed timer big enough to confirm edge", localFields)
if err := et.challengeConfirmer.beginConfirmationJob(
ctx,
assertionHash,
et.edge,
chalPeriod,
); err != nil {
return false, errors.Wrap(
err,
"could not complete confirmation job for royal, block challenge edge",
)
}
// The edge is now confirmed.
end := time.Since(start)
_ = end
_ = essentialPaths
_ = timer
if isConfirmable {
return true, nil
}
return false, nil
Expand Down

0 comments on commit 1cfe2fd

Please sign in to comment.