7 // "github.com/blockchain/errors"
8 "github.com/bytom/protocol/bc/legacy"
9 "github.com/bytom/protocol/state"
12 // Recover performs crash recovery, restoring the blockchain
13 // to a complete state. It returns the latest confirmed block
14 // and the corresponding state snapshot.
16 // If the blockchain is empty (missing initial block), this function
17 // returns a nil block and an empty snapshot.
18 func (c *Chain) Recover(ctx context.Context) (*legacy.Block, *state.Snapshot, error) {
19 //snapshot, snapshotHeight, err := c.store.LatestSnapshot(ctx)
21 return nil, nil, errors.Wrap(err, "getting latest snapshot")
24 if snapshotHeight > 0 {
25 b, err = c.store.GetBlock(ctx, snapshotHeight)
27 return nil, nil, errors.Wrap(err, "getting snapshot block")
29 c.lastQueuedSnapshot = b.Time()
32 snapshot = state.Empty()
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)
40 return nil, nil, errors.Wrap(err, "getting blockchain height")
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)
47 return nil, nil, errors.Wrap(err, "getting block")
49 err = snapshot.ApplyBlock(legacy.MapBlock(b))
51 return nil, nil, errors.Wrap(err, "applying block")
53 if b.AssetsMerkleRoot != snapshot.Tree.RootHash() {
54 return nil, nil, fmt.Errorf("block %d has state root %x; snapshot has root %x",
55 b.Height, b.AssetsMerkleRoot.Bytes(), snapshot.Tree.RootHash().Bytes())
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)
66 return nil, nil, errors.Wrap(err, "committing block")
69 return b, snapshot, nil