1#![warn(clippy::missing_docs_in_private_items)]
2
3use std::{
4 cmp::max,
5 collections::HashMap,
6};
7
8use derive_more::Display;
9use itertools::izip;
10use raiden_primitives::{
11 constants::LOCKSROOT_OF_NO_LOCKS,
12 serializers::u256_to_str,
13 traits::ToBytes,
14 types::{
15 Address,
16 AddressMetadata,
17 BalanceHash,
18 BalanceProofData,
19 BlockExpiration,
20 BlockHash,
21 BlockNumber,
22 BlockTimeout,
23 Bytes,
24 CanonicalIdentifier,
25 ChainID,
26 ChannelIdentifier,
27 EncodedLock,
28 FeeAmount,
29 LockTimeout,
30 LockedAmount,
31 Locksroot,
32 MessageHash,
33 MessageIdentifier,
34 Nonce,
35 PaymentIdentifier,
36 ProportionalFeeAmount,
37 RevealTimeout,
38 Secret,
39 SecretHash,
40 SettleTimeout,
41 Signature,
42 TokenAddress,
43 TokenAmount,
44 TokenNetworkAddress,
45 TokenNetworkRegistryAddress,
46 U256,
47 },
48};
49use rug::{
50 Complete,
51 Rational,
52};
53use serde::{
54 Deserialize,
55 Serialize,
56};
57
58use super::ContractSendEvent;
59use crate::{
60 constants::{
61 DEFAULT_MEDIATION_FLAT_FEE,
62 DEFAULT_MEDIATION_PROPORTIONAL_FEE,
63 DEFAULT_MEDIATION_PROPORTIONAL_IMBALANCE_FEE,
64 DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
65 MAXIMUM_PENDING_TRANSFERS,
66 },
67 errors::StateTransitionError,
68 types::{
69 Random,
70 TransactionExecutionStatus,
71 TransactionResult,
72 },
73 views,
74};
75
76#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
78pub enum TransferRole {
79 Initiator,
80 Mediator,
81 Target,
82}
83
84#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
86pub enum TransferTask {
87 Initiator(InitiatorTask),
88 Mediator(MediatorTask),
89 Target(TargetTask),
90}
91
92#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
94pub enum TransferState {
95 Pending,
96 Expired,
97 SecretRevealed,
98 Canceled,
99}
100
101#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
103pub enum PayeeState {
104 Pending,
105 SecretRevealed,
106 ContractUnlock,
107 BalanceProof,
108 Expired,
109}
110
111#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
113pub enum PayerState {
114 Pending,
115 SecretRevealed,
116 WaitingUnlock,
117 WaitingSecretReveal,
118 BalanceProof,
119 Expired,
120}
121
122#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
124pub enum TargetState {
125 Expired,
126 OffchainSecretReveal,
127 OnchainSecretReveal,
128 OnchainUnlock,
129 SecretRequest,
130}
131
132#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
134pub enum WaitingTransferStatus {
135 Waiting,
136 Expired,
137}
138
139#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
141pub struct InitiatorTransferState {
142 pub route: RouteState,
143 pub transfer_description: TransferDescriptionWithSecretState,
144 pub channel_identifier: ChannelIdentifier,
145 pub transfer: LockedTransferState,
146 pub received_secret_request: bool,
147 pub transfer_state: TransferState,
148}
149
150#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
155pub struct InitiatorPaymentState {
156 pub routes: Vec<RouteState>,
157 pub initiator_transfers: HashMap<SecretHash, InitiatorTransferState>,
158 pub cancelled_channels: Vec<ChannelIdentifier>,
159}
160
161#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
163pub struct InitiatorTask {
164 pub role: TransferRole,
165 pub token_network_address: TokenNetworkAddress,
166 pub manager_state: InitiatorPaymentState,
167}
168
169#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
171pub struct WaitingTransferState {
172 pub transfer: LockedTransferState,
173 pub status: WaitingTransferStatus,
174}
175
176#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
181pub struct MediationPairState {
182 pub payer_transfer: LockedTransferState,
183 pub payee_address: Address,
184 pub payee_transfer: LockedTransferState,
185 pub payer_state: PayerState,
186 pub payee_state: PayeeState,
187}
188
189#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
193pub struct MediatorTransferState {
194 pub secrethash: SecretHash,
195 pub routes: Vec<RouteState>,
196 pub refunded_channels: Vec<ChannelIdentifier>,
197 pub secret: Option<Secret>,
198 pub transfers_pair: Vec<MediationPairState>,
199 pub waiting_transfer: Option<WaitingTransferState>,
200}
201
202#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
204pub struct MediatorTask {
205 pub role: TransferRole,
206 pub token_network_address: TokenNetworkAddress,
207 pub mediator_state: MediatorTransferState,
208}
209#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
211pub struct TargetTask {
212 pub role: TransferRole,
213 pub token_network_address: TokenNetworkAddress,
214 pub target_state: TargetTransferState,
215}
216
217#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
219pub struct TargetTransferState {
220 pub from_hop: HopState,
221 pub transfer: LockedTransferState,
222 pub secret: Option<Secret>,
223 pub state: TargetState,
224 pub initiator_address_metadata: Option<AddressMetadata>,
225}
226
227#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
234pub struct PaymentMappingState {
235 pub secrethashes_to_task: HashMap<SecretHash, TransferTask>,
236}
237
238#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
242pub struct ChainState {
243 pub chain_id: ChainID,
244 pub block_number: BlockNumber,
245 pub block_hash: BlockHash,
246 pub our_address: Address,
247 pub identifiers_to_tokennetworkregistries: HashMap<Address, TokenNetworkRegistryState>,
248 pub payment_mapping: PaymentMappingState,
249 pub pending_transactions: Vec<ContractSendEvent>,
250 pub pseudo_random_number_generator: Random,
251}
252
253impl ChainState {
254 pub fn new(
256 chain_id: ChainID,
257 block_number: BlockNumber,
258 block_hash: BlockHash,
259 our_address: Address,
260 ) -> ChainState {
261 ChainState {
262 chain_id,
263 block_number,
264 block_hash,
265 our_address,
266 identifiers_to_tokennetworkregistries: HashMap::new(),
267 payment_mapping: PaymentMappingState { secrethashes_to_task: HashMap::new() },
268 pending_transactions: vec![],
269 pseudo_random_number_generator: Random::new(),
270 }
271 }
272}
273
274#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
276pub struct TokenNetworkRegistryState {
277 pub address: Address,
278 pub tokennetworkaddresses_to_tokennetworks: HashMap<Address, TokenNetworkState>,
279 pub tokenaddresses_to_tokennetworkaddresses: HashMap<Address, Address>,
280}
281
282impl TokenNetworkRegistryState {
283 pub fn new(
285 address: Address,
286 token_network_list: Vec<TokenNetworkState>,
287 ) -> TokenNetworkRegistryState {
288 let mut registry_state = TokenNetworkRegistryState {
289 address: Address::zero(),
290 tokennetworkaddresses_to_tokennetworks: HashMap::new(),
291 tokenaddresses_to_tokennetworkaddresses: HashMap::new(),
292 };
293 for token_network in token_network_list.iter() {
294 let token_network_address = token_network.address;
295 let token_address = token_network.token_address;
296 registry_state
297 .tokennetworkaddresses_to_tokennetworks
298 .insert(token_network_address, token_network.clone());
299
300 registry_state
301 .tokenaddresses_to_tokennetworkaddresses
302 .insert(token_address, token_network.address);
303 }
304 registry_state.address = address;
305 registry_state
306 }
307}
308
309#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
311pub struct TokenNetworkState {
312 pub address: Address,
313 pub token_address: TokenAddress,
314 pub channelidentifiers_to_channels: HashMap<U256, ChannelState>,
315 pub partneraddresses_to_channelidentifiers: HashMap<Address, Vec<ChannelIdentifier>>,
316}
317
318impl TokenNetworkState {
319 pub fn new(address: Address, token_address: TokenAddress) -> TokenNetworkState {
321 TokenNetworkState {
322 address,
323 token_address,
324 channelidentifiers_to_channels: HashMap::new(),
325 partneraddresses_to_channelidentifiers: HashMap::new(),
326 }
327 }
328}
329
330#[derive(Copy, Clone, Display, Debug, PartialEq, Eq, Serialize, Deserialize)]
332#[serde(rename_all = "lowercase")]
333pub enum ChannelStatus {
334 #[display(fmt = "opened")]
335 Opened,
336 #[display(fmt = "closing")]
337 Closing,
338 #[display(fmt = "closed")]
339 Closed,
340 #[display(fmt = "settling")]
341 Settling,
342 #[display(fmt = "settled")]
343 Settled,
344 #[display(fmt = "removed")]
345 Removed,
346 #[display(fmt = "unusable")]
347 Unusable,
348}
349
350#[derive(Default, Clone, Serialize, Deserialize, Debug)]
352pub struct MediationFeeConfig {
353 pub token_to_flat_fee: HashMap<Address, FeeAmount>,
354 pub token_to_proportional_fee: HashMap<Address, ProportionalFeeAmount>,
355 pub token_to_proportional_imbalance_fee: HashMap<Address, ProportionalFeeAmount>,
356 pub cap_meditation_fees: bool,
357}
358
359impl MediationFeeConfig {
360 pub fn get_flat_fee(&self, token_address: &Address) -> FeeAmount {
361 *self
362 .token_to_flat_fee
363 .get(token_address)
364 .unwrap_or(&DEFAULT_MEDIATION_FLAT_FEE.into())
365 }
366
367 pub fn get_proportional_fee(&self, token_address: &Address) -> ProportionalFeeAmount {
368 *self
369 .token_to_proportional_fee
370 .get(token_address)
371 .unwrap_or(&DEFAULT_MEDIATION_PROPORTIONAL_FEE.into())
372 }
373
374 pub fn get_proportional_imbalance_fee(&self, token_address: &Address) -> ProportionalFeeAmount {
375 *self
376 .token_to_proportional_imbalance_fee
377 .get(token_address)
378 .unwrap_or(&DEFAULT_MEDIATION_PROPORTIONAL_IMBALANCE_FEE.into())
379 }
380}
381
382#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
384pub struct ChannelState {
385 pub canonical_identifier: CanonicalIdentifier,
386 pub token_address: TokenAddress,
387 pub token_network_registry_address: TokenNetworkRegistryAddress,
388 pub reveal_timeout: RevealTimeout,
389 pub settle_timeout: SettleTimeout,
390 pub fee_schedule: FeeScheduleState,
391 pub our_state: ChannelEndState,
392 pub partner_state: ChannelEndState,
393 pub open_transaction: TransactionExecutionStatus,
394 pub close_transaction: Option<TransactionExecutionStatus>,
395 pub settle_transaction: Option<TransactionExecutionStatus>,
396 pub update_transaction: Option<TransactionExecutionStatus>,
397}
398
399impl ChannelState {
400 #[allow(clippy::too_many_arguments)]
402 pub fn new(
403 canonical_identifier: CanonicalIdentifier,
404 token_address: TokenAddress,
405 token_network_registry_address: TokenNetworkRegistryAddress,
406 our_address: Address,
407 partner_address: Address,
408 reveal_timeout: RevealTimeout,
409 settle_timeout: SettleTimeout,
410 open_transaction: TransactionExecutionStatus,
411 fee_config: MediationFeeConfig,
412 ) -> Result<ChannelState, StateTransitionError> {
413 if reveal_timeout >= settle_timeout {
414 return Err(StateTransitionError {
415 msg: format!(
416 "reveal_timeout({:?}) must be smaller than settle_timeout({:?})",
417 reveal_timeout, settle_timeout,
418 ),
419 })
420 }
421
422 let our_state = ChannelEndState::new(our_address);
423
424 let partner_state = ChannelEndState::new(partner_address);
425
426 Ok(ChannelState {
427 canonical_identifier,
428 token_address,
429 token_network_registry_address,
430 reveal_timeout,
431 settle_timeout,
432 our_state,
433 partner_state,
434 open_transaction,
435 close_transaction: None,
436 settle_transaction: None,
437 update_transaction: None,
438 fee_schedule: FeeScheduleState {
439 cap_fees: fee_config.cap_meditation_fees,
440 flat: fee_config.get_flat_fee(&token_address),
441 proportional: fee_config.get_proportional_fee(&token_address),
442 imbalance_penalty: None,
443 penalty_func: None,
444 },
445 })
446 }
447
448 pub fn status(&self) -> ChannelStatus {
450 let mut status = ChannelStatus::Opened;
451
452 if let Some(settle_transaction) = &self.settle_transaction {
453 let finished_successfully =
454 settle_transaction.result == Some(TransactionResult::Success);
455 let running = settle_transaction.finished_block_number.is_none();
456
457 if finished_successfully {
458 status = ChannelStatus::Settled;
459 } else if running {
460 status = ChannelStatus::Settling;
461 } else {
462 status = ChannelStatus::Unusable;
463 }
464 } else if let Some(close_transaction) = &self.close_transaction {
465 let finished_successfully =
466 close_transaction.result == Some(TransactionResult::Success);
467 let running = close_transaction.finished_block_number.is_none();
468
469 if finished_successfully {
470 status = ChannelStatus::Closed;
471 } else if running {
472 status = ChannelStatus::Closing;
473 } else {
474 status = ChannelStatus::Unusable;
475 }
476 }
477
478 status
479 }
480
481 pub fn our_total_deposit(&self) -> TokenAmount {
483 self.our_state.contract_balance
484 }
485
486 pub fn partner_total_deposit(&self) -> TokenAmount {
488 self.partner_state.contract_balance
489 }
490
491 pub fn our_total_withdraw(&self) -> TokenAmount {
493 self.our_state.total_withdraw()
494 }
495
496 pub fn partner_total_withdraw(&self) -> TokenAmount {
498 self.partner_state.total_withdraw()
499 }
500
501 pub fn capacity(&self) -> TokenAmount {
503 self.our_state.contract_balance + self.partner_state.contract_balance -
504 self.our_state.total_withdraw() -
505 self.partner_state.total_withdraw()
506 }
507
508 pub fn is_usable_for_new_transfer(
510 &self,
511 amount: TokenAmount,
512 lock_timeout: Option<LockTimeout>,
513 ) -> bool {
514 let pending_transfers = self.our_state.count_pending_transfers();
515 let distributable = views::channel_distributable(&self.our_state, &self.partner_state);
516 let lock_timeout_valid = match lock_timeout {
517 Some(lock_timeout) =>
518 lock_timeout <= self.settle_timeout && lock_timeout > self.reveal_timeout,
519 None => true,
520 };
521 let is_valid_settle_timeout = self.settle_timeout >= self.reveal_timeout * 2;
522
523 if self.status() != ChannelStatus::Opened {
524 return false
525 }
526
527 if !is_valid_settle_timeout {
528 return false
529 }
530
531 if pending_transfers >= MAXIMUM_PENDING_TRANSFERS {
532 return false
533 }
534
535 if amount > distributable {
536 return false
537 }
538
539 if !self.our_state.is_valid_amount(amount) {
540 return false
541 }
542
543 if !lock_timeout_valid {
544 return false
545 }
546
547 true
548 }
549
550 pub fn is_usable_for_mediation(
552 &self,
553 transfer_amount: TokenAmount,
554 lock_timeout: BlockTimeout,
555 ) -> bool {
556 self.is_usable_for_new_transfer(transfer_amount, Some(lock_timeout))
557 }
558}
559
560#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
562pub struct ChannelEndState {
563 pub address: Address,
564 pub contract_balance: TokenAmount,
565 pub onchain_total_withdraw: TokenAmount,
566 pub withdraws_pending: HashMap<U256, PendingWithdrawState>,
567 pub withdraws_expired: Vec<ExpiredWithdrawState>,
568 pub initiated_coop_settle: Option<CoopSettleState>,
569 pub expired_coop_settles: Vec<CoopSettleState>,
570 pub secrethashes_to_lockedlocks: HashMap<SecretHash, HashTimeLockState>,
571 pub secrethashes_to_unlockedlocks: HashMap<SecretHash, UnlockPartialProofState>,
572 pub secrethashes_to_onchain_unlockedlocks: HashMap<SecretHash, UnlockPartialProofState>,
573 pub balance_proof: Option<BalanceProofState>,
574 pub pending_locks: PendingLocksState,
575 pub onchain_locksroot: Locksroot,
576 pub nonce: Nonce,
577}
578
579impl ChannelEndState {
580 pub fn new(address: Address) -> Self {
582 Self {
583 address,
584 contract_balance: TokenAmount::zero(),
585 onchain_total_withdraw: TokenAmount::zero(),
586 withdraws_pending: HashMap::new(),
587 withdraws_expired: vec![],
588 secrethashes_to_lockedlocks: HashMap::new(),
589 secrethashes_to_unlockedlocks: HashMap::new(),
590 secrethashes_to_onchain_unlockedlocks: HashMap::new(),
591 balance_proof: None,
592 pending_locks: PendingLocksState::default(),
593 onchain_locksroot: *LOCKSROOT_OF_NO_LOCKS,
594 nonce: Nonce::zero(),
595 initiated_coop_settle: None,
596 expired_coop_settles: vec![],
597 }
598 }
599
600 pub fn offchain_total_withdraw(&self) -> TokenAmount {
602 self.withdraws_pending
603 .values()
604 .map(|w| w.total_withdraw)
605 .fold(TokenAmount::zero(), max)
606 }
607
608 pub fn total_withdraw(&self) -> TokenAmount {
610 max(self.offchain_total_withdraw(), self.onchain_total_withdraw)
611 }
612
613 pub fn next_nonce(&self) -> Nonce {
615 self.nonce + 1
616 }
617
618 pub fn count_pending_transfers(&self) -> usize {
620 self.pending_locks.locks.len()
621 }
622
623 pub fn locked_amount(&self) -> TokenAmount {
625 let total_pending: TokenAmount = self
626 .secrethashes_to_lockedlocks
627 .values()
628 .map(|lock| lock.amount)
629 .fold(TokenAmount::zero(), |acc, x| acc + x);
630 let total_unclaimed: TokenAmount = self
631 .secrethashes_to_unlockedlocks
632 .values()
633 .map(|unlock| unlock.lock.amount)
634 .fold(TokenAmount::zero(), |acc, x| acc + x);
635 let total_unclaimed_onchain: TokenAmount = self
636 .secrethashes_to_onchain_unlockedlocks
637 .values()
638 .map(|unlock| unlock.lock.amount)
639 .fold(TokenAmount::zero(), |acc, x| acc + x);
640 total_pending + total_unclaimed + total_unclaimed_onchain
641 }
642
643 pub fn get_current_balanceproof(&self) -> BalanceProofData {
645 match &self.balance_proof {
646 Some(bp) => (bp.locksroot, bp.nonce, bp.transferred_amount, bp.locked_amount),
647 None =>
648 (*LOCKSROOT_OF_NO_LOCKS, Nonce::default(), TokenAmount::zero(), TokenAmount::zero()),
649 }
650 }
651
652 pub fn is_valid_amount(&self, amount: TokenAmount) -> bool {
654 let (_, _, transferred_amount, locked_amount) = self.get_current_balanceproof();
655 let transferred_amount_after_unlock =
656 transferred_amount.checked_add(locked_amount).map(|r| r.saturating_add(amount));
657 transferred_amount_after_unlock.is_some()
658 }
659
660 pub fn is_secret_known(&self, secrethash: SecretHash) -> bool {
662 self.is_secret_known_offchain(secrethash) || self.secret_known_onchain(secrethash)
663 }
664
665 pub fn secret_known_onchain(&self, secrethash: SecretHash) -> bool {
667 self.secrethashes_to_onchain_unlockedlocks.contains_key(&secrethash)
668 }
669
670 pub fn is_secret_known_offchain(&self, secrethash: SecretHash) -> bool {
672 self.secrethashes_to_unlockedlocks.contains_key(&secrethash) ||
673 self.secrethashes_to_onchain_unlockedlocks.contains_key(&secrethash)
674 }
675
676 pub fn get_secret(&self, secrethash: SecretHash) -> Option<Secret> {
678 let mut partial_unlock_proof = self.secrethashes_to_unlockedlocks.get(&secrethash);
679 if partial_unlock_proof.is_none() {
680 partial_unlock_proof = self.secrethashes_to_onchain_unlockedlocks.get(&secrethash);
681 }
682
683 if let Some(partial_unlock_proof) = partial_unlock_proof {
684 return Some(partial_unlock_proof.secret.clone())
685 }
686
687 None
688 }
689}
690
691#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
694pub struct BalanceProofState {
695 pub nonce: Nonce,
696 pub transferred_amount: TokenAmount,
697 pub locked_amount: LockedAmount,
698 pub locksroot: Locksroot,
699 pub canonical_identifier: CanonicalIdentifier,
700 pub balance_hash: BalanceHash,
701 pub message_hash: Option<MessageHash>,
702 pub signature: Option<Signature>,
703 pub sender: Option<Address>,
704}
705
706#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
708pub struct PendingLocksState {
709 pub locks: Vec<EncodedLock>,
710}
711
712#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
714pub struct UnlockPartialProofState {
715 pub lock: HashTimeLockState,
716 pub secret: Secret,
717 pub amount: TokenAmount,
718 pub expiration: BlockExpiration,
719 pub secrethash: SecretHash,
720 pub encoded: EncodedLock,
721}
722
723#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
725pub struct HashTimeLockState {
726 pub amount: TokenAmount,
727 pub expiration: BlockExpiration,
728 pub secrethash: SecretHash,
729 pub encoded: EncodedLock,
730}
731
732impl HashTimeLockState {
733 pub fn create(
735 amount: TokenAmount,
736 expiration: BlockExpiration,
737 secrethash: SecretHash,
738 ) -> Self {
739 let mut data = expiration.to_be_bytes();
740 data.extend_from_slice(&amount.to_bytes());
741 data.extend_from_slice(secrethash.as_bytes());
742 Self { amount, expiration, secrethash, encoded: Bytes(data) }
743 }
744}
745
746#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
748pub struct ExpiredWithdrawState {
749 pub total_withdraw: TokenAmount,
750 pub expiration: BlockExpiration,
751 pub nonce: Nonce,
752 pub recipient_metadata: Option<AddressMetadata>,
753}
754
755#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
757pub struct PendingWithdrawState {
758 pub total_withdraw: TokenAmount,
759 pub expiration: BlockExpiration,
760 pub nonce: Nonce,
761 pub recipient_metadata: Option<AddressMetadata>,
762}
763
764impl PendingWithdrawState {
765 pub fn expiration_threshold(&self) -> BlockExpiration {
767 self.expiration
768 .saturating_add(DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS.saturating_mul(2).into())
769 .into()
770 }
771
772 pub fn has_expired(&self, current_block: BlockNumber) -> bool {
774 let threshold = self.expiration_threshold();
775 current_block >= threshold
776 }
777}
778
779#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
781pub struct CoopSettleState {
782 pub total_withdraw_initiator: TokenAmount,
783 pub total_withdraw_partner: TokenAmount,
784 pub expiration: BlockExpiration,
785 pub partner_signature_request: Option<Signature>,
786 pub partner_signature_confirmation: Option<Signature>,
787 pub transaction: Option<TransactionExecutionStatus>,
788}
789
790#[derive(Clone, Default, Debug, Eq, PartialEq)]
792pub struct Interpolate {
793 pub(crate) x_list: Vec<Rational>,
795 pub(crate) y_list: Vec<Rational>,
797 pub(crate) slopes: Vec<Rational>,
799}
800
801impl Interpolate {
802 pub fn new(x_list: Vec<Rational>, y_list: Vec<Rational>) -> Result<Self, String> {
803 for (x, y) in x_list.iter().zip(x_list[1..].iter()) {
804 let result = (y - x).complete();
805 if result <= 0 {
806 return Err("x_list must be in strictly ascending order".to_owned())
807 }
808 }
809 let intervals: Vec<_> = izip!(&x_list, &x_list[1..], &y_list, &y_list[1..]).collect();
810 let slopes = intervals
811 .into_iter()
812 .map(|(x1, x2, y1, y2)| ((y2 - y1).complete() / (x2 - x1).complete()))
813 .collect();
814
815 Ok(Self { x_list, y_list, slopes })
816 }
817
818 pub fn calculate(&self, x: Rational) -> Result<Rational, String> {
819 let last_x = self.x_list[self.x_list.len() - 1].clone();
820 let last_y = self.y_list[self.y_list.len() - 1].clone();
821 if !(self.x_list[0] <= x && x <= last_x) {
822 return Err("x out of bounds".to_owned())
823 }
824
825 if x == last_x {
826 return Ok(last_y)
827 }
828 let i = bisection::bisect_right(&self.x_list, &x) - 1;
829 Ok(self.y_list[i].clone() + (self.slopes[i].clone() * (x - self.x_list[i].clone())))
830 }
831}
832
833#[derive(Serialize, Deserialize, Clone, Default, Debug, Eq, PartialEq)]
835pub struct FeeScheduleState {
836 pub cap_fees: bool,
837 #[serde(serialize_with = "u256_to_str")]
838 pub flat: U256,
839 #[serde(serialize_with = "u256_to_str")]
840 pub proportional: U256,
841 pub imbalance_penalty: Option<Vec<(U256, U256)>>,
842 #[serde(skip)]
843 pub penalty_func: Option<Interpolate>,
844}
845
846impl FeeScheduleState {
847 pub fn update_penalty_func(&mut self) {
849 if let Some(imbalance_penalty) = &self.imbalance_penalty {
850 let x_list =
851 imbalance_penalty.iter().map(|(x, _)| Rational::from(x.as_u128())).collect();
852 let y_list =
853 imbalance_penalty.iter().map(|(_, y)| Rational::from(y.as_u128())).collect();
854 self.penalty_func = Interpolate::new(x_list, y_list).ok();
855 }
856 }
857
858 pub fn fee(&self, balance: Rational, amount: Rational) -> Result<Rational, String> {
860 let flat = Rational::from(self.flat.as_u128());
861 let proportional = Rational::from((self.proportional.as_u128(), 1000000));
862 let value = flat + (proportional * amount.clone());
863 let addition = if let Some(penalty_func) = &self.penalty_func {
864 penalty_func.calculate(balance.clone() + amount)? - penalty_func.calculate(balance)?
865 } else {
866 Rational::from(0)
867 };
868 Ok(value + addition)
869 }
870
871 #[allow(clippy::too_many_arguments)]
873 pub fn mediation_fee_func(
874 mut schedule_in: Self,
875 mut schedule_out: Self,
876 balance_in: TokenAmount,
877 balance_out: TokenAmount,
878 receivable: TokenAmount,
879 amount_with_fees: Option<TokenAmount>,
880 amount_without_fees: Option<TokenAmount>,
881 cap_fees: bool,
882 ) -> Result<Interpolate, String> {
883 if amount_with_fees.is_none() && amount_without_fees.is_none() {
884 return Err(
885 "Must be called with either amount_with_fees or amount_without_fees".to_owned()
886 )
887 }
888
889 if balance_out.is_zero() && receivable.is_zero() {
890 return Err("Undefined mediation fee".to_owned())
891 }
892
893 if schedule_in.penalty_func.is_none() {
894 let total = balance_in + receivable;
895 schedule_in.penalty_func = Some(Interpolate::new(
896 vec![Rational::from(0), Rational::from(total.as_u128())],
897 vec![Rational::from(0), Rational::from(0)],
898 )?);
899 }
900 if schedule_out.penalty_func.is_none() {
901 schedule_out.penalty_func = Some(Interpolate::new(
902 vec![Rational::from(0), Rational::from(balance_out.as_u128())],
903 vec![Rational::from(0), Rational::from(0)],
904 )?)
905 }
906 let max_x = if amount_with_fees.is_none() { receivable } else { balance_out };
907 let mut x_list = Self::calculate_x_values(
908 schedule_in.penalty_func.clone().expect("penalty_func set above"),
909 schedule_out.penalty_func.clone().expect("penalty_func set above"),
910 balance_in,
911 balance_out,
912 max_x,
913 );
914
915 let mut y_list = vec![];
916 for x in x_list.iter() {
917 let add_in = if let Some(amount) = amount_with_fees {
918 Rational::from(amount.as_u128())
919 } else {
920 x.clone()
921 };
922 let add_out = if let Some(amount) = amount_without_fees {
923 -Rational::from(amount.as_u128())
924 } else {
925 (-x).complete()
926 };
927
928 let fee_in = schedule_in.fee(Rational::from(balance_in.as_u128()), add_in)?;
929 let fee_out = schedule_out.fee(Rational::from(balance_out.as_u128()), add_out)?;
930
931 let y = fee_in + fee_out;
932 y_list.push(y);
933 }
934 if cap_fees {
935 (x_list, y_list) = Self::cap_fees(x_list, y_list);
936 }
937 Interpolate::new(x_list, y_list)
938 }
939
940 fn calculate_x_values(
942 penalty_func_in: Interpolate,
943 penalty_func_out: Interpolate,
944 balance_in: TokenAmount,
945 balance_out: TokenAmount,
946 max_x: TokenAmount,
947 ) -> Vec<Rational> {
948 let balance_in = Rational::from(balance_in.as_u128());
949 let balance_out = Rational::from(balance_out.as_u128());
950 let max_x = Rational::from(max_x.as_u128());
951 let all_x_values: Vec<Rational> = penalty_func_in
952 .x_list
953 .iter()
954 .map(|x| (x - balance_in.clone()))
955 .chain(penalty_func_out.x_list.iter().map(|x| balance_out.clone() - x))
956 .collect();
957 let mut all_x_values = all_x_values
958 .into_iter()
959 .map(|x| x.min(balance_out.clone()).min(max_x.clone()).max(Rational::from(0)))
960 .collect::<Vec<_>>();
961 all_x_values.sort();
962 all_x_values.dedup();
963 all_x_values
964 }
965
966 fn cap_fees(x_list: Vec<Rational>, y_list: Vec<Rational>) -> (Vec<Rational>, Vec<Rational>) {
968 let mut x_list = x_list;
969 let mut y_list = y_list;
970 for i in 0..x_list.len() - 1 {
971 let y1 = y_list[i].clone();
972 let y2 = y_list[i + 2].clone();
973 if Self::sign(&y1) * Self::sign(&y2) == -1 {
974 let x1 = x_list[i].clone();
975 let x2 = x_list[i + 2].clone();
976 let new_x = x1.clone() + y1.clone().abs() / (y2 - y1).abs() * (x2 - x1);
977 let new_index = bisection::bisect(&x_list, &new_x);
978 x_list.insert(new_index, new_x);
979 y_list.insert(new_index, Rational::from(0));
980 }
981 }
982 let y_list = y_list.into_iter().map(|y| y.max(Rational::from(0))).collect();
983 (x_list, y_list)
984 }
985
986 fn sign(x: &Rational) -> i8 {
988 if x == &Rational::from(0) {
989 return 0
990 }
991 if x < &Rational::from(0) {
992 return -1
993 }
994 1
995 }
996}
997
998#[derive(Serialize, Deserialize, Clone, Debug)]
1000pub struct TransactionChannelDeposit {
1001 pub participant_address: Address,
1002 pub contract_balance: TokenAmount,
1003 pub deposit_block_number: BlockNumber,
1004}
1005
1006#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
1008pub struct HopState {
1009 pub node_address: Address,
1010 pub channel_identifier: ChannelIdentifier,
1011}
1012
1013#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
1015pub struct RouteState {
1016 pub route: Vec<Address>,
1017 pub address_to_metadata: HashMap<Address, AddressMetadata>,
1018 pub swaps: HashMap<Address, Address>,
1019 pub estimated_fee: TokenAmount,
1020}
1021
1022impl RouteState {
1023 pub fn hop_after(&self, address: Address) -> Option<Address> {
1025 if let Some(index) = self.route.iter().position(|route| route == &address) {
1026 if index + 1 < self.route.len() {
1027 return Some(self.route[index + 1])
1028 }
1029 }
1030
1031 None
1032 }
1033}
1034
1035#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
1038pub struct TransferDescriptionWithSecretState {
1039 pub token_network_registry_address: TokenNetworkRegistryAddress,
1040 pub payment_identifier: PaymentIdentifier,
1041 pub amount: TokenAmount,
1042 pub token_network_address: TokenNetworkAddress,
1043 pub initiator: Address,
1044 pub target: Address,
1045 pub secret: Secret,
1046 pub secrethash: SecretHash,
1047 pub lock_timeout: Option<BlockTimeout>,
1048}
1049
1050#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
1052pub struct LockedTransferState {
1053 pub payment_identifier: PaymentIdentifier,
1054 pub token: Address,
1055 pub lock: HashTimeLockState,
1056 pub initiator: Address,
1057 pub target: Address,
1058 pub message_identifier: MessageIdentifier,
1059 pub route_states: Vec<RouteState>,
1060 pub balance_proof: BalanceProofState,
1061 pub secret: Option<Secret>,
1062}
1063
1064#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
1066pub struct PFSUpdate {
1067 pub canonical_identifier: CanonicalIdentifier,
1068 pub update_fee_schedule: bool,
1069}