1use std::{marker, ptr};
22use std::convert::From;
23use std::error::Error;
24use std::fmt;
25
26use bitcoin::blockdata::block::{Block, BlockHeader};
27use bitcoin::blockdata::transaction::Transaction;
28use bitcoin::blockdata::constants::{DIFFCHANGE_INTERVAL, DIFFCHANGE_TIMESPAN,
29 TARGET_BLOCK_SPACING, max_target, genesis_block};
30use bitcoin::network::constants::Network;
31use bitcoin::consensus::{Decodable, Encodable};
32use bitcoin::util::BitArray;
33use bitcoin::util::uint::Uint256;
34use bitcoin::util::hash::{BitcoinHash, Sha256dHash};
35use bitcoin::consensus::{Decoder, Encoder};
36use bitcoin;
37use patricia_tree::PatriciaTree;
38use bitcoin::consensus::encode;
39
40
41type BlockTree = PatriciaTree<Uint256, Box<BlockchainNode>>;
42type NodePtr = *const BlockchainNode;
43
44pub enum BlockchainError {
45 BlockNotFound,
46 DuplicateHash,
47 PrevHashNotFound,
48 BitcoinError(bitcoin::Error)
49}
50
51impl From<bitcoin::Error> for BlockchainError {
52 fn from(e: bitcoin::Error) -> Self {
53 BlockchainError::BitcoinError(e)
54 }
55}
56
57impl Error for BlockchainError {
58}
59
60impl fmt::Display for BlockchainError {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 match *self {
63 BlockchainError::BlockNotFound => write!(f, "Block not found"),
64 BlockchainError::DuplicateHash => write!(f, "Duplicate hash"),
65 BlockchainError::PrevHashNotFound => write!(f, "previous hash not found"),
66 BlockchainError::BitcoinError(ref err) => write!(f, "Serialize error: {}", err),
67 }
68 }
69}
70
71impl fmt::Debug for BlockchainError {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 (self as &fmt::Display).fmt(f)
74 }
75}
76
77pub struct BlockchainNode {
79 pub block: Block,
81 pub total_work: Uint256,
83 pub required_difficulty: Uint256,
86 pub height: u32,
88 pub has_txdata: bool,
90 prev: NodePtr,
92 next: NodePtr
94}
95
96unsafe impl Send for BlockchainNode {}
97
98impl BlockchainNode {
99 pub fn is_on_main_chain(&self, chain: &Blockchain) -> bool {
101 if self.block.header == unsafe { (*chain.best_tip).block.header } {
102 true
103 } else {
104 unsafe {
105 let mut scan = self.next;
106 while !scan.is_null() {
107 if (*scan).block.header == (*chain.best_tip).block.header {
108 return true;
109 }
110 scan = (*scan).next;
111 }
112 }
113 false
114 }
115 }
116}
117
118impl<S: Encoder> Encodable<S> for BlockchainNode {
119 #[inline]
120 fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> where S: Encoder {
121 try!(self.block.consensus_encode(s));
122 try!(self.total_work.consensus_encode(s));
123 try!(self.required_difficulty.consensus_encode(s));
124 try!(self.height.consensus_encode(s));
125 try!(self.has_txdata.consensus_encode(s));
126 Ok(())
128 }
129}
130
131impl<D: Decoder> Decodable<D> for BlockchainNode {
132 #[inline]
133 fn consensus_decode(d: &mut D) -> Result<BlockchainNode, encode::Error> where D: Decoder {
134 Ok(BlockchainNode {
135 block: try!(Decodable::consensus_decode(d)),
136 total_work: try!(Decodable::consensus_decode(d)),
137 required_difficulty: try!(Decodable::consensus_decode(d)),
138 height: try!(Decodable::consensus_decode(d)),
139 has_txdata: try!(Decodable::consensus_decode(d)),
140 prev: ptr::null(),
141 next: ptr::null()
142 })
143 }
144}
145
146impl BitcoinHash for BlockchainNode {
147 fn bitcoin_hash(&self) -> Sha256dHash {
148 self.block.header.bitcoin_hash()
149 }
150}
151
152pub struct Blockchain {
154 network: Network,
155 tree: BlockTree,
156 best_tip: NodePtr,
157 best_hash: Sha256dHash,
158 genesis_hash: Sha256dHash
159}
160
161unsafe impl Send for Blockchain {}
162
163impl<S: Encoder> Encodable<S> for Blockchain {
164 #[inline]
165 fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
166 try!(self.network.consensus_encode(s));
167 try!(self.tree.consensus_encode(s));
168 try!(self.best_hash.consensus_encode(s));
169 try!(self.genesis_hash.consensus_encode(s));
170 Ok(())
171 }
172}
173
174impl<D: Decoder> Decodable<D> for Blockchain {
175 fn consensus_decode(d: &mut D) -> Result<Blockchain, encode::Error> {
176 let network: Network = try!(Decodable::consensus_decode(d));
177 let mut tree: BlockTree = try!(Decodable::consensus_decode(d));
178 let best_hash: Sha256dHash = try!(Decodable::consensus_decode(d));
179 let genesis_hash: Sha256dHash = try!(Decodable::consensus_decode(d));
180
181 let best = match tree.lookup(&best_hash.into_le(), 256) {
183 Some(node) => &**node as NodePtr,
184 None => {
185 return Err(encode::Error::UnrecognizedNetworkCommand(format!("best tip {:x} not in tree", best_hash)));
187 }
188 };
189 if tree.lookup(&genesis_hash.into_le(), 256).is_none() {
191 return Err(encode::Error::UnrecognizedNetworkCommand(format!("genesis {:x} not in tree", genesis_hash)));
193 }
194 let raw_tree = &tree as *const BlockTree;
196 for node in tree.mut_iter() {
197 let hash = node.block.header.prev_blockhash.into_le();
198 let prevptr =
199 match unsafe { (*raw_tree).lookup(&hash, 256) } {
200 Some(node) => &**node as NodePtr,
201 None => ptr::null()
202 };
203 node.prev = prevptr;
204 }
205 unsafe {
207 let mut scan = best;
208 while !(*scan).prev.is_null() {
209 let prev = (*scan).prev as *mut BlockchainNode;
210 (*prev).next = scan;
211 scan = prev as NodePtr;
212 }
213
214 if (*scan).bitcoin_hash() != genesis_hash {
216 return Err(encode::Error::UnrecognizedNetworkCommand(format!("no path from tip {:x} to genesis {:x}",
218 best_hash, genesis_hash)));
219 }
220 }
221
222 Ok(Blockchain {
224 network: network,
225 tree: tree,
226 best_tip: best,
227 best_hash: best_hash,
228 genesis_hash: genesis_hash
229 })
230 }
231}
232
233struct LocatorHashIter {
236 index: NodePtr,
237 count: usize,
238 skip: usize
239}
240
241impl LocatorHashIter {
242 fn new(init: NodePtr) -> LocatorHashIter {
243 LocatorHashIter { index: init, count: 0, skip: 1 }
244 }
245}
246
247impl Iterator for LocatorHashIter {
248 type Item = Sha256dHash;
249
250 fn next(&mut self) -> Option<Sha256dHash> {
251 if self.index.is_null() {
252 return None;
253 }
254 let ret = Some(unsafe { (*self.index).bitcoin_hash() });
255
256 self.index = unsafe { (*self.index).prev };
258 if !self.index.is_null() {
260 for _ in 1..self.skip {
261 unsafe {
262 if (*self.index).prev.is_null() {
263 break;
264 }
265 self.index = (*self.index).prev;
266 }
267 }
268 }
269
270 self.count += 1;
271 if self.count > 10 {
272 self.skip *= 2;
273 }
274 ret
275 }
276}
277
278pub struct BlockIter<'tree> {
280 index: NodePtr,
281 marker: marker::PhantomData<&'tree Blockchain>
287}
288
289pub struct RevBlockIter<'tree> {
296 index: NodePtr,
297 marker: marker::PhantomData<&'tree Blockchain>
299}
300
301pub struct RevStaleBlockIter<'tree> {
315 index: NodePtr,
316 chain: &'tree Blockchain
317}
318
319impl<'tree> Iterator for BlockIter<'tree> {
320 type Item = &'tree BlockchainNode;
321
322 fn next(&mut self) -> Option<&'tree BlockchainNode> {
323 if self.index.is_null() {
324 return None;
325 }
326 unsafe {
327 let ret = Some(&*self.index);
328 self.index = (*self.index).next;
329 ret
330 }
331 }
332}
333
334impl<'tree> Iterator for RevBlockIter<'tree> {
335 type Item = &'tree BlockchainNode;
336
337 fn next(&mut self) -> Option<&'tree BlockchainNode> {
338 if self.index.is_null() {
339 return None;
340 }
341 unsafe {
342 let ret = Some(&*self.index);
343 self.index = (*self.index).prev;
344 ret
345 }
346 }
347}
348
349impl<'tree> Iterator for RevStaleBlockIter<'tree> {
350 type Item = &'tree Block;
351
352 fn next(&mut self) -> Option<&'tree Block> {
353 if self.index.is_null() {
354 return None;
355 }
356
357 unsafe {
358 let ret = Some(&(*self.index).block);
359 let next_index = (*self.index).prev;
360 if !next_index.is_null() &&
362 (*next_index).next != self.index &&
363 (&*next_index).is_on_main_chain(self.chain) {
364 self.index = ptr::null();
365 } else {
366 self.index = next_index;
367 }
368 ret
369 }
370 }
371}
372
373fn satoshi_the_precision(n: Uint256) -> Uint256 {
378 let bits = 8 * ((n.bits() + 7) / 8 - 3);
380 let mut ret = n >> bits;
381 if ret.bit(23) {
383 ret = (ret >> 8) << 8;
384 }
385 ret << bits
386}
387
388impl Blockchain {
389 pub fn new(network: Network) -> Blockchain {
391 let genesis = genesis_block(network);
392 let genhash = genesis.header.bitcoin_hash();
393 let new_node = Box::new(BlockchainNode {
394 total_work: Default::default(),
395 required_difficulty: genesis.header.target(),
396 block: genesis,
397 height: 0,
398 has_txdata: true,
399 prev: ptr::null(),
400 next: ptr::null()
401 });
402 let raw_ptr = &*new_node as NodePtr;
403 Blockchain {
404 network: network,
405 tree: {
406 let mut pat = PatriciaTree::new();
407 pat.insert(&genhash.into_le(), 256, new_node);
408 pat
409 },
410 best_hash: genhash,
411 genesis_hash: genhash,
412 best_tip: raw_ptr
413 }
414 }
415
416 fn replace_txdata(&mut self, hash: &Uint256, txdata: Vec<Transaction>, has_txdata: bool) -> Result<(), BlockchainError> {
417 match self.tree.lookup_mut(hash, 256) {
418 Some(existing_block) => {
419 existing_block.block.txdata.clone_from(&txdata);
420 existing_block.has_txdata = has_txdata;
421 Ok(())
422 },
423 None => Err(BlockchainError::BlockNotFound)
424 }
425 }
426
427 pub fn get_block(&self, hash: Sha256dHash) -> Option<&BlockchainNode> {
429 self.tree.lookup(&hash.into_le(), 256).map(|node| &**node)
430 }
431
432 pub fn add_txdata(&mut self, block: Block) -> Result<(), BlockchainError> {
434 self.replace_txdata(&block.header.bitcoin_hash().into_le(), block.txdata, true)
435 }
436
437 pub fn remove_txdata(&mut self, hash: Sha256dHash) -> Result<(), BlockchainError> {
439 self.replace_txdata(&hash.into_le(), vec![], false)
440 }
441
442 pub fn add_header(&mut self, header: BlockHeader) -> Result<(), BlockchainError> {
444 self.real_add_block(Block { header: header, txdata: vec![] }, false)
445 }
446
447 pub fn add_block(&mut self, block: Block) -> Result<(), BlockchainError> {
449 self.real_add_block(block, true)
450 }
451
452 fn real_add_block(&mut self, block: Block, has_txdata: bool) -> Result<(), BlockchainError> {
453 #[inline]
455 fn get_prev(chain: &Blockchain, hash: Sha256dHash) -> Option<NodePtr> {
456 if hash == chain.best_hash {
457 Some(chain.best_tip)
458 } else {
459 chain.tree.lookup(&hash.into_le(), 256).map(|boxptr| &**boxptr as NodePtr)
460 }
461 }
462 if self.tree.lookup(&block.header.bitcoin_hash().into_le(), 256).is_some() {
466 return Err(BlockchainError::DuplicateHash);
467 }
468 let new_block = match get_prev(self, block.header.prev_blockhash) {
470 Some(prev) => {
471 let difficulty =
472 if (unsafe { (*prev).height } + 1) % DIFFCHANGE_INTERVAL == 0 {
474 let timespan = unsafe {
475 let mut scan = prev;
477 for _ in 0..(DIFFCHANGE_INTERVAL - 1) {
478 scan = (*scan).prev;
479 }
480 match (*prev).block.header.time - (*scan).block.header.time {
482 n if n < DIFFCHANGE_TIMESPAN / 4 => DIFFCHANGE_TIMESPAN / 4,
483 n if n > DIFFCHANGE_TIMESPAN * 4 => DIFFCHANGE_TIMESPAN * 4,
484 n => n
485 }
486 };
487 let mut target = unsafe { (*prev).block.header.target() };
489 target = target.mul_u32(timespan);
490 target = target / Uint256::from_u64(DIFFCHANGE_TIMESPAN as u64).unwrap();
491 let max = max_target(self.network);
493 if target > max { target = max };
494 satoshi_the_precision(target)
496 } else if self.network == Network::Testnet &&
499 block.header.time > unsafe { (*prev).block.header.time } + 2*TARGET_BLOCK_SPACING {
500 max_target(self.network)
501 } else if self.network == Network::Testnet {
505 unsafe {
507 let mut scan = prev;
508 while (*scan).height % DIFFCHANGE_INTERVAL != 0 &&
509 (*scan).required_difficulty == max_target(self.network) {
510 scan = (*scan).prev;
511 }
512 (*scan).required_difficulty
513 }
514 } else {
516 unsafe { (*prev).required_difficulty }
517 };
518 let ret = Box::new(BlockchainNode {
520 total_work: block.header.work() + unsafe { (*prev).total_work },
521 block: block,
522 required_difficulty: difficulty,
523 height: unsafe { (*prev).height + 1 },
524 has_txdata: has_txdata,
525 prev: prev,
526 next: ptr::null()
527 });
528 unsafe {
529 let prev = prev as *mut BlockchainNode;
530 (*prev).next = &*ret as NodePtr;
531 }
532 ret
533 },
534 None => {
535 return Err(BlockchainError::PrevHashNotFound);
536 }
537 };
538
539 try!(new_block.block.header.spv_validate(&new_block.required_difficulty));
541
542 let raw_ptr = &*new_block as NodePtr;
544 self.tree.insert(&new_block.block.header.bitcoin_hash().into_le(), 256, new_block);
545 if unsafe { (*raw_ptr).total_work > (*self.best_tip).total_work } {
547 self.set_best_tip(raw_ptr);
548 }
549 Ok(())
550 }
551
552 fn set_best_tip(&mut self, tip: NodePtr) {
554 unsafe {
556 let mut scan = self.best_tip;
557 while !(*scan).prev.is_null() {
559 if scan == self.best_tip { break; }
561 let prev = (*scan).prev as *mut BlockchainNode;
563 (*prev).next = scan;
564 scan = (*scan).prev;
565 }
566 }
567 self.best_hash = unsafe { (*tip).bitcoin_hash() };
569 self.best_tip = tip;
570 }
571
572 pub fn genesis_hash(&self) -> Sha256dHash {
574 self.genesis_hash
575 }
576
577 pub fn best_tip(&self) -> &Block {
579 unsafe { &(*self.best_tip).block }
580 }
581
582 pub fn best_tip_height(&self) -> u32 {
584 unsafe { (*self.best_tip).height }
585 }
586
587 pub fn best_tip_hash(&self) -> Sha256dHash {
589 self.best_hash
590 }
591
592 pub fn locator_hashes(&self) -> Vec<Sha256dHash> {
594 LocatorHashIter::new(self.best_tip).collect()
595 }
596
597 pub fn iter(&self, start_hash: Sha256dHash) -> BlockIter {
599 let start = match self.tree.lookup(&start_hash.into_le(), 256) {
600 Some(boxptr) => &**boxptr as NodePtr,
601 None => ptr::null()
602 };
603 BlockIter {
604 index: start,
605 marker: marker::PhantomData
606 }
607 }
608
609 pub fn rev_iter(&self, start_hash: Sha256dHash) -> RevBlockIter {
611 let start = match self.tree.lookup(&start_hash.into_le(), 256) {
612 Some(boxptr) => &**boxptr as NodePtr,
613 None => ptr::null()
614 };
615 RevBlockIter {
616 index: start,
617 marker: marker::PhantomData
618 }
619 }
620
621 pub fn rev_stale_iter(&self, start_hash: Sha256dHash) -> RevStaleBlockIter {
623 let start = match self.tree.lookup(&start_hash.into_le(), 256) {
624 Some(boxptr) => {
625 if boxptr.is_on_main_chain(self) {
627 ptr::null()
628 } else {
629 &**boxptr as NodePtr
630 }
631 }
632 None => ptr::null()
633 };
634 RevStaleBlockIter {
635 index: start,
636 chain: self
637 }
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use super::Blockchain;
644 use bitcoin::blockdata::constants::genesis_block;
645 use bitcoin::network::constants::Network::Bitcoin;
646 use bitcoin::consensus::serialize;
647 use bitcoin::consensus::deserialize;
648 use bitcoin::BitcoinHash;
649
650
651 #[test]
652 fn blockchain_serialize_test() {
653 let empty_chain = Blockchain::new(Bitcoin);
654 assert_eq!(empty_chain.best_tip().header.bitcoin_hash(),
655 genesis_block(Bitcoin).header.bitcoin_hash());
656
657 let serial = serialize(&empty_chain);
658 let deserial: Result<Blockchain, _> = deserialize(&serial);
659
660 assert!(deserial.is_ok());
661 let read_chain = deserial.unwrap();
662 assert_eq!(read_chain.best_tip().header.bitcoin_hash(),
663 genesis_block(Bitcoin).header.bitcoin_hash());
664 }
665}
666
667
668