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 5package wire 6 7import ( 8 "bytes" 9 "io" 10 "time" 11 12 "github.com/btcsuite/btcd/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. 18const 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. 22type 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. 45const blockHeaderLen = 80 46 47// BlockHash computes the block identifier hash for the given block header. 48func (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. 63func (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. 71func (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. 78func (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. 88func (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. 98func 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. 116func 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. 124func 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} 129