1#![warn(clippy::missing_docs_in_private_items)]
2
3use std::iter;
4
5use num_traits::ToPrimitive;
6use raiden_primitives::{
7 constants::CANONICAL_IDENTIFIER_UNORDERED_QUEUE,
8 hashing::hash_secret,
9 types::{
10 Address,
11 BlockExpiration,
12 BlockHash,
13 BlockNumber,
14 BlockTimeout,
15 CanonicalIdentifier,
16 LockTimeout,
17 Secret,
18 SecretHash,
19 TokenAmount,
20 },
21};
22use rug::Rational;
23
24use super::{
25 channel,
26 routes,
27 secret_registry,
28 utils::{
29 self,
30 update_channel,
31 },
32};
33use crate::{
34 constants::{
35 PAYEE_STATE_SECRET_KNOWN,
36 PAYEE_STATE_TRANSFER_FINAL,
37 PAYEE_STATE_TRANSFER_PAID,
38 PAYER_STATE_SECRET_KNOWN,
39 PAYER_STATE_TRANSFER_FINAL,
40 PAYER_STATE_TRANSFER_PAID,
41 },
42 errors::StateTransitionError,
43 types::{
44 ActionInitMediator,
45 Block,
46 ChainState,
47 ChannelState,
48 ChannelStatus,
49 ContractReceiveSecretReveal,
50 ErrorUnexpectedReveal,
51 ErrorUnlockClaimFailed,
52 ErrorUnlockFailed,
53 Event,
54 FeeScheduleState,
55 HashTimeLockState,
56 Interpolate,
57 LockedTransferState,
58 MediationPairState,
59 MediatorTransferState,
60 PayeeState,
61 PayerState,
62 Random,
63 ReceiveLockExpired,
64 ReceiveSecretReveal,
65 ReceiveTransferRefund,
66 ReceiveUnlock,
67 SendMessageEventInner,
68 SendSecretReveal,
69 StateChange,
70 UnlockClaimSuccess,
71 UnlockSuccess,
72 WaitingTransferState,
73 WaitingTransferStatus,
74 },
75 views::{
76 self,
77 get_addresses_to_channels,
78 },
79};
80
81pub(super) type TransitionResult = std::result::Result<MediatorTransition, StateTransitionError>;
83
84#[derive(Debug)]
86pub struct MediatorTransition {
87 pub new_state: Option<MediatorTransferState>,
88 pub chain_state: ChainState,
89 pub events: Vec<Event>,
90}
91
92pub(crate) fn get_channel(
94 chain_state: &ChainState,
95 canonical_identifier: CanonicalIdentifier,
96) -> Option<&ChannelState> {
97 views::get_channel_by_canonical_identifier(chain_state, canonical_identifier)
98}
99
100fn is_send_transfer_almost_equal(
102 send: &LockedTransferState,
103 received: &LockedTransferState,
104) -> bool {
105 send.payment_identifier == received.payment_identifier &&
106 send.token == received.token &&
107 send.lock.expiration == received.lock.expiration &&
108 send.lock.secrethash == received.lock.secrethash &&
109 send.initiator == received.initiator &&
110 send.target == received.target
111}
112
113pub(super) fn is_safe_to_wait(
116 lock_expiration: BlockExpiration,
117 reveal_timeout: BlockTimeout,
118 block_number: BlockNumber,
119) -> Result<(), String> {
120 if lock_expiration < reveal_timeout {
121 return Err("Lock expiration must be larger than reveal timeout".to_owned())
122 }
123 let lock_timeout: LockTimeout = lock_expiration.saturating_sub(block_number.into()).into();
124 if lock_timeout > reveal_timeout {
125 return Ok(())
126 }
127
128 Err(format!(
129 "Lock timeout is unsafe. \
130 Timeout must be larger than {} but it is {}.\
131 expiration: {} block_number {}",
132 reveal_timeout, lock_timeout, lock_expiration, block_number
133 ))
134}
135
136fn find_intersection<LineFunc>(fee_func: Interpolate, line: LineFunc) -> Option<Rational>
144where
145 LineFunc: Fn(usize) -> Rational,
146{
147 let mut i = 0;
148 let mut y = fee_func.y_list[i].clone();
149 let compare = if y < line(i) { |x, y| -> bool { x < y } } else { |x, y| -> bool { x > y } };
150 while compare(y, line(i)) {
151 i += 1;
152 if i == fee_func.x_list.len() {
153 return None
154 }
155 y = fee_func.y_list[i].clone()
156 }
157
158 let x1 = fee_func.x_list[i - 1].clone();
159 let x2 = fee_func.x_list[i].clone();
160 let yf1 = fee_func.y_list[i - 1].clone();
161 let yf2 = fee_func.y_list[i].clone();
162 let yl1 = line(i - 1);
163 let yl2 = line(i);
164
165 Some((yl1.clone() - yf1.clone()) * (x2 - x1.clone()) / ((yf2 - yf1) - (yl2 - yl1)) + x1)
166}
167
168fn get_amount_without_fees(
170 amount_with_fees: TokenAmount,
171 channel_in: &ChannelState,
172 channel_out: &ChannelState,
173) -> Result<TokenAmount, String> {
174 let balance_in = views::channel_balance(&channel_in.our_state, &channel_in.partner_state);
175 let balance_out = views::channel_balance(&channel_out.our_state, &channel_out.partner_state);
176 let receivable =
177 channel_in.our_total_deposit() + channel_in.partner_total_deposit() - balance_in;
178
179 if channel_in.fee_schedule.cap_fees != channel_out.fee_schedule.cap_fees {
180 return Err(
181 "Both channels must have the same cap_fees setting for the same mediator".to_owned()
182 )
183 }
184
185 let fee_func = FeeScheduleState::mediation_fee_func(
186 channel_in.fee_schedule.clone(),
187 channel_out.fee_schedule.clone(),
188 balance_in,
189 balance_out,
190 receivable,
191 Some(amount_with_fees),
192 None,
193 channel_in.fee_schedule.cap_fees,
194 )?;
195 let amount_with_fees = Rational::from(amount_with_fees.as_u128());
196 if let Some(amount_without_fees) = find_intersection(fee_func.clone(), |i| {
197 amount_with_fees.clone() - fee_func.x_list[i].clone()
198 }) {
199 let amount_without_fees = TokenAmount::from(
200 amount_without_fees
201 .to_u128()
202 .ok_or("Could not convert rational to u128".to_owned())?,
203 );
204 Ok(amount_without_fees)
205 } else {
206 Err("Undefined mediation fee".to_owned())
207 }
208}
209
210fn forward_transfer_pair(
212 chain_state: &mut ChainState,
213 payer_transfer: &LockedTransferState,
214 payer_channel: ChannelState,
215 mut payee_channel: ChannelState,
216 block_number: BlockNumber,
217) -> Result<(Option<MediationPairState>, Vec<Event>), String> {
218 let amount_after_fees =
219 get_amount_without_fees(payer_transfer.lock.amount, &payer_channel, &payee_channel)?;
220 let lock_timeout = payer_transfer.lock.expiration - block_number;
221 let safe_to_use_channel =
222 payee_channel.is_usable_for_mediation(amount_after_fees, lock_timeout);
223 if !safe_to_use_channel {
224 return Ok((None, vec![]))
225 }
226
227 if payee_channel.settle_timeout < lock_timeout {
228 return Err("Settle timeout must be >= lock timeout".to_owned())
229 }
230
231 let message_identifier = chain_state.pseudo_random_number_generator.next();
232 let recipient_address = payee_channel.partner_state.address;
233 let recipient_metadata =
234 views::get_address_metadata(recipient_address, payer_transfer.route_states.clone());
235 let (new_payee_channel, locked_transfer_event) = channel::send_locked_transfer(
236 payee_channel.clone(),
237 payer_transfer.initiator,
238 payer_transfer.target,
239 amount_after_fees,
240 payer_transfer.lock.expiration,
241 payer_transfer.secret.clone(),
242 payer_transfer.lock.secrethash,
243 message_identifier,
244 payer_transfer.payment_identifier,
245 payer_transfer.route_states.clone(),
246 recipient_metadata,
247 )?;
248 payee_channel = new_payee_channel;
249 update_channel(chain_state, payee_channel.clone())?;
250
251 let locked_transfer = locked_transfer_event.transfer.clone();
252 let mediated_events = vec![locked_transfer_event.into()];
253
254 let transfer_pair = MediationPairState {
255 payer_transfer: payer_transfer.clone(),
256 payee_address: payee_channel.partner_state.address,
257 payee_transfer: locked_transfer,
258 payer_state: PayerState::Pending,
259 payee_state: PayeeState::Pending,
260 };
261
262 Ok((Some(transfer_pair), mediated_events))
263}
264
265fn mediate_transfer(
273 mut chain_state: ChainState,
274 mut mediator_state: MediatorTransferState,
275 payer_channel: &ChannelState,
276 payer_transfer: LockedTransferState,
277 block_number: BlockNumber,
278) -> TransitionResult {
279 if Some(payer_channel.partner_state.address) != payer_transfer.balance_proof.sender {
280 return Err(StateTransitionError { msg: "Transfer must be signed by sender".to_owned() })
281 }
282
283 let our_address = payer_channel.our_state.address;
284 let candidate_route_states = routes::filter_acceptable_routes(
293 mediator_state.routes.clone(),
294 mediator_state.refunded_channels.clone(),
295 get_addresses_to_channels(&chain_state),
296 payer_channel.canonical_identifier.token_network_address,
297 our_address,
298 );
299
300 let default_token_network_address = payer_channel.canonical_identifier.token_network_address;
301 for route_state in candidate_route_states {
302 let next_hop = match route_state.hop_after(our_address) {
303 Some(next_hop) => next_hop,
304 None => continue,
305 };
306 let target_token_network =
307 route_state.swaps.get(&our_address).unwrap_or(&default_token_network_address);
308 let payee_channel = match views::get_channel_by_token_network_and_partner(
309 &chain_state,
310 *target_token_network,
311 next_hop,
312 ) {
313 Some(channel) => channel.clone(),
314 None => continue,
315 };
316
317 let (mediation_transfer_pair, mediation_events) = forward_transfer_pair(
318 &mut chain_state,
319 &payer_transfer,
320 payer_channel.clone(),
321 payee_channel,
322 block_number,
323 )
324 .map_err(Into::into)?;
325 if let Some(mediation_transfer_pair) = mediation_transfer_pair {
326 mediator_state.transfers_pair.push(mediation_transfer_pair);
327 return Ok(MediatorTransition {
328 new_state: Some(mediator_state),
329 chain_state,
330 events: mediation_events,
331 })
332 }
333 }
334
335 mediator_state.waiting_transfer = Some(WaitingTransferState {
336 transfer: payer_transfer,
337 status: WaitingTransferStatus::Waiting,
338 });
339 Ok(MediatorTransition { new_state: Some(mediator_state), chain_state, events: vec![] })
340}
341
342fn has_secret_registration_started(
350 channel_states: Vec<&ChannelState>,
351 transfers_pair: &[MediationPairState],
352 secrethash: SecretHash,
353) -> bool {
354 let is_secret_registered_onchain = channel_states
355 .iter()
356 .any(|channel_state| channel_state.partner_state.secret_known_onchain(secrethash));
357
358 let has_pending_transaction = transfers_pair
359 .iter()
360 .any(|pair| pair.payer_state == PayerState::WaitingSecretReveal);
361
362 is_secret_registered_onchain || has_pending_transaction
363}
364
365fn events_to_remove_expired_locks(
370 chain_state: &mut ChainState,
371 mediator_state: &mut MediatorTransferState,
372 block_number: BlockNumber,
373) -> Result<Vec<Event>, String> {
374 let mut events = vec![];
375
376 if mediator_state.transfers_pair.is_empty() {
377 return Ok(events)
378 }
379
380 let initial_payer_transfer = mediator_state.transfers_pair[0].payer_transfer.clone();
381 for transfer_pair in mediator_state.transfers_pair.iter_mut() {
382 let balance_proof = &transfer_pair.payee_transfer.balance_proof;
383 let channel_identifier = balance_proof.canonical_identifier.clone();
384 let channel_state =
385 match views::get_channel_by_canonical_identifier(chain_state, channel_identifier) {
386 Some(channel_state) => channel_state.clone(),
387 None => return Ok(events),
388 };
389
390 let secrethash = mediator_state.secrethash;
391 let mut lock: Option<HashTimeLockState> = None;
392 if let Some(locked_lock) =
393 channel_state.our_state.secrethashes_to_lockedlocks.get(&secrethash)
394 {
395 if !channel_state.our_state.secrethashes_to_unlockedlocks.contains_key(&secrethash) {
396 lock = Some(locked_lock.clone());
397 }
398 } else if let Some(unlocked_lock) =
399 channel_state.our_state.secrethashes_to_unlockedlocks.get(&secrethash)
400 {
401 lock = Some(unlocked_lock.lock.clone());
402 }
403
404 if let Some(lock) = lock {
405 let lock_expiration_threshold =
406 channel::views::get_sender_expiration_threshold(lock.expiration);
407 let has_lock_expired = channel::validators::is_lock_expired(
408 &channel_state.our_state,
409 &lock,
410 block_number,
411 lock_expiration_threshold,
412 )
413 .is_ok();
414 let is_channel_open = channel_state.status() == ChannelStatus::Opened;
415 let payee_address_metadata = views::get_address_metadata(
416 transfer_pair.payee_address,
417 initial_payer_transfer.route_states.clone(),
418 );
419
420 if has_lock_expired && is_channel_open {
421 transfer_pair.payee_state = PayeeState::Expired;
422 let (channel_state, expired_lock_events) = channel::send_lock_expired(
423 channel_state,
424 lock,
425 &mut chain_state.pseudo_random_number_generator,
426 payee_address_metadata,
427 )?;
428 utils::update_channel(chain_state, channel_state)?;
429 events.extend(expired_lock_events.into_iter().map(Event::SendLockExpired));
430 events.push(
431 ErrorUnlockFailed {
432 identifier: transfer_pair.payee_transfer.payment_identifier,
433 secrethash,
434 reason: "Lock expired".to_owned(),
435 }
436 .into(),
437 )
438 }
439 }
440 }
441
442 Ok(events)
443}
444
445fn events_for_secret_reveal(
468 transfers_pair: &mut [MediationPairState],
469 secret: Secret,
470 pseudo_random_number_generator: &mut Random,
471) -> Vec<Event> {
472 let mut events = vec![];
473
474 for pair in transfers_pair.iter_mut().rev() {
475 let payee_knows_secret = PAYEE_STATE_SECRET_KNOWN.contains(&pair.payee_state);
476 let payer_knows_secret = PAYER_STATE_SECRET_KNOWN.contains(&pair.payer_state);
477 let is_transfer_pending = pair.payer_state == PayerState::Pending;
478 let should_send_secret = payee_knows_secret && !payer_knows_secret && is_transfer_pending;
479
480 if should_send_secret {
481 let message_identifier = pseudo_random_number_generator.next();
482 pair.payer_state = PayerState::SecretRevealed;
483 let payer_transfer = &pair.payer_transfer;
484 let recipient = payer_transfer.balance_proof.sender.expect("Should be set");
485 let reveal_secret = SendSecretReveal {
486 inner: SendMessageEventInner {
487 recipient,
488 recipient_metadata: views::get_address_metadata(
489 recipient,
490 payer_transfer.route_states.clone(),
491 ),
492 canonical_identifier: CANONICAL_IDENTIFIER_UNORDERED_QUEUE,
493 message_identifier,
494 },
495 secret: secret.clone(),
496 secrethash: SecretHash::from_slice(&hash_secret(&secret.0)),
497 };
498 events.push(reveal_secret.into());
499 }
500 }
501
502 events
503}
504
505fn events_for_balance_proof(
507 chain_state: &mut ChainState,
508 transfers_pair: &mut [MediationPairState],
509 secret: Secret,
510 secrethash: SecretHash,
511) -> Vec<Event> {
512 let mut events = vec![];
513
514 for pair in transfers_pair.iter_mut().rev() {
515 let payee_knows_secret = PAYEE_STATE_SECRET_KNOWN.contains(&pair.payee_state);
516 let payee_paid = PAYEE_STATE_TRANSFER_PAID.contains(&pair.payee_state);
517
518 let mut payee_channel = match get_channel(
519 chain_state,
520 pair.payee_transfer.balance_proof.canonical_identifier.clone(),
521 ) {
522 Some(payee_channel) => payee_channel.clone(),
523 None => continue,
524 };
525 let payer_channel = match get_channel(
526 chain_state,
527 pair.payer_transfer.balance_proof.canonical_identifier.clone(),
528 ) {
529 Some(payer_channel) => payer_channel,
530 None => continue,
531 };
532
533 let payee_channel_open = payee_channel.status() == ChannelStatus::Opened;
534
535 let mut is_safe_to_send_balance_proof = false;
541 if is_safe_to_wait(
542 pair.payer_transfer.lock.expiration,
543 payer_channel.reveal_timeout,
544 chain_state.block_number,
545 )
546 .is_ok()
547 {
548 is_safe_to_send_balance_proof = true;
549 }
550
551 let should_send_balance_proof_to_payee = payee_channel_open &&
552 payee_knows_secret &&
553 !payee_paid && is_safe_to_send_balance_proof;
554
555 if should_send_balance_proof_to_payee {
556 pair.payee_state = PayeeState::BalanceProof;
557
558 let message_identifier = chain_state.pseudo_random_number_generator.next();
559 let recipient_address = pair.payee_address;
560 let recipient_metadata = views::get_address_metadata(
561 recipient_address,
562 pair.payee_transfer.route_states.clone(),
563 );
564 if let Ok(unlock_lock) = channel::send_unlock(
565 &mut payee_channel,
566 message_identifier,
567 pair.payee_transfer.payment_identifier,
568 secret.clone(),
569 secrethash,
570 chain_state.block_number,
571 recipient_metadata,
572 ) {
573 let _ = update_channel(chain_state, payee_channel.clone());
574 events.push(unlock_lock.into());
575 events.push(
576 UnlockSuccess {
577 identifier: pair.payer_transfer.payment_identifier,
578 secrethash: pair.payer_transfer.lock.secrethash,
579 }
580 .into(),
581 )
582 }
583 }
584 }
585
586 events
587}
588
589fn events_for_onchain_secretreveal_if_closed(
600 chain_state: &ChainState,
601 transfers_pair: &mut [MediationPairState],
602 secret: Secret,
603 secrethash: SecretHash,
604 block_hash: BlockHash,
605) -> Vec<Event> {
606 let mut events = vec![];
607
608 let mut all_payer_channels = vec![];
609 for transfer_pair in transfers_pair.iter() {
610 if let Some(channel_state) = get_channel(
611 chain_state,
612 transfer_pair.payer_transfer.balance_proof.canonical_identifier.clone(),
613 ) {
614 all_payer_channels.push(channel_state);
615 }
616 }
617
618 let mut transaction_sent =
619 has_secret_registration_started(all_payer_channels, transfers_pair, secrethash);
620
621 let pending_transfers = transfers_pair.iter_mut().filter(|pair| {
622 !PAYEE_STATE_TRANSFER_FINAL.contains(&pair.payee_state) ||
623 !PAYER_STATE_TRANSFER_FINAL.contains(&pair.payer_state)
624 });
625 for pending_pair in pending_transfers {
626 let payer_channel = match get_channel(
627 chain_state,
628 pending_pair.payer_transfer.balance_proof.canonical_identifier.clone(),
629 ) {
630 Some(payer_channel) => payer_channel,
631 None => continue,
632 };
633
634 if payer_channel.status() == ChannelStatus::Closed {
635 pending_pair.payer_state = PayerState::WaitingSecretReveal;
636
637 if !transaction_sent {
638 if let Some(lock) =
639 channel::views::get_lock(&payer_channel.partner_state, secrethash)
640 {
641 let reveal_events = secret_registry::events_for_onchain_secretreveal(
642 payer_channel,
643 secret.clone(),
644 lock.expiration,
645 block_hash,
646 );
647
648 events.extend(reveal_events);
649 transaction_sent = true;
650 }
651 }
652 }
653 }
654
655 events
656}
657
658fn events_for_onchain_secretreveal_if_dangerzone(
661 chain_state: &ChainState,
662 transfers_pair: &mut [MediationPairState],
663 secrethash: SecretHash,
664 block_number: BlockNumber,
665 block_hash: BlockHash,
666) -> Result<Vec<Event>, String> {
667 let mut events = vec![];
668
669 let mut all_payer_channels = vec![];
670 for transfer_pair in transfers_pair.iter() {
671 if let Some(channel_state) = get_channel(
672 chain_state,
673 transfer_pair.payer_transfer.balance_proof.canonical_identifier.clone(),
674 ) {
675 all_payer_channels.push(channel_state);
676 }
677 }
678
679 let mut transaction_sent =
680 has_secret_registration_started(all_payer_channels, transfers_pair, secrethash);
681
682 let pending_transfers = transfers_pair.iter_mut().filter(|pair| {
689 !PAYEE_STATE_TRANSFER_FINAL.contains(&pair.payee_state) ||
690 !PAYER_STATE_TRANSFER_FINAL.contains(&pair.payer_state)
691 });
692 for pair in pending_transfers {
693 let payer_channel = match get_channel(
694 chain_state,
695 pair.payer_transfer.balance_proof.canonical_identifier.clone(),
696 ) {
697 Some(payer_channel) => payer_channel,
698 None => continue,
699 };
700
701 let lock = &pair.payer_transfer.lock;
702 let safe_to_wait =
703 is_safe_to_wait(lock.expiration, payer_channel.reveal_timeout, block_number).is_ok();
704 let secret_known =
705 payer_channel.partner_state.is_secret_known(pair.payer_transfer.lock.secrethash);
706
707 if !safe_to_wait && secret_known {
708 pair.payer_state = PayerState::WaitingSecretReveal;
709
710 if !transaction_sent {
711 let secret = match payer_channel.partner_state.get_secret(lock.secrethash) {
712 Some(secret) => secret,
713 None => return Err("The secret should be known at this point".to_owned()),
714 };
715
716 let reveal_events = secret_registry::events_for_onchain_secretreveal(
717 payer_channel,
718 secret,
719 lock.expiration,
720 block_hash,
721 );
722
723 events.extend(reveal_events);
724
725 transaction_sent = true;
726 }
727 }
728 }
729
730 Ok(events)
731}
732
733fn events_for_expired_pairs(
735 chain_state: &ChainState,
736 transfers_pair: &mut [MediationPairState],
737 waiting_transfer: &mut Option<WaitingTransferState>,
738 block_number: BlockNumber,
739) -> Vec<Event> {
740 let mut events = vec![];
741
742 let pending_transfers = transfers_pair.iter_mut().filter(|pair| {
743 !PAYEE_STATE_TRANSFER_FINAL.contains(&pair.payee_state) ||
744 !PAYER_STATE_TRANSFER_FINAL.contains(&pair.payer_state)
745 });
746 for pair in pending_transfers {
747 let payer_channel = match get_channel(
748 chain_state,
749 pair.payer_transfer.balance_proof.canonical_identifier.clone(),
750 ) {
751 Some(payer_channel) => payer_channel,
752 None => continue,
753 };
754 let has_payer_transfer_expired = channel::validators::is_transfer_expired(
755 &pair.payer_transfer,
756 payer_channel,
757 block_number,
758 );
759
760 if has_payer_transfer_expired {
761 pair.payer_state = PayerState::Expired;
762 let unlock_claim_failed = ErrorUnlockClaimFailed {
763 identifier: pair.payer_transfer.payment_identifier,
764 secrethash: pair.payer_transfer.lock.secrethash,
765 reason: "Lock expired".to_owned(),
766 };
767 events.push(unlock_claim_failed.into());
768 }
769 }
770
771 if let Some(waiting_transfer) = waiting_transfer {
772 let expiration_threshold = channel::views::get_receiver_expiration_threshold(
773 waiting_transfer.transfer.lock.expiration,
774 );
775 let should_waiting_transfer_expire = waiting_transfer.status !=
776 WaitingTransferStatus::Expired &&
777 expiration_threshold <= block_number;
778 if should_waiting_transfer_expire {
779 waiting_transfer.status = WaitingTransferStatus::Expired;
780
781 let unlock_claim_failed = ErrorUnlockClaimFailed {
782 identifier: waiting_transfer.transfer.payment_identifier,
783 secrethash: waiting_transfer.transfer.lock.secrethash,
784 reason: "Lock expired".to_owned(),
785 };
786 events.push(unlock_claim_failed.into());
787 }
788 }
789
790 events
791}
792
793fn set_offchain_secret(
795 chain_state: &mut ChainState,
796 mediator_state: &mut MediatorTransferState,
797 secret: Secret,
798 secrethash: SecretHash,
799) -> Vec<Event> {
800 mediator_state.secret = Some(secret.clone());
801
802 for pair in &mediator_state.transfers_pair {
803 if let Some(payer_channel) =
804 get_channel(chain_state, pair.payer_transfer.balance_proof.canonical_identifier.clone())
805 {
806 let mut payer_channel = payer_channel.clone();
807 channel::register_offchain_secret(&mut payer_channel, secret.clone(), secrethash);
808 let _ = update_channel(chain_state, payer_channel);
809 }
810 if let Some(payee_channel) =
811 get_channel(chain_state, pair.payee_transfer.balance_proof.canonical_identifier.clone())
812 {
813 let mut payee_channel = payee_channel.clone();
814 channel::register_offchain_secret(&mut payee_channel, secret.clone(), secrethash);
815 let _ = update_channel(chain_state, payee_channel);
816 }
817 }
818 if let Some(waiting_transfer) = &mediator_state.waiting_transfer {
827 if let Some(payer_channel) = get_channel(
828 chain_state,
829 waiting_transfer.transfer.balance_proof.canonical_identifier.clone(),
830 ) {
831 let mut payer_channel = payer_channel.clone();
832 channel::register_offchain_secret(&mut payer_channel, secret, secrethash);
833 let _ = update_channel(chain_state, payer_channel);
834
835 let unexpected_reveal = ErrorUnexpectedReveal {
836 secrethash,
837 reason: "The mediator has a waiting transfer".to_owned(),
838 };
839
840 return vec![unexpected_reveal.into()]
841 }
842 }
843
844 vec![]
845}
846
847fn set_offchain_reveal_state(transfers_pair: &mut Vec<MediationPairState>, payee_address: Address) {
849 for pair in transfers_pair {
850 if pair.payee_address == payee_address {
851 pair.payee_state = PayeeState::SecretRevealed;
852 }
853 }
854}
855
856fn set_onchain_secret(
859 chain_state: &mut ChainState,
860 mediator_state: &mut MediatorTransferState,
861 secret: Secret,
862 secrethash: SecretHash,
863 block_number: BlockNumber,
864) -> Vec<Event> {
865 mediator_state.secret = Some(secret.clone());
866
867 for pair in &mediator_state.transfers_pair {
868 if let Some(payer_channel) =
869 get_channel(chain_state, pair.payer_transfer.balance_proof.canonical_identifier.clone())
870 {
871 let mut payer_channel = payer_channel.clone();
872 channel::register_onchain_secret(
873 &mut payer_channel,
874 secret.clone(),
875 secrethash,
876 block_number,
877 true,
878 );
879 let _ = update_channel(chain_state, payer_channel);
880 }
881 if let Some(payee_channel) =
882 get_channel(chain_state, pair.payee_transfer.balance_proof.canonical_identifier.clone())
883 {
884 let mut payee_channel = payee_channel.clone();
885 channel::register_onchain_secret(
886 &mut payee_channel,
887 secret.clone(),
888 secrethash,
889 block_number,
890 true,
891 );
892 let _ = update_channel(chain_state, payee_channel);
893 }
894 }
895
896 if let Some(waiting_transfer) = &mediator_state.waiting_transfer {
899 if let Some(payer_channel) = get_channel(
900 chain_state,
901 waiting_transfer.transfer.balance_proof.canonical_identifier.clone(),
902 ) {
903 let mut payer_channel = payer_channel.clone();
904 channel::register_onchain_secret(
905 &mut payer_channel,
906 secret,
907 secrethash,
908 block_number,
909 true,
910 );
911 let _ = update_channel(chain_state, payer_channel);
912
913 let unexpected_reveal = ErrorUnexpectedReveal {
914 secrethash,
915 reason: "The mediator has a waiting transfer".to_owned(),
916 };
917
918 return vec![unexpected_reveal.into()]
919 }
920 }
921
922 vec![]
923}
924
925fn secret_learned(
928 mut chain_state: ChainState,
929 mut mediator_state: MediatorTransferState,
930 secret: Secret,
931 secrethash: SecretHash,
932 payee_address: Address,
933) -> TransitionResult {
934 let secret_reveal_events =
935 set_offchain_secret(&mut chain_state, &mut mediator_state, secret.clone(), secrethash);
936 set_offchain_reveal_state(&mut mediator_state.transfers_pair, payee_address);
937
938 let block_hash = chain_state.block_hash;
939 let onchain_secret_reveal = events_for_onchain_secretreveal_if_closed(
940 &chain_state,
941 &mut mediator_state.transfers_pair,
942 secret.clone(),
943 secrethash,
944 block_hash,
945 );
946
947 let offchain_secret_reveal = events_for_secret_reveal(
948 &mut mediator_state.transfers_pair,
949 secret.clone(),
950 &mut chain_state.pseudo_random_number_generator,
951 );
952
953 let balance_proof = events_for_balance_proof(
954 &mut chain_state,
955 &mut mediator_state.transfers_pair,
956 secret,
957 secrethash,
958 );
959
960 let mut events = vec![];
961 events.extend(secret_reveal_events);
962 events.extend(onchain_secret_reveal);
963 events.extend(offchain_secret_reveal);
964 events.extend(balance_proof);
965
966 Ok(MediatorTransition { new_state: Some(mediator_state), chain_state, events })
967}
968
969fn handle_block(
972 chain_state: ChainState,
973 mediator_state: Option<MediatorTransferState>,
974 state_change: Block,
975) -> TransitionResult {
976 let mediator_state = match mediator_state {
977 Some(mediator_state) => mediator_state,
978 None =>
979 return Err("Block should be accompanied by a valid mediator state".to_owned().into()),
980 };
981 let mut events = vec![];
982
983 let mut new_mediator_state = mediator_state;
984 let mut new_chain_state = chain_state;
985 if let Some(waiting_transfer) = new_mediator_state.waiting_transfer.clone() {
986 let secrethash = waiting_transfer.transfer.lock.secrethash;
987 let payer_channel_identifier =
988 waiting_transfer.transfer.balance_proof.canonical_identifier.clone();
989
990 if let Some(payer_channel) = views::get_channel_by_canonical_identifier(
991 &new_chain_state.clone(),
992 payer_channel_identifier,
993 ) {
994 let mediation_attempt = mediate_transfer(
995 new_chain_state.clone(),
996 new_mediator_state.clone(),
997 payer_channel,
998 waiting_transfer.transfer,
999 state_change.block_number,
1000 )?;
1001
1002 if let Some(mut mediator_state) = mediation_attempt.new_state {
1003 events.extend(mediation_attempt.events);
1004
1005 let mediation_happened = events.iter().any(|event| {
1006 if let Event::SendLockedTransfer(e) = event {
1007 return e.transfer.lock.secrethash == secrethash
1008 }
1009 false
1010 });
1011 if mediation_happened {
1012 mediator_state.waiting_transfer = None;
1013 }
1014 new_mediator_state = mediator_state;
1015 new_chain_state = mediation_attempt.chain_state;
1016 }
1017 }
1018 }
1019
1020 events.extend(
1021 events_to_remove_expired_locks(
1022 &mut new_chain_state,
1023 &mut new_mediator_state,
1024 state_change.block_number,
1025 )
1026 .map_err(Into::into)?,
1027 );
1028 events.extend(
1029 events_for_onchain_secretreveal_if_dangerzone(
1030 &new_chain_state,
1031 &mut new_mediator_state.transfers_pair,
1032 new_mediator_state.secrethash,
1033 state_change.block_number,
1034 state_change.block_hash,
1035 )
1036 .map_err(Into::into)?,
1037 );
1038 events.extend(events_for_expired_pairs(
1039 &new_chain_state,
1040 &mut new_mediator_state.transfers_pair,
1041 &mut new_mediator_state.waiting_transfer,
1042 state_change.block_number,
1043 ));
1044
1045 Ok(MediatorTransition {
1046 new_state: Some(new_mediator_state),
1047 chain_state: new_chain_state,
1048 events,
1049 })
1050}
1051
1052fn handle_init(mut chain_state: ChainState, state_change: ActionInitMediator) -> TransitionResult {
1054 let from_transfer = state_change.from_transfer;
1055 let mut payer_channel =
1056 match get_channel(&chain_state, from_transfer.balance_proof.canonical_identifier.clone()) {
1057 Some(channel) => channel.clone(),
1058 None => return Ok(MediatorTransition { new_state: None, chain_state, events: vec![] }),
1059 };
1060
1061 let mediator_state = MediatorTransferState {
1062 secrethash: from_transfer.lock.secrethash,
1063 routes: state_change.candidate_route_states,
1064 refunded_channels: vec![],
1065 secret: None,
1066 transfers_pair: vec![],
1067 waiting_transfer: None,
1068 };
1069
1070 let mut events = vec![];
1071 let payer_address_metadata = match from_transfer.balance_proof.sender {
1072 Some(sender) => views::get_address_metadata(sender, from_transfer.route_states.clone()),
1073 None => None,
1074 };
1075 match channel::handle_receive_locked_transfer(
1076 &mut payer_channel,
1077 from_transfer.clone(),
1078 payer_address_metadata,
1079 ) {
1080 Ok(locked_transfer_event) => {
1081 utils::update_channel(&mut chain_state, payer_channel.clone()).map_err(Into::into)?;
1082 events.push(locked_transfer_event);
1083 },
1084 Err((_error, locked_transfer_error_events)) =>
1085 return Ok(MediatorTransition {
1086 new_state: Some(mediator_state),
1087 chain_state,
1088 events: locked_transfer_error_events,
1089 }),
1090 };
1091
1092 let block_number = chain_state.block_number;
1093 let iteration =
1094 mediate_transfer(chain_state, mediator_state, &payer_channel, from_transfer, block_number)?;
1095 events.extend(iteration.events);
1096
1097 Ok(MediatorTransition {
1098 new_state: iteration.new_state,
1099 chain_state: iteration.chain_state,
1100 events,
1101 })
1102}
1103
1104fn handle_refund_transfer(
1114 mut chain_state: ChainState,
1115 mediator_state: Option<MediatorTransferState>,
1116 state_change: ReceiveTransferRefund,
1117) -> TransitionResult {
1118 let mut mediator_state = match mediator_state {
1119 Some(mediator_state) => mediator_state,
1120 None =>
1121 return Err("ReceiveTransferRefund should be accompanied by a valid mediator state"
1122 .to_owned()
1123 .into()),
1124 };
1125
1126 if mediator_state.secret.is_none() {
1127 return Ok(MediatorTransition {
1128 new_state: Some(mediator_state),
1129 chain_state,
1130 events: vec![],
1131 })
1132 }
1133
1134 if mediator_state.transfers_pair.is_empty() {
1135 return Ok(MediatorTransition {
1136 new_state: Some(mediator_state),
1137 chain_state,
1138 events: vec![],
1139 })
1140 }
1141
1142 let transfer_pair = mediator_state.transfers_pair.last().expect("Checked above");
1145 let payee_transfer = transfer_pair.payee_transfer.clone();
1146 let payer_transfer = transfer_pair.payer_transfer.clone();
1147 let canonical_identifier = payer_transfer.balance_proof.canonical_identifier.clone();
1148 let mut payer_channel = match get_channel(&chain_state, canonical_identifier) {
1149 Some(channel) => channel.clone(),
1150 None =>
1151 return Ok(MediatorTransition {
1152 new_state: Some(mediator_state),
1153 chain_state,
1154 events: vec![],
1155 }),
1156 };
1157
1158 let refund_transfer_event =
1159 match channel::handle_refund_transfer(&mut payer_channel, payee_transfer, state_change) {
1160 Ok(event) => event,
1161 Err(_) =>
1162 return Ok(MediatorTransition {
1163 new_state: Some(mediator_state),
1164 chain_state,
1165 events: vec![],
1166 }),
1167 };
1168
1169 update_channel(&mut chain_state, payer_channel.clone()).map_err(Into::into)?;
1170 mediator_state
1171 .refunded_channels
1172 .push(payer_channel.canonical_identifier.channel_identifier);
1173
1174 let block_number = chain_state.block_number;
1175 let iteration = mediate_transfer(
1176 chain_state,
1177 mediator_state,
1178 &payer_channel,
1179 payer_transfer,
1180 block_number,
1181 )?;
1182
1183 let mut events = vec![refund_transfer_event];
1184 events.extend(iteration.events);
1185
1186 Ok(MediatorTransition {
1187 new_state: iteration.new_state,
1188 chain_state: iteration.chain_state,
1189 events,
1190 })
1191}
1192
1193fn handle_offchain_secret_reveal(
1195 chain_state: ChainState,
1196 mediator_state: Option<MediatorTransferState>,
1197 state_change: ReceiveSecretReveal,
1198) -> TransitionResult {
1199 let mediator_state = match mediator_state {
1200 Some(mediator_state) => mediator_state,
1201 None =>
1202 return Err("ReceiveSecretReveal should be accompanied by a valid mediator state"
1203 .to_owned()
1204 .into()),
1205 };
1206
1207 let is_valid = utils::is_valid_secret_reveal(&state_change, mediator_state.secrethash);
1208 let is_secret_unknown = mediator_state.secret.is_none();
1209
1210 if mediator_state.transfers_pair.is_empty() {
1211 return Ok(MediatorTransition {
1214 new_state: Some(mediator_state),
1215 chain_state,
1216 events: vec![],
1217 })
1218 }
1219
1220 let transfer_pair = mediator_state.transfers_pair.last().expect("Should exist");
1224 let payer_transfer = &transfer_pair.payer_transfer;
1225 let canonical_identifier = payer_transfer.balance_proof.canonical_identifier.clone();
1226 let payer_channel = match get_channel(&chain_state, canonical_identifier) {
1227 Some(channel) => channel,
1228 None =>
1229 return Ok(MediatorTransition {
1230 new_state: Some(mediator_state),
1231 chain_state,
1232 events: vec![],
1233 }),
1234 };
1235
1236 let has_payer_transfer_expired = channel::validators::is_transfer_expired(
1237 payer_transfer,
1238 payer_channel,
1239 chain_state.block_number,
1240 );
1241
1242 if is_secret_unknown && is_valid && !has_payer_transfer_expired {
1243 return secret_learned(
1244 chain_state,
1245 mediator_state,
1246 state_change.secret,
1247 state_change.secrethash,
1248 state_change.sender,
1249 )
1250 }
1251
1252 Ok(MediatorTransition { new_state: Some(mediator_state), chain_state, events: vec![] })
1253}
1254
1255fn handle_onchain_secret_reveal(
1258 mut chain_state: ChainState,
1259 mediator_state: Option<MediatorTransferState>,
1260 state_change: ContractReceiveSecretReveal,
1261) -> TransitionResult {
1262 let mut mediator_state = match mediator_state {
1263 Some(mediator_state) => mediator_state,
1264 None =>
1265 return Err(
1266 "ContractReceiveSecretReveal should be accompanied by a valid mediator state"
1267 .to_owned()
1268 .into(),
1269 ),
1270 };
1271
1272 let mut events = vec![];
1273 if utils::is_valid_onchain_secret_reveal(&state_change, mediator_state.secrethash) {
1274 let secret = state_change.secret;
1275 let block_number = state_change.block_number;
1277
1278 let secret_reveal = set_onchain_secret(
1279 &mut chain_state,
1280 &mut mediator_state,
1281 secret.clone(),
1282 state_change.secrethash,
1283 block_number,
1284 );
1285 let balance_proof = events_for_balance_proof(
1286 &mut chain_state,
1287 &mut mediator_state.transfers_pair,
1288 secret,
1289 state_change.secrethash,
1290 );
1291
1292 events.extend(secret_reveal);
1293 events.extend(balance_proof);
1294 }
1295
1296 Ok(MediatorTransition { new_state: Some(mediator_state), chain_state, events })
1297}
1298
1299fn handle_unlock(
1301 mut chain_state: ChainState,
1302 mediator_state: Option<MediatorTransferState>,
1303 state_change: ReceiveUnlock,
1304) -> TransitionResult {
1305 let mut mediator_state = match mediator_state {
1306 Some(mediator_state) => mediator_state,
1307 None =>
1308 return Err("ReceiveUnlock should be accompanied by a valid mediator state"
1309 .to_owned()
1310 .into()),
1311 };
1312
1313 let mut events = vec![];
1314 let balance_proof_sender = state_change
1315 .balance_proof
1316 .sender
1317 .ok_or("Sender should be set".to_owned().into())?;
1318 let canonical_identifier = &state_change.balance_proof.canonical_identifier;
1319
1320 for pair in mediator_state.transfers_pair.iter_mut() {
1321 if pair.payer_transfer.balance_proof.sender == Some(balance_proof_sender) {
1322 if let Some(channel_state) = get_channel(&chain_state, canonical_identifier.clone()) {
1323 let recipient_metadata = views::get_address_metadata(
1324 balance_proof_sender,
1325 mediator_state.routes.clone(),
1326 );
1327 let mut channel_state = channel_state.clone();
1328
1329 match channel::handle_unlock(
1330 &mut channel_state,
1331 state_change.clone(),
1332 recipient_metadata,
1333 ) {
1334 Ok(handle_unlock_events) => {
1335 let _ = update_channel(&mut chain_state, channel_state);
1336
1337 events.push(handle_unlock_events);
1338
1339 events.push(
1340 UnlockClaimSuccess {
1341 identifier: pair.payee_transfer.payment_identifier,
1342 secrethash: pair.payee_transfer.lock.secrethash,
1343 }
1344 .into(),
1345 );
1346
1347 pair.payer_state = PayerState::BalanceProof;
1348 },
1349 Err((_, event)) => {
1350 events.push(event);
1351 },
1352 }
1353 }
1354 }
1355 }
1356
1357 Ok(MediatorTransition { new_state: Some(mediator_state), chain_state, events })
1358}
1359
1360fn handle_lock_expired(
1362 mut chain_state: ChainState,
1363 mediator_state: Option<MediatorTransferState>,
1364 state_change: ReceiveLockExpired,
1365) -> TransitionResult {
1366 let mut mediator_state = match mediator_state {
1367 Some(mediator_state) => mediator_state,
1368 None =>
1369 return Err("ReceiveLockExpired should be accompanied by a valid mediator state"
1370 .to_owned()
1371 .into()),
1372 };
1373
1374 let mut events = vec![];
1375
1376 for transfer_pair in mediator_state.transfers_pair.iter_mut() {
1377 let balance_proof = &transfer_pair.payer_transfer.balance_proof;
1378 let mut channel_state =
1379 match get_channel(&chain_state, balance_proof.canonical_identifier.clone()) {
1380 Some(channel) => channel.clone(),
1381 None =>
1382 return Ok(MediatorTransition {
1383 new_state: Some(mediator_state),
1384 chain_state,
1385 events: vec![],
1386 }),
1387 };
1388
1389 let recipient_address = channel_state.partner_state.address;
1390 let recipient_metadata =
1391 views::get_address_metadata(recipient_address, mediator_state.routes.clone());
1392 let result = channel::handle_receive_lock_expired(
1393 &mut channel_state,
1394 state_change.clone(),
1395 chain_state.block_number,
1396 recipient_metadata,
1397 )?;
1398 events.extend(result.events);
1399 if let Some(channel_state) = result.new_state {
1400 if channel::views::get_lock(&channel_state.partner_state, mediator_state.secrethash)
1401 .is_some()
1402 {
1403 transfer_pair.payer_state = PayerState::Expired;
1404 }
1405 update_channel(&mut chain_state, channel_state).map_err(Into::into)?;
1406 }
1407 }
1408
1409 if let Some(ref waiting_transfer) = mediator_state.waiting_transfer {
1410 if let Some(waiting_channel) = get_channel(
1411 &chain_state,
1412 waiting_transfer.transfer.balance_proof.canonical_identifier.clone(),
1413 ) {
1414 let mut waiting_channel = waiting_channel.clone();
1415 let recipient_address = waiting_channel.partner_state.address;
1416 let recipient_metadata =
1417 views::get_address_metadata(recipient_address, mediator_state.routes.clone());
1418 let result = channel::handle_receive_lock_expired(
1419 &mut waiting_channel,
1420 state_change,
1421 chain_state.block_number,
1422 recipient_metadata,
1423 )?;
1424 if let Some(waiting_channel_state) = result.new_state {
1425 update_channel(&mut chain_state, waiting_channel_state).map_err(Into::into)?;
1426 }
1427 events.extend(result.events);
1428 }
1429 }
1430
1431 Ok(MediatorTransition { new_state: Some(mediator_state), chain_state, events })
1432}
1433
1434pub fn clear_if_finalized(transition: MediatorTransition) -> MediatorTransition {
1440 let new_state = match transition.new_state {
1441 Some(ref new_state) => new_state,
1442 None => return transition,
1443 };
1444
1445 let secrethash = new_state.secrethash;
1446 for pair in &new_state.transfers_pair {
1447 if let Some(payer_channel) = get_channel(
1448 &transition.chain_state,
1449 pair.payer_transfer.balance_proof.canonical_identifier.clone(),
1450 ) {
1451 if channel::validators::is_lock_pending(&payer_channel.partner_state, secrethash) {
1452 return transition
1453 }
1454 }
1455
1456 if let Some(payee_channel) = get_channel(
1457 &transition.chain_state,
1458 pair.payee_transfer.balance_proof.canonical_identifier.clone(),
1459 ) {
1460 if channel::validators::is_lock_pending(&payee_channel.our_state, secrethash) {
1461 return transition
1462 }
1463 }
1464
1465 if let Some(waiting_transfer_state) = &new_state.waiting_transfer {
1466 let waiting_transfer = &waiting_transfer_state.transfer;
1467 let waiting_channel_identifier =
1468 waiting_transfer.balance_proof.canonical_identifier.clone();
1469 if let Some(waiting_channel) = views::get_channel_by_canonical_identifier(
1470 &transition.chain_state,
1471 waiting_channel_identifier,
1472 ) {
1473 if channel::validators::is_lock_pending(&waiting_channel.partner_state, secrethash)
1474 {
1475 return transition
1476 }
1477 }
1478 }
1479 }
1480
1481 MediatorTransition {
1482 new_state: None,
1483 chain_state: transition.chain_state,
1484 events: transition.events,
1485 }
1486}
1487
1488fn sanity_check(transition: MediatorTransition) -> TransitionResult {
1490 let mediator_state = match transition.new_state {
1491 Some(ref state) => state,
1492 None => return Ok(transition),
1493 };
1494
1495 if mediator_state
1496 .transfers_pair
1497 .iter()
1498 .any(|pair| PAYEE_STATE_TRANSFER_PAID.contains(&pair.payee_state)) &&
1499 mediator_state.secret.is_none()
1500 {
1501 return Err("Mediator state must have secret".to_owned().into())
1502 }
1503 if mediator_state
1504 .transfers_pair
1505 .iter()
1506 .any(|pair| PAYER_STATE_TRANSFER_PAID.contains(&pair.payer_state)) &&
1507 mediator_state.secret.is_none()
1508 {
1509 return Err("Mediator state must have secret".to_owned().into())
1510 }
1511
1512 if !mediator_state.transfers_pair.is_empty() {
1513 let first_pair = &mediator_state.transfers_pair[0];
1514 if mediator_state.secrethash != first_pair.payer_transfer.lock.secrethash {
1515 return Err("Secret hash mismatch".to_owned().into())
1516 }
1517 }
1518
1519 for pair in &mediator_state.transfers_pair {
1520 if !is_send_transfer_almost_equal(&pair.payee_transfer, &pair.payer_transfer) {
1521 return Err("Payee and payer transfers are too different".to_owned().into())
1522 }
1523 }
1524
1525 if mediator_state.transfers_pair.len() <= 2 {
1526 return Ok(transition)
1527 }
1528
1529 let exclude_last = mediator_state.transfers_pair.split_last().expect("Checked above").1;
1530 let exclude_first = mediator_state.transfers_pair.split_first().expect("Checked above").1;
1531 for (original, refund) in iter::zip(exclude_last, exclude_first) {
1532 if Some(original.payee_address) != refund.payer_transfer.balance_proof.sender {
1533 return Err("Payee/payer address mismatch".to_owned().into())
1534 }
1535
1536 let transfer_sent = &original.payee_transfer;
1537 let transfer_received = &refund.payer_transfer;
1538
1539 if !is_send_transfer_almost_equal(transfer_sent, transfer_received) {
1540 return Err("Payee and payer transfers are too different (refund)".to_owned().into())
1541 }
1542 }
1543
1544 if let Some(ref waiting_transfer) = mediator_state.waiting_transfer {
1545 let last_transfer_pair = mediator_state
1546 .transfers_pair
1547 .last()
1548 .ok_or("No transfer pairs found".to_owned().into())?;
1549
1550 let transfer_sent = &last_transfer_pair.payee_transfer;
1551 let transfer_received = &waiting_transfer.transfer;
1552
1553 if !is_send_transfer_almost_equal(transfer_sent, transfer_received) {
1554 return Err("Payee and payer transfers are too different (waiting transfer)"
1555 .to_owned()
1556 .into())
1557 }
1558 }
1559
1560 Ok(transition)
1561}
1562
1563pub fn state_transition(
1565 chain_state: ChainState,
1566 mediator_state: Option<MediatorTransferState>,
1567 state_change: StateChange,
1568) -> TransitionResult {
1569 let transition_result = match state_change {
1570 StateChange::Block(inner) => handle_block(chain_state, mediator_state, inner),
1571 StateChange::ActionInitMediator(inner) => handle_init(chain_state, inner),
1572 StateChange::ReceiveTransferRefund(inner) =>
1573 handle_refund_transfer(chain_state, mediator_state, inner),
1574 StateChange::ReceiveSecretReveal(inner) =>
1575 handle_offchain_secret_reveal(chain_state, mediator_state, inner),
1576 StateChange::ContractReceiveSecretReveal(inner) =>
1577 handle_onchain_secret_reveal(chain_state, mediator_state, inner),
1578 StateChange::ReceiveUnlock(inner) => handle_unlock(chain_state, mediator_state, inner),
1579 StateChange::ReceiveLockExpired(inner) =>
1580 handle_lock_expired(chain_state, mediator_state, inner),
1581 _ =>
1582 return Ok(MediatorTransition { new_state: mediator_state, chain_state, events: vec![] }),
1583 }?;
1584
1585 let transition_result = sanity_check(transition_result)?;
1586 Ok(clear_if_finalized(transition_result))
1587}