Skip to main content

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}