bitcoin/blockdata/
block.rs1use bitcoin_hashes::{sha256d, Hash};
24
25use util;
26use util::Error::{SpvBadTarget, SpvBadProofOfWork};
27use util::hash::BitcoinHash;
28use util::uint::Uint256;
29use consensus::encode::VarInt;
30use network::constants::Network;
31use blockdata::transaction::Transaction;
32use blockdata::constants::max_target;
33
34#[derive(Copy, PartialEq, Eq, Clone, Debug)]
37pub struct BlockHeader {
38 pub version: u32,
40 pub prev_blockhash: sha256d::Hash,
42 pub merkle_root: sha256d::Hash,
44 pub time: u32,
46 pub bits: u32,
49 pub nonce: u32,
51}
52
53#[derive(PartialEq, Eq, Clone, Debug)]
56pub struct Block {
57 pub header: BlockHeader,
59 pub coinbase_txn: Transaction,
61 pub block_hash: sha256d::Hash,
63 pub coinbase_branch_hashes: Vec<sha256d::Hash>,
65 pub coinbase_branch_side_mask: u32,
67 pub blockchain_branch_hashes: Vec<sha256d::Hash>,
69 pub blockchain_branch_side_mask: u32,
71 pub parent_block: BlockHeader,
73 pub txdata: Vec<Transaction>
75}
76
77#[derive(PartialEq, Eq, Clone, Debug)]
80pub struct LoneBlockHeader {
81 pub header: BlockHeader,
83 pub tx_count: VarInt
86}
87#[derive(PartialEq, Eq, Clone, Debug)]
89pub struct GenesisBlock {
90 pub header: BlockHeader,
92 pub txdata: Vec<Transaction>
94}
95impl BlockHeader {
96 pub fn target(&self) -> Uint256 {
98 let (mant, expt) = {
103 let unshifted_expt = self.bits >> 24;
104 if unshifted_expt <= 3 {
105 ((self.bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0)
106 } else {
107 (self.bits & 0xFFFFFF, 8 * ((self.bits >> 24) - 3))
108 }
109 };
110
111 if mant > 0x7FFFFF {
113 Default::default()
114 } else {
115 Uint256::from_u64(mant as u64).unwrap() << (expt as usize)
116 }
117 }
118
119 pub fn compact_target_from_u256(value: &Uint256) -> u32 {
121 let mut size = (value.bits() + 7) / 8;
122 let mut compact = if size <= 3 {
123 (value.low_u64() << (8 * (3 - size))) as u32
124 } else {
125 let bn = *value >> (8 * (size - 3));
126 bn.low_u32()
127 };
128
129 if (compact & 0x00800000) != 0 {
130 compact >>= 8;
131 size += 1;
132 }
133
134 compact | (size << 24) as u32
135 }
136
137 pub fn difficulty(&self, network: Network) -> u64 {
139 (max_target(network) / self.target()).low_u64()
140 }
141
142 pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), util::Error> {
146 use byteorder::{ByteOrder, LittleEndian};
147
148 let target = &self.target();
149 if target != required_target {
150 return Err(SpvBadTarget);
151 }
152 let data: [u8; 32] = self.bitcoin_hash().into_inner();
153 let mut ret = [0u64; 4];
154 LittleEndian::read_u64_into(&data, &mut ret);
155 let hash = &Uint256(ret);
156 if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) }
157 }
158
159 pub fn work(&self) -> Uint256 {
161 let mut ret = !self.target();
163 let mut ret1 = self.target();
164 ret1.increment();
165 ret = ret / ret1;
166 ret.increment();
167 ret
168 }
169}
170
171impl BitcoinHash for BlockHeader {
172 fn bitcoin_hash(&self) -> sha256d::Hash {
173 use consensus::encode::serialize;
174 sha256d::Hash::hash(&serialize(self))
175 }
176}
177
178impl BitcoinHash for Block {
179 fn bitcoin_hash(&self) -> sha256d::Hash {
180 self.header.bitcoin_hash()
181 }
182}
183impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
184impl_consensus_encoding!(Block, header, coinbase_txn, block_hash, coinbase_branch_hashes, coinbase_branch_side_mask, blockchain_branch_hashes, blockchain_branch_side_mask, parent_block, txdata);
185impl_consensus_encoding!(GenesisBlock, header, txdata);
186impl_consensus_encoding!(LoneBlockHeader, header, tx_count);
187
188#[cfg(test)]
189mod tests {
190 use hex::decode as hex_decode;
191
192 use blockdata::block::{Block, BlockHeader};
193 use consensus::encode::{deserialize, serialize};
194
195 #[test]
196 fn block_test() {
197 let some_block = hex_decode("040100106f378876737d2a2bfffd51ca4c7e3d6281dad5fbd0b8ce61cde88674440f0000aaa7bee217ab6c525b55734dfb013e6e7b7bb70848adb50407b6cc74fbf2011ee121525cf0ff0f1e0000000002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff292890e8b09682761713f0f091aef58669e8c37149aedd282337da6193edc7ffc8f50100000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000c69c3a951476397def6efd0d481944058f9d56497c040ff1c36c9f2ef090cbfb00000000000000005a5b000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510109ffffffff020040874e115cbd002321025687e93e908ab873cb37174215bed989791fe93e0ab5f5cc95f4250deb11fa8aac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
198 let cutoff_block = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000").unwrap();
199 let prevhash = hex_decode("6f378876737d2a2bfffd51ca4c7e3d6281dad5fbd0b8ce61cde88674440f0000").unwrap();
200 let merkle = hex_decode("aaa7bee217ab6c525b55734dfb013e6e7b7bb70848adb50407b6cc74fbf2011e").unwrap();
201
202 let decode: Result<Block, _> = deserialize(&some_block);
203 let bad_decode: Result<Block, _> = deserialize(&cutoff_block);
204
205 assert!(decode.is_ok());
206 assert!(bad_decode.is_err());
207 let real_decode = decode.unwrap();
208 assert_eq!(real_decode.header.version, 268435716);
209 assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash);
210 assert_eq!(serialize(&real_decode.header.merkle_root), merkle);
212 assert_eq!(real_decode.header.time, 1548886497);
213 assert_eq!(real_decode.header.bits, 504365040);
214 assert_eq!(real_decode.header.nonce, 0);
215 assert_eq!(serialize(&real_decode), some_block);
218 }
219
220 #[test]
221 fn compact_roundrtip_test() {
222 let some_header = hex_decode("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap();
223
224 let header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header");
225
226 assert_eq!(header.bits, BlockHeader::compact_target_from_u256(&header.target()));
227 }
228}
229