github.com/palcoin-project/palcd@v1.0.0/wire/blockheader.go (about)

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