github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/wire/blockheader.go (about)

     1  // Copyright (c) 2013-2015 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package wire
     7  
     8  import (
     9  	"bytes"
    10  	"io"
    11  	"time"
    12  )
    13  
    14  // BlockVersion is the current latest supported block version.
    15  const BlockVersion = 4
    16  
    17  // MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
    18  // Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes +
    19  // PrevBlock and MerkleRoot hashes.
    20  const MaxBlockHeaderPayload = 16 + (HashSize * 2)
    21  
    22  // BlockHeader defines information about a block and is used in the bitcoin
    23  // block (MsgBlock) and headers (MsgHeaders) messages.
    24  type BlockHeader struct {
    25  	// Version of the block.  This is not the same as the protocol version.
    26  	Version int32
    27  
    28  	// Hash of the previous block in the block chain.
    29  	PrevBlock ShaHash
    30  
    31  	// Merkle tree reference to hash of all transactions for the block.
    32  	MerkleRoot ShaHash
    33  
    34  	// Time the block was created.  This is, unfortunately, encoded as a
    35  	// uint32 on the wire and therefore is limited to 2106.
    36  	Timestamp time.Time
    37  
    38  	// Difficulty target for the block.
    39  	Bits uint32
    40  
    41  	// Nonce used to generate the block.
    42  	Nonce uint32
    43  }
    44  
    45  // blockHeaderLen is a constant that represents the number of bytes for a block
    46  // header.
    47  const blockHeaderLen = 80
    48  
    49  // BlockSha computes the block identifier hash for the given block header.
    50  func (h *BlockHeader) BlockSha() ShaHash {
    51  	// Encode the header and double sha256 everything prior to the number of
    52  	// transactions.  Ignore the error returns since there is no way the
    53  	// encode could fail except being out of memory which would cause a
    54  	// run-time panic.
    55  	var buf bytes.Buffer
    56  	_ = writeBlockHeader(&buf, 0, h)
    57  
    58  	return DoubleSha256SH(buf.Bytes())
    59  }
    60  
    61  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    62  // This is part of the Message interface implementation.
    63  // See Deserialize for decoding block headers stored to disk, such as in a
    64  // database, as opposed to decoding block headers from the wire.
    65  func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32) error {
    66  	return readBlockHeader(r, pver, h)
    67  }
    68  
    69  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    70  // This is part of the Message interface implementation.
    71  // See Serialize for encoding block headers to be stored to disk, such as in a
    72  // database, as opposed to encoding block headers for the wire.
    73  func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32) error {
    74  	return writeBlockHeader(w, pver, h)
    75  }
    76  
    77  // Deserialize decodes a block header from r into the receiver using a format
    78  // that is suitable for long-term storage such as a database while respecting
    79  // the Version field.
    80  func (h *BlockHeader) Deserialize(r io.Reader) error {
    81  	// At the current time, there is no difference between the wire encoding
    82  	// at protocol version 0 and the stable long-term storage format.  As
    83  	// a result, make use of readBlockHeader.
    84  	return readBlockHeader(r, 0, h)
    85  }
    86  
    87  // Serialize encodes a block header from r into the receiver using a format
    88  // that is suitable for long-term storage such as a database while respecting
    89  // the Version field.
    90  func (h *BlockHeader) Serialize(w io.Writer) error {
    91  	// At the current time, there is no difference between the wire encoding
    92  	// at protocol version 0 and the stable long-term storage format.  As
    93  	// a result, make use of writeBlockHeader.
    94  	return writeBlockHeader(w, 0, h)
    95  }
    96  
    97  // NewBlockHeader returns a new BlockHeader using the provided previous block
    98  // hash, merkle root hash, difficulty bits, and nonce used to generate the
    99  // block with defaults for the remaining fields.
   100  func NewBlockHeader(prevHash *ShaHash, merkleRootHash *ShaHash, bits uint32,
   101  	nonce uint32) *BlockHeader {
   102  
   103  	// Limit the timestamp to one second precision since the protocol
   104  	// doesn't support better.
   105  	return &BlockHeader{
   106  		Version:    BlockVersion,
   107  		PrevBlock:  *prevHash,
   108  		MerkleRoot: *merkleRootHash,
   109  		Timestamp:  time.Unix(time.Now().Unix(), 0),
   110  		Bits:       bits,
   111  		Nonce:      nonce,
   112  	}
   113  }
   114  
   115  // readBlockHeader reads a bitcoin block header from r.  See Deserialize for
   116  // decoding block headers stored to disk, such as in a database, as opposed to
   117  // decoding from the wire.
   118  func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
   119  	err := readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
   120  		(*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  // writeBlockHeader writes a bitcoin block header to w.  See Serialize for
   129  // encoding block headers to be stored to disk, such as in a database, as
   130  // opposed to encoding for the wire.
   131  func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
   132  	sec := uint32(bh.Timestamp.Unix())
   133  	err := writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
   134  		sec, bh.Bits, bh.Nonce)
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  	return nil
   140  }