CommitBlock takes a block, commits it to persistent storage and applies it to c. CommitBlock is idempotent. A duplicate call with a previously committed block will succeed.
(ctx context.Context, block *bc.Block)
| 74 | // it to c. CommitBlock is idempotent. A duplicate call with a previously |
| 75 | // committed block will succeed. |
| 76 | func (c *Chain) CommitBlock(ctx context.Context, block *bc.Block) error { |
| 77 | err := c.store.SaveBlock(ctx, block) |
| 78 | if err != nil { |
| 79 | return errors.Wrap(err, "storing block") |
| 80 | } |
| 81 | curSnapshot := c.State() |
| 82 | |
| 83 | // CommitBlock needs to be idempotent. If block's height is less than or |
| 84 | // equal to c's current block, then it was already applied. Because |
| 85 | // SaveBlock didn't error with a conflict, we know it's not a different |
| 86 | // block at the same height. |
| 87 | if block.Height <= curSnapshot.Height() { |
| 88 | return nil |
| 89 | } |
| 90 | |
| 91 | snapshot := state.Copy(curSnapshot) |
| 92 | err = snapshot.ApplyBlock(block.UnsignedBlock) |
| 93 | if err != nil { |
| 94 | return err |
| 95 | } |
| 96 | if block.ContractsRoot.Byte32() != snapshot.ContractsTree.RootHash() { |
| 97 | return ErrBadContractsRoot |
| 98 | } |
| 99 | if block.NoncesRoot.Byte32() != snapshot.NonceTree.RootHash() { |
| 100 | return ErrBadNoncesRoot |
| 101 | } |
| 102 | return c.finalizeCommitState(ctx, snapshot) |
| 103 | } |
| 104 | |
| 105 | func (c *Chain) finalizeCommitState(ctx context.Context, snapshot *state.Snapshot) error { |
| 106 | // Save the blockchain state tree snapshot to persistent storage |