Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] feat: predicate chaining #571

Draft
wants to merge 8 commits into
base: develop
Choose a base branch
from
Draft
28 changes: 17 additions & 11 deletions components/chainhook-cli/src/scan/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,20 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(

let res = match process_block_with_predicates(
block,
&vec![&predicate_spec],
predicate_spec.clone(),
&event_observer_config,
ctx,
)
.await
{
Ok(actions) => {
Ok((actions, new_chainhooks)) => {
if actions > 0 {
number_of_times_triggered += 1;
}
actions_triggered += actions;
for _new_chainhook in new_chainhooks {
todo!()
}
Ok(())
}
Err(e) => {
Expand Down Expand Up @@ -243,24 +246,27 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(

pub async fn process_block_with_predicates(
block: BitcoinBlockData,
predicates: &Vec<&BitcoinChainhookSpecification>,
predicates: BitcoinChainhookSpecification,
event_observer_config: &EventObserverConfig,
ctx: &Context,
) -> Result<u32, String> {
) -> Result<(u32, Vec<BitcoinChainhookSpecification>), String> {
let chain_event =
BitcoinChainEvent::ChainUpdatedWithBlocks(BitcoinChainUpdatedWithBlocksData {
new_blocks: vec![block],
confirmed_blocks: vec![],
});
// todo: use new hooks
let (predicates_triggered, _predicates_evaluated, _predicates_expired, new_chainhooks) =
evaluate_bitcoin_chainhooks_on_chain_event(chain_event, predicates, ctx);

let (predicates_triggered, _predicates_evaluated, _predicates_expired) =
evaluate_bitcoin_chainhooks_on_chain_event(&chain_event, predicates, ctx);

execute_predicates_action(predicates_triggered, &event_observer_config, &ctx).await
match execute_predicates_action(predicates_triggered, &event_observer_config, &ctx).await {
Ok(actions) => Ok((actions, new_chainhooks)),
Err(e) => Err(e),
}
}

pub async fn execute_predicates_action<'a>(
hits: Vec<BitcoinTriggerChainhook<'a>>,
pub async fn execute_predicates_action(
hits: Vec<BitcoinTriggerChainhook>,
config: &EventObserverConfig,
ctx: &Context,
) -> Result<u32, String> {
Expand All @@ -270,7 +276,7 @@ pub async fn execute_predicates_action<'a>(
if trigger.chainhook.include_proof {
gather_proofs(&trigger, &mut proofs, &config, &ctx);
}
let predicate_uuid = &trigger.chainhook.uuid;
let predicate_uuid = &trigger.chainhook.uuid.clone();
match handle_bitcoin_hook_action(trigger, &proofs) {
Err(e) => {
warn!(
Expand Down
40 changes: 27 additions & 13 deletions components/chainhook-cli/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use chainhook_sdk::chainhooks::types::{ChainhookConfig, ChainhookFullSpecificati
use chainhook_sdk::chainhooks::types::ChainhookSpecification;
use chainhook_sdk::observer::{
start_event_observer, HookExpirationData, ObserverCommand, ObserverEvent,
PredicateEvaluationReport,
PredicateEvaluationReport, StacksObserverStartupContext,
};
use chainhook_sdk::types::{Chain, StacksChainEvent};
use chainhook_sdk::types::{Chain, StacksBlockData, StacksChainEvent};
use chainhook_sdk::utils::Context;
use redis::{Commands, Connection};

Expand Down Expand Up @@ -243,24 +243,38 @@ impl Service {
let ctx = self.ctx.clone();
let stacks_db =
open_readonly_stacks_db_conn_with_retry(&config.expected_cache_path(), 3, &ctx)?;
let unconfirmed_blocks = match get_all_unconfirmed_blocks(&stacks_db, &ctx) {
let confirmed_tip = get_last_block_height_inserted(&stacks_db, &ctx).unwrap_or(0);
let stacks_startup_context = match get_all_unconfirmed_blocks(&stacks_db, &ctx) {
Ok(blocks) => {
let confirmed_tip = get_last_block_height_inserted(&stacks_db, &ctx).unwrap_or(0);
// any unconfirmed blocks that are earlier than confirmed blocks are invalid
Some(
blocks
.iter()
.filter(|&b| b.block_identifier.index > confirmed_tip)
.cloned()
.collect(),
)

let unconfirmed_blocks = blocks
.iter()
.filter(|&b| b.block_identifier.index > confirmed_tip)
.cloned()
.collect::<Vec<StacksBlockData>>();

let highest_appended = match unconfirmed_blocks
.iter()
.max_by_key(|b| b.block_identifier.index)
{
Some(highest_block) => highest_block.block_identifier.index,
None => confirmed_tip,
};
StacksObserverStartupContext {
block_pool_seed: unconfirmed_blocks,
last_block_height_appended: highest_appended,
}
}
Err(e) => {
info!(
self.ctx.expect_logger(),
"Failed to get stacks blocks from db to seed block pool: {}", e
);
None
StacksObserverStartupContext {
block_pool_seed: vec![],
last_block_height_appended: confirmed_tip,
}
}
};

Expand All @@ -272,7 +286,7 @@ impl Service {
observer_command_rx,
Some(observer_event_tx_moved),
None,
unconfirmed_blocks,
Some(stacks_startup_context),
self.ctx.clone(),
);

Expand Down
Loading
Loading