// SetCurrentHeader sets the current head header of the canonical chain. func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { if err := WriteHeadHeaderHash(hc.chainDb, head.Hash()); err != nil { glog.Fatalf("failed to insert head header hash: %v", err) } hc.currentHeader = head hc.currentHeaderHash = head.Hash() }
// WriteHeader writes a header into the local chain, given that its parent is // already known. If the total difficulty of the newly inserted header becomes // greater than the current known TD, the canonical chain is re-routed. // // Note: This method is not concurrent-safe with inserting blocks simultaneously // into the chain, as side effects caused by reorganisations cannot be emulated // without the real blocks. Hence, writing headers directly should only be done // in two scenarios: pure-header mode of operation (light clients), or properly // separated header/block phases (non-archive clients). func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, err error) { // Cache some values to prevent constant recalculation var ( hash = header.Hash() number = header.Number.Uint64() ) // Calculate the total difficulty of the header ptd := hc.GetTd(header.ParentHash) if ptd == nil { return NonStatTy, ParentError(header.ParentHash) } localTd := hc.GetTd(hc.currentHeaderHash) externTd := new(big.Int).Add(header.Difficulty, ptd) // If the total difficulty is higher than our known, add it to the canonical chain // Second clause in the if statement reduces the vulnerability to selfish mining. // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) { // Delete any canonical number assignments above the new head for i := number + 1; GetCanonicalHash(hc.chainDb, i) != (common.Hash{}); i++ { DeleteCanonicalHash(hc.chainDb, i) } // Overwrite any stale canonical number assignments var ( headHash = header.ParentHash headHeader = hc.GetHeader(headHash) headNumber = headHeader.Number.Uint64() ) for GetCanonicalHash(hc.chainDb, headNumber) != headHash { WriteCanonicalHash(hc.chainDb, headHash, headNumber) headHash = headHeader.ParentHash headHeader = hc.GetHeader(headHash) headNumber = headHeader.Number.Uint64() } // Extend the canonical chain with the new header if err := WriteCanonicalHash(hc.chainDb, hash, number); err != nil { glog.Fatalf("failed to insert header number: %v", err) } if err := WriteHeadHeaderHash(hc.chainDb, hash); err != nil { glog.Fatalf("failed to insert head header hash: %v", err) } hc.currentHeaderHash, hc.currentHeader = hash, types.CopyHeader(header) status = CanonStatTy } else { status = SideStatTy } // Irrelevant of the canonical status, write the header itself to the database if err := hc.WriteTd(hash, externTd); err != nil { glog.Fatalf("failed to write header total difficulty: %v", err) } if err := WriteHeader(hc.chainDb, header); err != nil { glog.Fatalf("failed to write header contents: %v", err) } hc.headerCache.Add(hash, header) return }
// ValidateHeader validates the given header and, depending on the pow arg, // checks the proof of work of the given header. Returns an error if the // validation failed. func (v *BlockValidator) ValidateHeader(header, parent *types.Header, checkPow bool) error { // Short circuit if the parent is missing. if parent == nil { return ParentError(header.ParentHash) } // Short circuit if the header's already known or its parent missing if v.bc.HasHeader(header.Hash()) { return nil } return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false) }
// ValidateHeader verifies the validity of a header, relying on the database and // POW behind the block processor. func (sm *BlockProcessor) ValidateHeader(header *types.Header, checkPow, uncle bool) error { // Short circuit if the header's already known or its parent missing if sm.bc.HasHeader(header.Hash()) { return nil } if parent := sm.bc.GetHeader(header.ParentHash); parent == nil { return ParentError(header.ParentHash) } else { return ValidateHeader(sm.Pow, header, parent, checkPow, uncle) } }
// WriteHeader serializes a block header into the database. func WriteHeader(db ethdb.Database, header *types.Header) error { data, err := rlp.EncodeToBytes(header) if err != nil { return err } key := append(append(blockPrefix, header.Hash().Bytes()...), headerSuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store header into database: %v", err) return err } glog.V(logger.Debug).Infof("stored header #%v [%x…]", header.Number, header.Hash().Bytes()[:4]) return nil }
func (self *worker) commitUncle(work *Work, uncle *types.Header) error { hash := uncle.Hash() if work.uncles.Has(hash) { return core.UncleError("Uncle not unique") } if !work.ancestors.Has(uncle.ParentHash) { return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } if work.family.Has(hash) { return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", hash)) } work.uncles.Add(uncle.Hash()) return nil }
// Validates a header. Returns an error if the header is invalid. // // See YP section 4.3.4. "Block Header Validity" func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error { if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 { return fmt.Errorf("Header extra data too long (%d)", len(header.Extra)) } if uncle { if header.Time.Cmp(common.MaxBig) == 1 { return BlockTSTooBigErr } } else { if header.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 { return BlockFutureErr } } if header.Time.Cmp(parent.Time) != 1 { return BlockEqualTSErr } expd := CalcDifficulty(config, header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty) if expd.Cmp(header.Difficulty) != 0 { return fmt.Errorf("Difficulty check failed for header %v, %v", header.Difficulty, expd) } a := new(big.Int).Set(parent.GasLimit) a = a.Sub(a, header.GasLimit) a.Abs(a) b := new(big.Int).Set(parent.GasLimit) b = b.Div(b, params.GasLimitBoundDivisor) if !(a.Cmp(b) < 0) || (header.GasLimit.Cmp(params.MinGasLimit) == -1) { return fmt.Errorf("GasLimit check failed for header %v (%v > %v)", header.GasLimit, a, b) } num := new(big.Int).Set(parent.Number) num.Sub(header.Number, num) if num.Cmp(big.NewInt(1)) != 0 { return BlockNumberErr } if checkPow { // Verify the nonce of the header. Return an error if it's not valid if !pow.Verify(types.NewBlockWithHeader(header)) { return &BlockNonceErr{header.Number, header.Hash(), header.Nonce.Uint64()} } } // If all checks passed, validate the extra-data field for hard forks return ValidateDAOHeaderExtraData(config, header) }
func (self *worker) commitUncle(uncle *types.Header) error { if self.current.uncles.Has(uncle.Hash()) { // Error not unique return core.UncleError("Uncle not unique") } self.current.uncles.Add(uncle.Hash()) if !self.current.family.Has(uncle.ParentHash) { return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } if self.current.family.Has(uncle.Hash()) { return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash())) } return nil }
func NewUncleRes(h *types.Header) *UncleRes { if h == nil { return nil } var v = new(UncleRes) v.BlockNumber = newHexNum(h.Number) v.BlockHash = newHexData(h.Hash()) v.ParentHash = newHexData(h.ParentHash) v.Sha3Uncles = newHexData(h.UncleHash) v.Nonce = newHexData(h.Nonce[:]) v.LogsBloom = newHexData(h.Bloom) v.TransactionRoot = newHexData(h.TxHash) v.StateRoot = newHexData(h.Root) v.Miner = newHexData(h.Coinbase) v.Difficulty = newHexNum(h.Difficulty) v.ExtraData = newHexData(h.Extra) v.GasLimit = newHexNum(h.GasLimit) v.GasUsed = newHexNum(h.GasUsed) v.UnixTimestamp = newHexNum(h.Time) v.ReceiptHash = newHexData(h.ReceiptHash) return v }
// writeHeader writes a header into the local chain, given that its parent is // already known. If the total difficulty of the newly inserted header becomes // greater than the current known TD, the canonical chain is re-routed. // // Note: This method is not concurrent-safe with inserting blocks simultaneously // into the chain, as side effects caused by reorganisations cannot be emulated // without the real blocks. Hence, writing headers directly should only be done // in two scenarios: pure-header mode of operation (light clients), or properly // separated header/block phases (non-archive clients). func (self *BlockChain) writeHeader(header *types.Header) error { self.wg.Add(1) defer self.wg.Done() // Calculate the total difficulty of the header ptd := self.GetTd(header.ParentHash) if ptd == nil { return ParentError(header.ParentHash) } localTd := self.GetTd(self.currentHeader.Hash()) externTd := new(big.Int).Add(header.Difficulty, ptd) // Make sure no inconsistent state is leaked during insertion self.mu.Lock() defer self.mu.Unlock() // If the total difficulty is higher than our known, add it to the canonical chain // Second clause in the if statement reduces the vulnerability to selfish mining. // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) { // Delete any canonical number assignments above the new head for i := header.Number.Uint64() + 1; GetCanonicalHash(self.chainDb, i) != (common.Hash{}); i++ { DeleteCanonicalHash(self.chainDb, i) } // Overwrite any stale canonical number assignments head := self.GetHeader(header.ParentHash) for GetCanonicalHash(self.chainDb, head.Number.Uint64()) != head.Hash() { WriteCanonicalHash(self.chainDb, head.Hash(), head.Number.Uint64()) head = self.GetHeader(head.ParentHash) } // Extend the canonical chain with the new header if err := WriteCanonicalHash(self.chainDb, header.Hash(), header.Number.Uint64()); err != nil { glog.Fatalf("failed to insert header number: %v", err) } if err := WriteHeadHeaderHash(self.chainDb, header.Hash()); err != nil { glog.Fatalf("failed to insert head header hash: %v", err) } self.currentHeader = types.CopyHeader(header) } // Irrelevant of the canonical status, write the header itself to the database if err := WriteTd(self.chainDb, header.Hash(), externTd); err != nil { glog.Fatalf("failed to write header total difficulty: %v", err) } if err := WriteHeader(self.chainDb, header); err != nil { glog.Fatalf("filed to write header contents: %v", err) } return nil }
// writeHeader writes a header into the local chain, given that its parent is // already known. If the total difficulty of the newly inserted header becomes // greater than the current known TD, the canonical chain is re-routed. // // Note: This method is not concurrent-safe with inserting blocks simultaneously // into the chain, as side effects caused by reorganisations cannot be emulated // without the real blocks. Hence, writing headers directly should only be done // in two scenarios: pure-header mode of operation (light clients), or properly // separated header/block phases (non-archive clients). func (self *BlockChain) writeHeader(header *types.Header) error { self.wg.Add(1) defer self.wg.Done() // Calculate the total difficulty of the header ptd := self.GetTd(header.ParentHash) if ptd == nil { return ParentError(header.ParentHash) } td := new(big.Int).Add(header.Difficulty, ptd) // Make sure no inconsistent state is leaked during insertion self.mu.Lock() defer self.mu.Unlock() // If the total difficulty is higher than our known, add it to the canonical chain if td.Cmp(self.GetTd(self.currentHeader.Hash())) > 0 { // Delete any canonical number assignments above the new head for i := header.Number.Uint64() + 1; GetCanonicalHash(self.chainDb, i) != (common.Hash{}); i++ { DeleteCanonicalHash(self.chainDb, i) } // Overwrite any stale canonical number assignments head := self.GetHeader(header.ParentHash) for GetCanonicalHash(self.chainDb, head.Number.Uint64()) != head.Hash() { WriteCanonicalHash(self.chainDb, head.Hash(), head.Number.Uint64()) head = self.GetHeader(head.ParentHash) } // Extend the canonical chain with the new header if err := WriteCanonicalHash(self.chainDb, header.Hash(), header.Number.Uint64()); err != nil { glog.Fatalf("failed to insert header number: %v", err) } if err := WriteHeadHeaderHash(self.chainDb, header.Hash()); err != nil { glog.Fatalf("failed to insert head header hash: %v", err) } self.currentHeader = types.CopyHeader(header) } // Irrelevant of the canonical status, write the header itself to the database if err := WriteTd(self.chainDb, header.Hash(), td); err != nil { glog.Fatalf("failed to write header total difficulty: %v", err) } if err := WriteHeader(self.chainDb, header); err != nil { glog.Fatalf("filed to write header contents: %v", err) } return nil }
// ValidateHeaderWithParent verifies the validity of a header, relying on the database and // POW behind the block processor. func (sm *BlockProcessor) ValidateHeaderWithParent(header, parent *types.Header, checkPow, uncle bool) error { if sm.bc.HasHeader(header.Hash()) { return nil } return ValidateHeader(sm.Pow, header, parent, checkPow, uncle) }