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