Skip to content

Commit

Permalink
feat: chain import: don't walk to genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
simlecode committed Dec 5, 2023
1 parent 903d745 commit 182d8dd
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 16 deletions.
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

0 comments on commit 182d8dd

Please sign in to comment.