1use crate::address::AddressSerializer;
4use crate::datastore::{Datastore, DatastoreDeserializer, DatastoreSerializer};
5use crate::prehash::{PreHashSet, PreHashed};
6use crate::secure_share::{
7 Id, SecureShare, SecureShareContent, SecureShareDeserializer, SecureShareSerializer,
8};
9use crate::{
10 address::{Address, AddressDeserializer},
11 amount::{Amount, AmountDeserializer, AmountSerializer},
12 error::ModelsError,
13 serialization::{StringDeserializer, StringSerializer, VecU8Deserializer, VecU8Serializer},
14};
15use massa_hash::{Hash, HashDeserializer};
16use massa_serialization::{
17 DeserializeError, Deserializer, SerializeError, Serializer, U16VarIntDeserializer,
18 U16VarIntSerializer, U32VarIntDeserializer, U32VarIntSerializer, U64VarIntDeserializer,
19 U64VarIntSerializer,
20};
21use massa_signature::PublicKey;
22use nom::error::{context, ErrorKind};
23use nom::multi::length_count;
24use nom::sequence::tuple;
25use nom::AsBytes;
26use nom::Parser;
27use nom::{
28 error::{ContextError, ParseError},
29 IResult,
30};
31use num_enum::{IntoPrimitive, TryFromPrimitive};
32use serde::{Deserialize, Serialize};
33use serde_with::{serde_as, DeserializeFromStr, SerializeDisplay};
34use std::convert::TryInto;
35use std::fmt::Formatter;
36use std::{ops::Bound::Included, ops::RangeInclusive, str::FromStr};
37use transition::Versioned;
38
39pub const OPERATION_ID_PREFIX_SIZE_BYTES: usize = 17;
41
42#[allow(missing_docs)]
44#[transition::versioned(versions("0"))]
45#[derive(
46 Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, SerializeDisplay, DeserializeFromStr,
47)]
48pub struct OperationId(Hash);
49
50const OPERATIONID_PREFIX: char = 'O';
51
52#[allow(missing_docs)]
54#[transition::versioned(versions("0"))]
55#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
56#[allow(unused_macros)]
57pub struct OperationPrefixId([u8; OPERATION_ID_PREFIX_SIZE_BYTES]);
58
59impl std::fmt::Display for OperationPrefixId {
60 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61 match self {
62 OperationPrefixId::OperationPrefixIdV0(prefix) => write!(f, "{}", prefix),
63 }
64 }
65}
66
67#[transition::impl_version(versions("0"))]
68impl std::fmt::Display for OperationPrefixId {
69 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
70 let u64_serializer = U64VarIntSerializer::new();
71 let mut bytes: Vec<u8> = Vec::new();
73 u64_serializer
74 .serialize(&Self::VERSION, &mut bytes)
75 .map_err(|_| std::fmt::Error)?;
76 bytes.extend(self.0.as_bytes());
77 write!(f, "{}", bs58::encode(bytes).into_string())
78 }
79}
80
81impl std::fmt::Debug for OperationPrefixId {
82 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
83 match self {
84 OperationPrefixId::OperationPrefixIdV0(prefix) => write!(f, "{:?}", prefix),
85 }
86 }
87}
88
89#[transition::impl_version(versions("0"))]
90impl std::fmt::Debug for OperationPrefixId {
91 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
92 write!(f, "{}", self)
93 }
94}
95
96impl std::fmt::Display for OperationId {
97 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
98 match self {
99 OperationId::OperationIdV0(id) => write!(f, "{}", id),
100 }
101 }
102}
103
104#[transition::impl_version(versions("0"))]
105impl std::fmt::Display for OperationId {
106 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
107 let u64_serializer = U64VarIntSerializer::new();
108 let mut bytes: Vec<u8> = Vec::new();
110 u64_serializer
111 .serialize(&Self::VERSION, &mut bytes)
112 .map_err(|_| std::fmt::Error)?;
113 bytes.extend(self.0.to_bytes());
114 write!(
115 f,
116 "{}{}",
117 OPERATIONID_PREFIX,
118 bs58::encode(bytes).with_check().into_string()
119 )
120 }
121}
122
123impl std::fmt::Debug for OperationId {
124 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
125 match self {
126 OperationId::OperationIdV0(id) => write!(f, "{:?}", id),
127 }
128 }
129}
130
131#[transition::impl_version(versions("0"))]
132impl std::fmt::Debug for OperationId {
133 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
134 write!(f, "{}", self)
135 }
136}
137
138impl FromStr for OperationId {
139 type Err = ModelsError;
140 fn from_str(s: &str) -> Result<Self, Self::Err> {
153 let mut chars = s.chars();
154 match chars.next() {
155 Some(prefix) if prefix == OPERATIONID_PREFIX => {
156 let data = chars.collect::<String>();
157 let decoded_bs58_check = bs58::decode(data)
158 .with_check(None)
159 .into_vec()
160 .map_err(|_| ModelsError::OperationIdParseError)?;
161 let operation_id_deserializer = OperationIdDeserializer::new();
162 let (rest, op_id) = operation_id_deserializer
163 .deserialize::<DeserializeError>(&decoded_bs58_check[..])
164 .map_err(|_| ModelsError::OperationIdParseError)?;
165 if rest.is_empty() {
166 Ok(op_id)
167 } else {
168 Err(ModelsError::OperationIdParseError)
169 }
170 }
171 _ => Err(ModelsError::OperationIdParseError),
172 }
173 }
174}
175
176#[transition::impl_version(versions("0"))]
177impl FromStr for OperationId {
178 type Err = ModelsError;
179 fn from_str(s: &str) -> Result<Self, Self::Err> {
180 let mut chars = s.chars();
181 match chars.next() {
182 Some(prefix) if prefix == OPERATIONID_PREFIX => {
183 let data = chars.collect::<String>();
184 let decoded_bs58_check = bs58::decode(data)
185 .with_check(None)
186 .into_vec()
187 .map_err(|_| ModelsError::OperationIdParseError)?;
188 let operation_id_deserializer = OperationIdDeserializer::new();
189 let (rest, op_id) = operation_id_deserializer
190 .deserialize::<DeserializeError>(&decoded_bs58_check[..])
191 .map_err(|_| ModelsError::OperationIdParseError)?;
192 if rest.is_empty() {
193 Ok(op_id)
194 } else {
195 Err(ModelsError::OperationIdParseError)
196 }
197 }
198 _ => Err(ModelsError::OperationIdParseError),
199 }
200 }
201}
202
203impl PreHashed for OperationId {}
204
205impl Id for OperationId {
206 fn new(hash: Hash) -> Self {
207 OperationId::OperationIdV0(OperationIdV0(hash))
208 }
209
210 fn get_hash(&self) -> &Hash {
211 match self {
212 OperationId::OperationIdV0(op_id) => op_id.get_hash(),
213 }
214 }
215}
216
217impl PreHashed for OperationPrefixId {}
218
219impl From<&[u8; OPERATION_ID_PREFIX_SIZE_BYTES]> for OperationPrefixId {
220 fn from(bytes: &[u8; OPERATION_ID_PREFIX_SIZE_BYTES]) -> Self {
222 OperationPrefixIdVariant)
223 }
224}
225
226impl From<&OperationPrefixId> for Vec<u8> {
227 fn from(prefix: &OperationPrefixId) -> Self {
228 match prefix {
229 OperationPrefixId::OperationPrefixIdV0(prefix) => prefix.0.to_vec(),
230 }
231 }
232}
233
234impl OperationId {
235 pub fn into_prefix(self) -> OperationPrefixId {
237 match self {
238 OperationId::OperationIdV0(op_id) => op_id.into_prefix(),
239 }
240 }
241
242 pub fn prefix(&self) -> OperationPrefixId {
244 match self {
245 OperationId::OperationIdV0(op_id) => op_id.prefix(),
246 }
247 }
248
249 pub fn get_version(&self) -> u64 {
251 match self {
252 OperationId::OperationIdV0(op_id) => op_id.get_version(),
253 }
254 }
255}
256
257#[transition::impl_version(versions("0"))]
258impl OperationId {
259 pub fn into_prefix(self) -> OperationPrefixId {
261 OperationPrefixId::OperationPrefixIdV0(OperationPrefixIdV0(
262 self.0.into_bytes()[..OPERATION_ID_PREFIX_SIZE_BYTES]
263 .try_into()
264 .expect("failed to truncate prefix from OperationId"),
265 ))
266 }
267
268 pub fn prefix(&self) -> OperationPrefixId {
270 OperationPrefixId::OperationPrefixIdV0(OperationPrefixIdV0(
271 self.0.to_bytes()[..OPERATION_ID_PREFIX_SIZE_BYTES]
272 .try_into()
273 .expect("failed to truncate prefix from OperationId"),
274 ))
275 }
276
277 fn get_hash(&self) -> &Hash {
278 &self.0
279 }
280
281 fn get_version(&self) -> u64 {
282 Self::VERSION
283 }
284}
285
286#[derive(Default, Clone)]
288pub struct OperationIdSerializer {
289 version_serializer: U64VarIntSerializer,
290}
291
292impl OperationIdSerializer {
293 pub fn new() -> Self {
295 Self {
296 version_serializer: U64VarIntSerializer::new(),
297 }
298 }
299}
300
301impl Serializer<OperationId> for OperationIdSerializer {
302 fn serialize(&self, value: &OperationId, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
303 self.version_serializer
304 .serialize(&value.get_version(), buffer)?;
305 match value {
306 OperationId::OperationIdV0(id) => self.serialize(id, buffer),
307 }
308 }
309}
310
311#[transition::impl_version(versions("0"), structures("OperationId"))]
312impl Serializer<OperationId> for OperationIdSerializer {
313 fn serialize(&self, value: &OperationId, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
314 buffer.extend(value.0.to_bytes());
315 Ok(())
316 }
317}
318
319#[derive(Clone)]
321pub struct OperationIdDeserializer {
322 hash_deserializer: HashDeserializer,
323 version_deserializer: U64VarIntDeserializer,
324}
325
326impl OperationIdDeserializer {
327 pub fn new() -> Self {
329 Self {
330 hash_deserializer: HashDeserializer::new(),
331 version_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
332 }
333 }
334}
335
336impl Default for OperationIdDeserializer {
337 fn default() -> Self {
338 Self::new()
339 }
340}
341
342impl Deserializer<OperationId> for OperationIdDeserializer {
343 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
344 &self,
345 buffer: &'a [u8],
346 ) -> IResult<&'a [u8], OperationId, E> {
347 if buffer.len() < 2 {
349 return Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof)));
350 }
351 let (rest, op_id_version) =
352 self.version_deserializer
353 .deserialize(buffer)
354 .map_err(|_: nom::Err<E>| {
355 nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))
356 })?;
357 match op_id_version {
358 <OperationId!["0"]>::VERSION => {
359 let (rest, op_id) = self.deserialize(rest)?;
360 Ok((rest, OperationIdVariant))
361 }
362 _ => Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))),
363 }
364 }
365}
366
367#[transition::impl_version(versions("0"), structures("OperationId"))]
368impl Deserializer<OperationId> for OperationIdDeserializer {
369 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
370 &self,
371 buffer: &'a [u8],
372 ) -> IResult<&'a [u8], OperationId, E> {
373 context("Failed OperationId deserialization", |input| {
374 self.hash_deserializer.deserialize(input)
375 })
376 .map(OperationId)
377 .parse(buffer)
378 }
379}
380
381#[derive(IntoPrimitive, Debug, Eq, PartialEq, TryFromPrimitive)]
382#[repr(u32)]
383enum OperationTypeId {
384 Transaction = 0,
385 RollBuy = 1,
386 RollSell = 2,
387 ExecuteSC = 3,
388 CallSC = 4,
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
393#[cfg_attr(test, derive(PartialEq))]
395pub struct Operation {
396 pub fee: Amount,
398 pub expire_period: u64,
400 pub op: OperationType,
402}
403
404impl std::fmt::Display for Operation {
405 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
406 writeln!(f, "Fee: {}", self.fee)?;
407 writeln!(f, "Expire period: {}", self.expire_period)?;
408 writeln!(f, "Operation type: {}", self.op)?;
409 Ok(())
410 }
411}
412
413pub type SecureShareOperation = SecureShare<Operation, OperationId>;
415
416impl SecureShareContent for Operation {
417 fn compute_hash(
418 &self,
419 content_serialized: &[u8],
420 content_creator_pub_key: &PublicKey,
421 chain_id: u64,
422 ) -> Hash {
423 let mut hash_data = Vec::new();
424 hash_data.extend(chain_id.to_be_bytes());
428 hash_data.extend(content_creator_pub_key.to_bytes());
429 hash_data.extend(content_serialized);
430 Hash::compute_from(&hash_data)
431 }
432}
433
434pub struct OperationSerializer {
436 u64_serializer: U64VarIntSerializer,
437 amount_serializer: AmountSerializer,
438 op_type_serializer: OperationTypeSerializer,
439}
440
441impl OperationSerializer {
442 pub fn new() -> Self {
444 Self {
445 u64_serializer: U64VarIntSerializer::new(),
446 amount_serializer: AmountSerializer::new(),
447 op_type_serializer: OperationTypeSerializer::new(),
448 }
449 }
450}
451
452impl Default for OperationSerializer {
453 fn default() -> Self {
454 Self::new()
455 }
456}
457
458impl Serializer<Operation> for OperationSerializer {
459 fn serialize(&self, value: &Operation, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
480 self.amount_serializer.serialize(&value.fee, buffer)?;
481 self.u64_serializer
482 .serialize(&value.expire_period, buffer)?;
483 self.op_type_serializer.serialize(&value.op, buffer)?;
484 Ok(())
485 }
486}
487
488pub struct OperationDeserializer {
490 expire_period_deserializer: U64VarIntDeserializer,
491 amount_deserializer: AmountDeserializer,
492 op_type_deserializer: OperationTypeDeserializer,
493}
494
495impl OperationDeserializer {
496 pub fn new(
498 max_bytecode_size: u64,
499 max_function_name_length: u16,
500 max_parameters_size: u32,
501 max_op_datastore_entry_count: u64,
502 max_op_datastore_key_length: u8,
503 max_op_datastore_value_length: u64,
504 ) -> Self {
505 Self {
506 expire_period_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
507 amount_deserializer: AmountDeserializer::new(
508 Included(Amount::MIN),
509 Included(Amount::MAX),
510 ),
511 op_type_deserializer: OperationTypeDeserializer::new(
512 max_bytecode_size,
513 max_function_name_length,
514 max_parameters_size,
515 max_op_datastore_entry_count,
516 max_op_datastore_key_length,
517 max_op_datastore_value_length,
518 ),
519 }
520 }
521}
522
523impl Deserializer<Operation> for OperationDeserializer {
524 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
559 &self,
560 buffer: &'a [u8],
561 ) -> IResult<&'a [u8], Operation, E> {
562 context(
563 "Failed Operation deserialization",
564 tuple((
565 context("Failed fee deserialization", |input| {
566 self.amount_deserializer.deserialize(input)
567 }),
568 context("Failed expire_period deserialization", |input| {
569 self.expire_period_deserializer.deserialize(input)
570 }),
571 context("Failed op deserialization", |input| {
572 let (rest, op) = self.op_type_deserializer.deserialize(input)?;
573 Ok((rest, op))
574 }),
575 )),
576 )
577 .map(|(fee, expire_period, op)| Operation {
578 fee,
579 expire_period,
580 op,
581 })
582 .parse(buffer)
583 }
584}
585
586#[serde_as]
588#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
589pub enum OperationType {
590 Transaction {
592 recipient_address: Address,
594 amount: Amount,
596 },
597 RollBuy {
599 roll_count: u64,
601 },
602 RollSell {
604 roll_count: u64,
606 },
607 ExecuteSC {
609 data: Vec<u8>,
611 max_gas: u64,
613 max_coins: Amount,
615 #[serde_as(as = "Vec<(_, _)>")]
617 datastore: Datastore,
618 },
619 CallSC {
621 target_addr: Address,
623 target_func: String,
625 param: Vec<u8>,
627 max_gas: u64,
629 coins: Amount,
631 },
632}
633
634impl std::fmt::Display for OperationType {
635 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
636 match self {
637 OperationType::Transaction {
638 recipient_address,
639 amount,
640 } => {
641 writeln!(f, "Transaction:")?;
642 writeln!(f, "\t- Recipient:{}", recipient_address)?;
643 writeln!(f, "\t Amount:{}", amount)?;
644 }
645 OperationType::RollBuy { roll_count } => {
646 writeln!(f, "Buy rolls:")?;
647 writeln!(f, "\t- Roll count:{}", roll_count)?;
648 }
649 OperationType::RollSell { roll_count } => {
650 writeln!(f, "Sell rolls:")?;
651 writeln!(f, "\t- Roll count:{}", roll_count)?;
652 }
653 OperationType::ExecuteSC {
654 max_gas,
655 max_coins,
656 ..
657 } => {
659 writeln!(f, "ExecuteSC: ")?;
660 writeln!(f, "\t- max_coins:{}", max_coins)?;
661 writeln!(f, "\t- max_gas:{}", max_gas)?;
662 },
663 OperationType::CallSC {
664 max_gas,
665 coins,
666 target_addr,
667 target_func,
668 param
669 } => {
670 writeln!(f, "CallSC:")?;
671 writeln!(f, "\t- target address:{}", target_addr)?;
672 writeln!(f, "\t- target function:{}", target_func)?;
673 writeln!(f, "\t- target parameter:{:?}", param)?;
674 writeln!(f, "\t- max_gas:{}", max_gas)?;
675 writeln!(f, "\t- coins:{}", coins)?;
676 }
677 }
678 Ok(())
679 }
680}
681
682pub struct OperationTypeSerializer {
684 u32_serializer: U32VarIntSerializer,
685 u64_serializer: U64VarIntSerializer,
686 vec_u8_serializer: VecU8Serializer,
687 amount_serializer: AmountSerializer,
688 address_serializer: AddressSerializer,
689 function_name_serializer: StringSerializer<U16VarIntSerializer, u16>,
690 datastore_serializer: DatastoreSerializer,
691}
692
693impl OperationTypeSerializer {
694 pub fn new() -> Self {
696 Self {
697 u32_serializer: U32VarIntSerializer::new(),
698 u64_serializer: U64VarIntSerializer::new(),
699 vec_u8_serializer: VecU8Serializer::new(),
700 amount_serializer: AmountSerializer::new(),
701 address_serializer: AddressSerializer::new(),
702 function_name_serializer: StringSerializer::new(U16VarIntSerializer::new()),
703 datastore_serializer: DatastoreSerializer::new(),
704 }
705 }
706}
707
708impl Default for OperationTypeSerializer {
709 fn default() -> Self {
710 Self::new()
711 }
712}
713
714impl Serializer<OperationType> for OperationTypeSerializer {
715 fn serialize(&self, value: &OperationType, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
734 match value {
735 OperationType::Transaction {
736 recipient_address,
737 amount,
738 } => {
739 self.u32_serializer
740 .serialize(&u32::from(OperationTypeId::Transaction), buffer)?;
741 self.address_serializer
742 .serialize(recipient_address, buffer)?;
743 self.amount_serializer.serialize(amount, buffer)?;
744 }
745 OperationType::RollBuy { roll_count } => {
746 self.u32_serializer
747 .serialize(&u32::from(OperationTypeId::RollBuy), buffer)?;
748 self.u64_serializer.serialize(roll_count, buffer)?;
749 }
750 OperationType::RollSell { roll_count } => {
751 self.u32_serializer
752 .serialize(&u32::from(OperationTypeId::RollSell), buffer)?;
753 self.u64_serializer.serialize(roll_count, buffer)?;
754 }
755 OperationType::ExecuteSC {
756 data,
757 max_gas,
758 max_coins,
759 datastore,
760 } => {
761 self.u32_serializer
762 .serialize(&u32::from(OperationTypeId::ExecuteSC), buffer)?;
763 self.u64_serializer.serialize(max_gas, buffer)?;
764 self.amount_serializer.serialize(max_coins, buffer)?;
765 self.vec_u8_serializer.serialize(data, buffer)?;
766 self.datastore_serializer.serialize(datastore, buffer)?;
767 }
768 OperationType::CallSC {
769 target_addr,
770 target_func,
771 param,
772 max_gas,
773 coins,
774 } => {
775 self.u32_serializer
776 .serialize(&u32::from(OperationTypeId::CallSC), buffer)?;
777 self.u64_serializer.serialize(max_gas, buffer)?;
778 self.amount_serializer.serialize(coins, buffer)?;
779 self.address_serializer.serialize(target_addr, buffer)?;
780 self.function_name_serializer
781 .serialize(target_func, buffer)?;
782 self.vec_u8_serializer.serialize(param, buffer)?;
783 }
784 }
785 Ok(())
786 }
787}
788
789pub struct OperationTypeDeserializer {
791 id_deserializer: U32VarIntDeserializer,
792 rolls_number_deserializer: U64VarIntDeserializer,
793 max_gas_deserializer: U64VarIntDeserializer,
794 address_deserializer: AddressDeserializer,
795 data_deserializer: VecU8Deserializer,
796 amount_deserializer: AmountDeserializer,
797 function_name_deserializer: StringDeserializer<U16VarIntDeserializer, u16>,
798 parameter_deserializer: VecU8Deserializer,
799 datastore_deserializer: DatastoreDeserializer,
800}
801
802impl OperationTypeDeserializer {
803 pub fn new(
805 max_bytecode_size: u64,
806 max_function_name_length: u16,
807 max_parameters_size: u32,
808 max_op_datastore_entry_count: u64,
809 max_op_datastore_key_length: u8,
810 max_op_datastore_value_length: u64,
811 ) -> Self {
812 Self {
813 id_deserializer: U32VarIntDeserializer::new(Included(0), Included(u32::MAX)),
814 rolls_number_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
815 max_gas_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
816 address_deserializer: AddressDeserializer::new(),
817 data_deserializer: VecU8Deserializer::new(Included(0), Included(max_bytecode_size)),
818 amount_deserializer: AmountDeserializer::new(
819 Included(Amount::MIN),
820 Included(Amount::MAX),
821 ),
822 function_name_deserializer: StringDeserializer::new(U16VarIntDeserializer::new(
823 Included(0),
824 Included(max_function_name_length),
825 )),
826 parameter_deserializer: VecU8Deserializer::new(
827 Included(0),
828 Included(max_parameters_size as u64),
829 ),
830 datastore_deserializer: DatastoreDeserializer::new(
831 max_op_datastore_entry_count,
832 max_op_datastore_key_length,
833 max_op_datastore_value_length,
834 ),
835 }
836 }
837}
838
839impl Deserializer<OperationType> for OperationTypeDeserializer {
840 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
875 &self,
876 buffer: &'a [u8],
877 ) -> IResult<&'a [u8], OperationType, E> {
878 context("Failed OperationType deserialization", |buffer| {
879 let (input, id) = self.id_deserializer.deserialize(buffer)?;
880 let id = OperationTypeId::try_from(id).map_err(|_| {
881 nom::Err::Error(ParseError::from_error_kind(
882 buffer,
883 nom::error::ErrorKind::Eof,
884 ))
885 })?;
886 match id {
887 OperationTypeId::Transaction => context(
888 "Failed Transaction deserialization",
889 tuple((
890 context("Failed recipient_address deserialization", |input| {
891 self.address_deserializer.deserialize(input)
892 }),
893 context("Failed amount deserialization", |input| {
894 self.amount_deserializer.deserialize(input)
895 }),
896 )),
897 )
898 .map(|(recipient_address, amount)| OperationType::Transaction {
899 recipient_address,
900 amount,
901 })
902 .parse(input),
903 OperationTypeId::RollBuy => context("Failed RollBuy deserialization", |input| {
904 self.rolls_number_deserializer.deserialize(input)
905 })
906 .map(|roll_count| OperationType::RollBuy { roll_count })
907 .parse(input),
908 OperationTypeId::RollSell => context("Failed RollSell deserialization", |input| {
909 self.rolls_number_deserializer.deserialize(input)
910 })
911 .map(|roll_count| OperationType::RollSell { roll_count })
912 .parse(input),
913 OperationTypeId::ExecuteSC => context(
914 "Failed ExecuteSC deserialization",
915 tuple((
916 context("Failed max_gas deserialization", |input| {
917 self.max_gas_deserializer.deserialize(input)
918 }),
919 context("Failed max_coins deserialization", |input| {
920 self.amount_deserializer.deserialize(input)
921 }),
922 context("Failed data deserialization", |input| {
923 self.data_deserializer.deserialize(input)
924 }),
925 context("Failed datastore deserialization", |input| {
926 self.datastore_deserializer.deserialize(input)
927 }),
928 )),
929 )
930 .map(
931 |(max_gas, max_coins, data, datastore)| OperationType::ExecuteSC {
932 data,
933 max_gas,
934 max_coins,
935 datastore,
936 },
937 )
938 .parse(input),
939 OperationTypeId::CallSC => context(
940 "Failed CallSC deserialization",
941 tuple((
942 context("Failed max_gas deserialization", |input| {
943 self.max_gas_deserializer.deserialize(input)
944 }),
945 context("Failed coins deserialization", |input| {
946 self.amount_deserializer.deserialize(input)
947 }),
948 context("Failed target_addr deserialization", |input| {
949 self.address_deserializer.deserialize(input)
950 }),
951 context("Failed target_func deserialization", |input| {
952 self.function_name_deserializer.deserialize(input)
953 }),
954 context("Failed param deserialization", |input| {
955 self.parameter_deserializer.deserialize(input)
956 }),
957 )),
958 )
959 .map(
960 |(max_gas, coins, target_addr, target_func, param)| OperationType::CallSC {
961 target_addr,
962 target_func,
963 param,
964 max_gas,
965 coins,
966 },
967 )
968 .parse(input),
969 }
970 })
971 .parse(buffer)
972 }
973}
974
975impl SecureShareOperation {
976 pub fn get_validity_range(&self, operation_validity_period: u64) -> RangeInclusive<u64> {
979 let start = self
980 .content
981 .expire_period
982 .saturating_sub(operation_validity_period);
983 start..=self.content.expire_period
984 }
985
986 pub fn get_gas_usage(&self, base_operation_gas_cost: u64, sp_compilation_cost: u64) -> u64 {
991 match &self.content.op {
992 OperationType::ExecuteSC { max_gas, .. } => max_gas.saturating_add(sp_compilation_cost),
993 OperationType::CallSC { max_gas, .. } => *max_gas,
994 OperationType::RollBuy { .. } => 0,
995 OperationType::RollSell { .. } => 0,
996 OperationType::Transaction { .. } => 0,
997 }
998 .saturating_add(base_operation_gas_cost)
999 }
1000
1001 pub fn check_gas_usage(
1010 &self,
1011 max_gas_per_block: u64,
1012 base_operation_gas_cost: u64,
1013 sp_compilation_cost: u64,
1014 ) -> Result<(), String> {
1015 let (op_name, gas_overhead) = match &self.content.op {
1017 OperationType::CallSC { .. } => ("CallSC", base_operation_gas_cost),
1018 OperationType::ExecuteSC { .. } => (
1019 "ExecuteSC",
1020 base_operation_gas_cost.saturating_add(sp_compilation_cost),
1021 ),
1022 OperationType::RollBuy { .. }
1023 | OperationType::RollSell { .. }
1024 | OperationType::Transaction { .. } => return Ok(()),
1025 };
1026 if self.get_gas_usage(base_operation_gas_cost, sp_compilation_cost) > max_gas_per_block {
1027 return Err(format!(
1028 "Upper gas limit for {} operation is {}. Your operation will never be included in a block.",
1029 op_name,
1030 max_gas_per_block.saturating_sub(gas_overhead)
1031 ));
1032 }
1033 Ok(())
1034 }
1035
1036 pub fn get_ledger_involved_addresses(&self) -> PreHashSet<Address> {
1038 let mut res = PreHashSet::<Address>::default();
1039 let emitter_address = Address::from_public_key(&self.content_creator_pub_key);
1040 res.insert(emitter_address);
1041 match &self.content.op {
1042 OperationType::Transaction {
1043 recipient_address, ..
1044 } => {
1045 res.insert(*recipient_address);
1046 }
1047 OperationType::RollBuy { .. } => {}
1048 OperationType::RollSell { .. } => {}
1049 OperationType::ExecuteSC { .. } => {}
1050 OperationType::CallSC { target_addr, .. } => {
1051 res.insert(*target_addr);
1052 }
1053 }
1054 res
1055 }
1056
1057 pub fn get_max_spending(&self, roll_price: Amount) -> Amount {
1059 let max_non_fee_seq_spending = match &self.content.op {
1061 OperationType::Transaction { amount, .. } => *amount,
1062 OperationType::RollBuy { roll_count } => roll_price.saturating_mul_u64(*roll_count),
1063 OperationType::RollSell { .. } => Amount::zero(),
1064 OperationType::ExecuteSC { max_coins, .. } => *max_coins,
1065 OperationType::CallSC { coins, .. } => *coins,
1066 };
1067
1068 max_non_fee_seq_spending.saturating_add(self.content.fee)
1070 }
1071
1072 pub fn get_roll_involved_addresses(&self) -> Result<PreHashSet<Address>, ModelsError> {
1074 let mut res = PreHashSet::<Address>::default();
1075 match self.content.op {
1076 OperationType::Transaction { .. } => {}
1077 OperationType::RollBuy { .. } => {
1078 res.insert(Address::from_public_key(&self.content_creator_pub_key));
1079 }
1080 OperationType::RollSell { .. } => {
1081 res.insert(Address::from_public_key(&self.content_creator_pub_key));
1082 }
1083 OperationType::ExecuteSC { .. } => {}
1084 OperationType::CallSC { .. } => {}
1085 }
1086 Ok(res)
1087 }
1088}
1089
1090pub type OperationPrefixIds = PreHashSet<OperationPrefixId>;
1092
1093pub struct OperationIdsSerializer {
1095 u32_serializer: U32VarIntSerializer,
1096 op_id_serializer: OperationIdSerializer,
1097}
1098
1099impl OperationIdsSerializer {
1100 pub fn new() -> Self {
1102 Self {
1103 u32_serializer: U32VarIntSerializer::new(),
1104 op_id_serializer: OperationIdSerializer::new(),
1105 }
1106 }
1107}
1108
1109impl Default for OperationIdsSerializer {
1110 fn default() -> Self {
1111 Self::new()
1112 }
1113}
1114
1115impl Serializer<Vec<OperationId>> for OperationIdsSerializer {
1116 fn serialize(
1129 &self,
1130 value: &Vec<OperationId>,
1131 buffer: &mut Vec<u8>,
1132 ) -> Result<(), SerializeError> {
1133 let list_len: u32 = value.len().try_into().map_err(|_| {
1134 SerializeError::NumberTooBig(
1135 "could not encode Vec<OperationId> list length as u32".into(),
1136 )
1137 })?;
1138 self.u32_serializer.serialize(&list_len, buffer)?;
1139 for hash in value {
1140 self.op_id_serializer.serialize(hash, buffer)?;
1141 }
1142 Ok(())
1143 }
1144}
1145
1146pub struct OperationIdsDeserializer {
1148 length_deserializer: U32VarIntDeserializer,
1149 op_id_deserializer: OperationIdDeserializer,
1150}
1151
1152impl OperationIdsDeserializer {
1153 pub fn new(max_operations_per_message: u32) -> Self {
1155 Self {
1156 length_deserializer: U32VarIntDeserializer::new(
1157 Included(0),
1158 Included(max_operations_per_message),
1159 ),
1160 op_id_deserializer: OperationIdDeserializer::new(),
1161 }
1162 }
1163}
1164
1165impl Deserializer<Vec<OperationId>> for OperationIdsDeserializer {
1166 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
1182 &self,
1183 buffer: &'a [u8],
1184 ) -> IResult<&'a [u8], Vec<OperationId>, E> {
1185 context(
1186 "Failed Vec<OperationId> deserialization",
1187 length_count(
1188 context("Failed length deserialization", |input| {
1189 self.length_deserializer.deserialize(input)
1190 }),
1191 context("Failed OperationId deserialization", |input| {
1192 self.op_id_deserializer.deserialize(input)
1193 }),
1194 ),
1195 )
1196 .parse(buffer)
1197 }
1198}
1199
1200#[derive(Default)]
1202pub struct OperationPrefixIdDeserializer;
1203
1204impl OperationPrefixIdDeserializer {
1205 pub const fn new() -> Self {
1207 Self
1208 }
1209}
1210
1211impl Deserializer<OperationPrefixId> for OperationPrefixIdDeserializer {
1212 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
1224 &self,
1225 buffer: &'a [u8],
1226 ) -> IResult<&'a [u8], OperationPrefixId, E> {
1227 context(
1228 "Failed operation prefix id deserialization",
1229 |input: &'a [u8]| {
1230 if buffer.len() < OPERATION_ID_PREFIX_SIZE_BYTES {
1231 return Err(nom::Err::Error(ParseError::from_error_kind(
1232 input,
1233 nom::error::ErrorKind::LengthValue,
1234 )));
1235 }
1236 Ok((
1237 &buffer[OPERATION_ID_PREFIX_SIZE_BYTES..],
1238 OperationPrefixId::from(
1239 &buffer[..OPERATION_ID_PREFIX_SIZE_BYTES]
1240 .try_into()
1241 .map_err(|_| {
1242 nom::Err::Error(ParseError::from_error_kind(
1243 input,
1244 nom::error::ErrorKind::Fail,
1245 ))
1246 })?,
1247 ),
1248 ))
1249 },
1250 )(buffer)
1251 }
1252}
1253
1254pub struct OperationPrefixIdsDeserializer {
1256 length_deserializer: U32VarIntDeserializer,
1257 pref_deserializer: OperationPrefixIdDeserializer,
1258}
1259
1260impl OperationPrefixIdsDeserializer {
1261 pub const fn new(max_operations_per_message: u32) -> Self {
1263 Self {
1264 length_deserializer: U32VarIntDeserializer::new(
1265 Included(0),
1266 Included(max_operations_per_message),
1267 ),
1268 pref_deserializer: OperationPrefixIdDeserializer::new(),
1269 }
1270 }
1271}
1272
1273impl Deserializer<OperationPrefixIds> for OperationPrefixIdsDeserializer {
1274 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
1289 &self,
1290 buffer: &'a [u8],
1291 ) -> IResult<&'a [u8], OperationPrefixIds, E> {
1292 context(
1293 "Failed OperationPrefixIds deserialization",
1294 length_count(
1295 context("Failed length deserialization", |input| {
1296 self.length_deserializer.deserialize(input)
1297 }),
1298 context("Failed OperationPrefixId deserialization", |input| {
1299 self.pref_deserializer.deserialize(input)
1300 }),
1301 ),
1302 )
1303 .map(|hashes| hashes.into_iter().collect())
1304 .parse(buffer)
1305 }
1306}
1307
1308#[derive(Clone)]
1310pub struct OperationPrefixIdsSerializer {
1311 u32_serializer: U32VarIntSerializer,
1312}
1313
1314impl OperationPrefixIdsSerializer {
1315 pub const fn new() -> Self {
1317 Self {
1318 u32_serializer: U32VarIntSerializer::new(),
1319 }
1320 }
1321}
1322
1323impl Default for OperationPrefixIdsSerializer {
1324 fn default() -> Self {
1325 Self::new()
1326 }
1327}
1328
1329impl Serializer<OperationPrefixIds> for OperationPrefixIdsSerializer {
1330 fn serialize(
1331 &self,
1332 value: &OperationPrefixIds,
1333 buffer: &mut Vec<u8>,
1334 ) -> Result<(), SerializeError> {
1335 let list_len: u32 = value.len().try_into().map_err(|_| {
1336 SerializeError::NumberTooBig(
1337 "could not encode Set<OperationId> list length as u32".into(),
1338 )
1339 })?;
1340 self.u32_serializer.serialize(&list_len, buffer)?;
1341 for prefix in value {
1342 buffer.extend(Vec::<u8>::from(prefix));
1343 }
1344 Ok(())
1345 }
1346}
1347
1348#[derive(Clone)]
1350pub struct OperationsSerializer {
1351 u32_serializer: U32VarIntSerializer,
1352 signed_op_serializer: SecureShareSerializer,
1353}
1354
1355impl OperationsSerializer {
1356 pub const fn new() -> Self {
1358 Self {
1359 u32_serializer: U32VarIntSerializer::new(),
1360 signed_op_serializer: SecureShareSerializer::new(),
1361 }
1362 }
1363}
1364
1365impl Default for OperationsSerializer {
1366 fn default() -> Self {
1367 Self::new()
1368 }
1369}
1370
1371impl Serializer<Vec<SecureShareOperation>> for OperationsSerializer {
1372 fn serialize(
1396 &self,
1397 value: &Vec<SecureShareOperation>,
1398 buffer: &mut Vec<u8>,
1399 ) -> Result<(), SerializeError> {
1400 let list_len: u32 = value.len().try_into().map_err(|_| {
1401 SerializeError::NumberTooBig("could not encode Operations list length as u32".into())
1402 })?;
1403 self.u32_serializer.serialize(&list_len, buffer)?;
1404 for op in value {
1405 self.signed_op_serializer.serialize(op, buffer)?;
1406 }
1407 Ok(())
1408 }
1409}
1410
1411pub struct OperationsDeserializer {
1413 length_deserializer: U32VarIntDeserializer,
1414 signed_op_deserializer: SecureShareDeserializer<Operation, OperationDeserializer>,
1415}
1416
1417impl OperationsDeserializer {
1418 #[allow(clippy::too_many_arguments)]
1419 pub fn new(
1421 max_operations_per_message: u32,
1422 max_bytecode_size: u64,
1423 max_function_name_length: u16,
1424 max_parameters_size: u32,
1425 max_op_datastore_entry_count: u64,
1426 max_op_datastore_key_length: u8,
1427 max_op_datastore_value_length: u64,
1428 chain_id: u64,
1429 ) -> Self {
1430 Self {
1431 length_deserializer: U32VarIntDeserializer::new(
1432 Included(0),
1433 Included(max_operations_per_message),
1434 ),
1435 signed_op_deserializer: SecureShareDeserializer::new(
1436 OperationDeserializer::new(
1437 max_bytecode_size,
1438 max_function_name_length,
1439 max_parameters_size,
1440 max_op_datastore_entry_count,
1441 max_op_datastore_key_length,
1442 max_op_datastore_value_length,
1443 ),
1444 chain_id,
1445 ),
1446 }
1447 }
1448}
1449
1450impl Deserializer<Vec<SecureShareOperation>> for OperationsDeserializer {
1451 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
1482 &self,
1483 buffer: &'a [u8],
1484 ) -> IResult<&'a [u8], Vec<SecureShareOperation>, E> {
1485 context(
1486 "Failed Operations deserialization",
1487 length_count(
1488 context("Failed length deserialization", |input| {
1489 self.length_deserializer.deserialize(input)
1490 }),
1491 context("Failed operation deserialization", |input| {
1492 self.signed_op_deserializer.deserialize(input)
1493 }),
1494 ),
1495 )
1496 .parse(buffer)
1497 }
1498}
1499
1500pub fn compute_operations_hash(
1502 op_ids: &[OperationId],
1503 op_id_serializer: &OperationIdSerializer,
1504) -> Hash {
1505 let op_ids = op_ids
1506 .iter()
1507 .map(|op_id| {
1508 let mut serialized = Vec::new();
1509 op_id_serializer
1510 .serialize(op_id, &mut serialized)
1511 .expect("serialization of operation id should not fail");
1512 serialized
1513 })
1514 .collect::<Vec<Vec<u8>>>();
1515 massa_hash::Hash::compute_from_tuple(
1516 &op_ids
1517 .iter()
1518 .map(|data| data.as_slice())
1519 .collect::<Vec<_>>(),
1520 )
1521}
1522
1523#[cfg(test)]
1524mod tests {
1525 use crate::config::{
1526 CHAINID, MAX_BYTECODE_LENGTH, MAX_FUNCTION_NAME_LENGTH,
1527 MAX_OPERATION_DATASTORE_ENTRY_COUNT, MAX_OPERATION_DATASTORE_KEY_LENGTH,
1528 MAX_OPERATION_DATASTORE_VALUE_LENGTH, MAX_PARAMETERS_SIZE,
1529 };
1530
1531 use super::*;
1532 use massa_serialization::DeserializeError;
1533 use massa_signature::KeyPair;
1534 use serde_json::Value;
1535 use serial_test::serial;
1536 use std::collections::BTreeMap;
1537
1538 #[test]
1539 #[serial]
1540 fn test_transaction_massa_docs() {
1541 let chain_id: u64 = 77658383;
1547 let sk = "S1CkpvD4WMjJWxR2WZcrDEkJ1kWG2kKe1e3Afe8miqmskHqovvA";
1548 let pk = "P1t4JZwHhWNLt4xYabCbukyVNxSbhYPdF6wCYuRmDuHD784juxd";
1549 let _addr = "AU12m1gXHUGxBZsDF4veeWfYaRmpztBCieHhPBaqf3fcRF2LdAuZ7";
1550 let op_fee = "0.001";
1551 let op_expiry_period = 1000;
1552
1553 let tx_dest_addr = "AU12v83xmHg2UrLM8GLsXRMrm7LQgn3DZVT6kUeFsuFyhZKLkbQtY";
1554 let tx_amount = "3.1";
1555
1556 let op_type = OperationType::Transaction {
1557 recipient_address: Address::from_str(tx_dest_addr).unwrap(),
1558 amount: Amount::from_str(tx_amount).unwrap(),
1559 };
1560
1561 let content = Operation {
1562 fee: Amount::from_str(op_fee).unwrap(),
1563 op: op_type,
1564 expire_period: op_expiry_period,
1565 };
1566
1567 let op_serializer = OperationSerializer::new();
1568 let sender_keypair = KeyPair::from_str(sk).unwrap();
1569
1570 assert_eq!(
1571 sender_keypair.get_public_key(),
1572 PublicKey::from_str(pk).unwrap()
1573 );
1574
1575 let op: SecureShare<Operation, OperationId> =
1576 Operation::new_verifiable(content, op_serializer, &sender_keypair, chain_id).unwrap();
1577
1578 println!("Chain id: {}", *CHAINID);
1579 println!("Operation id: {:?}", op.id);
1580
1581 let mut ser_op = Vec::new();
1582 SecureShareSerializer::new()
1583 .serialize(&op, &mut ser_op)
1584 .unwrap();
1585
1586 println!("Operation serialized:");
1587 println!("{:02X?}", ser_op);
1588 }
1589
1590 #[test]
1591 #[serial]
1592 fn test_transaction() {
1593 let sender_keypair = KeyPair::generate(0).unwrap();
1594 let recv_keypair = KeyPair::generate(0).unwrap();
1595
1596 let op = OperationType::Transaction {
1597 recipient_address: Address::from_public_key(&recv_keypair.get_public_key()),
1598 amount: Amount::default(),
1599 };
1600 let mut ser_type = Vec::new();
1601 OperationTypeSerializer::new()
1602 .serialize(&op, &mut ser_type)
1603 .unwrap();
1604 let (_, res_type) = OperationTypeDeserializer::new(
1605 MAX_BYTECODE_LENGTH,
1606 MAX_FUNCTION_NAME_LENGTH,
1607 MAX_PARAMETERS_SIZE,
1608 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1609 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1610 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1611 )
1612 .deserialize::<DeserializeError>(&ser_type)
1613 .unwrap();
1614
1615 assert_eq!(res_type, op);
1616
1617 let content = Operation {
1618 fee: Amount::from_str("20").unwrap(),
1619 op,
1620 expire_period: 50,
1621 };
1622
1623 let mut ser_content = Vec::new();
1624 OperationSerializer::new()
1625 .serialize(&content, &mut ser_content)
1626 .unwrap();
1627 let (_, res_content) = OperationDeserializer::new(
1628 MAX_BYTECODE_LENGTH,
1629 MAX_FUNCTION_NAME_LENGTH,
1630 MAX_PARAMETERS_SIZE,
1631 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1632 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1633 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1634 )
1635 .deserialize::<DeserializeError>(&ser_content)
1636 .unwrap();
1637 assert_eq!(res_content, content);
1638
1639 let op_serializer = OperationSerializer::new();
1640
1641 let op =
1642 Operation::new_verifiable(content, op_serializer, &sender_keypair, *CHAINID).unwrap();
1643
1644 let mut ser_op = Vec::new();
1645 SecureShareSerializer::new()
1646 .serialize(&op, &mut ser_op)
1647 .unwrap();
1648 let (_, res_op): (&[u8], SecureShareOperation) = SecureShareDeserializer::new(
1649 OperationDeserializer::new(
1650 MAX_BYTECODE_LENGTH,
1651 MAX_FUNCTION_NAME_LENGTH,
1652 MAX_PARAMETERS_SIZE,
1653 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1654 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1655 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1656 ),
1657 *CHAINID,
1658 )
1659 .deserialize::<DeserializeError>(&ser_op)
1660 .unwrap();
1661 assert_eq!(res_op, op);
1662
1663 assert_eq!(op.get_validity_range(10), 40..=50);
1664 }
1665
1666 #[test]
1667 #[serial]
1668 fn test_executesc() {
1669 let sender_keypair = KeyPair::generate(0).unwrap();
1670
1671 let op = OperationType::ExecuteSC {
1672 max_gas: 123,
1673 max_coins: Amount::from_str("1.0").unwrap(),
1674 data: vec![23u8, 123u8, 44u8],
1675 datastore: BTreeMap::from([
1676 (vec![1, 2, 3], vec![4, 5, 6, 7, 8, 9]),
1677 (vec![22, 33, 44, 55, 66, 77], vec![11]),
1678 ]),
1679 };
1680 let mut ser_type = Vec::new();
1681 OperationTypeSerializer::new()
1682 .serialize(&op, &mut ser_type)
1683 .unwrap();
1684 let (_, res_type) = OperationTypeDeserializer::new(
1685 MAX_BYTECODE_LENGTH,
1686 MAX_FUNCTION_NAME_LENGTH,
1687 MAX_PARAMETERS_SIZE,
1688 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1689 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1690 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1691 )
1692 .deserialize::<DeserializeError>(&ser_type)
1693 .unwrap();
1694 assert_eq!(res_type, op);
1695
1696 let content = Operation {
1697 fee: Amount::from_str("20").unwrap(),
1698 op,
1699 expire_period: 50,
1700 };
1701
1702 let mut ser_content = Vec::new();
1703 OperationSerializer::new()
1704 .serialize(&content, &mut ser_content)
1705 .unwrap();
1706 let (_, res_content) = OperationDeserializer::new(
1707 MAX_BYTECODE_LENGTH,
1708 MAX_FUNCTION_NAME_LENGTH,
1709 MAX_PARAMETERS_SIZE,
1710 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1711 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1712 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1713 )
1714 .deserialize::<DeserializeError>(&ser_content)
1715 .unwrap();
1716 assert_eq!(res_content, content);
1717 let op_serializer = OperationSerializer::new();
1718
1719 let op =
1720 Operation::new_verifiable(content, op_serializer, &sender_keypair, *CHAINID).unwrap();
1721
1722 let mut ser_op = Vec::new();
1723 SecureShareSerializer::new()
1724 .serialize(&op, &mut ser_op)
1725 .unwrap();
1726 let (_, res_op): (&[u8], SecureShareOperation) = SecureShareDeserializer::new(
1727 OperationDeserializer::new(
1728 MAX_BYTECODE_LENGTH,
1729 MAX_FUNCTION_NAME_LENGTH,
1730 MAX_PARAMETERS_SIZE,
1731 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1732 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1733 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1734 ),
1735 *CHAINID,
1736 )
1737 .deserialize::<DeserializeError>(&ser_op)
1738 .unwrap();
1739 assert_eq!(res_op, op);
1740
1741 assert_eq!(op.get_validity_range(10), 40..=50);
1742 }
1743
1744 #[test]
1745 #[serial]
1746 fn test_callsc() {
1747 let sender_keypair = KeyPair::generate(0).unwrap();
1748
1749 let target_keypair = KeyPair::generate(0).unwrap();
1750 let target_addr = Address::from_public_key(&target_keypair.get_public_key());
1751
1752 let op = OperationType::CallSC {
1753 max_gas: 123,
1754 target_addr,
1755 coins: Amount::from_str("456.789").unwrap(),
1756 target_func: "target function".to_string(),
1757 param: b"parameter".to_vec(),
1758 };
1759 let mut ser_type = Vec::new();
1760 OperationTypeSerializer::new()
1761 .serialize(&op, &mut ser_type)
1762 .unwrap();
1763 let (_, res_type) = OperationTypeDeserializer::new(
1764 MAX_BYTECODE_LENGTH,
1765 MAX_FUNCTION_NAME_LENGTH,
1766 MAX_PARAMETERS_SIZE,
1767 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1768 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1769 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1770 )
1771 .deserialize::<DeserializeError>(&ser_type)
1772 .unwrap();
1773 assert_eq!(res_type, op);
1774
1775 let content = Operation {
1776 fee: Amount::from_str("20").unwrap(),
1777 op,
1778 expire_period: 50,
1779 };
1780
1781 let mut ser_content = Vec::new();
1782 OperationSerializer::new()
1783 .serialize(&content, &mut ser_content)
1784 .unwrap();
1785 let (_, res_content) = OperationDeserializer::new(
1786 MAX_BYTECODE_LENGTH,
1787 MAX_FUNCTION_NAME_LENGTH,
1788 MAX_PARAMETERS_SIZE,
1789 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1790 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1791 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1792 )
1793 .deserialize::<DeserializeError>(&ser_content)
1794 .unwrap();
1795 assert_eq!(res_content, content);
1796 let op_serializer = OperationSerializer::new();
1797
1798 let op =
1799 Operation::new_verifiable(content, op_serializer, &sender_keypair, *CHAINID).unwrap();
1800
1801 let mut ser_op = Vec::new();
1802 SecureShareSerializer::new()
1803 .serialize(&op, &mut ser_op)
1804 .unwrap();
1805 let (_, res_op): (&[u8], SecureShareOperation) = SecureShareDeserializer::new(
1806 OperationDeserializer::new(
1807 MAX_BYTECODE_LENGTH,
1808 MAX_FUNCTION_NAME_LENGTH,
1809 MAX_PARAMETERS_SIZE,
1810 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1811 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1812 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1813 ),
1814 *CHAINID,
1815 )
1816 .deserialize::<DeserializeError>(&ser_op)
1817 .unwrap();
1818 assert_eq!(res_op, op);
1819
1820 assert_eq!(op.get_validity_range(10), 40..=50);
1821 }
1822
1823 #[test]
1824 #[serial]
1825 fn test_transaction_serde() {
1826 let recv_keypair = KeyPair::generate(0).unwrap();
1827
1828 let op: OperationType = OperationType::Transaction {
1829 recipient_address: Address::from_public_key(&recv_keypair.get_public_key()),
1830 amount: Amount::default(),
1831 };
1832 let mut ser_type = Vec::new();
1833 OperationTypeSerializer::new()
1834 .serialize(&op, &mut ser_type)
1835 .unwrap();
1836 let (_, res_type) = OperationTypeDeserializer::new(
1837 MAX_BYTECODE_LENGTH,
1838 MAX_FUNCTION_NAME_LENGTH,
1839 MAX_PARAMETERS_SIZE,
1840 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1841 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1842 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1843 )
1844 .deserialize::<DeserializeError>(&ser_type)
1845 .unwrap();
1846
1847 assert_eq!(res_type, op);
1848
1849 let orig_operation = Operation {
1850 fee: Amount::from_str("20").unwrap(),
1851 op,
1852 expire_period: 50,
1853 };
1854
1855 let serialized_operation = serde_json::to_string(&orig_operation).unwrap();
1856 let res_operation: Value = serde_json::from_str(&serialized_operation).unwrap();
1857 assert_eq!(orig_operation.fee.to_string(), res_operation["fee"]);
1859 assert_eq!(orig_operation.expire_period, res_operation["expire_period"]);
1860 }
1861
1862 #[test]
1863 #[serial]
1864 fn test_executesc_serde() {
1865 let op = OperationType::ExecuteSC {
1866 max_gas: 123,
1867 max_coins: Amount::from_str("1.0").unwrap(),
1868 data: vec![23u8, 123u8, 44u8],
1869 datastore: BTreeMap::from([
1870 (vec![1, 2, 3], vec![4, 5, 6, 7, 8, 9]),
1871 (vec![22, 33, 44, 55, 66, 77], vec![11]),
1872 ]),
1873 };
1874 let mut ser_type = Vec::new();
1875 OperationTypeSerializer::new()
1876 .serialize(&op, &mut ser_type)
1877 .unwrap();
1878 let (_, res_type) = OperationTypeDeserializer::new(
1879 MAX_BYTECODE_LENGTH,
1880 MAX_FUNCTION_NAME_LENGTH,
1881 MAX_PARAMETERS_SIZE,
1882 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1883 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1884 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1885 )
1886 .deserialize::<DeserializeError>(&ser_type)
1887 .unwrap();
1888 assert_eq!(res_type, op);
1889
1890 let orig_operation = Operation {
1891 fee: Amount::from_str("20").unwrap(),
1892 op,
1893 expire_period: 50,
1894 };
1895
1896 let serialized_operation = serde_json::to_string(&orig_operation).unwrap();
1897 let res_operation: Value = serde_json::from_str(&serialized_operation).unwrap();
1898 assert_eq!(orig_operation.fee.to_string(), res_operation["fee"]);
1900 assert_eq!(orig_operation.expire_period, res_operation["expire_period"]);
1901 }
1902
1903 #[test]
1904 #[serial]
1905 fn test_callsc_serde() {
1906 let target_keypair = KeyPair::generate(0).unwrap();
1907 let target_addr = Address::from_public_key(&target_keypair.get_public_key());
1908
1909 let op = OperationType::CallSC {
1910 max_gas: 123,
1911 target_addr,
1912 coins: Amount::from_str("456.789").unwrap(),
1913 target_func: "target function".to_string(),
1914 param: b"parameter".to_vec(),
1915 };
1916 let mut ser_type = Vec::new();
1917 OperationTypeSerializer::new()
1918 .serialize(&op, &mut ser_type)
1919 .unwrap();
1920 let (_, res_type) = OperationTypeDeserializer::new(
1921 MAX_BYTECODE_LENGTH,
1922 MAX_FUNCTION_NAME_LENGTH,
1923 MAX_PARAMETERS_SIZE,
1924 MAX_OPERATION_DATASTORE_ENTRY_COUNT,
1925 MAX_OPERATION_DATASTORE_KEY_LENGTH,
1926 MAX_OPERATION_DATASTORE_VALUE_LENGTH,
1927 )
1928 .deserialize::<DeserializeError>(&ser_type)
1929 .unwrap();
1930 assert_eq!(res_type, op);
1931
1932 let orig_operation = Operation {
1933 fee: Amount::from_str("20").unwrap(),
1934 op,
1935 expire_period: 50,
1936 };
1937
1938 let serialized_operation = serde_json::to_string(&orig_operation).unwrap();
1939 let res_operation: Value = serde_json::from_str(&serialized_operation).unwrap();
1940 assert_eq!(orig_operation.fee.to_string(), res_operation["fee"]);
1942 assert_eq!(orig_operation.expire_period, res_operation["expire_period"]);
1943 }
1944}