| 176 | |
| 177 | impl OpeningFeeParams { |
| 178 | pub fn validate( |
| 179 | &self, |
| 180 | secret: &[u8], |
| 181 | payment_size_msat: Option<Msat>, |
| 182 | receivable: Option<Msat>, |
| 183 | ) -> Result<(), Error> { |
| 184 | // LSPs MUST check that the opening_fee_params.promise does in fact |
| 185 | // prove that it previously promised the specified opening_fee_params. |
| 186 | let mut hmac = HmacEngine::<sha256::Hash>::new(&secret); |
| 187 | hmac.input(&self.min_fee_msat.msat().to_be_bytes()); |
| 188 | hmac.input(&self.proportional.ppm().to_be_bytes()); |
| 189 | hmac.input(self.valid_until.to_rfc3339().as_bytes()); |
| 190 | hmac.input(&self.min_lifetime.to_be_bytes()); |
| 191 | hmac.input(&self.max_client_to_self_delay.to_be_bytes()); |
| 192 | hmac.input(&self.min_payment_size_msat.msat().to_be_bytes()); |
| 193 | hmac.input(&self.max_payment_size_msat.msat().to_be_bytes()); |
| 194 | let promise: String = Hmac::from_engine(hmac) |
| 195 | .to_byte_array() |
| 196 | .iter() |
| 197 | .map(|b| format!("{:02x}", b)) |
| 198 | .collect(); |
| 199 | if self.promise != Promise(promise) { |
| 200 | return Err(Error::InvalidOpeningFeeParams); |
| 201 | } |
| 202 | |
| 203 | // LSPs MUST check that the opening_fee_params.valid_until is not a past |
| 204 | // datetime. |
| 205 | let now = Utc::now(); |
| 206 | if now > self.valid_until { |
| 207 | debug!("Got invalid opening fee params: timeout, {:?}", self); |
| 208 | return Err(Error::InvalidOpeningFeeParams); |
| 209 | } |
| 210 | |
| 211 | // If the payment_size_msat is specified in the request, the LSP: |
| 212 | // - MUST compute the opening_fee and check that the computation did |
| 213 | // not hit an overflow failure. |
| 214 | // - MUST check that the resulting opening_fee is strictly less than |
| 215 | // the payment_size_msat. |
| 216 | // - SHOULD check that it has sufficient incoming liquidity from the |
| 217 | // public network to be able to receive at least |
| 218 | // payment_size_msat. |
| 219 | if let Some(payment_size_msat) = payment_size_msat { |
| 220 | let opening_fee = compute_opening_fee( |
| 221 | payment_size_msat.msat(), |
| 222 | self.min_fee_msat.msat(), |
| 223 | self.proportional.ppm() as u64, |
| 224 | ) |
| 225 | .ok_or(Error::PaymentSizeTooLarge)?; |
| 226 | if opening_fee >= payment_size_msat.msat() { |
| 227 | return Err(Error::PaymentSizeTooSmall); |
| 228 | } |
| 229 | |
| 230 | if let Some(rec) = receivable { |
| 231 | if opening_fee >= rec.msat() { |
| 232 | return Err(Error::PaymentSizeTooLarge); |
| 233 | } |
| 234 | } |
| 235 | } |