github.com/lbryio/lbcd@v0.22.119/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/lbryio/lbcd/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, ClaimTrie, and MerkleRoot hashes.
    18  const MaxBlockHeaderPayload = 16 + (chainhash.HashSize * 3)
    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  	// ClaimTrie reference to hash of ClaimTrie.
    33  	ClaimTrie chainhash.Hash
    34  
    35  	// Time the block was created.  This is, unfortunately, encoded as a
    36  	// uint32 on the wire and therefore is limited to 2106.
    37  	Timestamp time.Time
    38  
    39  	// Difficulty target for the block.
    40  	Bits uint32
    41  
    42  	// Nonce used to generate the block.
    43  	Nonce uint32
    44  }
    45  
    46  // blockHeaderLen is a constant that represents the number of bytes for a block
    47  // header.
    48  const blockHeaderLen = 112
    49  
    50  // BlockHash computes the block identifier hash for the given block header.
    51  func (h *BlockHeader) BlockHash() chainhash.Hash {
    52  	// Encode the header and double sha256 everything prior to the number of
    53  	// transactions.  Ignore the error returns since there is no way the
    54  	// encode could fail except being out of memory which would cause a
    55  	// run-time panic.
    56  	buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload))
    57  	_ = writeBlockHeader(buf, 0, h)
    58  
    59  	return chainhash.DoubleHashH(buf.Bytes())
    60  }
    61  
    62  // BlockPoWHash computes the block identifier hash for the given block header.
    63  func (h *BlockHeader) BlockPoWHash() chainhash.Hash {
    64  	// Encode the header and double sha256 everything prior to the number of
    65  	// transactions.  Ignore the error returns since there is no way the
    66  	// encode could fail except being out of memory which would cause a
    67  	// run-time panic.
    68  	buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload))
    69  	_ = writeBlockHeader(buf, 0, h)
    70  
    71  	return chainhash.LbryPoWHashH(buf.Bytes())
    72  }
    73  
    74  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    75  // This is part of the Message interface implementation.
    76  // See Deserialize for decoding block headers stored to disk, such as in a
    77  // database, as opposed to decoding block headers from the wire.
    78  func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error {
    79  	return readBlockHeader(r, pver, h)
    80  }
    81  
    82  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    83  // This is part of the Message interface implementation.
    84  // See Serialize for encoding block headers to be stored to disk, such as in a
    85  // database, as opposed to encoding block headers for the wire.
    86  func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
    87  	return writeBlockHeader(w, pver, h)
    88  }
    89  
    90  // Deserialize decodes a block header from r into the receiver using a format
    91  // that is suitable for long-term storage such as a database while respecting
    92  // the Version field.
    93  func (h *BlockHeader) Deserialize(r io.Reader) error {
    94  	// At the current time, there is no difference between the wire encoding
    95  	// at protocol version 0 and the stable long-term storage format.  As
    96  	// a result, make use of readBlockHeader.
    97  	return readBlockHeader(r, 0, h)
    98  }
    99  
   100  // Serialize encodes a block header from r into the receiver using a format
   101  // that is suitable for long-term storage such as a database while respecting
   102  // the Version field.
   103  func (h *BlockHeader) Serialize(w io.Writer) error {
   104  	// At the current time, there is no difference between the wire encoding
   105  	// at protocol version 0 and the stable long-term storage format.  As
   106  	// a result, make use of writeBlockHeader.
   107  	return writeBlockHeader(w, 0, h)
   108  }
   109  
   110  // NewBlockHeader returns a new BlockHeader using the provided version, previous
   111  // block hash, merkle root hash, difficulty bits, and nonce used to generate the
   112  // block with defaults for the remaining fields.
   113  func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash,
   114  	claimTrieHash *chainhash.Hash, bits uint32, nonce uint32) *BlockHeader {
   115  
   116  	// Limit the timestamp to one second precision since the protocol
   117  	// doesn't support better.
   118  	return &BlockHeader{
   119  		Version:    version,
   120  		PrevBlock:  *prevHash,
   121  		MerkleRoot: *merkleRootHash,
   122  		ClaimTrie:  *claimTrieHash,
   123  		Timestamp:  time.Unix(time.Now().Unix(), 0),
   124  		Bits:       bits,
   125  		Nonce:      nonce,
   126  	}
   127  }
   128  
   129  // readBlockHeader reads a bitcoin block header from r.  See Deserialize for
   130  // decoding block headers stored to disk, such as in a database, as opposed to
   131  // decoding from the wire.
   132  func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
   133  	return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
   134  		&bh.ClaimTrie, (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce)
   135  }
   136  
   137  // writeBlockHeader writes a bitcoin block header to w.  See Serialize for
   138  // encoding block headers to be stored to disk, such as in a database, as
   139  // opposed to encoding for the wire.
   140  func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
   141  	sec := uint32(bh.Timestamp.Unix())
   142  	return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
   143  		&bh.ClaimTrie, sec, bh.Bits, bh.Nonce)
   144  }