raiden_state_machine/machine/
token_network.rs

1#![warn(clippy::missing_docs_in_private_items)]
2
3use raiden_primitives::types::{
4	H256,
5	U256,
6	U64,
7};
8
9use super::channel;
10use crate::{
11	errors::StateTransitionError,
12	types::{
13		ContractReceiveChannelOpened,
14		Event,
15		Random,
16		StateChange,
17		TokenNetworkState,
18	},
19};
20
21/// A transition result for the token network state machine.
22type TransitionResult = std::result::Result<TokenNetworkTransition, StateTransitionError>;
23
24/// Token network transition content.
25#[derive(Debug)]
26pub struct TokenNetworkTransition {
27	pub new_state: TokenNetworkState,
28	pub events: Vec<Event>,
29}
30
31/// Dispatch `state_change` to a channel by channei identifier.
32fn subdispatch_to_channel_by_id(
33	mut token_network_state: TokenNetworkState,
34	channel_identifier: U256,
35	state_change: StateChange,
36	block_number: U64,
37	block_hash: H256,
38	pseudo_random_number_generator: &mut Random,
39) -> TransitionResult {
40	let channel_state =
41		match token_network_state.channelidentifiers_to_channels.get(&channel_identifier) {
42			Some(channel_state) => channel_state.clone(),
43			None =>
44				return Ok(TokenNetworkTransition { new_state: token_network_state, events: vec![] }),
45		};
46
47	let result = channel::state_transition(
48		channel_state.clone(),
49		state_change,
50		block_number,
51		block_hash,
52		pseudo_random_number_generator,
53	)?;
54	match result.new_state {
55		Some(channel_state) => {
56			token_network_state
57				.channelidentifiers_to_channels
58				.insert(channel_identifier, channel_state);
59		},
60		None => {
61			token_network_state.channelidentifiers_to_channels.remove(&channel_identifier);
62
63			token_network_state
64				.partneraddresses_to_channelidentifiers
65				.remove(&channel_state.partner_state.address);
66		},
67	}
68
69	Ok(TokenNetworkTransition { new_state: token_network_state, events: result.events })
70}
71
72/// Handle `ContractReceiveChannelOpened` state change.
73fn handle_contract_receive_channel_opened(
74	mut token_network_state: TokenNetworkState,
75	state_change: ContractReceiveChannelOpened,
76) -> TransitionResult {
77	let channel_state = state_change.channel_state;
78	let canonical_identifier = channel_state.canonical_identifier.clone();
79
80	token_network_state
81		.partneraddresses_to_channelidentifiers
82		.entry(channel_state.partner_state.address)
83		.or_insert(vec![]);
84	if let Some(entry) = token_network_state
85		.partneraddresses_to_channelidentifiers
86		.get_mut(&channel_state.partner_state.address)
87	{
88		if !entry.contains(&canonical_identifier.channel_identifier) {
89			entry.push(canonical_identifier.channel_identifier);
90		}
91	}
92
93	token_network_state
94		.channelidentifiers_to_channels
95		.entry(canonical_identifier.channel_identifier)
96		.or_insert(channel_state);
97
98	Ok(TokenNetworkTransition { new_state: token_network_state, events: vec![] })
99}
100
101/// State machine for the token network.
102pub fn state_transition(
103	token_network_state: TokenNetworkState,
104	state_change: StateChange,
105	block_number: U64,
106	block_hash: H256,
107	pseudo_random_number_generator: &mut Random,
108) -> TransitionResult {
109	match state_change {
110		StateChange::ActionChannelClose(ref inner) => {
111			let channel_identifier = inner.canonical_identifier.channel_identifier;
112			subdispatch_to_channel_by_id(
113				token_network_state,
114				channel_identifier,
115				state_change,
116				block_number,
117				block_hash,
118				pseudo_random_number_generator,
119			)
120		},
121		StateChange::ActionChannelWithdraw(ref inner) => {
122			let channel_identifier = inner.canonical_identifier.channel_identifier;
123			subdispatch_to_channel_by_id(
124				token_network_state,
125				channel_identifier,
126				state_change,
127				block_number,
128				block_hash,
129				pseudo_random_number_generator,
130			)
131		},
132		StateChange::ActionChannelCoopSettle(ref inner) => {
133			let channel_identifier = inner.canonical_identifier.channel_identifier;
134			subdispatch_to_channel_by_id(
135				token_network_state,
136				channel_identifier,
137				state_change,
138				block_number,
139				block_hash,
140				pseudo_random_number_generator,
141			)
142		},
143		StateChange::ActionChannelSetRevealTimeout(ref inner) => {
144			let channel_identifier = inner.canonical_identifier.channel_identifier;
145			subdispatch_to_channel_by_id(
146				token_network_state,
147				channel_identifier,
148				state_change,
149				block_number,
150				block_hash,
151				pseudo_random_number_generator,
152			)
153		},
154		StateChange::ContractReceiveChannelOpened(inner) =>
155			handle_contract_receive_channel_opened(token_network_state, inner),
156		StateChange::ContractReceiveChannelClosed(ref inner) => {
157			let channel_identifier = inner.canonical_identifier.channel_identifier;
158			subdispatch_to_channel_by_id(
159				token_network_state,
160				channel_identifier,
161				state_change,
162				block_number,
163				block_hash,
164				pseudo_random_number_generator,
165			)
166		},
167		StateChange::ContractReceiveChannelDeposit(ref inner) => {
168			let channel_identifier = inner.canonical_identifier.channel_identifier;
169			subdispatch_to_channel_by_id(
170				token_network_state,
171				channel_identifier,
172				state_change,
173				block_number,
174				block_hash,
175				pseudo_random_number_generator,
176			)
177		},
178		StateChange::ContractReceiveChannelWithdraw(ref inner) => {
179			let channel_identifier = inner.canonical_identifier.channel_identifier;
180			subdispatch_to_channel_by_id(
181				token_network_state,
182				channel_identifier,
183				state_change,
184				block_number,
185				block_hash,
186				pseudo_random_number_generator,
187			)
188		},
189		StateChange::ContractReceiveChannelSettled(ref inner) => {
190			let channel_identifier = inner.canonical_identifier.channel_identifier;
191			subdispatch_to_channel_by_id(
192				token_network_state,
193				channel_identifier,
194				state_change,
195				block_number,
196				block_hash,
197				pseudo_random_number_generator,
198			)
199		},
200		StateChange::ContractReceiveUpdateTransfer(ref inner) => {
201			let channel_identifier = inner.canonical_identifier.channel_identifier;
202			subdispatch_to_channel_by_id(
203				token_network_state,
204				channel_identifier,
205				state_change,
206				block_number,
207				block_hash,
208				pseudo_random_number_generator,
209			)
210		},
211		StateChange::ContractReceiveChannelBatchUnlock(ref inner) => {
212			let channel_identifier = inner.canonical_identifier.channel_identifier;
213			subdispatch_to_channel_by_id(
214				token_network_state,
215				channel_identifier,
216				state_change,
217				block_number,
218				block_hash,
219				pseudo_random_number_generator,
220			)
221		},
222		StateChange::ReceiveWithdrawRequest(ref inner) => {
223			let channel_identifier = inner.canonical_identifier.channel_identifier;
224			subdispatch_to_channel_by_id(
225				token_network_state,
226				channel_identifier,
227				state_change,
228				block_number,
229				block_hash,
230				pseudo_random_number_generator,
231			)
232		},
233		StateChange::ReceiveWithdrawConfirmation(ref inner) => {
234			let channel_identifier = inner.canonical_identifier.channel_identifier;
235			subdispatch_to_channel_by_id(
236				token_network_state,
237				channel_identifier,
238				state_change,
239				block_number,
240				block_hash,
241				pseudo_random_number_generator,
242			)
243		},
244		StateChange::ReceiveWithdrawExpired(ref inner) => {
245			let channel_identifier = inner.canonical_identifier.channel_identifier;
246			subdispatch_to_channel_by_id(
247				token_network_state,
248				channel_identifier,
249				state_change,
250				block_number,
251				block_hash,
252				pseudo_random_number_generator,
253			)
254		},
255		_ => Err(StateTransitionError { msg: String::from("Could not transition token network") }),
256	}
257}