github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/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  	"golang.org/x/crypto/scrypt"
    13  
    14  	"github.com/mit-dci/lit/btcutil/chaincfg/chainhash"
    15  )
    16  
    17  // BlockVersion is the current latest supported block version.
    18  const BlockVersion = 4
    19  
    20  // MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
    21  // Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes +
    22  // PrevBlock and MerkleRoot hashes.
    23  //const MaxBlockHeaderPayload = 16 + (chainhash.HashSize * 2)
    24  const MaxBlockHeaderPayload = 16 + (chainhash.HashSize * 2) + 500
    25  
    26  // BlockHeader defines information about a block and is used in the bitcoin
    27  // block (MsgBlock) and headers (MsgHeaders) messages.
    28  type BlockHeader struct {
    29  	// Version of the block.  This is not the same as the protocol version.
    30  	Version int32
    31  
    32  	// Hash of the previous block in the block chain.
    33  	PrevBlock chainhash.Hash
    34  
    35  	// Merkle tree reference to hash of all transactions for the block.
    36  	MerkleRoot chainhash.Hash
    37  
    38  	// Time the block was created.  This is, unfortunately, encoded as a
    39  	// uint32 on the wire and therefore is limited to 2106.
    40  	Timestamp time.Time
    41  
    42  	// Difficulty target for the block.
    43  	Bits uint32
    44  
    45  	// Nonce used to generate the block.
    46  	Nonce uint32
    47  }
    48  
    49  // blockHeaderLen is a constant that represents the number of bytes for a block
    50  // header.
    51  const blockHeaderLen = 80
    52  
    53  // BlockHash computes the block identifier hash for the given block header.
    54  func (h *BlockHeader) BlockHash() chainhash.Hash {
    55  	// Encode the header and double sha256 everything prior to the number of
    56  	// transactions.  Ignore the error returns since there is no way the
    57  	// encode could fail except being out of memory which would cause a
    58  	// run-time panic.
    59  	var buf bytes.Buffer
    60  	_ = WriteBlockHeader(&buf, 0, h)
    61  
    62  	return chainhash.DoubleHashH(buf.Bytes())
    63  }
    64  
    65  // ScryptHash returns the 32 byte scrypt hash of the 80 byte header
    66  func (h *BlockHeader) ScryptHash() chainhash.Hash {
    67  	var buf bytes.Buffer
    68  	_ = WriteBlockHeader(&buf, 0, h)
    69  
    70  	scryptBytes, _ := scrypt.Key(buf.Bytes(), buf.Bytes(), 1024, 1, 1, 32)
    71  
    72  	var scryptHash [32]byte
    73  	copy(scryptHash[:], scryptBytes)
    74  	return scryptHash
    75  }
    76  
    77  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    78  // This is part of the Message interface implementation.
    79  // See Deserialize for decoding block headers stored to disk, such as in a
    80  // database, as opposed to decoding block headers from the wire.
    81  func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error {
    82  	return readBlockHeader(r, pver, h)
    83  }
    84  
    85  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    86  // This is part of the Message interface implementation.
    87  // See Serialize for encoding block headers to be stored to disk, such as in a
    88  // database, as opposed to encoding block headers for the wire.
    89  func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
    90  	return WriteBlockHeader(w, pver, h)
    91  }
    92  
    93  // Deserialize decodes a block header from r into the receiver using a format
    94  // that is suitable for long-term storage such as a database while respecting
    95  // the Version field.
    96  func (h *BlockHeader) Deserialize(r io.Reader) error {
    97  	// At the current time, there is no difference between the wire encoding
    98  	// at protocol version 0 and the stable long-term storage format.  As
    99  	// a result, make use of readBlockHeader.
   100  	return readBlockHeader(r, 0, h)
   101  }
   102  
   103  // Serialize encodes a block header from r into the receiver using a format
   104  // that is suitable for long-term storage such as a database while respecting
   105  // the Version field.
   106  func (h *BlockHeader) Serialize(w io.Writer) error {
   107  	// At the current time, there is no difference between the wire encoding
   108  	// at protocol version 0 and the stable long-term storage format.  As
   109  	// a result, make use of writeBlockHeader.
   110  	return WriteBlockHeader(w, 0, h)
   111  }
   112  
   113  // NewBlockHeader returns a new BlockHeader using the provided previous block
   114  // hash, merkle root hash, difficulty bits, and nonce used to generate the
   115  // block with defaults for the remaining fields.
   116  func NewBlockHeader(prevHash *chainhash.Hash, merkleRootHash *chainhash.Hash,
   117  	bits uint32, nonce uint32) *BlockHeader {
   118  
   119  	// Limit the timestamp to one second precision since the protocol
   120  	// doesn't support better.
   121  	return &BlockHeader{
   122  		Version:    BlockVersion,
   123  		PrevBlock:  *prevHash,
   124  		MerkleRoot: *merkleRootHash,
   125  		Timestamp:  time.Unix(time.Now().Unix(), 0),
   126  		Bits:       bits,
   127  		Nonce:      nonce,
   128  	}
   129  }
   130  
   131  // readBlockHeader reads a bitcoin block header from r.  See Deserialize for
   132  // decoding block headers stored to disk, such as in a database, as opposed to
   133  // decoding from the wire.
   134  func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
   135  	err := readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
   136  		(*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce)
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	return nil
   142  }
   143  
   144  // writeBlockHeader writes a bitcoin block header to w.  See Serialize for
   145  // encoding block headers to be stored to disk, such as in a database, as
   146  // opposed to encoding for the wire.
   147  func WriteBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
   148  	sec := uint32(bh.Timestamp.Unix())
   149  	err := writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot,
   150  		sec, bh.Bits, bh.Nonce)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	return nil
   156  }