Skip to content

feat: certstore snapshot export #1032

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

hanabi1224
Copy link
Contributor

@hanabi1224 hanabi1224 commented Jun 26, 2025

This is a draft implementation of F3 snapshot export functionality in the format proposed in filecoin-project/FIPs#1169 to collect feedbacks

This PR implements

  • exporting and importing a certstore snapshot in FRC-0108 format
  • unit test

Tried to export snapshots on mainnet(@instance 176187) and calibnet(@instance 483660), below are some basic stats

➜  tmp ls -ahl f3*
-rw-r--r-- 1 me me 299M Jul  8 17:27 f3_snap_calibnet.bin
-rw-r--r-- 1 me me 113M Jul  8 17:27 f3_snap_calibnet.bin.zst
-rw-r--r-- 1 me me 173M Jul  8 17:26 f3_snap_mainnet.bin
-rw-r--r-- 1 me me  88M Jul  8 17:26 f3_snap_mainnet.bin.zst

Copy link

codecov bot commented Jun 26, 2025

Codecov Report

Attention: Patch coverage is 44.91525% with 65 lines in your changes missing coverage. Please review.

Project coverage is 64.56%. Comparing base (7f2287c) to head (246fdf9).

Files with missing lines Patch % Lines
certstore/snapshot.go 46.90% 40 Missing and 20 partials ⚠️
f3.go 0.00% 5 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1032      +/-   ##
==========================================
- Coverage   64.96%   64.56%   -0.41%     
==========================================
  Files          80       81       +1     
  Lines        9751     9869     +118     
==========================================
+ Hits         6335     6372      +37     
- Misses       2918     2975      +57     
- Partials      498      522      +24     
Files with missing lines Coverage Δ
f3.go 54.34% <0.00%> (+0.57%) ⬆️
certstore/snapshot.go 46.90% <46.90%> (ø)

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@BigLep BigLep moved this from Todo to In progress in F3 Jun 26, 2025
@BigLep BigLep requested a review from Kubuxu June 26, 2025 15:23
Copy link
Member

@masih masih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to pin down high level abstractions more concretely. Left a bunch of suggestions and thank you for pushing this work forward 🍻


"github.com/filecoin-project/go-f3/gpbft"
"github.com/ipfs/go-datastore"
xerrors "golang.org/x/xerrors"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo avoids using xerrors in favour of standard Go SDK packages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


var ErrlatestCertificateNil = errors.New("latest certificate is not available")

// Exports an F3 snapshot that includes the finality certificate chain until the current `latestCertificate`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By convention start godoc with the function name. Ditto in other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

return cs.ExportSnapshot(ctx, cs.latestCertificate.GPBFTInstance, writer)
}

// Exports an F3 snapshot that includes the finality certificate chain until the specified `lastInstance`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify what the from instance is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

}

// Exports an F3 snapshot that includes the finality certificate chain until the specified `lastInstance`.
func (cs *Store) ExportSnapshot(ctx context.Context, lastInstance uint64, writer io.Writer) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply call latestInstance, to? There is nothing in the logic that mandates "latest instance".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

InitialPowerTable gpbft.PowerEntries
}

func (h *SnapshotHeader) WriteToSnapshot(writer io.Writer) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend adhering to the existing SDK interfaces like io.WriterTo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

}

// Writes CBOR-encoded header or data block with a varint-encoded length prefix
func writeSnapshotCborEncodedBlock(writer io.Writer, block MarshalCBOR) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems over refactored, i.e. called only from one place.

return nil
}

type MarshalCBOR interface {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this type defined? Consider using existing types from cborgen?

Copy link
Contributor Author

@hanabi1224 hanabi1224 Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. (Only found Marshaler in github.com/filecoin-project/go-state-types/cbor)

}

// Exports an F3 snapshot that includes the finality certificate chain until the specified `lastInstance`.
func (cs *Store) ExportSnapshot(ctx context.Context, lastInstance uint64, writer io.Writer) error {
Copy link
Member

@masih masih Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe makes sense to define an Exporter type that implements io.WriterTo instead, which takes Store and any other to-from instance params? also see other comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

io.WriterTo does not take context.Context for cancellation given the export/import could take some time

var ErrlatestCertificateNil = errors.New("latest certificate is not available")

// Exports an F3 snapshot that includes the finality certificate chain until the current `latestCertificate`.
func (cs *Store) ExportLatestSnapshot(ctx context.Context, writer io.Writer) error {
Copy link
Member

@masih masih Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term Snapshot doesn't carry enough of a weight within the context of go-f3. What we really mean by it at this stage is simply: export certificates.

You could make it mean something: define a type Snapshot that is either produced by the Store, or takes the Store, and implements io.WriterTo, io.ReaderFrom etc.

Or avoid the term entirely and instead make the store simply an Iterator of certs and separate IO ops elsewhere.

I would probably go with the first approach but there is not enough implementation in this PR for me to fully wrap my head around how you are thinking of approaching the problem.

So please feel free to ignore the recommendations if they happen to not make sense as the work progresses forward.

Copy link
Contributor Author

@hanabi1224 hanabi1224 Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added FRC link to the comment to define Snapshot. As I understand, a Snapshot struct is an in-memory representation of the snapshot which is not ideal for implementing a streaming export with a low RAM usage. Implementing io.WriterTo would not allow cancellation with context.Context.

@hanabi1224 hanabi1224 force-pushed the hm/snapshot-export branch from fe81652 to e1507fa Compare July 14, 2025 11:42
@hanabi1224 hanabi1224 force-pushed the hm/snapshot-export branch from e1507fa to 0ebf227 Compare July 14, 2025 11:50
@hanabi1224 hanabi1224 marked this pull request as ready for review July 14, 2025 13:11
@hanabi1224
Copy link
Contributor Author

Hey @BigLep @Kubuxu this one is ready for review, please let me know your feedback, especially if the export / import APIs can be easily integrated into Lotus. Thanks!

@BigLep BigLep moved this from In progress to In review in F3 Jul 15, 2025
@BigLep BigLep added this to FilOz Jul 15, 2025
@github-project-automation github-project-automation bot moved this to 📌 Triage in FilOz Jul 15, 2025
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting Review in FilOz Jul 15, 2025
// ExportSnapshot exports an F3 snapshot that includes the finality certificate chain from the `Store.firstInstance` to the specified `lastInstance`.
//
// Checkout the snapshot format specification at <https://github.com/filecoin-project/FIPs/blob/master/FRCs/frc-0108.md>
func (cs *Store) ExportSnapshot(ctx context.Context, latestInstance uint64, writer io.Writer) (cid.Cid, *SnapshotHeader, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have questions about how to use it, especially with go-car, because IDK if we can provide the header with the CID afterwards.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a draft Forest implementation of v2 snapshot export. The flow is

  • exporting F3 snapshot to a tmp file
  • exporting v2 Filecoin snapshot with F3 snapshot CID and tmp file
  • cleanup the tmp file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go-car has ReplaceRootsInFile which will update the header after write as long as you start off with a dummy root CID that's the same length: https://pkg.go.dev/github.com/ipld/go-car/v2#ReplaceRootsInFile

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks Rod

@BigLep
Copy link
Member

BigLep commented Jul 22, 2025

What are the next steps? Is this needing full review comments from @Kubuxu ?

@BigLep BigLep requested a review from Kubuxu July 22, 2025 16:55
@BigLep
Copy link
Member

BigLep commented Jul 22, 2025

Per comment in 2025-07-22 implementer working group, it looks like this is ready for maintainer review.

@hanabi1224 : will you look at the failing checks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In review
Status: 🔎 Awaiting Review
Development

Successfully merging this pull request may close these issues.

5 participants