· 7 years ago · Mar 16, 2018, 10:04 PM
1// Not complete, but you get the idea.
2
3impl<'a> Transactions<'a> {
4 pub const SERVICE_ID: u16 = 1;
5
6 fn write_payload(&self, writer: &mut ::exonum::messages::MessageWriter) {
7 match *self {
8 Transactions::CreateWallet { public_key, name } => {
9 let __from = 0 as ::exonum::encoding::Offset;
10 let __size = <&'a PublicKey as ::exonum::encoding::Field>::field_size();
11 writer.write(public_key, __from, __from + __size);
12 let __from = __from + __size;
13 let __size = <&'a str as ::exonum::encoding::Field>::field_size();
14 writer.write(name, __from, __from + __size);
15 }
16
17 Transactions::Transfer { from, to, amount, seed } => {
18 let __from = 0 as ::exonum::encoding::Offset;
19 let __size = <&'a PublicKey as ::exonum::encoding::Field>::field_size();
20 writer.write(from, __from, __from + __size);
21 let __from = __from + __size;
22 let __size = <&'a PublicKey as ::exonum::encoding::Field>::field_size();
23 writer.write(to, __from, __from + __size);
24 let __from = __from + __size;
25 let __size = <u64 as ::exonum::encoding::Field>::field_size();
26 writer.write(amount, __from, __from + __size);
27 let __from = __from + __size;
28 let __size = <u64 as ::exonum::encoding::Field>::field_size();
29 writer.write(seed, __from, __from + __size);
30 }
31 }
32 }
33
34 fn header_size(&self) -> u32 {
35 match *self {
36 Transactions::CreateWallet { .. } => {
37 <&'a PublicKey as ::exonum::encoding::Field>::field_size() +
38 <&'a str as ::exonum::encoding::Field>::field_size()
39 }
40 Transactions::Transfer { .. } => {
41 <&'a PublicKey as ::exonum::encoding::Field>::field_size() +
42 <&'a PublicKey as ::exonum::encoding::Field>::field_size() +
43 <u64 as ::exonum::encoding::Field>::field_size() +
44 <u64 as ::exonum::encoding::Field>::field_size()
45 }
46 }
47 }
48
49 fn sign(self, secret_key: &::exonum::crypto::SecretKey) -> ::exonum::messages::RawMessage {
50 let message_id = match self {
51 Transactions::CreateWallet { .. } => 0,
52 Transactions::Transfer { .. } => 1,
53 };
54
55 let mut writer = ::exonum::messages::MessageWriter::new(
56 ::exonum::messages::PROTOCOL_MAJOR_VERSION,
57 ::exonum::messages::TEST_NETWORK_ID,
58 Self::SERVICE_ID,
59 message_id,
60 self.header_size() as usize,
61 );
62 self.write_payload(&mut writer);
63
64 ::exonum::messages::RawMessage::new(writer.sign(secret_key))
65 }
66
67 pub fn from(raw: &'a ::exonum::messages::RawMessage) -> Result<Self, ::exonum::encoding::Error> {
68 // FIXME checks
69 Ok(unsafe { Self::unchecked_from(raw) })
70 }
71
72 unsafe fn unchecked_from(raw: &'a ::exonum::messages::RawMessage) -> Self {
73 match raw.message_type() {
74 0 => {
75 let __from = 0 as ::exonum::encoding::Offset;
76 let __size = <&'a PublicKey as ::exonum::encoding::Field>::field_size();
77 let public_key = raw.read::<&'a PublicKey>(__from, __from + __size);
78 let __from = __from + __size;
79 let __size = <&'a str as ::exonum::encoding::Field>::field_size();
80 let name = raw.read::<&'a str>(__from, __from + __size);
81
82 Transactions::CreateWallet {
83 public_key,
84 name,
85 }
86 },
87 1 => {
88 let __from = 0 as ::exonum::encoding::Offset;
89 let __size = <&'a PublicKey as ::exonum::encoding::Field>::field_size();
90 let from = raw.read::<&'a PublicKey>(__from, __from + __size);
91 let __from = __from + __size;
92 let __size = <&'a PublicKey as ::exonum::encoding::Field>::field_size();
93 let to = raw.read::<&'a PublicKey>(__from, __from + __size);
94 let __from = __from + __size;
95 let __size = <u64 as ::exonum::encoding::Field>::field_size();
96 let amount = raw.read::<u64>(__from, __from + __size);
97 let __from = __from + __size;
98 let __size = <u64 as ::exonum::encoding::Field>::field_size();
99 let seed = raw.read::<u64>(__from, __from + __size);
100
101 Transactions::Transfer {
102 from,
103 to,
104 amount,
105 seed,
106 }
107 },
108 _ => unreachable!("unchecked_from called inappropriately"),
109 }
110 }
111}
112
113impl<'a> Transactions<'a> {
114 pub fn tx_from_raw(raw: ::exonum::messages::RawTransaction)
115 -> Result<Box<::exonum::blockchain::Transaction>, ::exonum::encoding::Error>
116 {
117 // `BoxedTransactions` type defined here; I've separated it for clarity
118 BoxedTransactions::from_raw(raw).map(|tx| Box::new(tx) as Box<::exonum::blockchain::Transaction>)
119 }
120}
121
122#[derive(Debug)]
123struct BoxedTransactions {
124 raw: ::exonum::messages::RawMessage,
125}
126
127impl ::exonum::blockchain::Transaction for BoxedTransactions {
128 fn verify(&self) -> bool {
129 let tx = unsafe { Transactions::unchecked_from(&self.raw) };
130 match tx {
131 Transactions::CreateWallet { public_key, .. } => {
132 self.verify_signature(public_key)
133 }
134 Transactions::Transfer { from, .. } => {
135 self.verify_signature(from)
136 }
137 }
138 }
139
140 fn execute(&self, fork: &mut ::exonum::storage::Fork) -> ::exonum::blockchain::ExecutionResult {
141 let tx = unsafe { Transactions::unchecked_from(&self.raw) };
142 match tx {
143 Transactions::CreateWallet { public_key, name } => {
144 Transactions::create_wallet(fork, public_key, name)
145 }
146 Transactions::Transfer { from, to, amount, seed } => {
147 Transactions::transfer(fork, from, to, amount, seed)
148 }
149 }
150 }
151}
152
153impl ::exonum::messages::Message for BoxedTransactions {
154 fn from_raw(
155 raw: ::exonum::messages::RawMessage,
156 ) -> ::std::result::Result<Self, ::exonum::encoding::Error> {
157 Transactions::from(&raw)?;
158 Ok(BoxedTransactions { raw })
159 }
160
161 fn raw(&self) -> &::exonum::messages::RawMessage {
162 &self.raw
163 }
164}
165
166impl ::exonum::encoding::serialize::json::ExonumJson for BoxedTransactions {
167 fn deserialize_field<B> (
168 value: &::exonum::encoding::serialize::json::reexport::Value,
169 buffer: &mut B,
170 from: ::exonum::encoding::Offset,
171 to: ::exonum::encoding::Offset,
172 ) -> ::std::result::Result<(), ::std::boxed::Box<::std::error::Error>>
173 where B: ::exonum::encoding::serialize::WriteBufferWrapper
174 {
175 // FIXME deser
176 Ok(())
177 }
178
179 fn serialize_field(&self)
180 -> ::std::result::Result<::exonum::encoding::serialize::json::reexport::Value,
181 ::std::boxed::Box<::std::error::Error + Send + Sync>>
182 {
183 unimplemented!()
184 }
185}