From 2e9a052f62757ff46d79e5f856e6dcae0284d8aa Mon Sep 17 00:00:00 2001 From: hannahhoward Date: Thu, 19 Mar 2020 17:16:26 -0700 Subject: [PATCH] fix(chainsync): support longer graphsync fetches with loop --- chain/blocksync/graphsync_client.go | 63 ++++++++++++++++++----------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/chain/blocksync/graphsync_client.go b/chain/blocksync/graphsync_client.go index 5d4af01cb..6fadb44b2 100644 --- a/chain/blocksync/graphsync_client.go +++ b/chain/blocksync/graphsync_client.go @@ -41,6 +41,9 @@ const ( // field index of values array AMT node amtNodeValuesFieldIndex = 2 + + // maximum depth per traversal + maxRequestLength = 50 ) var blockHeadersSelector, fullSelector ipld.Node @@ -132,15 +135,6 @@ func (bs *BlockSync) fetchBlocksGraphSync(ctx context.Context, p peer.ID, req *B ctx, cancel := context.WithCancel(ctx) defer cancel() - sel := selectorForRequest(req) - - // TODO: - for _, c := range req.Start { - if _, err := bs.bserv.GetBlock(ctx, c); err != nil { - return nil, xerrors.Errorf("failed to fetch blocks: %w") - } - } - immediateTsSelector := firstTipsetSelector(req) // Do this because we can only request one root at a time @@ -150,20 +144,43 @@ func (bs *BlockSync) fetchBlocksGraphSync(ctx context.Context, p peer.ID, req *B } } - // execute the selector forreal - if err := bs.executeGsyncSelector(ctx, p, req.Start[0], sel); err != nil { - return nil, err + var totalDepth uint64 = 0 + var nextReq BlockSyncRequest = *req + var wholeChain []*BSTipSet + var reachedGenesis bool + for totalDepth < req.RequestLength && !reachedGenesis { + if nextReq.RequestLength > maxRequestLength { + nextReq.RequestLength = maxRequestLength + } + + sel := selectorForRequest(&nextReq) + + // execute the selector forreal + if err := bs.executeGsyncSelector(ctx, p, req.Start[0], sel); err != nil { + return nil, err + } + + // Now pull the data we fetched out of the chainstore (where it should now be persisted) + tempcs := store.NewChainStore(bs.bserv.Blockstore(), datastore.NewMapDatastore(), nil) + + opts := ParseBSOptions(req.Options) + tsk := types.NewTipSetKey(req.Start...) + chain, err := collectChainSegment(tempcs, tsk, req.RequestLength, opts) + if err != nil { + return nil, xerrors.Errorf("failed to load chain data from chainstore after successful graphsync response (start = %v): %w", req.Start, err) + } + wholeChain = append(wholeChain, chain...) + totalDepth += nextReq.RequestLength + nextCids := make([]cid.Cid, 0, len(chain[len(chain)-1].Blocks)) + for _, blk := range chain[len(chain)-1].Blocks { + if blk.Height == 0 || blk.Parents == nil { + reachedGenesis = true + } + nextCids = append(nextCids, blk.Cid()) + } + nextReq.Start = nextCids + nextReq.RequestLength = req.RequestLength - totalDepth } - // Now pull the data we fetched out of the chainstore (where it should now be persisted) - tempcs := store.NewChainStore(bs.bserv.Blockstore(), datastore.NewMapDatastore(), nil) - - opts := ParseBSOptions(req.Options) - tsk := types.NewTipSetKey(req.Start...) - chain, err := collectChainSegment(tempcs, tsk, req.RequestLength, opts) - if err != nil { - return nil, xerrors.Errorf("failed to load chain data from chainstore after successful graphsync response (start = %v): %w", req.Start, err) - } - - return &BlockSyncResponse{Chain: chain}, nil + return &BlockSyncResponse{Chain: wholeChain}, nil }