dusk_core/transfer/
data.rs1use alloc::string::String;
11use alloc::vec::Vec;
12use alloc::{format, vec};
13
14use bytecheck::CheckBytes;
15use dusk_bytes::{DeserializableSlice, Error as BytesError, Serializable};
16use piecrust_uplink::StandardBufSerializer;
17use rkyv::ser::serializers::{
18 BufferScratch, BufferSerializer, CompositeSerializer,
19};
20use rkyv::ser::Serializer;
21use rkyv::validation::validators::DefaultValidator;
22use rkyv::{Archive, Deserialize, Infallible, Serialize};
23
24use crate::abi::ContractId;
25use crate::Error;
26
27pub const MAX_MEMO_SIZE: usize = 512;
29
30#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
32#[archive_attr(derive(CheckBytes))]
33#[allow(clippy::large_enum_variant)]
34pub enum TransactionData {
35 Call(ContractCall),
37 Deploy(ContractDeploy),
39 Memo(Vec<u8>),
42}
43
44impl From<ContractCall> for TransactionData {
45 fn from(c: ContractCall) -> Self {
46 TransactionData::Call(c)
47 }
48}
49
50impl From<ContractDeploy> for TransactionData {
51 fn from(d: ContractDeploy) -> Self {
52 TransactionData::Deploy(d)
53 }
54}
55
56impl From<Vec<u8>> for TransactionData {
57 fn from(d: Vec<u8>) -> Self {
58 TransactionData::Memo(d)
59 }
60}
61
62impl From<String> for TransactionData {
63 fn from(d: String) -> Self {
64 TransactionData::Memo(d.as_bytes().to_vec())
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
70#[archive_attr(derive(CheckBytes))]
71pub struct ContractDeploy {
72 pub bytecode: ContractBytecode,
74 pub owner: Vec<u8>,
76 pub init_args: Option<Vec<u8>>,
78 pub nonce: u64,
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
84#[archive_attr(derive(CheckBytes))]
85pub struct ContractCall {
86 pub contract: ContractId,
88 pub fn_name: String,
90 pub fn_args: Vec<u8>,
92}
93
94impl ContractDeploy {
95 #[must_use]
97 pub fn to_var_bytes(&self) -> Vec<u8> {
98 let mut bytes = Vec::new();
99
100 bytes.extend(&self.bytecode.to_var_bytes());
101
102 bytes.extend((self.owner.len() as u64).to_bytes());
103 bytes.extend(&self.owner);
104
105 match &self.init_args {
106 Some(init_args) => {
107 bytes.push(1);
108 bytes.extend((init_args.len() as u64).to_bytes());
109 bytes.extend(init_args);
110 }
111 None => bytes.push(0),
112 }
113
114 bytes.extend(self.nonce.to_bytes());
115
116 bytes
117 }
118
119 pub fn from_slice(buf: &[u8]) -> Result<Self, BytesError> {
124 let mut buf = buf;
125
126 let bytecode = ContractBytecode::from_buf(&mut buf)?;
127
128 let owner = crate::read_vec(&mut buf)?;
129
130 let init_args = match u8::from_reader(&mut buf)? {
131 0 => None,
132 1 => Some(crate::read_vec(&mut buf)?),
133 _ => return Err(BytesError::InvalidData),
134 };
135
136 let nonce = u64::from_reader(&mut buf)?;
137
138 Ok(Self {
139 bytecode,
140 owner,
141 init_args,
142 nonce,
143 })
144 }
145}
146
147impl ContractCall {
148 pub fn new(
159 contract: impl Into<ContractId>,
160 fn_name: impl Into<String>,
161 ) -> Self {
162 Self {
163 contract: contract.into(),
164 fn_name: fn_name.into(),
165 fn_args: vec![],
166 }
167 }
168
169 #[must_use]
178 pub fn with_raw_args(mut self, fn_args: Vec<u8>) -> Self {
179 self.fn_args = fn_args;
180 self
181 }
182
183 pub fn with_args<A>(self, fn_arg: &A) -> Result<Self, Error>
200 where
201 A: for<'b> Serialize<StandardBufSerializer<'b>>,
202 A::Archived: for<'b> CheckBytes<DefaultValidator<'b>>,
203 {
204 const SCRATCH_SPACE: usize = 1024;
206 const PAGE_SIZE: usize = 0x1000;
207
208 let mut sbuf = [0u8; SCRATCH_SPACE];
209 let scratch = BufferScratch::new(&mut sbuf);
210 let mut buffer = [0u8; PAGE_SIZE];
211 let ser = BufferSerializer::new(&mut buffer[..]);
212 let mut ser = CompositeSerializer::new(ser, scratch, Infallible);
213
214 ser.serialize_value(fn_arg)
215 .map_err(|e| Error::Rkyv(format!("{e:?}")))?;
216 let pos = ser.pos();
217
218 let fn_args = buffer[..pos].to_vec();
219
220 Ok(self.with_raw_args(fn_args))
221 }
222
223 #[must_use]
225 pub fn to_var_bytes(&self) -> Vec<u8> {
226 let mut bytes = Vec::new();
227
228 bytes.extend(self.contract.as_bytes());
229
230 let fn_name_bytes = self.fn_name.as_bytes();
231 bytes.extend((fn_name_bytes.len() as u64).to_bytes());
232 bytes.extend(fn_name_bytes);
233
234 bytes.extend((self.fn_args.len() as u64).to_bytes());
235 bytes.extend(&self.fn_args);
236
237 bytes
238 }
239
240 pub fn from_slice(buf: &[u8]) -> Result<Self, BytesError> {
245 let mut buf = buf;
246
247 let contract = crate::read_arr::<32>(&mut buf)?;
248
249 let fn_name = crate::read_str(&mut buf)?;
250
251 let fn_args = crate::read_vec(&mut buf)?;
252
253 Ok(Self {
254 contract: contract.into(),
255 fn_name,
256 fn_args,
257 })
258 }
259}
260
261#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
262#[archive_attr(derive(CheckBytes))]
263pub struct ContractBytecode {
265 pub hash: [u8; 32],
267 pub bytes: Vec<u8>,
269}
270
271impl ContractBytecode {
272 #[must_use]
274 pub fn to_hash_input_bytes(&self) -> Vec<u8> {
275 self.hash.to_vec()
276 }
277
278 #[must_use]
280 pub fn to_var_bytes(&self) -> Vec<u8> {
281 let mut bytes = Vec::new();
282 bytes.extend(self.hash);
283 bytes.extend((self.bytes.len() as u64).to_bytes());
284 bytes.extend(&self.bytes);
285 bytes
286 }
287
288 pub fn from_buf(buf: &mut &[u8]) -> Result<Self, BytesError> {
294 let hash = crate::read_arr::<32>(buf)?;
295 let bytes = crate::read_vec(buf)?;
296 Ok(Self { hash, bytes })
297 }
298}