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 }