1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use super::*;
impl<N: Network> FromBytes for Transition<N> {
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let version = u16::read_le(&mut reader)?;
if version != 0 {
return Err(error("Invalid transition version"));
}
let transition_id = N::TransitionID::read_le(&mut reader)?;
let program_id = FromBytes::read_le(&mut reader)?;
let function_name = FromBytes::read_le(&mut reader)?;
let num_inputs: u16 = FromBytes::read_le(&mut reader)?;
let mut inputs = Vec::with_capacity(num_inputs as usize);
for _ in 0..num_inputs {
inputs.push(FromBytes::read_le(&mut reader)?);
}
let num_outputs: u16 = FromBytes::read_le(&mut reader)?;
let mut outputs = Vec::with_capacity(num_outputs as usize);
for _ in 0..num_outputs {
outputs.push(FromBytes::read_le(&mut reader)?);
}
let finalize_variant = u8::read_le(&mut reader)?;
let finalize = match finalize_variant {
0 => None,
1 => {
let num_finalize_inputs = u16::read_le(&mut reader)?;
let mut finalize = Vec::with_capacity(num_finalize_inputs as usize);
for _ in 0..num_finalize_inputs {
finalize.push(FromBytes::read_le(&mut reader)?);
}
Some(finalize)
}
2.. => return Err(error(format!("Invalid transition finalize variant ({finalize_variant})"))),
};
let proof = FromBytes::read_le(&mut reader)?;
let tpk = FromBytes::read_le(&mut reader)?;
let tcm = FromBytes::read_le(&mut reader)?;
let fee = FromBytes::read_le(&mut reader)?;
let transition = Self::new(program_id, function_name, inputs, outputs, finalize, proof, tpk, tcm, fee)
.map_err(|e| error(e.to_string()))?;
match transition_id == *transition.id() {
true => Ok(transition),
false => Err(error("Transition ID is incorrect, possible data corruption")),
}
}
}
impl<N: Network> ToBytes for Transition<N> {
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
0u16.write_le(&mut writer)?;
self.id.write_le(&mut writer)?;
self.program_id.write_le(&mut writer)?;
self.function_name.write_le(&mut writer)?;
(self.inputs.len() as u16).write_le(&mut writer)?;
self.inputs.write_le(&mut writer)?;
(self.outputs.len() as u16).write_le(&mut writer)?;
self.outputs.write_le(&mut writer)?;
match &self.finalize {
None => {
0u8.write_le(&mut writer)?;
}
Some(finalize) => {
1u8.write_le(&mut writer)?;
(finalize.len() as u16).write_le(&mut writer)?;
finalize.write_le(&mut writer)?;
}
}
self.proof.write_le(&mut writer)?;
self.tpk.write_le(&mut writer)?;
self.tcm.write_le(&mut writer)?;
self.fee.write_le(&mut writer)
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::network::Testnet3;
type CurrentNetwork = Testnet3;
#[test]
fn test_bytes() -> Result<()> {
let expected = crate::process::test_helpers::sample_transition();
let expected_bytes = expected.to_bytes_le()?;
assert_eq!(expected, Transition::read_le(&expected_bytes[..])?);
assert!(Transition::<CurrentNetwork>::read_le(&expected_bytes[1..]).is_err());
Ok(())
}
}