2 Package protocol provides the logic to tie together
3 storage and validation for a Chain Protocol blockchain.
5 This comprises all behavior that's common to every full
6 node, as well as other functions that need to operate on the
9 Here are a few examples of typical full node types.
13 A generator has two basic jobs: collecting transactions from
14 other nodes and putting them into blocks.
16 To add a new block to the blockchain, call GenerateBlock,
17 sign the block (possibly collecting signatures from other
18 parties), and call CommitBlock.
22 A signer validates blocks generated by the Generator and signs
23 at most one block at each height.
27 A participant node in a network may select outputs for spending
28 and compose transactions.
30 To publish a new transaction, prepare your transaction
31 (select outputs, and compose and sign the tx) and send the
32 transaction to the network's generator. To wait for
33 confirmation, call BlockWaiter on successive block heights
34 and inspect the blockchain state until you find that the
35 transaction has been either confirmed or rejected. Note
36 that transactions may be malleable if there's no commitment
39 To ingest a block, call ValidateBlock and CommitBlock.
48 "github.com/golang/groupcache/lru"
50 "github.com/bytom/errors"
51 //"github.com/blockchain/log"
52 "github.com/bytom/protocol/bc"
53 "github.com/bytom/protocol/bc/legacy"
54 "github.com/bytom/protocol/state"
57 // maxCachedValidatedTxs is the max number of validated txs to cache.
58 const maxCachedValidatedTxs = 1000
61 // ErrTheDistantFuture is returned when waiting for a blockheight
62 // too far in excess of the tip of the blockchain.
63 ErrTheDistantFuture = errors.New("block height too far in future")
66 // Store provides storage for blockchain data: blocks and state tree
69 // Note, this is different from a state snapshot. A state snapshot
70 // provides access to the state at a given point in time -- outputs
71 // and issuance memory. The Chain type uses Store to load state
72 // from storage and persist validated data.
73 type Store interface {
74 Height(context.Context) (uint64, error)
75 GetBlock(context.Context, uint64) (*legacy.Block, error)
76 // LatestSnapshot(context.Context) (*state.Snapshot, uint64, error)
78 // SaveBlock(context.Context, *legacy.Block) error
79 FinalizeBlock(context.Context, uint64) error
80 // SaveSnapshot(context.Context, uint64, *state.Snapshot) error
83 // Chain provides a complete, minimal blockchain database. It
84 // delegates the underlying storage to other objects, and uses
85 // validation logic from package validation to decide what
86 // objects can be safely stored.
88 InitialBlockHash bc.Hash
89 MaxIssuanceWindow time.Duration // only used by generators
92 cond sync.Cond // protects height, block, snapshot
94 block *legacy.Block // current only if leader
95 snapshot *state.Snapshot // current only if leader
99 lastQueuedSnapshot time.Time
100 pendingSnapshots chan pendingSnapshot
102 prevalidated prevalidatedTxsCache
105 type pendingSnapshot struct {
107 snapshot *state.Snapshot
110 // NewChain returns a new Chain using store as the underlying storage.
111 func NewChain(ctx context.Context, initialBlockHash bc.Hash, store Store, heights <-chan uint64) (*Chain, error) {
113 InitialBlockHash: initialBlockHash,
115 pendingSnapshots: make(chan pendingSnapshot, 1),
116 prevalidated: prevalidatedTxsCache{
117 lru: lru.New(maxCachedValidatedTxs),
120 c.state.cond.L = new(sync.Mutex)
123 c.state.height, err = store.Height(ctx)
125 return nil, errors.Wrap(err, "looking up blockchain height")
128 // Note that c.height.n may still be zero here.
131 for h := range heights {
142 //case ps := <-c.pendingSnapshots:
143 /*err = store.SaveSnapshot(ctx, ps.height, ps.snapshot)
145 log.Error(ctx, err, "at", "saving snapshot")
155 // Height returns the current height of the blockchain.
156 func (c *Chain) Height() uint64 {
157 c.state.cond.L.Lock()
158 defer c.state.cond.L.Unlock()
159 return c.state.height
162 // TimestampMS returns the latest known block timestamp.
163 func (c *Chain) TimestampMS() uint64 {
164 c.state.cond.L.Lock()
165 defer c.state.cond.L.Unlock()
166 if c.state.block == nil {
169 return c.state.block.TimestampMS
172 // State returns the most recent state available. It will not be current
173 // unless the current process is the leader. Callers should examine the
174 // returned block header's height if they need to verify the current state.
175 func (c *Chain) State() (*legacy.Block, *state.Snapshot) {
176 c.state.cond.L.Lock()
177 defer c.state.cond.L.Unlock()
178 return c.state.block, c.state.snapshot
181 func (c *Chain) setState(b *legacy.Block, s *state.Snapshot) {
182 c.state.cond.L.Lock()
183 defer c.state.cond.L.Unlock()
186 if b != nil && b.Height > c.state.height {
187 c.state.height = b.Height
188 c.state.cond.Broadcast()
192 // BlockSoonWaiter returns a channel that
193 // waits for the block at the given height,
194 // but it is an error to wait for a block far in the future.
195 // WaitForBlockSoon will timeout if the context times out.
196 // To wait unconditionally, the caller should use WaitForBlock.
197 func (c *Chain) BlockSoonWaiter(ctx context.Context, height uint64) <-chan error {
198 ch := make(chan error, 1)
202 if height > c.Height()+slop {
203 ch <- ErrTheDistantFuture
208 case <-c.BlockWaiter(height):
218 // BlockWaiter returns a channel that
219 // waits for the block at the given height.
220 func (c *Chain) BlockWaiter(height uint64) <-chan struct{} {
221 ch := make(chan struct{}, 1)
223 c.state.cond.L.Lock()
224 defer c.state.cond.L.Unlock()
225 for c.state.height < height {