Skip to content

Commit 84a9544

Browse files
committed
test(silentpayments): add integration test
1 parent 117af52 commit 84a9544

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed

src/silentpayments/mod.rs

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

0 commit comments

Comments
 (0)