rust_chain/
transaction.rs

1use crate::serializer::{
2    Packer,
3    Encoder,
4    Decoder,
5};
6
7use crate::structs::{
8    TimePointSec,
9    Uint128,
10};
11
12use crate::varint::{
13    VarUint32,
14};
15
16use crate::action::{
17    Action,
18};
19
20use crate::{
21    vec::Vec,
22    Name,
23    send_deferred,
24    tapos_block_num,
25    tapos_block_prefix
26};
27
28#[cfg_attr(feature = "std", derive(crate::eosio_scale_info::TypeInfo))]
29#[derive(Clone, Eq, PartialEq, Default)]
30pub struct TransactionExtension {
31    pub ty:     u16,
32    pub data:   Vec<u8>,
33}
34
35impl Packer for TransactionExtension {
36    fn size(&self) -> usize {
37        let mut _size: usize = 0;
38        _size += self.ty.size();
39        _size += self.data.size();
40        return _size;
41    }
42
43    fn pack(&self, enc: &mut Encoder) -> usize {
44        let pos = enc.get_size();
45
46        self.ty.pack(enc);
47        self.data.pack(enc);
48
49        enc.get_size() - pos
50    }
51    fn unpack(&mut self, data: &[u8]) -> usize {
52        let mut dec = Decoder::new(data);
53        dec.unpack::<u16>(&mut self.ty);
54        dec.unpack::<Vec<u8>>(&mut self.data);
55        return dec.get_pos();
56    }
57}
58
59#[cfg_attr(feature = "std", derive(crate::eosio_scale_info::TypeInfo))]
60#[derive(Clone, Eq, PartialEq, Default)]
61pub struct Transaction {
62    expiration:             TimePointSec,
63    ref_block_num:          u16,
64    ref_block_prefix:       u32,
65    //[VLQ or Base-128 encoding](https://en.wikipedia.org/wiki/Variable-length_quantity)
66    //unsigned_int vaint (eosio.cdt/libraries/eosiolib/core/eosio/varint.hpp)
67    max_net_usage_words:    VarUint32, /// number of 8 byte words this transaction can serialize into after compressions
68    max_cpu_usage_ms:       u8, /// number of CPU usage units to bill transaction for
69    delay_sec:              VarUint32, /// number of seconds to delay transaction, default: 0
70    context_free_actions:   Vec<Action>,
71    actions:                Vec<Action>,
72    extension:              Vec<TransactionExtension>,
73}
74
75impl Transaction {
76    pub fn new(expiration: u32, delay_sec: u32) -> Self {
77        Self {
78            expiration: TimePointSec { seconds: expiration },
79            ref_block_num: tapos_block_num() as u16,
80            ref_block_prefix: tapos_block_prefix(),
81            max_net_usage_words: VarUint32::new(0),
82            max_cpu_usage_ms: 0,
83            delay_sec: VarUint32::new(delay_sec),
84            context_free_actions: Vec::new(),
85            actions: Vec::new(),
86            extension: Vec::new()
87        }
88    }
89
90    pub fn expiration(&self) -> TimePointSec {
91        return self.expiration;
92    }
93
94    pub fn ref_block_num(&self) -> u32 {
95        return self.ref_block_num as u32;
96    }
97
98    pub fn ref_block_prefix(&self) -> u32 {
99        return self.ref_block_prefix;
100    }
101
102    pub fn max_net_usage_words(&self) -> u32 {
103        return self.max_net_usage_words.value();
104    }
105
106    pub fn max_cpu_usage_ms(&self) -> u32 {
107        return self.max_cpu_usage_ms as u32;
108    }
109
110    pub fn delay_sec(&self) -> u32 {
111        return self.delay_sec.value();
112    }
113
114    pub fn actions(&self) -> &Vec<Action> {
115        return &self.actions;
116    }
117
118    pub fn add_action(&mut self, action: Action) {
119        self.actions.push(action);
120    }
121
122    pub fn context_free_actions(&self) -> &Vec<Action> {
123        return &self.context_free_actions;
124    }
125
126    pub fn extension(&self) -> &Vec<TransactionExtension> {
127        return &self.extension;
128    }
129
130    pub fn send(&self, payer: Name, id: u128, replace_existing: bool) {
131        let id = Uint128{lo: (id & u64::MAX as u128) as u64, hi: (id >> 64) as u64};
132        send_deferred(&id, payer, &Encoder::pack(self), replace_existing.into());
133    }
134
135}
136
137impl Packer for Transaction {
138    fn size(&self) -> usize {
139        let mut _size: usize = 0;
140        _size += self.expiration.size();
141        _size += self.ref_block_num.size();
142        _size += self.ref_block_prefix.size();
143        _size += self.max_net_usage_words.size();
144        _size += self.max_cpu_usage_ms.size();
145        _size += self.delay_sec.size();
146        _size += self.context_free_actions.size();
147        _size += self.actions.size();
148        _size += self.extension.size();
149        return _size;
150    }
151
152    fn pack(&self, enc: &mut Encoder) -> usize {
153        let pos = enc.get_size();
154
155        self.expiration.pack(enc);
156        self.ref_block_num.pack(enc);
157        self.ref_block_prefix.pack(enc);
158        self.max_net_usage_words.pack(enc);
159        self.max_cpu_usage_ms.pack(enc);
160        self.delay_sec.pack(enc);
161        self.context_free_actions.pack(enc);
162        self.actions.pack(enc);
163        self.extension.pack(enc);
164
165        enc.get_size() - pos
166    }
167
168    fn unpack(&mut self, data: &[u8]) -> usize {
169        let mut dec = Decoder::new(data);
170        dec.unpack(&mut self.expiration);
171        dec.unpack(&mut self.ref_block_num);
172        dec.unpack(&mut self.ref_block_prefix);
173        dec.unpack(&mut self.max_net_usage_words);
174        dec.unpack(&mut self.max_cpu_usage_ms);
175        dec.unpack(&mut self.delay_sec);
176        dec.unpack(&mut self.context_free_actions);
177        dec.unpack(&mut self.actions);
178        dec.unpack(&mut self.extension);
179        return dec.get_pos();
180    }
181}
182
183// bool
184// check_transaction_authorization( const transaction&                 trx,
185//                                  const std::set<permission_level>&  provided_permissions ,
186//                                  const std::set<public_key>&        provided_keys = std::set<public_key>()
187//                                )