Merge pull request #454 from jrawsthorne/improved-bip158-types

Implement new FilterHeader type to differentiate from FilterHash
This commit is contained in:
Andrew Poelstra 2020-11-05 16:46:50 +00:00 committed by GitHub
commit 8295885e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 26 additions and 16 deletions

View File

@ -35,7 +35,7 @@ use std::io::{Cursor, Read, Write};
use hashes::hex::ToHex;
use hashes::{sha256d, Hash};
use hash_types::{BlockHash, FilterHash, TxMerkleNode};
use hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader};
use util::endian;
use util::psbt;
@ -593,6 +593,7 @@ macro_rules! impl_vec {
}
impl_vec!(BlockHash);
impl_vec!(FilterHash);
impl_vec!(FilterHeader);
impl_vec!(TxMerkleNode);
impl_vec!(Transaction);
impl_vec!(TxOut);

View File

@ -50,7 +50,8 @@ hash_newtype!(WitnessMerkleNode, sha256d::Hash, 32, doc="A hash corresponding to
hash_newtype!(WitnessCommitment, sha256d::Hash, 32, doc="A hash corresponding to the witness structure commitment in the coinbase transaction");
hash_newtype!(XpubIdentifier, hash160::Hash, 20, doc="XpubIdentifier as defined in BIP-32.");
hash_newtype!(FilterHash, sha256d::Hash, 32, doc="Bloom filter souble-SHA256 locator hash, as defined in BIP-168");
hash_newtype!(FilterHash, sha256d::Hash, 32, doc="Filter hash, as defined in BIP-157");
hash_newtype!(FilterHeader, sha256d::Hash, 32, doc="Filter header, as defined in BIP-157");
impl_hashencode!(Txid);
@ -60,3 +61,4 @@ impl_hashencode!(BlockHash);
impl_hashencode!(TxMerkleNode);
impl_hashencode!(WitnessMerkleNode);
impl_hashencode!(FilterHash);
impl_hashencode!(FilterHeader);

View File

@ -397,7 +397,7 @@ mod test {
NetworkMessage::GetCFilters(GetCFilters{filter_type: 2, start_height: 52, stop_hash: hash([42u8; 32]).into()}),
NetworkMessage::CFilter(CFilter{filter_type: 7, block_hash: hash([25u8; 32]).into(), filter: vec![1,2,3]}),
NetworkMessage::GetCFHeaders(GetCFHeaders{filter_type: 4, start_height: 102, stop_hash: hash([47u8; 32]).into()}),
NetworkMessage::CFHeaders(CFHeaders{filter_type: 13, stop_hash: hash([53u8; 32]).into(), previous_filter: hash([12u8; 32]).into(), filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()]}),
NetworkMessage::CFHeaders(CFHeaders{filter_type: 13, stop_hash: hash([53u8; 32]).into(), previous_filter_header: hash([12u8; 32]).into(), filter_hashes: vec![hash([4u8; 32]).into(), hash([12u8; 32]).into()]}),
NetworkMessage::GetCFCheckpt(GetCFCheckpt{filter_type: 17, stop_hash: hash([25u8; 32]).into()}),
NetworkMessage::CFCheckpt(CFCheckpt{filter_type: 27, stop_hash: hash([77u8; 32]).into(), filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()]}),
NetworkMessage::Alert(vec![45,66,3,2,6,8,9,12,3,130]),

View File

@ -2,7 +2,7 @@
//! BIP157 Client Side Block Filtering network messages
//!
use hash_types::{BlockHash, FilterHash};
use hash_types::{BlockHash, FilterHash, FilterHeader};
#[derive(PartialEq, Eq, Clone, Debug)]
/// getcfilters message
@ -48,11 +48,11 @@ pub struct CFHeaders {
/// The hash of the last block in the requested range
pub stop_hash: BlockHash,
/// The filter header preceding the first block in the requested range
pub previous_filter: FilterHash,
pub previous_filter_header: FilterHeader,
/// The filter hashes for each block in the requested range
pub filter_hashes: Vec<FilterHash>,
}
impl_consensus_encoding!(CFHeaders, filter_type, stop_hash, previous_filter, filter_hashes);
impl_consensus_encoding!(CFHeaders, filter_type, stop_hash, previous_filter_header, filter_hashes);
#[derive(PartialEq, Eq, Clone, Debug)]
/// getcfcheckpt message
@ -72,6 +72,6 @@ pub struct CFCheckpt {
/// The hash of the last block in the requested range
pub stop_hash: BlockHash,
/// The filter headers at intervals of 1,000
pub filter_headers: Vec<FilterHash>,
pub filter_headers: Vec<FilterHeader>,
}
impl_consensus_encoding!(CFCheckpt, filter_type, stop_hash, filter_headers);

View File

@ -53,7 +53,7 @@ use std::cmp::Ordering;
use hashes::{Hash, siphash24};
use hash_types::{BlockHash, FilterHash};
use hash_types::{BlockHash, FilterHash, FilterHeader};
use blockdata::block::Block;
use blockdata::script::Script;
@ -100,14 +100,21 @@ pub struct BlockFilter {
pub content: Vec<u8>
}
impl FilterHash {
/// compute the filter header from a filter hash and previous filter header
pub fn filter_header(&self, previous_filter_header: &FilterHeader) -> FilterHeader {
let mut header_data = [0u8; 64];
header_data[0..32].copy_from_slice(&self[..]);
header_data[32..64].copy_from_slice(&previous_filter_header[..]);
FilterHeader::hash(&header_data)
}
}
impl BlockFilter {
/// compute this filter's id in a chain of filters
pub fn filter_id(&self, previous_filter_id: &FilterHash) -> FilterHash {
pub fn filter_header(&self, previous_filter_header: &FilterHeader) -> FilterHeader {
let filter_hash = FilterHash::hash(self.content.as_slice());
let mut header_data = [0u8; 64];
header_data[0..32].copy_from_slice(&filter_hash[..]);
header_data[32..64].copy_from_slice(&previous_filter_id[..]);
FilterHash::hash(&header_data)
filter_hash.filter_header(previous_filter_header)
}
/// create a new filter from pre-computed data
@ -555,9 +562,9 @@ mod test {
let block: Block = deserialize(&Vec::from_hex(&t.get(2).unwrap().as_str().unwrap()).unwrap()).unwrap();
assert_eq!(block.block_hash(), block_hash);
let scripts = t.get(3).unwrap().as_array().unwrap();
let previous_filter_id = FilterHash::from_hex(&t.get(4).unwrap().as_str().unwrap()).unwrap();
let previous_filter_header = FilterHeader::from_hex(&t.get(4).unwrap().as_str().unwrap()).unwrap();
let filter_content = Vec::from_hex(&t.get(5).unwrap().as_str().unwrap()).unwrap();
let filter_id = FilterHash::from_hex(&t.get(6).unwrap().as_str().unwrap()).unwrap();
let filter_header = FilterHeader::from_hex(&t.get(6).unwrap().as_str().unwrap()).unwrap();
let mut txmap = HashMap::new();
let mut si = scripts.iter();
@ -590,7 +597,7 @@ mod test {
}
}
assert_eq!(filter_id, filter.filter_id(&previous_filter_id));
assert_eq!(filter_header, filter.filter_header(&previous_filter_header));
}
}