Skip to content

Commit

Permalink
feat: check block filter hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
yangby-cryptape committed Mar 15, 2023
1 parent 09b9ae5 commit 5ec5fd4
Show file tree
Hide file tree
Showing 27 changed files with 2,049 additions and 311 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ckb-traits = "0.108.0"
ckb-resource = "0.108.0"
ckb-verification = "0.108.0"
ckb-systemtime = "0.108.0"
ckb-hash = "0.108.0"
ckb-merkle-mountain-range = "0.5.1"
golomb-coded-set = "0.2.0"
rocksdb = { package = "ckb-rocksdb", version ="=0.19.0", features = ["snappy"], default-features = false }
Expand Down
3 changes: 3 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ mod types;
mod utils;
mod verify;

// TODO Remove the patches if the code was merged into CKB.
mod patches;

use config::AppConfig;

fn main() -> anyhow::Result<()> {
Expand Down
73 changes: 73 additions & 0 deletions src/patches.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::io::{Cursor, Write};

#[cfg(not(test))]
use ckb_hash::blake2b_256;
use golomb_coded_set::{GCSFilterWriter, SipHasher24Builder, M, P};

use ckb_types::{core::TransactionView, packed, prelude::*};

/// Provides data for building block filter data.
pub trait FilterDataProvider {
/// Finds the cell through its out point.
fn cell(&self, out_point: &packed::OutPoint) -> Option<packed::CellOutput>;
}

/// Builds filter data for transactions.
pub fn build_filter_data<P: FilterDataProvider>(
provider: P,
transactions: &[TransactionView],
) -> (Vec<u8>, Vec<packed::OutPoint>) {
let mut filter_writer = Cursor::new(Vec::new());
let mut filter = build_gcs_filter(&mut filter_writer);
let mut missing_out_points = Vec::new();
for tx in transactions {
if !tx.is_cellbase() {
for out_point in tx.input_pts_iter() {
if let Some(input_cell) = provider.cell(&out_point) {
filter.add_element(input_cell.calc_lock_hash().as_slice());
if let Some(type_script) = input_cell.type_().to_opt() {
filter.add_element(type_script.calc_script_hash().as_slice());
}
} else {
missing_out_points.push(out_point);
}
}
}
for output_cell in tx.outputs() {
filter.add_element(output_cell.calc_lock_hash().as_slice());
if let Some(type_script) = output_cell.type_().to_opt() {
filter.add_element(type_script.calc_script_hash().as_slice());
}
}
}
filter
.finish()
.expect("flush to memory writer should be OK");
let filter_data = filter_writer.into_inner();
(filter_data, missing_out_points)
}

/// Calculates a block filter hash.
#[cfg(not(test))]
pub fn calc_filter_hash(
parent_block_filter_hash: &packed::Byte32,
filter_data: &packed::Bytes,
) -> [u8; 32] {
blake2b_256(
[
parent_block_filter_hash.as_slice(),
filter_data.calc_raw_data_hash().as_slice(),
]
.concat(),
)
}

// TODO Use real block filter hashes in unit tests.
#[cfg(test)]
pub fn calc_filter_hash(_: &packed::Byte32, _: &packed::Bytes) -> [u8; 32] {
Default::default()
}

fn build_gcs_filter(out: &mut dyn Write) -> GCSFilterWriter<SipHasher24Builder> {
GCSFilterWriter::new(out, SipHasher24Builder::new(0, 0), M, P)
}
Loading

0 comments on commit 5ec5fd4

Please sign in to comment.