github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/headerchain.go (about) 1 package core 2 3 import ( 4 crand "crypto/rand" 5 "errors" 6 "fmt" 7 "math" 8 "math/big" 9 mrand "math/rand" 10 "sync/atomic" 11 "time" 12 13 "github.com/quickchainproject/quickchain/common" 14 "github.com/quickchainproject/quickchain/consensus" 15 "github.com/quickchainproject/quickchain/core/types" 16 "github.com/quickchainproject/quickchain/qctdb" 17 "github.com/quickchainproject/quickchain/log" 18 "github.com/quickchainproject/quickchain/params" 19 "github.com/hashicorp/golang-lru" 20 ) 21 22 const ( 23 headerCacheLimit = 512 24 tdCacheLimit = 1024 25 numberCacheLimit = 2048 26 ) 27 28 // HeaderChain implements the basic block header chain logic that is shared by 29 // core.BlockChain and light.LightChain. It is not usable in itself, only as 30 // a part of either structure. 31 // It is not thread safe either, the encapsulating chain structures should do 32 // the necessary mutex locking/unlocking. 33 type HeaderChain struct { 34 config *params.ChainConfig 35 36 chainDb qctdb.Database 37 genesisHeader *types.Header 38 39 currentHeader atomic.Value // Current head of the header chain (may be above the block chain!) 40 currentHeaderHash common.Hash // Hash of the current head of the header chain (prevent recomputing all the time) 41 42 headerCache *lru.Cache // Cache for the most recent block headers 43 tdCache *lru.Cache // Cache for the most recent block total difficulties 44 numberCache *lru.Cache // Cache for the most recent block numbers 45 46 procInterrupt func() bool 47 48 rand *mrand.Rand 49 engine consensus.Engine 50 } 51 52 // NewHeaderChain creates a new HeaderChain structure. 53 // getValidator should return the parent's validator 54 // procInterrupt points to the parent's interrupt semaphore 55 // wg points to the parent's shutdown wait group 56 func NewHeaderChain(chainDb qctdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) { 57 headerCache, _ := lru.New(headerCacheLimit) 58 tdCache, _ := lru.New(tdCacheLimit) 59 numberCache, _ := lru.New(numberCacheLimit) 60 61 // Seed a fast but crypto originating random generator 62 seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) 63 if err != nil { 64 return nil, err 65 } 66 67 hc := &HeaderChain{ 68 config: config, 69 chainDb: chainDb, 70 headerCache: headerCache, 71 tdCache: tdCache, 72 numberCache: numberCache, 73 procInterrupt: procInterrupt, 74 rand: mrand.New(mrand.NewSource(seed.Int64())), 75 engine: engine, 76 } 77 78 hc.genesisHeader = hc.GetHeaderByNumber(0) 79 if hc.genesisHeader == nil { 80 return nil, ErrNoGenesis 81 } 82 83 hc.currentHeader.Store(hc.genesisHeader) 84 if head := GetHeadBlockHash(chainDb); head != (common.Hash{}) { 85 if chead := hc.GetHeaderByHash(head); chead != nil { 86 hc.currentHeader.Store(chead) 87 } 88 } 89 hc.currentHeaderHash = hc.CurrentHeader().Hash() 90 91 return hc, nil 92 } 93 94 // GetBlockNumber retrieves the block number belonging to the given hash 95 // from the cache or database 96 func (hc *HeaderChain) GetBlockNumber(hash common.Hash) uint64 { 97 if cached, ok := hc.numberCache.Get(hash); ok { 98 return cached.(uint64) 99 } 100 number := GetBlockNumber(hc.chainDb, hash) 101 if number != missingNumber { 102 hc.numberCache.Add(hash, number) 103 } 104 return number 105 } 106 107 // WriteHeader writes a header into the local chain, given that its parent is 108 // already known. If the total difficulty of the newly inserted header becomes 109 // greater than the current known TD, the canonical chain is re-routed. 110 // 111 // Note: This method is not concurrent-safe with inserting blocks simultaneously 112 // into the chain, as side effects caused by reorganisations cannot be emulated 113 // without the real blocks. Hence, writing headers directly should only be done 114 // in two scenarios: pure-header mode of operation (light clients), or properly 115 // separated header/block phases (non-archive clients). 116 func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, err error) { 117 // Cache some values to prevent constant recalculation 118 var ( 119 hash = header.Hash() 120 number = header.Number.Uint64() 121 ) 122 // Calculate the total difficulty of the header 123 ptd := hc.GetTd(header.ParentHash, number-1) 124 if ptd == nil { 125 return NonStatTy, consensus.ErrUnknownAncestor 126 } 127 localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64()) 128 externTd := new(big.Int).Add(header.Difficulty, ptd) 129 130 // Irrelevant of the canonical status, write the td and header to the database 131 if err := hc.WriteTd(hash, number, externTd); err != nil { 132 log.Crit("Failed to write header total difficulty", "err", err) 133 } 134 if err := WriteHeader(hc.chainDb, header); err != nil { 135 log.Crit("Failed to write header content", "err", err) 136 } 137 // If the total difficulty is higher than our known, add it to the canonical chain 138 // Second clause in the if statement reduces the vulnerability to selfish mining. 139 // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf 140 if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) { 141 // Delete any canonical number assignments above the new head 142 for i := number + 1; ; i++ { 143 hash := GetCanonicalHash(hc.chainDb, i) 144 if hash == (common.Hash{}) { 145 break 146 } 147 DeleteCanonicalHash(hc.chainDb, i) 148 } 149 // Overwrite any stale canonical number assignments 150 var ( 151 headHash = header.ParentHash 152 headNumber = header.Number.Uint64() - 1 153 headHeader = hc.GetHeader(headHash, headNumber) 154 ) 155 for GetCanonicalHash(hc.chainDb, headNumber) != headHash { 156 WriteCanonicalHash(hc.chainDb, headHash, headNumber) 157 158 headHash = headHeader.ParentHash 159 headNumber = headHeader.Number.Uint64() - 1 160 headHeader = hc.GetHeader(headHash, headNumber) 161 } 162 // Extend the canonical chain with the new header 163 if err := WriteCanonicalHash(hc.chainDb, hash, number); err != nil { 164 log.Crit("Failed to insert header number", "err", err) 165 } 166 if err := WriteHeadHeaderHash(hc.chainDb, hash); err != nil { 167 log.Crit("Failed to insert head header hash", "err", err) 168 } 169 hc.currentHeaderHash = hash 170 hc.currentHeader.Store(types.CopyHeader(header)) 171 172 status = CanonStatTy 173 } else { 174 status = SideStatTy 175 } 176 177 hc.headerCache.Add(hash, header) 178 hc.numberCache.Add(hash, number) 179 180 return 181 } 182 183 // WhCallback is a callback function for inserting individual headers. 184 // A callback is used for two reasons: first, in a LightChain, status should be 185 // processed and light chain events sent, while in a BlockChain this is not 186 // necessary since chain events are sent after inserting blocks. Second, the 187 // header writes should be protected by the parent chain mutex individually. 188 type WhCallback func(*types.Header) error 189 190 func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) { 191 // Do a sanity check that the provided chain is actually ordered and linked 192 for i := 1; i < len(chain); i++ { 193 if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() { 194 // Chain broke ancestry, log a messge (programming error) and skip insertion 195 log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", chain[i].Hash(), 196 "parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", chain[i-1].Hash()) 197 198 return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, chain[i-1].Number, 199 chain[i-1].Hash().Bytes()[:4], i, chain[i].Number, chain[i].Hash().Bytes()[:4], chain[i].ParentHash[:4]) 200 } 201 } 202 203 // Generate the list of seal verification requests, and start the parallel verifier 204 seals := make([]bool, len(chain)) 205 for i := 0; i < len(seals)/checkFreq; i++ { 206 index := i*checkFreq + hc.rand.Intn(checkFreq) 207 if index >= len(seals) { 208 index = len(seals) - 1 209 } 210 seals[index] = true 211 } 212 seals[len(seals)-1] = true // Last should always be verified to avoid junk 213 214 abort, results := hc.engine.VerifyHeaders(hc, chain, seals) 215 defer close(abort) 216 217 // Iterate over the headers and ensure they all check out 218 for i, header := range chain { 219 // If the chain is terminating, stop processing blocks 220 if hc.procInterrupt() { 221 log.Debug("Premature abort during headers verification") 222 return 0, errors.New("aborted") 223 } 224 // If the header is a banned one, straight out abort 225 if BadHashes[header.Hash()] { 226 return i, ErrBlacklistedHash 227 } 228 // Otherwise wait for headers checks and ensure they pass 229 if err := <-results; err != nil { 230 return i, err 231 } 232 } 233 234 return 0, nil 235 } 236 237 // InsertHeaderChain attempts to insert the given header chain in to the local 238 // chain, possibly creating a reorg. If an error is returned, it will return the 239 // index number of the failing header as well an error describing what went wrong. 240 // 241 // The verify parameter can be used to fine tune whether nonce verification 242 // should be done or not. The reason behind the optional check is because some 243 // of the header retrieval mechanisms already need to verfy nonces, as well as 244 // because nonces can be verified sparsely, not needing to check each. 245 func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCallback, start time.Time) (int, error) { 246 // Collect some import statistics to report on 247 stats := struct{ processed, ignored int }{} 248 // All headers passed verification, import them into the database 249 for i, header := range chain { 250 // Short circuit insertion if shutting down 251 if hc.procInterrupt() { 252 log.Debug("Premature abort during headers import") 253 return i, errors.New("aborted") 254 } 255 // If the header's already known, skip it, otherwise store 256 if hc.HasHeader(header.Hash(), header.Number.Uint64()) { 257 stats.ignored++ 258 continue 259 } 260 if err := writeHeader(header); err != nil { 261 return i, err 262 } 263 stats.processed++ 264 } 265 // Report some public statistics so the user has a clue what's going on 266 last := chain[len(chain)-1] 267 log.Info("Imported new block headers", "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)), 268 "number", last.Number, "hash", last.Hash(), "ignored", stats.ignored) 269 270 return 0, nil 271 } 272 273 // GetBlockHashesFromHash retrieves a number of block hashes starting at a given 274 // hash, fetching towards the genesis block. 275 func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { 276 // Get the origin header from which to fetch 277 header := hc.GetHeaderByHash(hash) 278 if header == nil { 279 return nil 280 } 281 // Iterate the headers until enough is collected or the genesis reached 282 chain := make([]common.Hash, 0, max) 283 for i := uint64(0); i < max; i++ { 284 next := header.ParentHash 285 if header = hc.GetHeader(next, header.Number.Uint64()-1); header == nil { 286 break 287 } 288 chain = append(chain, next) 289 if header.Number.Sign() == 0 { 290 break 291 } 292 } 293 return chain 294 } 295 296 // GetTd retrieves a block's total difficulty in the canonical chain from the 297 // database by hash and number, caching it if found. 298 func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int { 299 // Short circuit if the td's already in the cache, retrieve otherwise 300 if cached, ok := hc.tdCache.Get(hash); ok { 301 return cached.(*big.Int) 302 } 303 td := GetTd(hc.chainDb, hash, number) 304 if td == nil { 305 return nil 306 } 307 // Cache the found body for next time and return 308 hc.tdCache.Add(hash, td) 309 return td 310 } 311 312 // GetTdByHash retrieves a block's total difficulty in the canonical chain from the 313 // database by hash, caching it if found. 314 func (hc *HeaderChain) GetTdByHash(hash common.Hash) *big.Int { 315 return hc.GetTd(hash, hc.GetBlockNumber(hash)) 316 } 317 318 // WriteTd stores a block's total difficulty into the database, also caching it 319 // along the way. 320 func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) error { 321 if err := WriteTd(hc.chainDb, hash, number, td); err != nil { 322 return err 323 } 324 hc.tdCache.Add(hash, new(big.Int).Set(td)) 325 return nil 326 } 327 328 // GetHeader retrieves a block header from the database by hash and number, 329 // caching it if found. 330 func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header { 331 // Short circuit if the header's already in the cache, retrieve otherwise 332 if header, ok := hc.headerCache.Get(hash); ok { 333 return header.(*types.Header) 334 } 335 header := GetHeader(hc.chainDb, hash, number) 336 if header == nil { 337 return nil 338 } 339 // Cache the found header for next time and return 340 hc.headerCache.Add(hash, header) 341 return header 342 } 343 344 // GetHeaderByHash retrieves a block header from the database by hash, caching it if 345 // found. 346 func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header { 347 return hc.GetHeader(hash, hc.GetBlockNumber(hash)) 348 } 349 350 // HasHeader checks if a block header is present in the database or not. 351 func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool { 352 if hc.numberCache.Contains(hash) || hc.headerCache.Contains(hash) { 353 return true 354 } 355 ok, _ := hc.chainDb.Has(headerKey(hash, number)) 356 return ok 357 } 358 359 // GetHeaderByNumber retrieves a block header from the database by number, 360 // caching it (associated with its hash) if found. 361 func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header { 362 hash := GetCanonicalHash(hc.chainDb, number) 363 if hash == (common.Hash{}) { 364 return nil 365 } 366 return hc.GetHeader(hash, number) 367 } 368 369 // CurrentHeader retrieves the current head header of the canonical chain. The 370 // header is retrieved from the HeaderChain's internal cache. 371 func (hc *HeaderChain) CurrentHeader() *types.Header { 372 return hc.currentHeader.Load().(*types.Header) 373 } 374 375 // SetCurrentHeader sets the current head header of the canonical chain. 376 func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { 377 if err := WriteHeadHeaderHash(hc.chainDb, head.Hash()); err != nil { 378 log.Crit("Failed to insert head header hash", "err", err) 379 } 380 hc.currentHeader.Store(head) 381 hc.currentHeaderHash = head.Hash() 382 } 383 384 // DeleteCallback is a callback function that is called by SetHead before 385 // each header is deleted. 386 type DeleteCallback func(common.Hash, uint64) 387 388 // SetHead rewinds the local chain to a new head. Everything above the new head 389 // will be deleted and the new one set. 390 func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) { 391 height := uint64(0) 392 393 if hdr := hc.CurrentHeader(); hdr != nil { 394 height = hdr.Number.Uint64() 395 } 396 397 for hdr := hc.CurrentHeader(); hdr != nil && hdr.Number.Uint64() > head; hdr = hc.CurrentHeader() { 398 hash := hdr.Hash() 399 num := hdr.Number.Uint64() 400 if delFn != nil { 401 delFn(hash, num) 402 } 403 DeleteHeader(hc.chainDb, hash, num) 404 DeleteTd(hc.chainDb, hash, num) 405 hc.currentHeader.Store(hc.GetHeader(hdr.ParentHash, hdr.Number.Uint64()-1)) 406 } 407 // Roll back the canonical chain numbering 408 for i := height; i > head; i-- { 409 DeleteCanonicalHash(hc.chainDb, i) 410 } 411 // Clear out any stale content from the caches 412 hc.headerCache.Purge() 413 hc.tdCache.Purge() 414 hc.numberCache.Purge() 415 416 if hc.CurrentHeader() == nil { 417 hc.currentHeader.Store(hc.genesisHeader) 418 } 419 hc.currentHeaderHash = hc.CurrentHeader().Hash() 420 421 if err := WriteHeadHeaderHash(hc.chainDb, hc.currentHeaderHash); err != nil { 422 log.Crit("Failed to reset head header hash", "err", err) 423 } 424 } 425 426 // SetGenesis sets a new genesis block header for the chain 427 func (hc *HeaderChain) SetGenesis(head *types.Header) { 428 hc.genesisHeader = head 429 } 430 431 // Config retrieves the header chain's chain configuration. 432 func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config } 433 434 // Engine retrieves the header chain's consensus engine. 435 func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine } 436 437 // GetBlock implements consensus.ChainReader, and returns nil for every input as 438 // a header chain does not have blocks available for retrieval. 439 func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block { 440 return nil 441 }