concordium_std/prims.rs
1//! This module provides the primitive interface to the chain.
2//! Functions here should be wrapped in safer wrappers when used from contracts.
3//! **This module is provided for expert users who wish to optimize their smart
4//! contract to the utmost for space and size, and should not be used by the
5//! majority of users.**
6//!
7//! The functions in this module are inherently unsafe, and if preconditions
8//! that they state are not ensured then strange behaviour will occur. The
9//! behaviour is well-defined on the compiled Wasm by the semantics of the
10//! chain, but it is essentially impossible to predict since it is affected by
11//! memory layout decided by the compiler and the allocator, and other Rust
12//! implementation details. Consequences can range from accidental memory
13//! corruption to program termination.
14
15// Interface to the chain. These functions are assumed to be instantiated by
16// the scheduler with relevant primitives.
17#[cfg_attr(target_arch = "wasm32", link(wasm_import_module = "concordium"))]
18extern "C" {
19 /// Invoke a host instruction. The arguments are
20 ///
21 /// - `tag`, which instruction to invoke
22 /// - 0 for transfer to account
23 /// - 1 for call to a contract
24 /// - 2 for query an account balance (protocol 5 onwards).
25 /// - 3 for query a contract balance (protocol 5 onwards).
26 /// - 4 for query the exchange rates (protocol 5 onwards).
27 /// - 5 for checking an account signature (protocol 6 onwards).
28 /// - 6 for getting the public keys of an account (protocol 6 onwards).
29 /// - 7 for getting the module reference of a contract instance (protocol
30 /// 7 onwards).
31 /// - 8 for getting the contract name of a contract instance (protocol 7
32 /// onwards).
33 /// - `start`, pointer to the start of the invoke payload
34 /// - `length`, length of the payload
35 /// - if the last 5 bytes are 0 then the call succeeded. In this case the
36 /// first bit of the response indicates whether our own state has changed
37 /// (1) or not (0) the remaining 23 bits are the index of the return value
38 /// that can be used in a call to `get_parameter_section` and
39 /// `get_parameter_size`.
40 /// - otherwise
41 /// - if the fourth byte is 0 the call failed because of a logic error and
42 /// there is a return value. Bits 1..24 of the response are the index of
43 /// the return value. Bits 32..64 are to be interpreted in two's
44 /// complement and will be a negative number indicating the error code.
45 /// - otherwise only the fourth byte is set.
46 /// - if it is 1 then call failed due to transfer of non-existent amount
47 /// - if it is 2 then the account to transfer to did not exist
48 /// - if it is 3 then the contract to invoke did not exist
49 /// - if it is 4 then the entrypoint did not exist
50 /// - if it is 5 then sending a message to V0 contract failed.
51 /// - if it is 6 then invoking a contract failed with a runtime error
52 /// - no other values are possible
53 pub fn invoke(tag: u32, start: *const u8, length: u32) -> u64;
54 /// Write to the return value of the contract. The parameters are
55 ///
56 /// - `start` the pointer to the location in memory where the data resides
57 /// - `length` the size of data (in bytes)
58 /// - `offset` where in the return value to write the data
59 ///
60 /// The return value indicates how many bytes were written.
61 pub fn write_output(start: *const u8, length: u32, offset: u32) -> u32;
62 /// Upgrade the smart contract module to a provided module.
63 /// The only argument is a pointer to 32 bytes for the module reference to
64 /// become the new smart contract module of this instance.
65 /// A return value of:
66 /// - `0` means the upgrade succeeded.
67 /// - `0x07_0000_0000` means the upgrade failed: The provided module was not
68 /// found.
69 /// - `0x08_0000_0000` means the upgrade failed: The new module did not
70 /// contain a contract with the same name.
71 /// - `0x09_0000_0000` means the upgrade failed: The new module is an
72 /// unsupported smart contract module version.
73 pub fn upgrade(module_ref: *const u8) -> u64;
74 /// Get the size of the `i`-th parameter to the call. 0-th parameter is
75 /// always the original parameter that the method was invoked with,
76 /// invoking a contract adds additional parameters to the stack. Returns
77 /// `-1` if the given parameter does not exist.
78 pub fn get_parameter_size(i: u32) -> i32;
79 /// Write a section of the `i`-th parameter to the given location. Return
80 /// the number of bytes written or `-1` if the parameter does not exist.
81 /// The location is assumed to contain enough memory to
82 /// write the requested length into.
83 pub fn get_parameter_section(i: u32, param_bytes: *mut u8, length: u32, offset: u32) -> i32;
84 /// Write a section of the policy to the given location. Return the number
85 /// of bytes written. The location is assumed to contain enough memory to
86 /// write the requested length into.
87 pub fn get_policy_section(policy_bytes: *mut u8, length: u32, offset: u32) -> u32;
88 /// Add a log item. Return values are
89 /// - -1 if logging failed due to the message being too long
90 /// - 0 if the log is already full
91 /// - 1 if data was successfully logged.
92 pub fn log_event(start: *const u8, length: u32) -> i32;
93
94 /// Lookup an entry with the given key. The return value is either
95 /// u64::MAX if the entry at the given key does not exist, or else
96 /// the first bit of the result is 0, and the remaining bits
97 /// are an entry identifier that may be used in subsequent calls.
98 pub fn state_lookup_entry(key_start: *const u8, key_length: u32) -> u64;
99
100 /// Create an empty entry with the given key. The return value is either
101 /// u64::MAX if creating the entry failed because of an iterator lock on
102 /// the part of the tree, or else the first bit is 0, and the remaining
103 /// bits are an entry identifier that maybe used in subsequent calls.
104 /// If an entry at that key already exists it is set to the empty entry.
105 pub fn state_create_entry(key_start: *const u8, key_length: u32) -> u64;
106
107 /// Delete the entry. Returns one of
108 /// - 0 if the part of the tree this entry was in is locked
109 /// - 1 if the entry did not exist
110 /// - 2 if the entry was deleted as a result of this call.
111 pub fn state_delete_entry(key_start: *const u8, key_length: u32) -> u32;
112
113 /// Delete a prefix in the tree, that is, delete all parts of the tree that
114 /// have the given key as prefix. Returns
115 /// - 0 if the tree was locked and thus deletion failed.
116 /// - 1 if the tree **was not locked**, but the key points to an empty part
117 /// of the tree
118 /// - 2 if a part of the tree was successfully deleted
119 pub fn state_delete_prefix(key_start: *const u8, key_length: u32) -> u32;
120
121 /// Construct an iterator over a part of the tree. This **locks the part of
122 /// the tree that has the given prefix**. Locking means that no
123 /// deletions or insertions of entries may occur in that subtree.
124 /// Returns
125 /// - all 1 bits if too many iterators already exist with this key
126 /// - all but second bit set to 1 if there is no value in the state with the
127 /// given key
128 /// - otherwise the first bit is 0, and the remaining bits are the iterator
129 /// identifier
130 /// that may be used in subsequent calls to advance it, or to get its key.
131 pub fn state_iterate_prefix(prefix_start: *const u8, prefix_length: u32) -> u64;
132
133 /// Return the next entry along the iterator, and advance the iterator.
134 /// The return value is
135 /// - u64::MAX if the iterator does not exist (it was deleted, or the ID is
136 /// invalid)
137 /// - all but the second bit set to 1 if no more entries are left, the
138 /// iterator
139 /// is exhausted. All further calls will yield the same until the iterator
140 /// is deleted.
141 /// - otherwise the first bit is 0, and the remaining bits encode an entry
142 /// identifier that can be passed to any of the entry methods.
143 pub fn state_iterator_next(iterator: u64) -> u64;
144
145 /// Delete the iterator, unlocking the subtree. Returns
146 /// - u64::MAX if the iterator does not exist.
147 /// - 0 if the iterator was already deleted
148 /// - 1 if the iterator was successfully deleted as a result of this call.
149 pub fn state_iterator_delete(iterator: u64) -> u32;
150
151 /// Get the size of the key that the iterator is currently pointing at.
152 /// Returns
153 /// - u32::MAX if the iterator does not exist
154 /// - otherwise the length of the key in bytes.
155 pub fn state_iterator_key_size(iterator: u64) -> u32;
156
157 /// Read a section of the key the iterator is currently pointing at. Returns
158 /// either
159 /// - u32::MAX if the iterator has already been deleted
160 /// - the amount of data that was copied. This will never be more than the
161 /// supplied length.
162 /// Before the first call to the [state_iterator_next] function this returns
163 /// (sections of) the key that was used to create the iterator. After
164 /// [state_iterator_next] returns (the encoding of) [None] this method
165 /// returns (sections of) the key at the first node returned by the
166 /// iterator.
167 pub fn state_iterator_key_read(iterator: u64, start: *mut u8, length: u32, offset: u32) -> u32;
168
169 // Operations on the entry.
170
171 /// Read a part of the entry. The arguments are
172 /// entry ... entry id returned by state_iterator_next or state_create_entry
173 /// start ... where to write in Wasm memory
174 /// length ... length of the data to read
175 /// offset ... where to start reading in the entry
176 /// The return value is
177 /// - u32::MAX if the entry does not exist (has been invalidated, or never
178 /// existed). In this case no data is written.
179 /// - amount of data that was read. This is never more than length.
180 pub fn state_entry_read(entry: u64, start: *mut u8, length: u32, offset: u32) -> u32;
181
182 /// Write a part of the entry. The arguments are
183 /// entry ... entry id returned by state_iterator_next or state_create_entry
184 /// start ... where to read from Wasm memory
185 /// length ... length of the data to read
186 /// offset ... where to start writing in the entry
187 /// The return value is
188 /// - u32::MAX if the entry does not exist (has been invalidated, or never
189 /// existed). In this case no data is written.
190 /// - amount of data that was written. This is never more than length.
191 pub fn state_entry_write(entry: u64, start: *const u8, length: u32, offset: u32) -> u32;
192
193 /// Return the current size of the entry in bytes.
194 /// The return value is either
195 /// - u32::MAX if the entry does not exist (has been invalidated, or never
196 /// existed). In this case no data is written.
197 /// - or the size of the entry.
198 pub fn state_entry_size(entry: u64) -> u32;
199
200 /// Resize the entry to the given size. Returns
201 /// - u32::MAX if the entry has already been invalidated
202 /// - 0 if the attempt was unsuccessful because new_size exceeds maximum
203 /// entry size
204 /// - 1 if the entry was successfully resized.
205 pub fn state_entry_resize(entry: u64, new_size: u32) -> u32;
206
207 // Getter for the init context.
208 /// Address of the sender, 32 bytes
209 pub fn get_init_origin(start: *mut u8);
210
211 // Getters for the receive context
212 /// Invoker of the top-level transaction, AccountAddress.
213 pub fn get_receive_invoker(start: *mut u8);
214 /// Address of the contract itself, ContractAddress.
215 pub fn get_receive_self_address(start: *mut u8);
216 /// Self-balance of the contract, returns the amount
217 pub fn get_receive_self_balance() -> u64;
218 /// Immediate sender of the message (either contract or account).
219 pub fn get_receive_sender(start: *mut u8);
220 /// Owner of the contract, AccountAddress.
221 pub fn get_receive_owner(start: *mut u8);
222
223 /// Get the size of the entrypoint that was named.
224 pub fn get_receive_entrypoint_size() -> u32;
225
226 /// Write the receive entrypoint name into the given location.
227 /// It is assumed that the location contains enough space to write the name.
228 pub fn get_receive_entrypoint(start: *mut u8);
229
230 // Getters for the chain meta data
231 /// Slot time from chain meta data.
232 /// Note that this is a Timestamp (unix timestamp with millisecond
233 /// precision).
234 pub fn get_slot_time() -> u64;
235
236 // Cryptographic primitives
237
238 /// Verify an ed25519 signature. The public key is expected to be 32 bytes,
239 /// the signature is expected to be 64 bytes, and the message may be
240 /// variable length.
241 ///
242 /// The return value is 0 if verification fails, and 1 if it succeeds. No
243 /// other return values are possible.
244 pub fn verify_ed25519_signature(
245 public_key: *const u8,
246 signature: *const u8,
247 message: *const u8,
248 message_len: u32,
249 ) -> i32;
250
251 /// Verify an ecdsa over secp256k1 with bitcoin-core implementation.
252 /// The public key is expected to be 33 bytes, the signature is expected
253 /// to be 64 bytes (serialized in compressed format), and the message
254 /// must be 32 bytes. We only allow checking signatures on 32-byte arrays
255 /// which are expected to be message hashes.
256 ///
257 /// The return value is 0 if verification fails, and 1 if it succeeds. No
258 /// other return values are possible.
259 pub fn verify_ecdsa_secp256k1_signature(
260 public_key: *const u8,
261 signature: *const u8,
262 message_hash: *const u8,
263 ) -> i32;
264
265 /// Hash the data using the SHA2-256 algorithm. The resulting hash (32
266 /// bytes) is written starting at the `output` pointer. The output
267 /// segment *may* overlap with the data segment.
268 pub fn hash_sha2_256(data: *const u8, data_len: u32, output: *mut u8);
269
270 /// Hash the data using the SHA3-256 algorithm. The resulting hash (32
271 /// bytes) is written starting at the `output` pointer. The output
272 /// segment *may* overlap with the data segment.
273 pub fn hash_sha3_256(data: *const u8, data_len: u32, output: *mut u8);
274
275 /// Hash the data using Keccak-256 algorithm. The resulting hash (32 bytes)
276 /// is written starting at the `output` pointer. The output segment
277 /// *may* overlap with the data segment.
278 pub fn hash_keccak_256(data: *const u8, data_len: u32, output: *mut u8);
279
280 #[cfg(all(feature = "wasm-test", target_arch = "wasm32"))]
281 /// Reporting back an error, only exists in debug mode
282 pub(crate) fn report_error(
283 msg_start: *const u8,
284 msg_length: u32,
285 filename_start: *const u8,
286 filename_length: u32,
287 line: u32,
288 column: u32,
289 );
290
291 #[cfg(feature = "debug")]
292 /// Emit text together with the source location.
293 /// This is used as the equivalent of the `dbg!` macro when the
294 /// `debug` feature is enabled.
295 ///
296 /// Note that this function is not allowed on the chain, it is only there to
297 /// ease local testing.
298 pub fn debug_print(
299 msg_start: *const u8,
300 msg_length: u32,
301 filename_start: *const u8,
302 filename_length: u32,
303 line: u32,
304 column: u32,
305 );
306
307 #[cfg(all(feature = "wasm-test", feature = "concordium-quickcheck", target_arch = "wasm32"))]
308 /// Generating random numbers for randomised testing.
309 /// Not available for contracts deployed on the chain.
310 pub(crate) fn get_random(dest: *mut u8, size: u32);
311}
312
313// For every external function, we must provide a dummy function.
314// This is necessary to compile to x86_64 during unit tests on Windows and OSX.
315#[cfg(not(target_arch = "wasm32"))]
316mod host_dummy_functions {
317 #[no_mangle]
318 fn invoke(_tag: u32, _start: *const u8, _length: u32) -> u64 {
319 unimplemented!("Dummy function! Not to be executed")
320 }
321 #[no_mangle]
322 fn write_output(_start: *const u8, _length: u32, _offset: u32) -> u32 {
323 unimplemented!("Dummy function! Not to be executed")
324 }
325 #[no_mangle]
326 fn upgrade(_module_ref: *const u8) -> u64 {
327 unimplemented!("Dummy function! Not to be executed.")
328 }
329 #[no_mangle]
330 extern "C" fn get_parameter_size(_i: u32) -> i32 {
331 unimplemented!("Dummy function! Not to be executed")
332 }
333 #[no_mangle]
334 extern "C" fn get_parameter_section(
335 _i: u32,
336 _param_bytes: *mut u8,
337 _length: u32,
338 _offset: u32,
339 ) -> i32 {
340 unimplemented!("Dummy function! Not to be executed")
341 }
342 #[no_mangle]
343 extern "C" fn get_policy_section(_policy_bytes: *mut u8, _length: u32, _offset: u32) -> u32 {
344 unimplemented!("Dummy function! Not to be executed")
345 }
346 #[no_mangle]
347 extern "C" fn log_event(_start: *const u8, _length: u32) -> i32 {
348 unimplemented!("Dummy function! Not to be executed")
349 }
350 #[no_mangle]
351 pub(crate) fn state_lookup_entry(_key_start: *const u8, _key_length: u32) -> u64 {
352 unimplemented!("Dummy function! Not to be executed")
353 }
354 #[no_mangle]
355 pub(crate) fn state_create_entry(_key_start: *const u8, _key_length: u32) -> u64 {
356 unimplemented!("Dummy function! Not to be executed")
357 }
358 #[no_mangle]
359 pub(crate) fn state_delete_entry(_entry: u64) -> u32 {
360 unimplemented!("Dummy function! Not to be executed")
361 }
362 #[no_mangle]
363 pub(crate) fn state_delete_prefix(_key_start: *const u8, _key_length: u32) -> u32 {
364 unimplemented!("Dummy function! Not to be executed")
365 }
366 #[no_mangle]
367 pub(crate) fn state_iterate_prefix(_prefix_start: *const u8, _prefix_length: u32) -> u64 {
368 unimplemented!("Dummy function! Not to be executed")
369 }
370 #[no_mangle]
371 pub(crate) fn state_iterator_next(_iterator: u64) -> u64 {
372 unimplemented!("Dummy function! Not to be executed")
373 }
374 #[no_mangle]
375 pub(crate) fn state_iterator_delete(_iterator: u64) -> u32 {
376 unimplemented!("Dummy function! Not to be executed")
377 }
378 #[no_mangle]
379 pub(crate) fn state_iterator_key_size(_iterator: u64) -> u32 {
380 unimplemented!("Dummy function! Not to be executed")
381 }
382 #[no_mangle]
383 pub(crate) fn state_iterator_key_read(
384 _iterator: u64,
385 _start: *mut u8,
386 _length: u32,
387 _offset: u32,
388 ) -> u32 {
389 unimplemented!("Dummy function! Not to be executed")
390 }
391 #[no_mangle]
392 pub(crate) fn state_entry_read(
393 _entry: u64,
394 _start: *mut u8,
395 _length: u32,
396 _offset: u32,
397 ) -> u32 {
398 unimplemented!("Dummy function! Not to be executed")
399 }
400 #[no_mangle]
401 pub(crate) fn state_entry_write(
402 _entry: u64,
403 _start: *const u8,
404 _length: u32,
405 _offset: u32,
406 ) -> u32 {
407 unimplemented!("Dummy function! Not to be executed")
408 }
409 #[no_mangle]
410 pub(crate) fn state_entry_resize(_entry: u64, _new_size: u32) -> u32 {
411 unimplemented!("Dummy function! Not to be executed")
412 }
413 #[no_mangle]
414 pub(crate) fn state_entry_size(_entry: u64) -> u32 {
415 unimplemented!("Dummy function! Not to be executed")
416 }
417 #[no_mangle]
418 extern "C" fn get_init_origin(_start: *mut u8) {
419 unimplemented!("Dummy function! Not to be executed")
420 }
421 #[no_mangle]
422 extern "C" fn get_receive_invoker(_start: *mut u8) {
423 unimplemented!("Dummy function! Not to be executed")
424 }
425 #[no_mangle]
426 extern "C" fn get_receive_self_address(_start: *mut u8) {
427 unimplemented!("Dummy function! Not to be executed")
428 }
429 #[no_mangle]
430 extern "C" fn get_receive_self_balance() -> u64 {
431 unimplemented!("Dummy function! Not to be executed")
432 }
433 #[no_mangle]
434 extern "C" fn get_receive_sender(_start: *mut u8) {
435 unimplemented!("Dummy function! Not to be executed")
436 }
437 #[no_mangle]
438 extern "C" fn get_receive_owner(_start: *mut u8) {
439 unimplemented!("Dummy function! Not to be executed")
440 }
441 #[no_mangle]
442 extern "C" fn get_receive_entrypoint_size() -> u32 {
443 unimplemented!("Dummy function! Not to be executed")
444 }
445 #[no_mangle]
446 extern "C" fn get_receive_entrypoint(_start: *mut u8) {
447 unimplemented!("Dummy function! Not to be executed")
448 }
449
450 #[no_mangle]
451 extern "C" fn get_slot_time() -> u64 { unimplemented!("Dummy function! Not to be executed") }
452
453 #[no_mangle]
454 extern "C" fn verify_ed25519_signature(
455 _public_key: *const u8,
456 _signature: *const u8,
457 _message: *const u8,
458 _message_len: u32,
459 ) -> i32 {
460 unimplemented!("Dummy function! Not to be executed")
461 }
462
463 #[no_mangle]
464 fn verify_ecdsa_secp256k1_signature(
465 _public_key: *const u8,
466 _signature: *const u8,
467 _message_hash: *const u8,
468 ) -> i32 {
469 unimplemented!("Dummy function! Not to be executed")
470 }
471
472 #[no_mangle]
473 fn hash_sha2_256(_data: *const u8, _data_len: u32, _output: *mut u8) {
474 unimplemented!("Dummy function! Not to be executed")
475 }
476
477 #[no_mangle]
478 fn hash_sha3_256(_data: *const u8, _data_len: u32, _output: *mut u8) {
479 unimplemented!("Dummy function! Not to be executed")
480 }
481
482 #[no_mangle]
483 fn hash_keccak_256(_data: *const u8, _data_len: u32, _output: *mut u8) {
484 unimplemented!("Dummy function! Not to be executed")
485 }
486
487 #[no_mangle]
488 fn report_error(
489 _msg_start: *const u8,
490 _msg_length: u32,
491 _filename_start: *const u8,
492 _filename_length: u32,
493 _line: u32,
494 _column: u32,
495 ) {
496 unimplemented!("Dummy function! Not to be executed")
497 }
498
499 #[no_mangle]
500 fn debug_print(
501 _msg_start: *const u8,
502 _msg_length: u32,
503 _filename_start: *const u8,
504 _filename_length: u32,
505 _line: u32,
506 _column: u32,
507 ) {
508 unimplemented!("Dummy function! Not to be executed")
509 }
510
511 #[no_mangle]
512 fn get_random(_dest: *mut u8, _size: u32) {
513 unimplemented!("Dummy function! Not to be executed")
514 }
515}