Skip to content

Commit 2a18b1d

Browse files
committed
Add finalize API to EC backend
Expand the F3 EC backend API to mark a given tipset as final. This translates to checkpointing the tipset in Lotus beyond which no forks are allowed. Part of #603
1 parent 92a5658 commit 2a18b1d

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

ec/ec.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,21 @@ type Backend interface {
1414
GetTipsetByEpoch(ctx context.Context, epoch int64) (TipSet, error)
1515
// GetTipset returns the tipset with the given key.
1616
GetTipset(context.Context, gpbft.TipSetKey) (TipSet, error)
17-
// GetHead returns the current head tipset of the chain
17+
// GetHead returns the current head tipset of the chain, which must be a
18+
// descendant of the latest finalized tipset.
19+
//
20+
// See Finalize.
1821
GetHead(context.Context) (TipSet, error)
1922
// GetParent returns the parent of the current tipset.
2023
GetParent(context.Context, TipSet) (TipSet, error)
2124
// GetPowerTable returns the power table at the tipset given as an argument.
2225
GetPowerTable(context.Context, gpbft.TipSetKey) (gpbft.PowerEntries, error)
26+
// Finalize marks the tipset that corresponds to the given key as finalised
27+
// beyond which no forks are allowed to occur. The finalised tipset overrides the
28+
// head tipset if it is not an ancestor of the current head.
29+
//
30+
// See GetHead.
31+
Finalize(context.Context, gpbft.TipSetKey) error
2332
}
2433

2534
type TipSet interface {

host.go

+15-4
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ import (
1515
"github.com/filecoin-project/go-f3/internal/clock"
1616
"github.com/filecoin-project/go-f3/internal/psutil"
1717
"github.com/filecoin-project/go-f3/manifest"
18-
"go.opentelemetry.io/otel/metric"
19-
2018
pubsub "github.com/libp2p/go-libp2p-pubsub"
2119
peer "github.com/libp2p/go-libp2p/core/peer"
20+
"go.opentelemetry.io/otel/metric"
2221
"go.uber.org/multierr"
2322
"golang.org/x/sync/errgroup"
2423
)
@@ -188,6 +187,18 @@ func (h *gpbftRunner) Start(ctx context.Context) (_err error) {
188187
}
189188

190189
func (h *gpbftRunner) receiveCertificate(c *certs.FinalityCertificate) error {
190+
// Call to Finalize checkpoints the tipset in Lotus chain store. This may cause a
191+
// sync in a case where the target tipset is not already stored by the chain
192+
// store, which is a blocking operation.
193+
//
194+
// Triggering the checkpointing here means that certstore remains the sole source
195+
// of truth in terms of tipset has been finalised.
196+
if err := h.ec.Finalize(h.runningCtx, c.ECChain.Head().Key); err != nil {
197+
err := fmt.Errorf("error while finalizing decision at EC: %w", err)
198+
log.Error(err)
199+
return err
200+
}
201+
191202
nextInstance := c.GPBFTInstance + 1
192203
currentInstance := h.participant.CurrentInstance()
193204
if h.participant.CurrentInstance() >= nextInstance {
@@ -428,7 +439,7 @@ func (h *gpbftHost) collectChain(base ec.TipSet, head ec.TipSet) ([]ec.TipSet, e
428439
return res[1:], nil
429440
}
430441

431-
func (h *gpbftRunner) Stop(_ctx context.Context) error {
442+
func (h *gpbftRunner) Stop(context.Context) error {
432443
h.ctxCancel()
433444
return multierr.Combine(
434445
h.errgrp.Wait(),
@@ -624,7 +635,7 @@ func (h *gpbftHost) SetAlarm(at time.Time) {
624635
// we cannot reuse the timer because we don't know if it was read or not
625636
h.alertTimer.Stop()
626637
if at.IsZero() {
627-
// It "at" is zero, we cancel the timer entirely. Unfortunately, we still have to
638+
// If "at" is zero, we cancel the timer entirely. Unfortunately, we still have to
628639
// replace it for the reason stated above.
629640
h.alertTimer = h.clock.Timer(0)
630641
if !h.alertTimer.Stop() {

internal/consensus/fake_ec.go

+2
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,5 @@ func (ec *FakeEC) GetTipset(_ context.Context, tsk gpbft.TipSetKey) (ec.TipSet,
183183
epoch := binary.BigEndian.Uint64(tsk[6+32-8 : 6+32])
184184
return ec.genTipset(int64(epoch)), nil
185185
}
186+
187+
func (ec *FakeEC) Finalize(context.Context, gpbft.TipSetKey) error { return nil }

0 commit comments

Comments
 (0)