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