Skip to content

Commit abcf809

Browse files
author
Ludo Galabru
authored
Merge pull request #468 from hirosystems/feat/jubilee
chore: support for Jubilee
2 parents 823f430 + 60d2276 commit abcf809

File tree

16 files changed

+459
-391
lines changed

16 files changed

+459
-391
lines changed

Cargo.lock

Lines changed: 293 additions & 299 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/chainhook-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ redis = "0.21.5"
1515
serde-redis = "0.12.0"
1616
hex = "0.4.3"
1717
rand = "0.8.5"
18-
chainhook-sdk = { version = "0.11.0", default-features = false, features = [
18+
chainhook-sdk = { version = "0.12.1", default-features = false, features = [
1919
"zeromq",
2020
], path = "../chainhook-sdk" }
2121
hiro-system-kit = "0.3.1"

components/chainhook-cli/src/scan/bitcoin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ pub async fn execute_predicates_action<'a>(
287287
Ok(action) => {
288288
actions_triggered += 1;
289289
match action {
290-
BitcoinChainhookOccurrence::Http(request) => {
290+
BitcoinChainhookOccurrence::Http(request, _) => {
291291
send_request(request, 10, 3, &ctx).await?
292292
}
293293
BitcoinChainhookOccurrence::File(path, bytes) => {

components/chainhook-cli/src/service/tests/helpers/mock_bitcoin_rpc.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use chainhook_sdk::bitcoin::Network;
12
use chainhook_sdk::bitcoincore_rpc_json::GetRawTransactionResultVoutScriptPubKey;
23
use chainhook_sdk::indexer::bitcoin::BitcoinBlockFullBreakdown;
34
use chainhook_sdk::indexer::bitcoin::BitcoinTransactionFullBreakdown;
@@ -36,7 +37,7 @@ struct Rpc {
3637

3738
fn branch_and_height_to_hash(branch: Option<char>, height: u64) -> BlockHash {
3839
let hash = Hash::from_str(&branch_and_height_to_hash_str(branch, height)).unwrap();
39-
BlockHash::from_hash(hash)
40+
BlockHash::from_raw_hash(hash)
4041
}
4142

4243
#[derive(Clone, Serialize, Deserialize, Debug)]
@@ -139,7 +140,8 @@ fn handle_rpc(
139140
hex: vec![],
140141
req_sigs: None,
141142
type_: None,
142-
addresses: None,
143+
addresses: vec![],
144+
address: None,
143145
},
144146
}],
145147
};
@@ -164,7 +166,8 @@ fn handle_rpc(
164166
hex: vec![],
165167
req_sigs: None,
166168
type_: None,
167-
addresses: None,
169+
addresses: vec![],
170+
address: None,
168171
},
169172
}],
170173
};
@@ -192,7 +195,7 @@ fn handle_rpc(
192195

193196
let hash = branch_and_height_to_hash(Some(*branch), *chain_tip);
194197
let blockchain_info = GetBlockchainInfoResult {
195-
chain: "regtest".into(),
198+
chain: Network::Regtest,
196199
blocks: chain_tip.to_owned(),
197200
headers: 0,
198201
best_block_hash: hash,

components/chainhook-sdk/Cargo.toml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "chainhook-sdk"
3-
version = "0.11.0"
3+
version = "0.12.1"
44
description = "Stateless Transaction Indexing Engine for Stacks and Bitcoin"
55
license = "GPL-3.0"
66
edition = "2021"
@@ -13,16 +13,14 @@ serde_json = { version = "1", features = ["arbitrary_precision"] }
1313
serde-hex = "0.1.0"
1414
serde_derive = "1"
1515
stacks-rpc-client = "2"
16-
clarinet-utils = "1.0.0"
1716
hiro-system-kit = { version = "0.3.1", optional = true }
1817
# stacks-rpc-client = { version = "1", path = "../../../clarinet/components/stacks-rpc-client" }
19-
# clarinet-utils = { version = "1", path = "../../../clarinet/components/clarinet-utils" }
2018
# hiro-system-kit = { version = "0.1.0", path = "../../../clarinet/components/hiro-system-kit" }
21-
chainhook-types = { version = "1.2.0", path = "../chainhook-types-rs" }
19+
chainhook-types = { version = "1.3.0", path = "../chainhook-types-rs" }
2220
rocket = { version = "=0.5.0-rc.3", features = ["json"] }
23-
bitcoincore-rpc = "0.16.0"
24-
bitcoincore-rpc-json = "0.16.0"
25-
base64 = "0.13.0"
21+
bitcoincore-rpc = "0.18.0"
22+
bitcoincore-rpc-json = "0.18.0"
23+
base64 = "0.21.5"
2624
reqwest = { version = "0.11", default-features = false, features = [
2725
"blocking",
2826
"json",
@@ -33,7 +31,7 @@ base58 = "0.2.0"
3331
schemars = { version = "0.8.10", git = "https://github.com/hirosystems/schemars.git", branch = "feat-chainhook-fixes" }
3432
crossbeam-channel = "0.5.6"
3533
futures = "0.3.21"
36-
hyper = { version = "0.14.24", features = ["http1", "client"] }
34+
hyper = { version = "=0.14.27", features = ["http1", "client"] }
3735
hex = "0.4.3"
3836
threadpool = "1.8.1"
3937
rand = "0.8.5"
@@ -42,7 +40,7 @@ dashmap = "5.4.0"
4240
fxhash = "0.2.1"
4341
lazy_static = "1.4.0"
4442
regex = "1.9.3"
45-
miniscript = "10.0.0"
43+
miniscript = "11.0.0"
4644

4745
[dev-dependencies]
4846
test-case = "3.1.0"

components/chainhook-sdk/src/chainhooks/bitcoin/mod.rs

Lines changed: 65 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use super::types::{
44
};
55
use crate::utils::Context;
66

7-
use bitcoincore_rpc::bitcoin::util::address::Payload;
8-
use bitcoincore_rpc::bitcoin::Address;
7+
use bitcoincore_rpc_json::bitcoin::{address::Payload, Address};
98
use chainhook_types::{
109
BitcoinBlockData, BitcoinChainEvent, BitcoinTransactionData, BlockIdentifier, OrdinalOperation,
1110
StacksBaseChainOperation, TransactionIdentifier,
@@ -18,8 +17,10 @@ use miniscript::Descriptor;
1817

1918
use reqwest::{Client, Method};
2019
use serde_json::Value as JsonValue;
21-
use std::collections::{BTreeMap, HashMap};
22-
use std::str::FromStr;
20+
use std::{
21+
collections::{BTreeMap, HashMap},
22+
str::FromStr,
23+
};
2324

2425
use reqwest::RequestBuilder;
2526

@@ -48,8 +49,44 @@ pub struct BitcoinChainhookOccurrencePayload {
4849
pub chainhook: BitcoinChainhookPayload,
4950
}
5051

52+
impl BitcoinChainhookOccurrencePayload {
53+
pub fn from_trigger<'a>(
54+
trigger: BitcoinTriggerChainhook<'a>,
55+
) -> BitcoinChainhookOccurrencePayload {
56+
BitcoinChainhookOccurrencePayload {
57+
apply: trigger
58+
.apply
59+
.into_iter()
60+
.map(|(transactions, block)| {
61+
let mut block = block.clone();
62+
block.transactions = transactions
63+
.into_iter()
64+
.map(|t| t.clone())
65+
.collect::<Vec<_>>();
66+
BitcoinTransactionPayload { block }
67+
})
68+
.collect::<Vec<_>>(),
69+
rollback: trigger
70+
.rollback
71+
.into_iter()
72+
.map(|(transactions, block)| {
73+
let mut block = block.clone();
74+
block.transactions = transactions
75+
.into_iter()
76+
.map(|t| t.clone())
77+
.collect::<Vec<_>>();
78+
BitcoinTransactionPayload { block }
79+
})
80+
.collect::<Vec<_>>(),
81+
chainhook: BitcoinChainhookPayload {
82+
uuid: trigger.chainhook.uuid.clone(),
83+
},
84+
}
85+
}
86+
}
87+
5188
pub enum BitcoinChainhookOccurrence {
52-
Http(RequestBuilder),
89+
Http(RequestBuilder, BitcoinChainhookOccurrencePayload),
5390
File(String, Vec<u8>),
5491
Data(BitcoinChainhookOccurrencePayload),
5592
}
@@ -155,12 +192,12 @@ pub fn evaluate_bitcoin_chainhooks_on_chain_event<'a>(
155192
}
156193

157194
pub fn serialize_bitcoin_payload_to_json<'a>(
158-
trigger: BitcoinTriggerChainhook<'a>,
195+
trigger: &BitcoinTriggerChainhook<'a>,
159196
proofs: &HashMap<&'a TransactionIdentifier, String>,
160197
) -> JsonValue {
161-
let predicate_spec = &trigger.chainhook;
198+
let predicate_spec = trigger.chainhook;
162199
json!({
163-
"apply": trigger.apply.into_iter().map(|(transactions, block)| {
200+
"apply": trigger.apply.iter().map(|(transactions, block)| {
164201
json!({
165202
"block_identifier": block.block_identifier,
166203
"parent_block_identifier": block.parent_block_identifier,
@@ -169,7 +206,7 @@ pub fn serialize_bitcoin_payload_to_json<'a>(
169206
"metadata": block.metadata,
170207
})
171208
}).collect::<Vec<_>>(),
172-
"rollback": trigger.rollback.into_iter().map(|(transactions, block)| {
209+
"rollback": trigger.rollback.iter().map(|(transactions, block)| {
173210
json!({
174211
"block_identifier": block.block_identifier,
175212
"parent_block_identifier": block.parent_block_identifier,
@@ -251,54 +288,27 @@ pub fn handle_bitcoin_hook_action<'a>(
251288
.map_err(|e| format!("unable to build http client: {}", e.to_string()))?;
252289
let host = format!("{}", http.url);
253290
let method = Method::POST;
254-
let body = serde_json::to_vec(&serialize_bitcoin_payload_to_json(trigger, proofs))
291+
let body = serde_json::to_vec(&serialize_bitcoin_payload_to_json(&trigger, proofs))
255292
.map_err(|e| format!("unable to serialize payload {}", e.to_string()))?;
256-
Ok(BitcoinChainhookOccurrence::Http(
257-
client
258-
.request(method, &host)
259-
.header("Content-Type", "application/json")
260-
.header("Authorization", http.authorization_header.clone())
261-
.body(body),
262-
))
293+
let request = client
294+
.request(method, &host)
295+
.header("Content-Type", "application/json")
296+
.header("Authorization", http.authorization_header.clone())
297+
.body(body);
298+
299+
let data = BitcoinChainhookOccurrencePayload::from_trigger(trigger);
300+
Ok(BitcoinChainhookOccurrence::Http(request, data))
263301
}
264302
HookAction::FileAppend(disk) => {
265-
let bytes = serde_json::to_vec(&serialize_bitcoin_payload_to_json(trigger, proofs))
303+
let bytes = serde_json::to_vec(&serialize_bitcoin_payload_to_json(&trigger, proofs))
266304
.map_err(|e| format!("unable to serialize payload {}", e.to_string()))?;
267305
Ok(BitcoinChainhookOccurrence::File(
268306
disk.path.to_string(),
269307
bytes,
270308
))
271309
}
272310
HookAction::Noop => Ok(BitcoinChainhookOccurrence::Data(
273-
BitcoinChainhookOccurrencePayload {
274-
apply: trigger
275-
.apply
276-
.into_iter()
277-
.map(|(transactions, block)| {
278-
let mut block = block.clone();
279-
block.transactions = transactions
280-
.into_iter()
281-
.map(|t| t.clone())
282-
.collect::<Vec<_>>();
283-
BitcoinTransactionPayload { block }
284-
})
285-
.collect::<Vec<_>>(),
286-
rollback: trigger
287-
.rollback
288-
.into_iter()
289-
.map(|(transactions, block)| {
290-
let mut block = block.clone();
291-
block.transactions = transactions
292-
.into_iter()
293-
.map(|t| t.clone())
294-
.collect::<Vec<_>>();
295-
BitcoinTransactionPayload { block }
296-
})
297-
.collect::<Vec<_>>(),
298-
chainhook: BitcoinChainhookPayload {
299-
uuid: trigger.chainhook.uuid.clone(),
300-
},
301-
},
311+
BitcoinChainhookOccurrencePayload::from_trigger(trigger),
302312
)),
303313
}
304314
}
@@ -387,7 +397,7 @@ impl BitcoinPredicateType {
387397
encoded_address,
388398
))) => {
389399
let address = match Address::from_str(encoded_address) {
390-
Ok(address) => address,
400+
Ok(address) => address.assume_checked(),
391401
Err(_) => return false,
392402
};
393403
let address_bytes = hex::encode(address.script_pubkey().as_bytes());
@@ -405,13 +415,13 @@ impl BitcoinPredicateType {
405415
encoded_address,
406416
))) => {
407417
let address = match Address::from_str(encoded_address) {
408-
Ok(address) => match address.payload {
409-
Payload::WitnessProgram {
410-
version: _,
411-
program: _,
412-
} => address,
413-
_ => return false,
414-
},
418+
Ok(address) => {
419+
let checked_address = address.assume_checked();
420+
match checked_address.payload() {
421+
Payload::WitnessProgram(_) => checked_address,
422+
_ => return false,
423+
}
424+
}
415425
Err(_) => return false,
416426
};
417427
let address_bytes = hex::encode(address.script_pubkey().as_bytes());

components/chainhook-sdk/src/chainhooks/bitcoin/tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ fn test_opreturn_evaluation(script_pubkey: &str, rule: MatchingRule, matches: bo
7878
)]
7979
fn test_descriptor_evaluation(addr: &str, expr: &str) {
8080
// turn the address into a script_pubkey with a 0x prefix, as expected by the evaluator.
81-
let script_pubkey = Address::from_str(addr).unwrap().script_pubkey();
81+
let script_pubkey = Address::from_str(addr)
82+
.unwrap()
83+
.assume_checked()
84+
.script_pubkey();
8285
let matching_script_pubkey = format!("0x{}", hex::encode(script_pubkey));
8386

8487
let rule = DescriptorMatchingRule {

components/chainhook-sdk/src/chainhooks/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ pub fn get_stacks_canonical_magic_bytes(network: &BitcoinNetwork) -> [u8; 2] {
535535
BitcoinNetwork::Mainnet => *b"X2",
536536
BitcoinNetwork::Testnet => *b"T2",
537537
BitcoinNetwork::Regtest => *b"id",
538-
BitcoinNetwork::Signet => unreachable!()
538+
BitcoinNetwork::Signet => unreachable!(),
539539
}
540540
}
541541

components/chainhook-sdk/src/indexer/bitcoin/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ impl BitcoinTransactionInputFullBreakdown {
103103
#[serde(rename_all = "camelCase")]
104104
pub struct BitcoinTransactionInputPrevoutFullBreakdown {
105105
pub height: u64,
106-
#[serde(with = "bitcoin::util::amount::serde::as_btc")]
106+
#[serde(with = "bitcoin::amount::serde::as_btc")]
107107
pub value: Amount,
108108
}
109109

110110
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
111111
#[serde(rename_all = "camelCase")]
112112
pub struct BitcoinTransactionOutputFullBreakdown {
113-
#[serde(with = "bitcoin::util::amount::serde::as_btc")]
113+
#[serde(with = "bitcoin::amount::serde::as_btc")]
114114
pub value: Amount,
115115
pub n: u32,
116116
pub script_pub_key: GetRawTransactionResultVoutScriptPubKey,

components/chainhook-sdk/src/indexer/tests/helpers/transactions.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,32 @@ pub fn generate_test_tx_bitcoin_p2pkh_transfer(
8484
let pubkey_hash = recipient
8585
.from_base58()
8686
.expect("Unable to get bytes from btc address");
87+
let slice = [
88+
pubkey_hash[1],
89+
pubkey_hash[2],
90+
pubkey_hash[3],
91+
pubkey_hash[4],
92+
pubkey_hash[5],
93+
pubkey_hash[6],
94+
pubkey_hash[7],
95+
pubkey_hash[8],
96+
pubkey_hash[9],
97+
pubkey_hash[10],
98+
pubkey_hash[11],
99+
pubkey_hash[12],
100+
pubkey_hash[13],
101+
pubkey_hash[14],
102+
pubkey_hash[15],
103+
pubkey_hash[16],
104+
pubkey_hash[17],
105+
pubkey_hash[18],
106+
pubkey_hash[19],
107+
pubkey_hash[20],
108+
];
87109
let script = BitcoinScriptBuilder::new()
88110
.push_opcode(opcodes::all::OP_DUP)
89111
.push_opcode(opcodes::all::OP_HASH160)
90-
.push_slice(&pubkey_hash[1..21])
112+
.push_slice(&slice)
91113
.push_opcode(opcodes::all::OP_EQUALVERIFY)
92114
.push_opcode(opcodes::all::OP_CHECKSIG)
93115
.into_script();

0 commit comments

Comments
 (0)