      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104

    use std::cmp;
    use hash::H256;
    use hex::FromHex;
    use ser::{Serializable, serialized_list_size, serialized_list_size_with_flags, deserialize, SERIALIZE_TRANSACTION_WITNESS};
    use block::Block;
    use transaction::Transaction;
    use merkle_root::merkle_root;
    use indexed_header::IndexedBlockHeader;
    use indexed_transaction::IndexedTransaction;

    #[derive(Debug, Clone, Deserializable)]
    pub struct IndexedBlock {
    	pub header: IndexedBlockHeader,
    	pub transactions: Vec<IndexedTransaction>,
    }

    impl From<Block> for IndexedBlock {
    	fn from(block: Block) -> Self {
    		let Block { block_header, transactions } = block;

    		IndexedBlock {
    			header: block_header.into(),
    			transactions: transactions.into_iter().map(Into::into).collect(),
    		}
    	}
    }

    impl cmp::PartialEq for IndexedBlock {
    	fn eq(&self, other: &Self) -> bool {
    		self.header.hash == other.header.hash
    	}
    }

    impl IndexedBlock {
    	pub fn new(header: IndexedBlockHeader, transactions: Vec<IndexedTransaction>) -> Self {
    		IndexedBlock {
    			header: header,
    			transactions: transactions,
    		}
    	}

    	pub fn hash(&self) -> &H256 {
    		&self.header.hash
    	}

    	pub fn to_raw_block(self) -> Block {
    		Block::new(self.header.raw, self.transactions.into_iter().map(|tx| tx.raw).collect())
    	}

    	pub fn size(&self) -> usize {
    		let header_size = self.header.raw.serialized_size();
    		let transactions = self.transactions.iter().map(|tx| &tx.raw).collect::<Vec<_>>();
    		let txs_size = serialized_list_size::<Transaction, &Transaction>(&transactions);
    		header_size + txs_size
    	}

    	pub fn size_with_witness(&self) -> usize {
    		let header_size = self.header.raw.serialized_size();
    		let transactions = self.transactions.iter().map(|tx| &tx.raw).collect::<Vec<_>>();
    		let txs_size = serialized_list_size_with_flags::<Transaction, &Transaction>(&transactions, SERIALIZE_TRANSACTION_WITNESS);
    		header_size + txs_size
    	}

    	pub fn merkle_root(&self) -> H256 {
    		merkle_root(&self.transactions.iter().map(|tx| &tx.hash).collect::<Vec<&H256>>())
    	}

    	pub fn witness_merkle_root(&self) -> H256 {
    		let hashes = match self.transactions.split_first() {
    			None => vec![],
    			Some((_, rest)) => {
    				let mut hashes = vec![H256::from(0)];
    				hashes.extend(rest.iter().map(|tx| tx.raw.witness_hash()));
    				hashes
    			},
    		};
    		merkle_root(&hashes)
    	}

    	pub fn is_final(&self, height: u32) -> bool {
    		self.transactions.iter().all(|tx| tx.raw.is_final_in_block(height, self.header.raw.time))
    	}
    }

    impl From<&'static str> for IndexedBlock {
    	fn from(s: &'static str) -> Self {
    		deserialize(&s.from_hex::<Vec<u8>>().unwrap() as &[u8]).unwrap()
    	}
    }

    #[cfg(test)]
    mod tests {
    	use super::IndexedBlock;

    	#[test]
    	fn size_with_witness_not_equal_to_size() {
    		let block_without_witness: IndexedBlock = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
    		assert_eq!(block_without_witness.size(), block_without_witness.size_with_witness());

    		// bip143 block
    		let block_with_witness: IndexedBlock = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010100000000000000000000000000000000000000000000000000000000000000000000000000000000000001010000000000".into();
    		assert!(block_with_witness.size() != block_with_witness.size_with_witness());
    	}
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g. `str,u8` or `String,struct:Vec,test`)