--- /dev/null
+// Copyright (c) 2013-2016 The btcsuite developers
+// Copyright (c) 2015 The Decred developers
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package chainhash
+
+import (
+ "encoding/hex"
+ "fmt"
+)
+
+// HashSize of array used to store hashes. See Hash.
+const HashSize = 32
+
+// MaxHashStringSize is the maximum length of a Hash hash string.
+const MaxHashStringSize = HashSize * 2
+
+// ErrHashStrSize describes an error that indicates the caller specified a hash
+// string that has too many characters.
+var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize)
+
+// Hash is used in several of the bitcoin messages and common structures. It
+// typically represents the double sha256 of data.
+type Hash [HashSize]byte
+
+// String returns the Hash as the hexadecimal string of the byte-reversed
+// hash.
+func (hash Hash) String() string {
+ for i := 0; i < HashSize/2; i++ {
+ hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
+ }
+ return hex.EncodeToString(hash[:])
+}
+
+// CloneBytes returns a copy of the bytes which represent the hash as a byte
+// slice.
+//
+// NOTE: It is generally cheaper to just slice the hash directly thereby reusing
+// the same bytes rather than calling this method.
+func (hash *Hash) CloneBytes() []byte {
+ newHash := make([]byte, HashSize)
+ copy(newHash, hash[:])
+
+ return newHash
+}
+
+// SetBytes sets the bytes which represent the hash. An error is returned if
+// the number of bytes passed in is not HashSize.
+func (hash *Hash) SetBytes(newHash []byte) error {
+ nhlen := len(newHash)
+ if nhlen != HashSize {
+ return fmt.Errorf("invalid hash length of %v, want %v", nhlen,
+ HashSize)
+ }
+ copy(hash[:], newHash)
+
+ return nil
+}
+
+// IsEqual returns true if target is the same as hash.
+func (hash *Hash) IsEqual(target *Hash) bool {
+ if hash == nil && target == nil {
+ return true
+ }
+ if hash == nil || target == nil {
+ return false
+ }
+ return *hash == *target
+}
+
+// NewHash returns a new Hash from a byte slice. An error is returned if
+// the number of bytes passed in is not HashSize.
+func NewHash(newHash []byte) (*Hash, error) {
+ var sh Hash
+ err := sh.SetBytes(newHash)
+ if err != nil {
+ return nil, err
+ }
+ return &sh, err
+}
+
+// NewHashFromStr creates a Hash from a hash string. The string should be
+// the hexadecimal string of a byte-reversed hash, but any missing characters
+// result in zero padding at the end of the Hash.
+func NewHashFromStr(hash string) (*Hash, error) {
+ ret := new(Hash)
+ err := Decode(ret, hash)
+ if err != nil {
+ return nil, err
+ }
+ return ret, nil
+}
+
+// Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a
+// destination.
+func Decode(dst *Hash, src string) error {
+ // Return error if hash string is too long.
+ if len(src) > MaxHashStringSize {
+ return ErrHashStrSize
+ }
+
+ // Hex decoder expects the hash to be a multiple of two. When not, pad
+ // with a leading zero.
+ var srcBytes []byte
+ if len(src)%2 == 0 {
+ srcBytes = []byte(src)
+ } else {
+ srcBytes = make([]byte, 1+len(src))
+ srcBytes[0] = '0'
+ copy(srcBytes[1:], src)
+ }
+
+ // Hex decode the source bytes to a temporary destination.
+ var reversedHash Hash
+ _, err := hex.Decode(reversedHash[HashSize-hex.DecodedLen(len(srcBytes)):], srcBytes)
+ if err != nil {
+ return err
+ }
+
+ // Reverse copy from the temporary hash to destination. Because the
+ // temporary was zeroed, the written result will be correctly padded.
+ for i, b := range reversedHash[:HashSize/2] {
+ dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b
+ }
+
+ return nil
+}
--- /dev/null
+package wire
+
+import (
+ "bytes"
+ "io"
+ "time"
+
+ "github.com/blockchain/rpc/chainhash"
+)
+
+// MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
+// Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes +
+// PrevBlock and MerkleRoot hashes.
+const MaxBlockHeaderPayload = 16 + (chainhash.HashSize * 2)
+
+type uint32Time time.Time
+
+// BlockHeader defines information about a block and is used in the bitcoin
+// block (MsgBlock) and headers (MsgHeaders) messages.
+type BlockHeader struct {
+ // Version of the block. This is not the same as the protocol version.
+ Version int32
+
+ // Hash of the previous block in the block chain.
+ PrevBlock chainhash.Hash
+
+ // Merkle tree reference to hash of all transactions for the block.
+ MerkleRoot chainhash.Hash
+
+ // Time the block was created. This is, unfortunately, encoded as a
+ // uint32 on the wire and therefore is limited to 2106.
+ Timestamp time.Time
+
+ // Difficulty target for the block.
+ Bits uint32
+
+ // Nonce used to generate the block.
+ Nonce uint32
+}
+
+// blockHeaderLen is a constant that represents the number of bytes for a block
+// header.
+const blockHeaderLen = 80
+
+// BlockHash computes the block identifier hash for the given block header.
+func (h *BlockHeader) BlockHash() chainhash.Hash {
+ // Encode the header and double sha256 everything prior to the number of
+ // transactions. Ignore the error returns since there is no way the
+ // encode could fail except being out of memory which would cause a
+ // run-time panic.
+ buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload))
+ _ = writeBlockHeader(buf, 0, h)
+
+ return chainhash.DoubleHashH(buf.Bytes())
+}
+
+// BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
+// This is part of the Message interface implementation.
+// See Deserialize for decoding block headers stored to disk, such as in a
+// database, as opposed to decoding block headers from the wire.
+func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32) error {
+ return readBlockHeader(r, pver, h)
+}
+
+// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
+// This is part of the Message interface implementation.
+// See Serialize for encoding block headers to be stored to disk, such as in a
+// database, as opposed to encoding block headers for the wire.
+func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32) error {
+ return writeBlockHeader(w, pver, h)
+}
+
+// Deserialize decodes a block header from r into the receiver using a format
+// that is suitable for long-term storage such as a database while respecting
+// the Version field.
+func (h *BlockHeader) Deserialize(r io.Reader) error {
+ // At the current time, there is no difference between the wire encoding
+ // at protocol version 0 and the stable long-term storage format. As
+ // a result, make use of readBlockHeader.
+ return readBlockHeader(r, 0, h)
+}
+
+// Serialize encodes a block header from r into the receiver using a format
+// that is suitable for long-term storage such as a database while respecting
+// the Version field.
+func (h *BlockHeader) Serialize(w io.Writer) error {
+ // At the current time, there is no difference between the wire encoding
+ // at protocol version 0 and the stable long-term storage format. As
+ // a result, make use of writeBlockHeader.
+ return writeBlockHeader(w, 0, h)
+}
+
+// NewBlockHeader returns a new BlockHeader using the provided version, previous
+// block hash, merkle root hash, difficulty bits, and nonce used to generate the
+// block with defaults for the remaining fields.
+func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash,
+ bits uint32, nonce uint32) *BlockHeader {
+
+ // Limit the timestamp to one second precision since the protocol
+ // doesn't support better.
+ return &BlockHeader{
+ Version: version,
+ PrevBlock: *prevHash,
+ MerkleRoot: *merkleRootHash,
+ Timestamp: time.Unix(time.Now().Unix(), 0),
+ Bits: bits,
+ Nonce: nonce,
+ }
+}
+
+// readBlockHeader reads a bitcoin block header from r. See Deserialize for
+// decoding block headers stored to disk, such as in a database, as opposed to
+// decoding from the wire.
+func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
+ return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
+ (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce)
+}
+// writeBlockHeader writes a bitcoin block header to w. See Serialize for
+// encoding block headers to be stored to disk, such as in a database, as
+// opposed to encoding for the wire.
+func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
+ sec := uint32(bh.Timestamp.Unix())
+ return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
+ sec, bh.Bits, bh.Nonce)
+}
+
+func writeElements(w io.Writer, elements ...interface{}) error {
+ /*
+ for _, element := range elements {
+ err := writeElement(w, element)
+ if err != nil {
+ return err
+ }
+ }
+*/
+ return nil
+}
+
+func readElements(r io.Reader, elements ...interface{}) error {
+/*
+ for _, element := range elements {
+ err := readElement(r, element)
+ if err != nil {
+ return err
+ }
+ }
+*/
+ return nil
+}
--- /dev/null
+// Copyright (c) 2013-2017 The btcsuite developers\r
+// Use of this source code is governed by an ISC\r
+// license that can be found in the LICENSE file.\r
+\r
+package wire\r
+\r
+import (\r
+ "math/big"\r
+ //"time"\r
+\r
+ "github.com/blockchain/rpc/chainhash"\r
+\r
+)\r
+\r
+var (\r
+ // bigOne is 1 represented as a big.Int. It is defined here to avoid\r
+ // the overhead of creating it multiple times.\r
+ bigOne = big.NewInt(1)\r
+\r
+ // oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid\r
+ // the overhead of creating it multiple times.\r
+ oneLsh256 = new(big.Int).Lsh(bigOne, 256)\r
+)\r
+\r
+// HashToBig converts a chainhash.Hash into a big.Int that can be used to\r
+// perform math comparisons.\r
+func HashToBig(hash *chainhash.Hash) *big.Int {\r
+ // A Hash is in little-endian, but the big package wants the bytes in\r
+ // big-endian, so reverse them.\r
+ buf := *hash\r
+ blen := len(buf)\r
+ for i := 0; i < blen/2; i++ {\r
+ buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]\r
+ }\r
+\r
+ return new(big.Int).SetBytes(buf[:])\r
+}\r
+/*\r
+// CompactToBig converts a compact representation of a whole number N to an\r
+// unsigned 32-bit number. The representation is similar to IEEE754 floating\r
+// point numbers.\r
+//\r
+// Like IEEE754 floating point, there are three basic components: the sign,\r
+// the exponent, and the mantissa. They are broken out as follows:\r
+//\r
+// * the most significant 8 bits represent the unsigned base 256 exponent\r
+// * bit 23 (the 24th bit) represents the sign bit\r
+// * the least significant 23 bits represent the mantissa\r
+//\r
+// -------------------------------------------------\r
+// | Exponent | Sign | Mantissa |\r
+// -------------------------------------------------\r
+// | 8 bits [31-24] | 1 bit [23] | 23 bits [22-00] |\r
+// -------------------------------------------------\r
+//\r
+// The formula to calculate N is:\r
+// N = (-1^sign) * mantissa * 256^(exponent-3)\r
+//\r
+// This compact form is only used in bitcoin to encode unsigned 256-bit numbers\r
+// which represent difficulty targets, thus there really is not a need for a\r
+// sign bit, but it is implemented here to stay consistent with bitcoind.\r
+func CompactToBig(compact uint32) *big.Int {\r
+ // Extract the mantissa, sign bit, and exponent.\r
+ mantissa := compact & 0x007fffff\r
+ isNegative := compact&0x00800000 != 0\r
+ exponent := uint(compact >> 24)\r
+\r
+ // Since the base for the exponent is 256, the exponent can be treated\r
+ // as the number of bytes to represent the full 256-bit number. So,\r
+ // treat the exponent as the number of bytes and shift the mantissa\r
+ // right or left accordingly. This is equivalent to:\r
+ // N = mantissa * 256^(exponent-3)\r
+ var bn *big.Int\r
+ if exponent <= 3 {\r
+ mantissa >>= 8 * (3 - exponent)\r
+ bn = big.NewInt(int64(mantissa))\r
+ } else {\r
+ bn = big.NewInt(int64(mantissa))\r
+ bn.Lsh(bn, 8*(exponent-3))\r
+ }\r
+\r
+ // Make it negative if the sign bit is set.\r
+ if isNegative {\r
+ bn = bn.Neg(bn)\r
+ }\r
+\r
+ return bn\r
+}\r
+\r
+// BigToCompact converts a whole number N to a compact representation using\r
+// an unsigned 32-bit number. The compact representation only provides 23 bits\r
+// of precision, so values larger than (2^23 - 1) only encode the most\r
+// significant digits of the number. See CompactToBig for details.\r
+func BigToCompact(n *big.Int) uint32 {\r
+ // No need to do any work if it's zero.\r
+ if n.Sign() == 0 {\r
+ return 0\r
+ }\r
+\r
+ // Since the base for the exponent is 256, the exponent can be treated\r
+ // as the number of bytes. So, shift the number right or left\r
+ // accordingly. This is equivalent to:\r
+ // mantissa = mantissa / 256^(exponent-3)\r
+ var mantissa uint32\r
+ exponent := uint(len(n.Bytes()))\r
+ if exponent <= 3 {\r
+ mantissa = uint32(n.Bits()[0])\r
+ mantissa <<= 8 * (3 - exponent)\r
+ } else {\r
+ // Use a copy to avoid modifying the caller's original number.\r
+ tn := new(big.Int).Set(n)\r
+ mantissa = uint32(tn.Rsh(tn, 8*(exponent-3)).Bits()[0])\r
+ }\r
+\r
+ // When the mantissa already has the sign bit set, the number is too\r
+ // large to fit into the available 23-bits, so divide the number by 256\r
+ // and increment the exponent accordingly.\r
+ if mantissa&0x00800000 != 0 {\r
+ mantissa >>= 8\r
+ exponent++\r
+ }\r
+\r
+ // Pack the exponent, sign bit, and mantissa into an unsigned 32-bit\r
+ // int and return it.\r
+ compact := uint32(exponent<<24) | mantissa\r
+ if n.Sign() < 0 {\r
+ compact |= 0x00800000\r
+ }\r
+ return compact\r
+}\r
+\r
+// CalcWork calculates a work value from difficulty bits. Bitcoin increases\r
+// the difficulty for generating a block by decreasing the value which the\r
+// generated hash must be less than. This difficulty target is stored in each\r
+// block header using a compact representation as described in the documentation\r
+// for CompactToBig. The main chain is selected by choosing the chain that has\r
+// the most proof of work (highest difficulty). Since a lower target difficulty\r
+// value equates to higher actual difficulty, the work value which will be\r
+// accumulated must be the inverse of the difficulty. Also, in order to avoid\r
+// potential division by zero and really small floating point numbers, the\r
+// result adds 1 to the denominator and multiplies the numerator by 2^256.\r
+func CalcWork(bits uint32) *big.Int {\r
+ // Return a work value of zero if the passed difficulty bits represent\r
+ // a negative number. Note this should not happen in practice with valid\r
+ // blocks, but an invalid block could trigger it.\r
+ difficultyNum := CompactToBig(bits)\r
+ if difficultyNum.Sign() <= 0 {\r
+ return big.NewInt(0)\r
+ }\r
+\r
+ // (1 << 256) / (difficultyNum + 1)\r
+ denominator := new(big.Int).Add(difficultyNum, bigOne)\r
+ return new(big.Int).Div(oneLsh256, denominator)\r
+}\r
+\r
+// calcEasiestDifficulty calculates the easiest possible difficulty that a block\r
+// can have given starting difficulty bits and a duration. It is mainly used to\r
+// verify that claimed proof of work by a block is sane as compared to a\r
+// known good checkpoint.\r
+func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {\r
+ // Convert types used in the calculations below.\r
+ durationVal := int64(duration / time.Second)\r
+ adjustmentFactor := big.NewInt(b.chainParams.RetargetAdjustmentFactor)\r
+\r
+ // The test network rules allow minimum difficulty blocks after more\r
+ // than twice the desired amount of time needed to generate a block has\r
+ // elapsed.\r
+ if b.chainParams.ReduceMinDifficulty {\r
+ reductionTime := int64(b.chainParams.MinDiffReductionTime /\r
+ time.Second)\r
+ if durationVal > reductionTime {\r
+ return b.chainParams.PowLimitBits\r
+ }\r
+ }\r
+\r
+ // Since easier difficulty equates to higher numbers, the easiest\r
+ // difficulty for a given duration is the largest value possible given\r
+ // the number of retargets for the duration and starting difficulty\r
+ // multiplied by the max adjustment factor.\r
+ newTarget := CompactToBig(bits)\r
+ for durationVal > 0 && newTarget.Cmp(b.chainParams.PowLimit) < 0 {\r
+ newTarget.Mul(newTarget, adjustmentFactor)\r
+ durationVal -= b.maxRetargetTimespan\r
+ }\r
+\r
+ // Limit new value to the proof of work limit.\r
+ if newTarget.Cmp(b.chainParams.PowLimit) > 0 {\r
+ newTarget.Set(b.chainParams.PowLimit)\r
+ }\r
+\r
+ return BigToCompact(newTarget)\r
+}\r
+\r
+// findPrevTestNetDifficulty returns the difficulty of the previous block which\r
+// did not have the special testnet minimum difficulty rule applied.\r
+//\r
+// This function MUST be called with the chain state lock held (for writes).\r
+func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32, error) {\r
+ // Search backwards through the chain for the last block without\r
+ // the special rule applied.\r
+ iterNode := startNode\r
+ for iterNode != nil && iterNode.height%b.blocksPerRetarget != 0 &&\r
+ iterNode.bits == b.chainParams.PowLimitBits {\r
+\r
+ // Get the previous block node. This function is used over\r
+ // simply accessing iterNode.parent directly as it will\r
+ // dynamically create previous block nodes as needed. This\r
+ // helps allow only the pieces of the chain that are needed\r
+ // to remain in memory.\r
+ var err error\r
+ iterNode, err = b.index.PrevNodeFromNode(iterNode)\r
+ if err != nil {\r
+ log.Errorf("PrevNodeFromNode: %v", err)\r
+ return 0, err\r
+ }\r
+ }\r
+\r
+ // Return the found difficulty or the minimum difficulty if no\r
+ // appropriate block was found.\r
+ lastBits := b.chainParams.PowLimitBits\r
+ if iterNode != nil {\r
+ lastBits = iterNode.bits\r
+ }\r
+ return lastBits, nil\r
+}\r
+\r
+// calcNextRequiredDifficulty calculates the required difficulty for the block\r
+// after the passed previous block node based on the difficulty retarget rules.\r
+// This function differs from the exported CalcNextRequiredDifficulty in that\r
+// the exported version uses the current best chain as the previous block node\r
+// while this function accepts any block node.\r
+//\r
+// This function MUST be called with the chain state lock held (for writes).\r
+func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTime time.Time) (uint32, error) {\r
+ // Genesis block.\r
+ if lastNode == nil {\r
+ return b.chainParams.PowLimitBits, nil\r
+ }\r
+\r
+ // Return the previous block's difficulty requirements if this block\r
+ // is not at a difficulty retarget interval.\r
+ if (lastNode.height+1)%b.blocksPerRetarget != 0 {\r
+ // For networks that support it, allow special reduction of the\r
+ // required difficulty once too much time has elapsed without\r
+ // mining a block.\r
+ if b.chainParams.ReduceMinDifficulty {\r
+ // Return minimum difficulty when more than the desired\r
+ // amount of time has elapsed without mining a block.\r
+ reductionTime := int64(b.chainParams.MinDiffReductionTime /\r
+ time.Second)\r
+ allowMinTime := lastNode.timestamp + reductionTime\r
+ if newBlockTime.Unix() > allowMinTime {\r
+ return b.chainParams.PowLimitBits, nil\r
+ }\r
+\r
+ // The block was mined within the desired timeframe, so\r
+ // return the difficulty for the last block which did\r
+ // not have the special minimum difficulty rule applied.\r
+ prevBits, err := b.findPrevTestNetDifficulty(lastNode)\r
+ if err != nil {\r
+ return 0, err\r
+ }\r
+ return prevBits, nil\r
+ }\r
+\r
+ // For the main network (or any unrecognized networks), simply\r
+ // return the previous block's difficulty requirements.\r
+ return lastNode.bits, nil\r
+ }\r
+\r
+ // Get the block node at the previous retarget (targetTimespan days\r
+ // worth of blocks).\r
+ firstNode := lastNode\r
+ for i := int32(0); i < b.blocksPerRetarget-1 && firstNode != nil; i++ {\r
+ // Get the previous block node. This function is used over\r
+ // simply accessing firstNode.parent directly as it will\r
+ // dynamically create previous block nodes as needed. This\r
+ // helps allow only the pieces of the chain that are needed\r
+ // to remain in memory.\r
+ var err error\r
+ firstNode, err = b.index.PrevNodeFromNode(firstNode)\r
+ if err != nil {\r
+ return 0, err\r
+ }\r
+ }\r
+\r
+ if firstNode == nil {\r
+ return 0, AssertError("unable to obtain previous retarget block")\r
+ }\r
+\r
+ // Limit the amount of adjustment that can occur to the previous\r
+ // difficulty.\r
+ actualTimespan := lastNode.timestamp - firstNode.timestamp\r
+ adjustedTimespan := actualTimespan\r
+ if actualTimespan < b.minRetargetTimespan {\r
+ adjustedTimespan = b.minRetargetTimespan\r
+ } else if actualTimespan > b.maxRetargetTimespan {\r
+ adjustedTimespan = b.maxRetargetTimespan\r
+ }\r
+\r
+ // Calculate new target difficulty as:\r
+ // currentDifficulty * (adjustedTimespan / targetTimespan)\r
+ // The result uses integer division which means it will be slightly\r
+ // rounded down. Bitcoind also uses integer division to calculate this\r
+ // result.\r
+ oldTarget := CompactToBig(lastNode.bits)\r
+ newTarget := new(big.Int).Mul(oldTarget, big.NewInt(adjustedTimespan))\r
+ targetTimeSpan := int64(b.chainParams.TargetTimespan / time.Second)\r
+ newTarget.Div(newTarget, big.NewInt(targetTimeSpan))\r
+\r
+ // Limit new value to the proof of work limit.\r
+ if newTarget.Cmp(b.chainParams.PowLimit) > 0 {\r
+ newTarget.Set(b.chainParams.PowLimit)\r
+ }\r
+\r
+ // Log new target difficulty and return it. The new target logging is\r
+ // intentionally converting the bits back to a number instead of using\r
+ // newTarget since conversion to the compact representation loses\r
+ // precision.\r
+ newTargetBits := BigToCompact(newTarget)\r
+ log.Debugf("Difficulty retarget at block height %d", lastNode.height+1)\r
+ log.Debugf("Old target %08x (%064x)", lastNode.bits, oldTarget)\r
+ log.Debugf("New target %08x (%064x)", newTargetBits, CompactToBig(newTargetBits))\r
+ log.Debugf("Actual timespan %v, adjusted timespan %v, target timespan %v",\r
+ time.Duration(actualTimespan)*time.Second,\r
+ time.Duration(adjustedTimespan)*time.Second,\r
+ b.chainParams.TargetTimespan)\r
+\r
+ return newTargetBits, nil\r
+}\r
+\r
+// CalcNextRequiredDifficulty calculates the required difficulty for the block\r
+// after the end of the current best chain based on the difficulty retarget\r
+// rules.\r
+//\r
+// This function is safe for concurrent access.\r
+func (b *BlockChain) CalcNextRequiredDifficulty(timestamp time.Time) (uint32, error) {\r
+ b.chainLock.Lock()\r
+ difficulty, err := b.calcNextRequiredDifficulty(b.bestNode, timestamp)\r
+ b.chainLock.Unlock()\r
+ return difficulty, err\r
+}\r
+*/\r