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