Skip to content

feat: chain import: don't walk to genesis #6243

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

Merged
merged 1 commit into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 2 additions & 6 deletions cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func importChain(ctx context.Context, r repo.Repo, fname string) error {
}

bar.Start()
tip, err := chainStore.Import(ctx, ir)
tip, genesisBlk, err := chainStore.Import(ctx, ir)
if err != nil {
return fmt.Errorf("importing chain failed: %s", err)
}
Expand All @@ -101,11 +101,7 @@ func importChain(ctx context.Context, r repo.Repo, fname string) error {
}
logImport.Infof("accepting %s as new head", tip.Key().String())

genesis, err := chainStore.GetTipSetByHeight(ctx, tip, 0, false)
if err != nil {
return fmt.Errorf("got genesis failed: %v", err)
}
if err := chainStore.PersistGenesisCID(ctx, genesis.Blocks()[0]); err != nil {
if err := chainStore.PersistGenesisCID(ctx, genesisBlk); err != nil {
return fmt.Errorf("persist genesis failed: %v", err)
}

Expand Down
45 changes: 35 additions & 10 deletions pkg/chain/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -987,12 +987,20 @@ func (store *Store) WalkSnapshot(ctx context.Context, ts *types.TipSet, inclRece
}

// Import import a car file into local db
func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, error) {
func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, *types.BlockHeader, error) {
br, err := carv2.NewBlockReader(r)
if err != nil {
return nil, fmt.Errorf("loadcar failed: %w", err)
return nil, nil, fmt.Errorf("loadcar failed: %w", err)
}

if len(br.Roots) == 0 {
return nil, nil, fmt.Errorf("no roots in snapshot car file")
}

var tailBlock types.BlockHeader
tailBlock.Height = abi.ChainEpoch(-1)
nextTailCid := br.Roots[0]

parallelPuts := 5
putThrottle := make(chan error, parallelPuts)
for i := 0; i < parallelPuts; i++ {
Expand All @@ -1006,20 +1014,33 @@ func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, err
if err == io.EOF {
if len(buf) > 0 {
if err := store.bsstore.PutMany(ctx, buf); err != nil {
return nil, err
return nil, nil, err
}
}

break
}
return nil, err
return nil, nil, err
}

// check for header block, looking for genesis
if blk.Cid() == nextTailCid && tailBlock.Height != 0 {
if err := tailBlock.UnmarshalCBOR(bytes.NewReader(blk.RawData())); err != nil {
return nil, nil, fmt.Errorf("failed to unmarshal genesis block: %w", err)
}
if len(tailBlock.Parents) > 0 {
nextTailCid = tailBlock.Parents[0]
} else {
// note: even the 0th block has a parent linking to the cbor genesis block
return nil, nil, fmt.Errorf("current block (epoch %d cid %s) has no parents", tailBlock.Height, tailBlock.Cid())
}
}

buf = append(buf, blk)

if len(buf) > 1000 {
if lastErr := <-putThrottle; lastErr != nil { // consume one error to have the right to add one
return nil, lastErr
return nil, nil, lastErr
}

go func(buf []blocks.Block) {
Expand All @@ -1032,13 +1053,17 @@ func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, err
// check errors
for i := 0; i < parallelPuts; i++ {
if lastErr := <-putThrottle; lastErr != nil {
return nil, lastErr
return nil, nil, lastErr
}
}

if tailBlock.Height != 0 {
return nil, nil, fmt.Errorf("expected genesis block to have height 0 (genesis), got %d: %s", tailBlock.Height, tailBlock.Cid())
}

root, err := store.GetTipSet(ctx, types.NewTipSetKey(br.Roots...))
if err != nil {
return nil, fmt.Errorf("failed to load root tipset from chainfile: %w", err)
return nil, nil, fmt.Errorf("failed to load root tipset from chainfile: %w", err)
}

// Notice here is different with lotus, because the head tipset in lotus is not computed,
Expand All @@ -1058,7 +1083,7 @@ func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, err
curTipsetKey := curTipset.Parents()
curParentTipset, err := store.GetTipSet(ctx, curTipsetKey)
if err != nil {
return nil, fmt.Errorf("failed to load root tipset from chainfile: %w", err)
return nil, nil, fmt.Errorf("failed to load root tipset from chainfile: %w", err)
}

if curParentTipset.Height() == 0 {
Expand All @@ -1077,7 +1102,7 @@ func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, err
TipSetReceipts: curTipset.At(0).ParentMessageReceipts,
})
if err != nil {
return nil, err
return nil, nil, err
}

// save tipsetkey
Expand All @@ -1086,7 +1111,7 @@ func (store *Store) Import(ctx context.Context, r io.Reader) (*types.TipSet, err
curTipset = curParentTipset
}

return root, nil
return root, &tailBlock, nil
}

// SetCheckPoint set current checkpoint
Expand Down