github.com/btcsuite/btcd@v0.24.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  	"io"
     9  	"time"
    10  
    11  	"github.com/btcsuite/btcd/chaincfg/chainhash"
    12  )
    13  
    14  // MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
    15  // Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes +
    16  // PrevBlock and MerkleRoot hashes.
    17  const MaxBlockHeaderPayload = 16 + (chainhash.HashSize * 2)
    18  
    19  // BlockHeader defines information about a block and is used in the bitcoin
    20  // block (MsgBlock) and headers (MsgHeaders) messages.
    21  type BlockHeader struct {
    22  	// Version of the block.  This is not the same as the protocol version.
    23  	Version int32
    24  
    25  	// Hash of the previous block header in the block chain.
    26  	PrevBlock chainhash.Hash
    27  
    28  	// Merkle tree reference to hash of all transactions for the block.
    29  	MerkleRoot chainhash.Hash
    30  
    31  	// Time the block was created.  This is, unfortunately, encoded as a
    32  	// uint32 on the wire and therefore is limited to 2106.
    33  	Timestamp time.Time
    34  
    35  	// Difficulty target for the block.
    36  	Bits uint32
    37  
    38  	// Nonce used to generate the block.
    39  	Nonce uint32
    40  }
    41  
    42  // blockHeaderLen is a constant that represents the number of bytes for a block
    43  // header.
    44  const blockHeaderLen = 80
    45  
    46  // BlockHash computes the block identifier hash for the given block header.
    47  func (h *BlockHeader) BlockHash() chainhash.Hash {
    48  	return chainhash.DoubleHashRaw(func(w io.Writer) error {
    49  		return writeBlockHeader(w, 0, h)
    50  	})
    51  }
    52  
    53  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    54  // This is part of the Message interface implementation.
    55  // See Deserialize for decoding block headers stored to disk, such as in a
    56  // database, as opposed to decoding block headers from the wire.
    57  func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error {
    58  	return readBlockHeader(r, pver, h)
    59  }
    60  
    61  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    62  // This is part of the Message interface implementation.
    63  // See Serialize for encoding block headers to be stored to disk, such as in a
    64  // database, as opposed to encoding block headers for the wire.
    65  func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
    66  	return writeBlockHeader(w, pver, h)
    67  }
    68  
    69  // Deserialize decodes a block header from r into the receiver using a format
    70  // that is suitable for long-term storage such as a database while respecting
    71  // the Version field.
    72  func (h *BlockHeader) Deserialize(r io.Reader) error {
    73  	// At the current time, there is no difference between the wire encoding
    74  	// at protocol version 0 and the stable long-term storage format.  As
    75  	// a result, make use of readBlockHeader.
    76  	return readBlockHeader(r, 0, h)
    77  }
    78  
    79  // Serialize encodes a block header from r into the receiver using a format
    80  // that is suitable for long-term storage such as a database while respecting
    81  // the Version field.
    82  func (h *BlockHeader) Serialize(w io.Writer) error {
    83  	// At the current time, there is no difference between the wire encoding
    84  	// at protocol version 0 and the stable long-term storage format.  As
    85  	// a result, make use of writeBlockHeader.
    86  	return writeBlockHeader(w, 0, h)
    87  }
    88  
    89  // NewBlockHeader returns a new BlockHeader using the provided version, previous
    90  // block hash, merkle root hash, difficulty bits, and nonce used to generate the
    91  // block with defaults for the remaining fields.
    92  func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash,
    93  	bits uint32, nonce uint32) *BlockHeader {
    94  
    95  	// Limit the timestamp to one second precision since the protocol
    96  	// doesn't support better.
    97  	return &BlockHeader{
    98  		Version:    version,
    99  		PrevBlock:  *prevHash,
   100  		MerkleRoot: *merkleRootHash,
   101  		Timestamp:  time.Unix(time.Now().Unix(), 0),
   102  		Bits:       bits,
   103  		Nonce:      nonce,
   104  	}
   105  }
   106  
   107  // readBlockHeader reads a bitcoin block header from r.  See Deserialize for
   108  // decoding block headers stored to disk, such as in a database, as opposed to
   109  // decoding from the wire.
   110  //
   111  // DEPRECATED: Use readBlockHeaderBuf instead.
   112  func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
   113  	buf := binarySerializer.Borrow()
   114  	err := readBlockHeaderBuf(r, pver, bh, buf)
   115  	binarySerializer.Return(buf)
   116  	return err
   117  }
   118  
   119  // readBlockHeaderBuf reads a bitcoin block header from r.  See Deserialize for
   120  // decoding block headers stored to disk, such as in a database, as opposed to
   121  // decoding from the wire.
   122  //
   123  // If b is non-nil, the provided buffer will be used for serializing small
   124  // values.  Otherwise a buffer will be drawn from the binarySerializer's pool
   125  // and return when the method finishes.
   126  //
   127  // NOTE: b MUST either be nil or at least an 8-byte slice.
   128  func readBlockHeaderBuf(r io.Reader, pver uint32, bh *BlockHeader,
   129  	buf []byte) error {
   130  
   131  	if _, err := io.ReadFull(r, buf[:4]); err != nil {
   132  		return err
   133  	}
   134  	bh.Version = int32(littleEndian.Uint32(buf[:4]))
   135  
   136  	if _, err := io.ReadFull(r, bh.PrevBlock[:]); err != nil {
   137  		return err
   138  	}
   139  
   140  	if _, err := io.ReadFull(r, bh.MerkleRoot[:]); err != nil {
   141  		return err
   142  	}
   143  
   144  	if _, err := io.ReadFull(r, buf[:4]); err != nil {
   145  		return err
   146  	}
   147  	bh.Timestamp = time.Unix(int64(littleEndian.Uint32(buf[:4])), 0)
   148  
   149  	if _, err := io.ReadFull(r, buf[:4]); err != nil {
   150  		return err
   151  	}
   152  	bh.Bits = littleEndian.Uint32(buf[:4])
   153  
   154  	if _, err := io.ReadFull(r, buf[:4]); err != nil {
   155  		return err
   156  	}
   157  	bh.Nonce = littleEndian.Uint32(buf[:4])
   158  
   159  	return nil
   160  }
   161  
   162  // writeBlockHeader writes a bitcoin block header to w.  See Serialize for
   163  // encoding block headers to be stored to disk, such as in a database, as
   164  // opposed to encoding for the wire.
   165  //
   166  // DEPRECATED: Use writeBlockHeaderBuf instead.
   167  func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
   168  	buf := binarySerializer.Borrow()
   169  	err := writeBlockHeaderBuf(w, pver, bh, buf)
   170  	binarySerializer.Return(buf)
   171  	return err
   172  }
   173  
   174  // writeBlockHeaderBuf writes a bitcoin block header to w.  See Serialize for
   175  // encoding block headers to be stored to disk, such as in a database, as
   176  // opposed to encoding for the wire.
   177  //
   178  // If b is non-nil, the provided buffer will be used for serializing small
   179  // values.  Otherwise a buffer will be drawn from the binarySerializer's pool
   180  // and return when the method finishes.
   181  //
   182  // NOTE: b MUST either be nil or at least an 8-byte slice.
   183  func writeBlockHeaderBuf(w io.Writer, pver uint32, bh *BlockHeader,
   184  	buf []byte) error {
   185  
   186  	littleEndian.PutUint32(buf[:4], uint32(bh.Version))
   187  	if _, err := w.Write(buf[:4]); err != nil {
   188  		return err
   189  	}
   190  
   191  	if _, err := w.Write(bh.PrevBlock[:]); err != nil {
   192  		return err
   193  	}
   194  
   195  	if _, err := w.Write(bh.MerkleRoot[:]); err != nil {
   196  		return err
   197  	}
   198  
   199  	littleEndian.PutUint32(buf[:4], uint32(bh.Timestamp.Unix()))
   200  	if _, err := w.Write(buf[:4]); err != nil {
   201  		return err
   202  	}
   203  
   204  	littleEndian.PutUint32(buf[:4], bh.Bits)
   205  	if _, err := w.Write(buf[:4]); err != nil {
   206  		return err
   207  	}
   208  
   209  	littleEndian.PutUint32(buf[:4], bh.Nonce)
   210  	if _, err := w.Write(buf[:4]); err != nil {
   211  		return err
   212  	}
   213  
   214  	return nil
   215  }