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

chore(release): publish v1.6.0 #584

Merged
merged 7 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion components/chainhook-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "chainhook"
version = "1.5.1"
version = "1.6.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
4 changes: 2 additions & 2 deletions components/chainhook-cli/src/scan/stacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ pub async fn scan_stacks_chainstate_via_rocksdb_using_predicate(
Ok(action) => {
number_of_times_triggered += 1;
let res = match action {
StacksChainhookOccurrence::Http(request) => {
StacksChainhookOccurrence::Http(request, _) => {
send_request(request, 3, 1, &ctx).await
}
StacksChainhookOccurrence::File(path, bytes) => file_append(path, bytes, &ctx),
Expand Down Expand Up @@ -488,7 +488,7 @@ pub async fn scan_stacks_chainstate_via_csv_using_predicate(
Ok(action) => {
occurrences_found += 1;
let res = match action {
StacksChainhookOccurrence::Http(request) => {
StacksChainhookOccurrence::Http(request, _) => {
send_request(request, 10, 3, &ctx).await
}
StacksChainhookOccurrence::File(path, bytes) => file_append(path, bytes, &ctx),
Expand Down
68 changes: 55 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, PredicateInterruptedData, 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 Expand Up @@ -618,6 +632,24 @@ impl Service {
}
}
}
ObserverEvent::PredicateInterrupted(PredicateInterruptedData {
predicate_key,
error,
}) => {
if let PredicatesApi::On(ref config) = self.config.http_api {
let Ok(mut predicates_db_conn) =
open_readwrite_predicates_db_conn_verbose(&config, &ctx)
else {
continue;
};
set_predicate_interrupted_status(
error,
&predicate_key,
&mut predicates_db_conn,
&ctx,
);
}
}
ObserverEvent::Terminate => {
info!(
self.ctx.expect_logger(),
Expand Down Expand Up @@ -743,6 +775,16 @@ fn update_status_from_report(
}
}

fn set_predicate_interrupted_status(
error: String,
predicate_key: &str,
predicates_db_conn: &mut Connection,
ctx: &Context,
) {
let status = PredicateStatus::Interrupted(error);
update_predicate_status(predicate_key, status, predicates_db_conn, ctx);
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum StreamingDataType {
Occurrence {
Expand Down
24 changes: 10 additions & 14 deletions components/chainhook-cli/src/service/runloops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use crate::{
bitcoin::scan_bitcoin_chainstate_via_rpc_using_predicate,
stacks::scan_stacks_chainstate_via_rocksdb_using_predicate,
},
service::{
open_readwrite_predicates_db_conn_or_panic, update_predicate_status, PredicateStatus,
},
service::{open_readwrite_predicates_db_conn_or_panic, set_predicate_interrupted_status},
storage::open_readonly_stacks_db_conn,
};

Expand Down Expand Up @@ -73,14 +71,13 @@ pub fn start_stacks_scan_runloop(

// Update predicate status in redis
if let PredicatesApi::On(ref api_config) = moved_config.http_api {
let status = PredicateStatus::Interrupted(format!(
"Unable to evaluate predicate on Stacks chainstate: {e}"
));
let error =
format!("Unable to evaluate predicate on Stacks chainstate: {e}");
let mut predicates_db_conn =
open_readwrite_predicates_db_conn_or_panic(api_config, &moved_ctx);
update_predicate_status(
set_predicate_interrupted_status(
error,
&predicate_spec.key(),
status,
&mut predicates_db_conn,
&moved_ctx,
);
Expand Down Expand Up @@ -147,17 +144,16 @@ pub fn start_bitcoin_scan_runloop(

// Update predicate status in redis
if let PredicatesApi::On(ref api_config) = moved_config.http_api {
let status = PredicateStatus::Interrupted(format!(
"Unable to evaluate predicate on Bitcoin chainstate: {e}"
));
let error =
format!("Unable to evaluate predicate on Bitcoin chainstate: {e}");
let mut predicates_db_conn =
open_readwrite_predicates_db_conn_or_panic(api_config, &moved_ctx);
update_predicate_status(
set_predicate_interrupted_status(
error,
&predicate_spec.key(),
status,
&mut predicates_db_conn,
&moved_ctx,
);
)
}
return;
}
Expand Down
81 changes: 52 additions & 29 deletions components/chainhook-sdk/src/chainhooks/bitcoin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub struct BitcoinTriggerChainhook<'a> {

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BitcoinTransactionPayload {
#[serde(flatten)]
pub block: BitcoinBlockData,
}

Expand Down Expand Up @@ -233,38 +234,60 @@ pub fn serialize_bitcoin_transactions_to_json<'a>(
.into_iter()
.map(|transaction| {
let mut metadata = serde_json::Map::new();
if predicate_spec.include_inputs {
metadata.insert(
"inputs".into(),
json!(transaction
.metadata
.inputs
.iter()
.map(|input| {
json!({

metadata.insert("fee".into(), json!(transaction.metadata.fee));
metadata.insert("index".into(), json!(transaction.metadata.index));

let inputs = if predicate_spec.include_inputs {
transaction
.metadata
.inputs
.iter()
.map(|input| {
let witness = if predicate_spec.include_witness {
input.witness.clone()
} else {
vec![]
};
json!({
"previous_output": {
"txin": input.previous_output.txid.hash.to_string(),
"vout": input.previous_output.vout,
"sequence": input.sequence,
})
"value": input.previous_output.value,
"block_height": input.previous_output.block_height,
},
"script_sig": input.script_sig,
"sequence": input.sequence,
"witness": witness
})
.collect::<Vec<_>>()),
);
}
if predicate_spec.include_outputs {
metadata.insert("outputs".into(), json!(transaction.metadata.outputs));
}
if !transaction.metadata.stacks_operations.is_empty() {
metadata.insert(
"stacks_operations".into(),
json!(transaction.metadata.stacks_operations),
);
}
if !transaction.metadata.ordinal_operations.is_empty() {
metadata.insert(
"ordinal_operations".into(),
json!(transaction.metadata.ordinal_operations),
);
}
})
.collect::<Vec<_>>()
} else {
vec![]
};
metadata.insert("inputs".into(), json!(inputs));

let outputs = if predicate_spec.include_outputs {
transaction.metadata.outputs.clone()
} else {
vec![]
};
metadata.insert("outputs".into(), json!(outputs));

let stacks_ops = if transaction.metadata.stacks_operations.is_empty() {
vec![]
} else {
transaction.metadata.stacks_operations.clone()
};
metadata.insert("stacks_operations".into(), json!(stacks_ops));

let ordinals_ops = if transaction.metadata.ordinal_operations.is_empty() {
vec![]
} else {
transaction.metadata.ordinal_operations.clone()
};
metadata.insert("ordinal_operations".into(), json!(ordinals_ops));

metadata.insert(
"proof".into(),
json!(proofs.get(&transaction.transaction_identifier)),
Expand Down
59 changes: 59 additions & 0 deletions components/chainhook-sdk/src/chainhooks/bitcoin/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use super::super::types::MatchingRule;
use super::*;
use crate::indexer::tests::helpers::accounts;
use crate::indexer::tests::helpers::bitcoin_blocks::generate_test_bitcoin_block;
use crate::indexer::tests::helpers::transactions::generate_test_tx_bitcoin_p2pkh_transfer;
use crate::types::BitcoinTransactionMetadata;
use chainhook_types::bitcoin::TxOut;

use chainhook_types::BitcoinNetwork;
use test_case::test_case;

#[test_case(
Expand Down Expand Up @@ -134,3 +138,58 @@ fn script_pubkey_evaluation(output: OutputPredicate, script_pubkey: &str, matche

assert_eq!(matches, predicate.evaluate_transaction_predicate(&tx, &ctx));
}

#[test_case(
true, true, true, true;
"including all optional fields"
)]
#[test_case(
false, false, false, false;
"omitting all optional fields"
)]

fn it_serdes_occurrence_payload(
include_proof: bool,
include_inputs: bool,
include_outputs: bool,
include_witness: bool,
) {
let transaction = generate_test_tx_bitcoin_p2pkh_transfer(
0,
&accounts::wallet_1_btc_address(),
&accounts::wallet_3_btc_address(),
3,
);
let block = generate_test_bitcoin_block(0, 0, vec![transaction.clone()], None);
let chainhook = &BitcoinChainhookSpecification {
uuid: "uuid".into(),
owner_uuid: None,
name: "name".into(),
network: BitcoinNetwork::Mainnet,
version: 0,
blocks: None,
start_block: None,
end_block: None,
expire_after_occurrence: None,
predicate: BitcoinPredicateType::Block,
action: HookAction::Noop,
include_proof,
include_inputs,
include_outputs,
include_witness,
enabled: true,
expired_at: None,
};
let trigger = BitcoinTriggerChainhook {
chainhook,
apply: vec![(vec![&transaction], &block)],
rollback: vec![],
};
let payload = serde_json::to_vec(&serialize_bitcoin_payload_to_json(
&trigger,
&HashMap::new(),
))
.unwrap();

let _: BitcoinChainhookOccurrencePayload = serde_json::from_slice(&payload[..]).unwrap();
}
Loading
Loading