Skip to content

Commit 8441263

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 8441263

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-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 is guaranteed to
18+
// be a 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

+16-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
)
@@ -190,6 +189,19 @@ func (h *gpbftRunner) Start(ctx context.Context) (_err error) {
190189
func (h *gpbftRunner) receiveCertificate(c *certs.FinalityCertificate) error {
191190
nextInstance := c.GPBFTInstance + 1
192191
currentInstance := h.participant.CurrentInstance()
192+
193+
// Call to Finalize checkpoints the tipset in Lotus chain store. This may cause a
194+
// sync in a case where the target tipset is not already stored by the chain
195+
// store, which is a blocking operation.
196+
//
197+
// Triggering the checkpointing here means that certstore remains the sole source
198+
// of truth in terms of tipset has been finalised.
199+
if err := h.ec.Finalize(h.runningCtx, c.ECChain.Head().Key); err != nil {
200+
err := fmt.Errorf("error while finalizing decision at EC: %w", err)
201+
log.Error(err)
202+
return err
203+
}
204+
193205
if h.participant.CurrentInstance() >= nextInstance {
194206
return nil
195207
}
@@ -428,7 +440,7 @@ func (h *gpbftHost) collectChain(base ec.TipSet, head ec.TipSet) ([]ec.TipSet, e
428440
return res[1:], nil
429441
}
430442

431-
func (h *gpbftRunner) Stop(_ctx context.Context) error {
443+
func (h *gpbftRunner) Stop(context.Context) error {
432444
h.ctxCancel()
433445
return multierr.Combine(
434446
h.errgrp.Wait(),
@@ -624,7 +636,7 @@ func (h *gpbftHost) SetAlarm(at time.Time) {
624636
// we cannot reuse the timer because we don't know if it was read or not
625637
h.alertTimer.Stop()
626638
if at.IsZero() {
627-
// It "at" is zero, we cancel the timer entirely. Unfortunately, we still have to
639+
// If "at" is zero, we cancel the timer entirely. Unfortunately, we still have to
628640
// replace it for the reason stated above.
629641
h.alertTimer = h.clock.Timer(0)
630642
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)