use ? instead of try macro
[rust-lightning] / src / ln / chan_utils.rs
1 use bitcoin::blockdata::script::{Script,Builder};
2 use bitcoin::blockdata::opcodes;
3 use bitcoin::util::hash::Hash160;
4
5 use secp256k1::key::{PublicKey,SecretKey};
6 use secp256k1::Secp256k1;
7 use secp256k1;
8
9 use crypto::digest::Digest;
10 use crypto::sha2::Sha256;
11 use crypto::ripemd160::Ripemd160;
12
13 // Various functions for key derivation and transaction creation for use within channels. Primarily
14 // used in Channel and ChannelMonitor.
15
16 pub fn build_commitment_secret(commitment_seed: [u8; 32], idx: u64) -> [u8; 32] {
17         let mut res: [u8; 32] = commitment_seed;
18         for i in 0..48 {
19                 let bitpos = 47 - i;
20                 if idx & (1 << bitpos) == (1 << bitpos) {
21                         res[bitpos / 8] ^= 1 << (bitpos & 7);
22                         let mut sha = Sha256::new();
23                         sha.input(&res);
24                         sha.result(&mut res);
25                 }
26         }
27         res
28 }
29
30 pub fn derive_private_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
31         let mut sha = Sha256::new();
32         sha.input(&per_commitment_point.serialize());
33         sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).unwrap().serialize());
34         let mut res = [0; 32];
35         sha.result(&mut res);
36
37         let mut key = base_secret.clone();
38         key.add_assign(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &res)?)?;
39         Ok(key)
40 }
41
42 pub fn derive_public_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
43         let mut sha = Sha256::new();
44         sha.input(&per_commitment_point.serialize());
45         sha.input(&base_point.serialize());
46         let mut res = [0; 32];
47         sha.result(&mut res);
48
49         let hashkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &res)?).unwrap();
50         base_point.combine(&secp_ctx, &hashkey)
51 }
52
53 /// Derives a revocation key from its constituent parts
54 pub fn derive_private_revocation_key(secp_ctx: &Secp256k1, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
55         let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret).unwrap();
56         let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret).unwrap();
57
58         let rev_append_commit_hash_key = {
59                 let mut sha = Sha256::new();
60                 sha.input(&revocation_base_point.serialize());
61                 sha.input(&per_commitment_point.serialize());
62                 let mut res = [0; 32];
63                 sha.result(&mut res);
64
65                 SecretKey::from_slice(&secp_ctx, &res)?
66         };
67         let commit_append_rev_hash_key = {
68                 let mut sha = Sha256::new();
69                 sha.input(&per_commitment_point.serialize());
70                 sha.input(&revocation_base_point.serialize());
71                 let mut res = [0; 32];
72                 sha.result(&mut res);
73
74                 SecretKey::from_slice(&secp_ctx, &res)?
75         };
76
77         let mut part_a = revocation_base_secret.clone();
78         part_a.mul_assign(&secp_ctx, &rev_append_commit_hash_key)?;
79         let mut part_b = per_commitment_secret.clone();
80         part_b.mul_assign(&secp_ctx, &commit_append_rev_hash_key)?;
81         part_a.add_assign(&secp_ctx, &part_b)?;
82         Ok(part_a)
83 }
84
85 pub fn derive_public_revocation_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
86         let rev_append_commit_hash_key = {
87                 let mut sha = Sha256::new();
88                 sha.input(&revocation_base_point.serialize());
89                 sha.input(&per_commitment_point.serialize());
90                 let mut res = [0; 32];
91                 sha.result(&mut res);
92
93                 SecretKey::from_slice(&secp_ctx, &res)?
94         };
95         let commit_append_rev_hash_key = {
96                 let mut sha = Sha256::new();
97                 sha.input(&per_commitment_point.serialize());
98                 sha.input(&revocation_base_point.serialize());
99                 let mut res = [0; 32];
100                 sha.result(&mut res);
101
102                 SecretKey::from_slice(&secp_ctx, &res)?
103         };
104
105         let mut part_a = revocation_base_point.clone();
106         part_a.mul_assign(&secp_ctx, &rev_append_commit_hash_key)?;
107         let mut part_b = per_commitment_point.clone();
108         part_b.mul_assign(&secp_ctx, &commit_append_rev_hash_key)?;
109         part_a.combine(&secp_ctx, &part_b)
110 }
111
112 pub struct TxCreationKeys {
113         pub per_commitment_point: PublicKey,
114         pub revocation_key: PublicKey,
115         pub a_htlc_key: PublicKey,
116         pub b_htlc_key: PublicKey,
117         pub a_delayed_payment_key: PublicKey,
118         pub b_payment_key: PublicKey,
119 }
120
121 impl TxCreationKeys {
122         pub fn new(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
123                 Ok(TxCreationKeys {
124                         per_commitment_point: per_commitment_point.clone(),
125                         revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &b_revocation_base)?,
126                         a_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &a_htlc_base)?,
127                         b_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &b_htlc_base)?,
128                         a_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &a_delayed_payment_base)?,
129                         b_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &b_payment_base)?,
130                 })
131         }
132 }
133
134 /// Gets the "to_local" output redeemscript, ie the script which is time-locked or spendable by
135 /// the revocation key
136 pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, to_self_delay: u16, delayed_payment_key: &PublicKey) -> Script {
137         Builder::new().push_opcode(opcodes::All::OP_IF)
138                                      .push_slice(&revocation_key.serialize())
139                                      .push_opcode(opcodes::All::OP_ELSE)
140                                      .push_int(to_self_delay as i64)
141                                      .push_opcode(opcodes::OP_CSV)
142                                      .push_opcode(opcodes::All::OP_DROP)
143                                      .push_slice(&delayed_payment_key.serialize())
144                                      .push_opcode(opcodes::All::OP_ENDIF)
145                                      .push_opcode(opcodes::All::OP_CHECKSIG)
146                                      .into_script()
147 }
148
149 #[derive(Clone)]
150 pub struct HTLCOutputInCommitment {
151         pub offered: bool,
152         pub amount_msat: u64,
153         pub cltv_expiry: u32,
154         pub payment_hash: [u8; 32],
155         pub transaction_output_index: u32,
156 }
157
158 #[inline]
159 pub fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey, offered: bool) -> Script {
160         let payment_hash160 = {
161                 let mut ripemd = Ripemd160::new();
162                 ripemd.input(&htlc.payment_hash);
163                 let mut res = [0; 20];
164                 ripemd.result(&mut res);
165                 res
166         };
167         if offered {
168                 Builder::new().push_opcode(opcodes::All::OP_DUP)
169                               .push_opcode(opcodes::All::OP_HASH160)
170                               .push_slice(&Hash160::from_data(&revocation_key.serialize())[..])
171                               .push_opcode(opcodes::All::OP_EQUAL)
172                               .push_opcode(opcodes::All::OP_IF)
173                               .push_opcode(opcodes::All::OP_CHECKSIG)
174                               .push_opcode(opcodes::All::OP_ELSE)
175                               .push_slice(&b_htlc_key.serialize()[..])
176                               .push_opcode(opcodes::All::OP_SWAP)
177                               .push_opcode(opcodes::All::OP_SIZE)
178                               .push_int(32)
179                               .push_opcode(opcodes::All::OP_EQUAL)
180                               .push_opcode(opcodes::All::OP_NOTIF)
181                               .push_opcode(opcodes::All::OP_DROP)
182                               .push_int(2)
183                               .push_opcode(opcodes::All::OP_SWAP)
184                               .push_slice(&a_htlc_key.serialize()[..])
185                               .push_int(2)
186                               .push_opcode(opcodes::All::OP_CHECKMULTISIG)
187                               .push_opcode(opcodes::All::OP_ELSE)
188                               .push_opcode(opcodes::All::OP_HASH160)
189                               .push_slice(&payment_hash160)
190                               .push_opcode(opcodes::All::OP_EQUALVERIFY)
191                               .push_opcode(opcodes::All::OP_CHECKSIG)
192                               .push_opcode(opcodes::All::OP_ENDIF)
193                               .push_opcode(opcodes::All::OP_ENDIF)
194                               .into_script()
195         } else {
196                 Builder::new().push_opcode(opcodes::All::OP_DUP)
197                               .push_opcode(opcodes::All::OP_HASH160)
198                               .push_slice(&Hash160::from_data(&revocation_key.serialize())[..])
199                               .push_opcode(opcodes::All::OP_EQUAL)
200                               .push_opcode(opcodes::All::OP_IF)
201                               .push_opcode(opcodes::All::OP_CHECKSIG)
202                               .push_opcode(opcodes::All::OP_ELSE)
203                               .push_slice(&b_htlc_key.serialize()[..])
204                               .push_opcode(opcodes::All::OP_SWAP)
205                               .push_opcode(opcodes::All::OP_SIZE)
206                               .push_int(32)
207                               .push_opcode(opcodes::All::OP_EQUAL)
208                               .push_opcode(opcodes::All::OP_IF)
209                               .push_opcode(opcodes::All::OP_HASH160)
210                               .push_slice(&payment_hash160)
211                               .push_opcode(opcodes::All::OP_EQUALVERIFY)
212                               .push_int(2)
213                               .push_opcode(opcodes::All::OP_SWAP)
214                               .push_slice(&a_htlc_key.serialize()[..])
215                               .push_int(2)
216                               .push_opcode(opcodes::All::OP_CHECKMULTISIG)
217                               .push_opcode(opcodes::All::OP_ELSE)
218                               .push_opcode(opcodes::All::OP_DROP)
219                               .push_int(htlc.cltv_expiry as i64)
220                               .push_opcode(opcodes::OP_CLTV)
221                               .push_opcode(opcodes::All::OP_DROP)
222                               .push_opcode(opcodes::All::OP_CHECKSIG)
223                               .push_opcode(opcodes::All::OP_ENDIF)
224                               .push_opcode(opcodes::All::OP_ENDIF)
225                               .into_script()
226         }
227 }
228
229 /// note here that 'a_revocation_key' is generated using b_revocation_basepoint and a's
230 /// commitment secret. 'htlc' does *not* need to have its previous_output_index filled.
231 #[inline]
232 pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys, offered: bool) -> Script {
233         get_htlc_redeemscript_with_explicit_keys(htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, offered)
234 }