func (ch *Chain) PreCheckBlock(bl *btc.Block) (er error, dos bool, maybelater bool) { // Size limits if len(bl.Raw) < 81 { er = errors.New("CheckBlock() : size limits failed - RPC_Result:bad-blk-length") dos = true return } if bl.Version() == 0 { er = errors.New("CheckBlock() : Block version 0 not allowed - RPC_Result:bad-version") dos = true return } // Check proof-of-work if !btc.CheckProofOfWork(bl.Hash, bl.Bits()) { er = errors.New("CheckBlock() : proof of work failed - RPC_Result:high-hash") dos = true return } // Check timestamp (must not be higher than now +2 hours) if int64(bl.BlockTime()) > time.Now().Unix()+2*60*60 { er = errors.New("CheckBlock() : block timestamp too far in the future - RPC_Result:time-too-new") dos = true return } if prv, pres := ch.BlockIndex[bl.Hash.BIdx()]; pres { if prv.Parent == nil { // This is genesis block er = errors.New("Genesis") return } else { er = errors.New("CheckBlock: " + bl.Hash.String() + " already in - RPC_Result:duplicate") return } } prevblk, ok := ch.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()] if !ok { er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found - RPC_Result:bad-prevblk") maybelater = true return } bl.Height = prevblk.Height + 1 // Reject the block if it reaches into the chain deeper than our unwind buffer if prevblk != ch.BlockTreeEnd && int(ch.BlockTreeEnd.Height)-int(bl.Height) >= MovingCheckopintDepth { er = errors.New(fmt.Sprint("CheckBlock: btc.Block ", bl.Hash.String(), " hooks too deep into the chain: ", bl.Height, "/", ch.BlockTreeEnd.Height, " ", btc.NewUint256(bl.ParentHash()).String(), " - RPC_Result:bad-prevblk")) return } // Check proof of work gnwr := ch.GetNextWorkRequired(prevblk, bl.BlockTime()) if bl.Bits() != gnwr { er = errors.New("CheckBlock: incorrect proof of work - RPC_Result:bad-diffbits") dos = true return } // Check timestamp against prev bl.MedianPastTime = prevblk.GetMedianTimePast() if bl.BlockTime() <= bl.MedianPastTime { er = errors.New("CheckBlock: block's timestamp is too early - RPC_Result:time-too-old") dos = true return } if bl.Version() < 2 && bl.Height >= ch.Consensus.BIP34Height || bl.Version() < 3 && bl.Height >= ch.Consensus.BIP66Height || bl.Version() < 4 && bl.Height >= ch.Consensus.BIP65Height { // bad block version erstr := fmt.Sprintf("0x%08x", bl.Version()) er = errors.New("CheckBlock() : Rejected Version=" + erstr + " blolck - RPC_Result:bad-version(" + erstr + ")") dos = true return } return }