2014-01-09 06:44:08 +01:00
|
|
|
// Copyright (c) 2013-2014 Conformal Systems LLC.
|
2013-05-08 21:31:00 +02:00
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package btcwire
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// BlockVersion is the current latest supported block version.
|
|
|
|
const BlockVersion uint32 = 2
|
|
|
|
|
|
|
|
// Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes +
|
Remove BlockHeader.TxnCount field.
This commit removes the TxnCount field from the BlockHeader type and
updates the tests accordingly. Note that this change does not affect the
actual wire protocol encoding in any way.
The reason the field has been removed is it really doesn't belong there
even though the wire protocol wiki entry on the official bitcoin wiki
implies it does. The implication is an artifact from the way the
reference implementation serializes headers (MsgHeaders) messages. It
includes the transaction count, which is naturally always 0 for headers,
along with every header. However, in reality, a block header does not
include the transaction count. This can be evidenced by looking at how a
block hash is calculated. It is only up to and including the Nonce field
(a total of 80 bytes).
From an API standpoint, having the field as part of the BlockHeader type
results in several odd cases.
For example, the transaction count for MsgBlocks (the only place that
actually has a real transaction count since MsgHeaders does not) is
available by taking the len of the Transactions slice. As such, having
the extra field in the BlockHeader is really a useless field that could
potentially get out of sync and cause the encode to fail.
Another example is related to deserializing a block header from the
database in order to serve it in response to a getheaders (MsgGetheaders)
request. If a block header is assumed to have the transaction count as a
part of it, then derserializing a block header not only consumes more than
the 80 bytes that actually comprise the header as stated above, but you
then need to change the transaction count to 0 before sending the headers
(MsgHeaders) message. So, not only are you reading and deserializing more
bytes than needed, but worse, you generally have to make a copy of it so
you can change the transaction count without busting cached headers.
This is part 1 of #13.
2014-01-19 02:37:33 +01:00
|
|
|
// PrevBlock and MerkleRoot hashes.
|
|
|
|
const maxBlockHeaderPayload = 16 + (HashSize * 2)
|
2013-05-08 21:31:00 +02:00
|
|
|
|
|
|
|
// BlockHeader defines information about a block and is used in the bitcoin
|
|
|
|
// block (MsgBlock) and headers (MsgHeaders) messages.
|
|
|
|
type BlockHeader struct {
|
|
|
|
// Version of the block. This is not the same as the protocol version.
|
|
|
|
Version uint32
|
|
|
|
|
|
|
|
// Hash of the previous block in the block chain.
|
|
|
|
PrevBlock ShaHash
|
|
|
|
|
|
|
|
// Merkle tree reference to hash of all transactions for the block.
|
|
|
|
MerkleRoot ShaHash
|
|
|
|
|
|
|
|
// Time the block was created. This is, unfortunately, encoded as a
|
|
|
|
// uint32 on the wire and therefore is limited to 2106.
|
|
|
|
Timestamp time.Time
|
|
|
|
|
|
|
|
// Difficulty target for the block.
|
|
|
|
Bits uint32
|
|
|
|
|
|
|
|
// Nonce used to generate the block.
|
|
|
|
Nonce uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// blockHashLen is a constant that represents how much of the block header is
|
|
|
|
// used when computing the block sha 0:blockHashLen
|
|
|
|
const blockHashLen = 80
|
|
|
|
|
|
|
|
// BlockSha computes the block identifier hash for the given block header.
|
2013-08-05 23:24:50 +02:00
|
|
|
func (h *BlockHeader) BlockSha() (ShaHash, error) {
|
2013-05-12 21:01:50 +02:00
|
|
|
// Encode the header and run double sha256 everything prior to the
|
|
|
|
// number of transactions. Ignore the error returns since there is no
|
|
|
|
// way the encode could fail except being out of memory which would
|
|
|
|
// cause a run-time panic. Also, SetBytes can't fail here due to the
|
|
|
|
// fact DoubleSha256 always returns a []byte of the right size
|
|
|
|
// regardless of input.
|
2013-05-08 21:31:00 +02:00
|
|
|
var buf bytes.Buffer
|
2013-05-12 21:01:50 +02:00
|
|
|
var sha ShaHash
|
2013-08-05 23:24:50 +02:00
|
|
|
_ = writeBlockHeader(&buf, 0, h)
|
2013-05-12 21:01:50 +02:00
|
|
|
_ = sha.SetBytes(DoubleSha256(buf.Bytes()[0:blockHashLen]))
|
|
|
|
|
|
|
|
// Even though this function can't currently fail, it still returns
|
|
|
|
// a potential error to help future proof the API should a failure
|
|
|
|
// become possible.
|
|
|
|
return sha, nil
|
2013-05-08 21:31:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewBlockHeader returns a new BlockHeader using the provided previous block
|
|
|
|
// hash, merkle root hash, difficulty bits, and nonce used to generate the
|
|
|
|
// block with defaults for the remaining fields.
|
|
|
|
func NewBlockHeader(prevHash *ShaHash, merkleRootHash *ShaHash, bits uint32,
|
|
|
|
nonce uint32) *BlockHeader {
|
|
|
|
|
|
|
|
return &BlockHeader{
|
|
|
|
Version: BlockVersion,
|
|
|
|
PrevBlock: *prevHash,
|
|
|
|
MerkleRoot: *merkleRootHash,
|
|
|
|
Timestamp: time.Now(),
|
|
|
|
Bits: bits,
|
|
|
|
Nonce: nonce,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// readBlockHeader reads a bitcoin block header from r.
|
|
|
|
func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
|
|
|
|
var sec uint32
|
|
|
|
err := readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, &sec,
|
|
|
|
&bh.Bits, &bh.Nonce)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
bh.Timestamp = time.Unix(int64(sec), 0)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// writeBlockHeader writes a bitcoin block header to w.
|
|
|
|
func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
|
|
|
|
sec := uint32(bh.Timestamp.Unix())
|
2013-11-07 07:56:20 +01:00
|
|
|
err := writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
|
2013-05-08 21:31:00 +02:00
|
|
|
sec, bh.Bits, bh.Nonce)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|