Skip to content

Commit 18e176b

Browse files
committed
test(silentpayments): add integration test
1 parent fd9b34f commit 18e176b

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

src/silentpayments/mod.rs

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,195 @@
1818
//! implementation without requiring any further elliptic-curve operations from the wallet.
1919
pub mod recipient;
2020
pub mod sender;
21+
22+
#[cfg(test)]
23+
mod test {
24+
use crate::{
25+
silentpayments::{recipient as sp_rx, sender as sp_tx},
26+
Keypair, PublicKey, SecretKey, XOnlyPublicKey,
27+
};
28+
use std::collections::HashMap;
29+
30+
const SENDER_SECRET_KEYS: [[u8; 32]; 2] = [
31+
[
32+
0x34, 0x18, 0x5f, 0xd2, 0xc0, 0xc3, 0x71, 0x19,
33+
0x73, 0x46, 0x2e, 0xc7, 0x7b, 0x65, 0x69, 0x95,
34+
0x43, 0x20, 0x5a, 0xee, 0x4f, 0x30, 0xf4, 0xee,
35+
0x32, 0x5b, 0xd8, 0x37, 0x6a, 0x1b, 0x36, 0xf3,
36+
],
37+
[
38+
0xcf, 0x3e, 0x69, 0x66, 0x58, 0xa9, 0x6e, 0x45,
39+
0x70, 0x96, 0xcb, 0x2e, 0xc9, 0xa9, 0x7c, 0x27,
40+
0x8c, 0x1b, 0xf0, 0xc6, 0x0d, 0x1d, 0xc3, 0x13,
41+
0x92, 0x7d, 0xef, 0xac, 0xc2, 0x86, 0xae, 0x88,
42+
],
43+
];
44+
45+
const SMALLEST_OUTPOINT: [u8; 36] = [
46+
0x16, 0x9e, 0x1e, 0x83, 0xe9, 0x30, 0x85, 0x33, 0x91,
47+
0xbc, 0x6f, 0x35, 0xf6, 0x05, 0xc6, 0x75, 0x4c, 0xfe,
48+
0xad, 0x57, 0xcf, 0x83, 0x87, 0x63, 0x9d, 0x3b, 0x40,
49+
0x96, 0xc5, 0x4f, 0x18, 0xf4, 0x00, 0x00, 0x00, 0x00,
50+
];
51+
52+
const BOB_SCAN_SECKEY: [u8; 32] = [
53+
0xa8, 0x90, 0x54, 0xc9, 0x5b, 0xe3, 0xc3, 0x01,
54+
0x56, 0x65, 0x74, 0xf2, 0xaa, 0x93, 0xad, 0xe0,
55+
0x51, 0x85, 0x09, 0x03, 0xa6, 0x9c, 0xbd, 0xd1,
56+
0xd4, 0x7e, 0xae, 0x26, 0x3d, 0x7b, 0xc0, 0x31,
57+
];
58+
59+
const BOB_SPEND_PUBKEY: [u8; 33] = [
60+
0x02, 0xee, 0x97, 0xdf, 0x83, 0xb2, 0x54, 0x6a,
61+
0xf5, 0xa7, 0xd0, 0x62, 0x15, 0xd9, 0x8b, 0xcb,
62+
0x63, 0x7f, 0xe0, 0x5d, 0xd0, 0xfa, 0x37, 0x3b,
63+
0xd8, 0x20, 0xe6, 0x64, 0xd3, 0x72, 0xde, 0x9a, 0x01,
64+
];
65+
66+
const BOB_ADDRESS: [[u8; 33]; 2] = [
67+
[
68+
0x02, 0x15, 0x40, 0xae, 0xa8, 0x97, 0x54, 0x7a,
69+
0xd4, 0x39, 0xb4, 0xe0, 0xf6, 0x09, 0xe5, 0xf0,
70+
0xfa, 0x63, 0xde, 0x89, 0xab, 0x11, 0xed, 0xe3,
71+
0x1e, 0x8c, 0xde, 0x4b, 0xe2, 0x19, 0x42, 0x5f, 0x23,
72+
],
73+
[
74+
0x02, 0x3e, 0xff, 0xf8, 0x18, 0x51, 0x65, 0xea,
75+
0x63, 0xa9, 0x92, 0xb3, 0x9f, 0x31, 0xd8, 0xfd,
76+
0x8e, 0x0e, 0x64, 0xae, 0xf9, 0xd3, 0x88, 0x07,
77+
0x34, 0x97, 0x37, 0x14, 0xa5, 0x3d, 0x83, 0x11, 0x8d,
78+
],
79+
];
80+
81+
const CAROL_SCAN_KEY: [u8; 32] = [
82+
0x04, 0xb2, 0xa4, 0x11, 0x63, 0x5c, 0x09, 0x77,
83+
0x59, 0xaa, 0xcd, 0x0f, 0x00, 0x5a, 0x4c, 0x82,
84+
0xc8, 0xc9, 0x28, 0x62, 0xc6, 0xfc, 0x28, 0x4b,
85+
0x80, 0xb8, 0xef, 0xeb, 0xc2, 0x0c, 0x3d, 0x17,
86+
];
87+
88+
const CAROL_ADDRESS: [[u8; 33]; 2] = [
89+
[
90+
0x03, 0xbb, 0xc6, 0x3f, 0x12, 0x74, 0x5d, 0x3b,
91+
0x9e, 0x9d, 0x24, 0xc6, 0xcd, 0x7a, 0x1e, 0xfe,
92+
0xba, 0xd0, 0xa7, 0xf4, 0x69, 0x23, 0x2f, 0xbe,
93+
0xcf, 0x31, 0xfb, 0xa7, 0xb4, 0xf7, 0xdd, 0xed, 0xa8,
94+
],
95+
[
96+
0x03, 0x81, 0xeb, 0x9a, 0x9a, 0x9e, 0xc7, 0x39,
97+
0xd5, 0x27, 0xc1, 0x63, 0x1b, 0x31, 0xb4, 0x21,
98+
0x56, 0x6f, 0x5c, 0x2a, 0x47, 0xb4, 0xab, 0x5b,
99+
0x1f, 0x6a, 0x68, 0x6d, 0xfb, 0x68, 0xea, 0xb7, 0x16,
100+
],
101+
];
102+
103+
#[test]
104+
fn full_silentpayment_flow_one_sender_two_receivers() {
105+
// Assign references to the addresses
106+
let sp_addresses: [&[[u8; 33]; 2]; 3] = [
107+
&CAROL_ADDRESS, // 1.0 BTC
108+
&BOB_ADDRESS, // 2.0 BTC
109+
&CAROL_ADDRESS, // 3.0 BTC
110+
];
111+
112+
let mut recipients = Vec::<sp_tx::Recipient>::new();
113+
for (index, [scan_pubkey, spend_pubkey]) in sp_addresses.iter().enumerate() {
114+
let scan_pubkey = PublicKey::from_slice(scan_pubkey).expect("deterministic, shouldn't fail");
115+
let spend_pubkey = PublicKey::from_slice(spend_pubkey).expect("deterministic, shouldn't fail");
116+
117+
let silentpayment_recipient =
118+
sp_tx::Recipient::new(&scan_pubkey, &spend_pubkey, index);
119+
120+
recipients.push(silentpayment_recipient);
121+
}
122+
123+
let recipients: Vec<&mut sp_tx::Recipient> =
124+
recipients.iter_mut().map(|k| k as &mut _).collect();
125+
126+
let mut taproot_seckeys = Vec::<Keypair>::new();
127+
let mut tx_inputs = Vec::<XOnlyPublicKey>::new();
128+
129+
for &key in SENDER_SECRET_KEYS.iter() {
130+
let seckey: [u8; 32] = key;
131+
132+
let keypair = Keypair::from_seckey_byte_array(seckey).expect("deterministic, shouldn't fail");
133+
134+
taproot_seckeys.push(keypair);
135+
136+
tx_inputs.push(keypair.x_only_public_key().0);
137+
}
138+
139+
let taproot_seckeys: Vec<&Keypair> = taproot_seckeys.iter().collect();
140+
141+
let tx_outputs = sp_tx::create_outputs(
142+
&recipients,
143+
&SMALLEST_OUTPOINT,
144+
Some(&taproot_seckeys),
145+
None,
146+
).expect("deterministic, shouldn't fail");
147+
148+
assert_eq!("249d9a68bf413c9edddc6b48db0a912bc475b4da9a9b53fc755edf9b06bec69d", format!("{}", tx_outputs[0]));
149+
assert_eq!("9d5aa1cb80d9d7433ed0c8287297d4f76e52de2a930f011417311716d6a933cc", format!("{}", tx_outputs[1]));
150+
assert_eq!("dfb7b9b4414bd084041a83bba20d8a7d36263d5dc26489a8da0bcaa881a07340", format!("{}", tx_outputs[2]));
151+
152+
let bob_scan_seckey = SecretKey::from_secret_bytes(BOB_SCAN_SECKEY).expect("deterministic, shouldn't fail");
153+
let m: u32 = 1;
154+
155+
let (label, label_tweak32) = sp_rx::create_label(&bob_scan_seckey, m).expect("deterministic, shouldn't fail");
156+
157+
let bob_spend_pubkey = PublicKey::from_slice(&BOB_SPEND_PUBKEY).expect("deterministic, shouldn't fail");
158+
159+
let _labeled_spend_pubkey =
160+
sp_rx::create_labeled_spend_pubkey(&bob_spend_pubkey, &label).expect("deterministic, shouldn't fail");
161+
162+
let tx_inputs_ref: Vec<&XOnlyPublicKey> = tx_inputs.iter().collect();
163+
let tx_inputs_ref = tx_inputs_ref.as_slice();
164+
165+
let public_data: sp_rx::PrevoutsSummary =
166+
sp_rx::PrevoutsSummary::create(&SMALLEST_OUTPOINT, Some(tx_inputs_ref), None).expect("deterministic, shouldn't fail");
167+
168+
let mut tweak_map = HashMap::<[u8; 33], [u8; 32]>::new();
169+
170+
tweak_map.insert(label.serialize(), label_tweak32);
171+
172+
let tx_outputs_ref: Vec<_> = tx_outputs.iter().collect();
173+
174+
let label_lookup = |key: &[u8; 33]| -> Option<[u8; 32]> { tweak_map.get(key).copied() };
175+
176+
assert_eq!(label_lookup(&label.serialize()), Some(label_tweak32));
177+
178+
let found_outputs = sp_rx::scan_outputs(
179+
&tx_outputs_ref,
180+
&bob_scan_seckey,
181+
&public_data,
182+
&bob_spend_pubkey,
183+
Some(label_lookup),
184+
).expect("deterministic, shouldn't fail");
185+
186+
assert_eq!(found_outputs.len(), 1, "First receiver should find one output after full scanning");
187+
assert_eq!("9d5aa1cb80d9d7433ed0c8287297d4f76e52de2a930f011417311716d6a933cc", format!("{}", found_outputs[0]));
188+
189+
let carol_scan_key = SecretKey::from_secret_bytes(CAROL_SCAN_KEY).expect("deterministic, shouldn't fail");
190+
191+
let carol_spend_pubkey = PublicKey::from_slice(&CAROL_ADDRESS[1]).expect("deterministic, shouldn't fail");
192+
193+
let found_outputs = sp_rx::scan_outputs(
194+
&tx_outputs_ref,
195+
&carol_scan_key,
196+
&public_data,
197+
&carol_spend_pubkey,
198+
None::<fn(&[u8; 33]) -> Option<[u8; 32]>>,
199+
)
200+
.expect("deterministic, shouldn't fail");
201+
202+
assert_eq!(found_outputs.len(), 2, "Second receiver should find two outputs after full scanning");
203+
assert_eq!(
204+
"dfb7b9b4414bd084041a83bba20d8a7d36263d5dc26489a8da0bcaa881a07340",
205+
format!("{}", found_outputs[0])
206+
);
207+
assert_eq!(
208+
"249d9a68bf413c9edddc6b48db0a912bc475b4da9a9b53fc755edf9b06bec69d",
209+
format!("{}", found_outputs[1])
210+
);
211+
}
212+
}

0 commit comments

Comments
 (0)