OSDN Git Service

36a3ad2a96396631872859a1c47a4cc9183d5767
[bytom/bytom.git] / protocol / protocol.go
1 package protocol
2
3 import (
4         "encoding/hex"
5         "sync"
6
7         log "github.com/sirupsen/logrus"
8
9         "github.com/bytom/bytom/config"
10         "github.com/bytom/bytom/consensus"
11         "github.com/bytom/bytom/errors"
12         "github.com/bytom/bytom/event"
13         "github.com/bytom/bytom/protocol/bc"
14         "github.com/bytom/bytom/protocol/bc/types"
15         "github.com/bytom/bytom/protocol/state"
16 )
17
18 const (
19         maxProcessBlockChSize  = 1024
20         maxProcessRollbackSize = 1024
21 )
22
23 // Chain provides functions for working with the Bytom block chain.
24 type Chain struct {
25         orphanManage      *OrphanManage
26         txPool            *TxPool
27         store             Store
28         casper            *Casper
29         processBlockCh    chan *processBlockMsg
30         processRollbackCh chan *rollbackMsg
31         eventDispatcher   *event.Dispatcher
32
33         cond                 sync.Cond
34         bestBlockHeader      *types.BlockHeader // the last block on current main chain
35 }
36
37 // NewChain returns a new Chain using store as the underlying storage.
38 func NewChain(store Store, txPool *TxPool, eventDispatcher *event.Dispatcher) (*Chain, error) {
39         return NewChainWithOrphanManage(store, txPool, NewOrphanManage(), eventDispatcher)
40 }
41
42 func NewChainWithOrphanManage(store Store, txPool *TxPool, manage *OrphanManage, eventDispatcher *event.Dispatcher) (*Chain, error) {
43         c := &Chain{
44                 orphanManage:      manage,
45                 eventDispatcher:   eventDispatcher,
46                 txPool:            txPool,
47                 store:             store,
48                 processRollbackCh: make(chan *rollbackMsg, maxProcessRollbackSize),
49                 processBlockCh:    make(chan *processBlockMsg, maxProcessBlockChSize),
50         }
51         c.cond.L = new(sync.Mutex)
52
53         storeStatus := store.GetStoreStatus()
54         if storeStatus == nil {
55                 if err := c.initChainStatus(); err != nil {
56                         return nil, err
57                 }
58                 storeStatus = store.GetStoreStatus()
59         }
60
61         var err error
62         c.bestBlockHeader, err = c.store.GetBlockHeader(storeStatus.Hash)
63         if err != nil {
64                 return nil, err
65         }
66
67         casper, err := newCasper(store, storeStatus, c.processRollbackCh)
68         if err != nil {
69                 return nil, err
70         }
71
72         c.casper = casper
73         go c.blockProcessor()
74         return c, nil
75 }
76
77 func (c *Chain) initChainStatus() error {
78         genesisBlock := config.GenesisBlock()
79         if err := c.store.SaveBlock(genesisBlock); err != nil {
80                 return err
81         }
82
83         checkpoint := &state.Checkpoint{
84                 Height:    0,
85                 Hash:      genesisBlock.Hash(),
86                 Timestamp: genesisBlock.Timestamp,
87                 Status:    state.Justified,
88         }
89
90         if err := c.store.SaveCheckpoints([]*state.Checkpoint{checkpoint}); err != nil {
91                 return err
92         }
93
94         utxoView := state.NewUtxoViewpoint()
95         bcBlock := types.MapBlock(genesisBlock)
96         if err := utxoView.ApplyBlock(bcBlock); err != nil {
97                 return err
98         }
99
100         contractView := state.NewContractViewpoint()
101         genesisBlockHeader := &genesisBlock.BlockHeader
102         return c.store.SaveChainStatus(genesisBlockHeader, []*types.BlockHeader{genesisBlockHeader}, utxoView, contractView, 0, &checkpoint.Hash)
103 }
104
105 func newCasper(store Store, storeStatus *BlockStoreState, rollbackCh chan *rollbackMsg) (*Casper, error) {
106         checkpoints, err := store.CheckpointsFromNode(storeStatus.FinalizedHeight, storeStatus.FinalizedHash)
107         if err != nil {
108                 return nil, err
109         }
110
111         return NewCasper(store, checkpoints, rollbackCh), nil
112 }
113
114 // LastFinalizedHeader returns the last finalized block header of the block chain
115 func (c *Chain) LastJustifiedHeader() (*types.BlockHeader, error) {
116         _, hash := c.casper.LastJustified()
117         return c.store.GetBlockHeader(&hash)
118 }
119
120 // ProcessBlockVerification process block verification
121 func (c *Chain) ProcessBlockVerification(v *Verification) error {
122         if err := c.casper.AuthVerification(v); err != nil {
123                 return err
124         }
125
126         pubKey, _ := hex.DecodeString(v.PubKey)
127         signature, _ := hex.DecodeString(v.Signature)
128         return c.eventDispatcher.Post(event.BlockVerificationEvent{
129                 SourceHeight: v.SourceHeight,
130                 SourceHash:   v.SourceHash,
131                 TargetHeight: v.TargetHeight,
132                 TargetHash:   v.TargetHash,
133                 PubKey:       pubKey,
134                 Signature:    signature,
135         })
136 }
137
138 // BestBlockHeight returns the current height of the blockchain.
139 func (c *Chain) BestBlockHeight() uint64 {
140         c.cond.L.Lock()
141         defer c.cond.L.Unlock()
142         return c.bestBlockHeader.Height
143 }
144
145 // BestBlockHash return the hash of the chain tail block
146 func (c *Chain) BestBlockHash() *bc.Hash {
147         c.cond.L.Lock()
148         defer c.cond.L.Unlock()
149         bestHash := c.bestBlockHeader.Hash()
150         return &bestHash
151 }
152
153 // GetValidator return validator by specified blockHash and timestamp
154 func (c *Chain) GetValidator(prevHash *bc.Hash, timeStamp uint64) (*state.Validator, error) {
155         prevCheckpoint, err := c.casper.parentCheckpointByPrevHash(prevHash)
156         if err != nil {
157                 return nil, err
158         }
159
160         validators := prevCheckpoint.Validators()
161         startTimestamp := prevCheckpoint.Timestamp + consensus.ActiveNetParams.BlockTimeInterval
162         order := getValidatorOrder(startTimestamp, timeStamp, uint64(len(validators)))
163         for _, validator := range validators {
164                 if validator.Order == int(order) {
165                         return validator, nil
166                 }
167         }
168         return nil, errors.New("get blocker failure")
169 }
170
171 func getValidatorOrder(startTimestamp, blockTimestamp, numOfValidators uint64) uint64 {
172         // One round of product block time for all consensus nodes
173         roundBlockTime := numOfValidators * consensus.ActiveNetParams.BlockTimeInterval
174         // The start time of the last round of product block
175         lastRoundStartTime := startTimestamp + (blockTimestamp-startTimestamp)/roundBlockTime*roundBlockTime
176         // Order of blocker
177         return (blockTimestamp - lastRoundStartTime) / consensus.ActiveNetParams.BlockTimeInterval
178 }
179
180 // BestBlockHeader returns the chain tail block
181 func (c *Chain) BestBlockHeader() *types.BlockHeader {
182         c.cond.L.Lock()
183         defer c.cond.L.Unlock()
184         return c.bestBlockHeader
185 }
186
187 // InMainChain checks wheather a block is in the main chain
188 func (c *Chain) InMainChain(hash bc.Hash) bool {
189         blockHeader, err := c.store.GetBlockHeader(&hash)
190         if err != nil {
191                 return false
192         }
193
194         blockHash, err := c.store.GetMainChainHash(blockHeader.Height)
195         if err != nil {
196                 log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height}).Debug("not contain block hash in main chain for specified height")
197                 return false
198         }
199         return *blockHash == hash
200 }
201
202 func (c *Chain) SignBlockHeader(blockHeader *types.BlockHeader) {
203         xprv := config.CommonConfig.PrivateKey()
204         signature := xprv.Sign(blockHeader.Hash().Bytes())
205         blockHeader.Set(signature)
206 }
207
208 // This function must be called with mu lock in above level
209 func (c *Chain) setState(blockHeader *types.BlockHeader, mainBlockHeaders []*types.BlockHeader, view *state.UtxoViewpoint, contractView *state.ContractViewpoint) error {
210         finalizedHeight, finalizedHash := c.casper.LastFinalized()
211         if err := c.store.SaveChainStatus(blockHeader, mainBlockHeaders, view, contractView, finalizedHeight, &finalizedHash); err != nil {
212                 return err
213         }
214
215         c.cond.L.Lock()
216         defer c.cond.L.Unlock()
217
218         c.bestBlockHeader = blockHeader
219
220         hash := c.bestBlockHeader.Hash()
221         log.WithFields(log.Fields{"module": logModule, "height": c.bestBlockHeader.Height, "hash": hash.String()}).Debug("chain best status has been update")
222         c.cond.Broadcast()
223         return nil
224 }
225
226 // BlockWaiter returns a channel that waits for the block at the given height.
227 func (c *Chain) BlockWaiter(height uint64) <-chan struct{} {
228         ch := make(chan struct{}, 1)
229         go func() {
230                 c.cond.L.Lock()
231                 defer c.cond.L.Unlock()
232                 for c.bestBlockHeader.Height < height {
233                         c.cond.Wait()
234                 }
235                 ch <- struct{}{}
236         }()
237
238         return ch
239 }
240
241 // GetTxPool return chain txpool.
242 func (c *Chain) GetTxPool() *TxPool {
243         return c.txPool
244 }
245
246 // PrevCheckpointByPrevHash get previous checkpoint by previous block hash
247 func (c *Chain) PrevCheckpointByPrevHash(preBlockHash *bc.Hash) (*state.Checkpoint, error) {
248         return c.casper.parentCheckpointByPrevHash(preBlockHash)
249 }