MCPcopy Index your code
hub / github.com/chain/Core / Recover

Method Recover

protocol/recover.go:18–70  ·  view source on GitHub ↗

Recover performs crash recovery, restoring the blockchain to a complete state. It returns the latest confirmed block and the corresponding state snapshot. If the blockchain is empty (missing initial block), this function returns a nil block and an empty snapshot.

(ctx context.Context)

Source from the content-addressed store, hash-verified

16// If the blockchain is empty (missing initial block), this function
17// returns a nil block and an empty snapshot.
18func (c *Chain) Recover(ctx context.Context) (*legacy.Block, *state.Snapshot, error) {
19 snapshot, snapshotHeight, err := c.store.LatestSnapshot(ctx)
20 if err != nil {
21 return nil, nil, errors.Wrap(err, "getting latest snapshot")
22 }
23 var b *legacy.Block
24 if snapshotHeight > 0 {
25 b, err = c.store.GetBlock(ctx, snapshotHeight)
26 if err != nil {
27 return nil, nil, errors.Wrap(err, "getting snapshot block")
28 }
29 c.lastQueuedSnapshot = b.Time()
30 }
31 if snapshot == nil {
32 snapshot = state.Empty()
33 }
34
35 // The true height of the blockchain might be higher than the
36 // height at which the state snapshot was taken. Replay all
37 // existing blocks higher than the snapshot height.
38 height, err := c.store.Height(ctx)
39 if err != nil {
40 return nil, nil, errors.Wrap(err, "getting blockchain height")
41 }
42
43 // Bring the snapshot up to date with the latest block
44 for h := snapshotHeight + 1; h <= height; h++ {
45 b, err = c.store.GetBlock(ctx, h)
46 if err != nil {
47 return nil, nil, errors.Wrap(err, "getting block")
48 }
49 err = snapshot.ApplyBlock(legacy.MapBlock(b))
50 if err != nil {
51 return nil, nil, errors.Wrap(err, "applying block")
52 }
53 if b.AssetsMerkleRoot != snapshot.Tree.RootHash() {
54 return nil, nil, fmt.Errorf("block %d has state root %s; snapshot has root %s",
55 b.Height, b.AssetsMerkleRoot, snapshot.Tree.RootHash())
56 }
57 }
58 if b != nil {
59 // All blocks before the latest one have been fully processed
60 // (saved in the db, callbacks invoked). The last one may have
61 // been too, but make sure just in case. Also "finalize" the last
62 // block (notifying other processes of the latest block height)
63 // and maybe persist the snapshot.
64 err = c.CommitAppliedBlock(ctx, b, snapshot)
65 if err != nil {
66 return nil, nil, errors.Wrap(err, "committing block")
67 }
68 }
69 return b, snapshot, nil
70}

Callers 5

generateBlockFunction · 0.95
leadMethod · 0.80

Calls 7

CommitAppliedBlockMethod · 0.95
TimeMethod · 0.80
ApplyBlockMethod · 0.80
RootHashMethod · 0.80
LatestSnapshotMethod · 0.65
GetBlockMethod · 0.65
HeightMethod · 0.65

Tested by 4

generateBlockFunction · 0.76