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 }