Crate concordium_std

source ·
Expand description

This library provides the core API that can be used to write smart contracts for the Concordium blockchain. It aims to provide safe wrappers around the core primitives exposed by the chain and accessible to smart contracts.

The library is meant to be used as a standard library for developing smart contracts. For this reason it re-exports a number of definitions from other libraries.

Versions

The concordium blockchain at present supports two variants of smart contracts. The original V0 contracts that use message-passing for communication and have limited state, and V1 contracts which use synchronous calls, and have extended state. Versions 1 and 2 of concordium-std support only V0 contracts. Version 3 and later of concordium-std supports only V1 contracts.

Also note that concordium-std version 4 only works with cargo-concordium version 2.1+.

Panic handler

When compiled without the std feature this crate sets the panic handler so that it terminates the process immediately, without any unwinding or prints. Concretely, when compiled to the wasm32 target panic boils down to the unreachable instruction, which triggers a runtime failure, aborting execution of the program.

Features

This library has the following features: std, build-schema, wasm-test, crypto-primitives, and wee_alloc

std: Build with the Rust standard library

By default this library will be linked with the std crate, the rust standard library, however to minimize code size this library supports toggling compilation with the #![no_std] attribute via the feature std which is enabled by default. Compilation without the std feature requires a nightly version of rust.

To use this library without the std feature you have to disable it, which can be done, for example, as follows.

[dependencies.concordium-std]
default-features = false

In your project’s Cargo.toml file.

build-schema: Build for generating a module schema

WARNING Building with this feature enabled is meant for tooling, and the result is not intended to be deployed on chain.

This library provides a way to automate the building of smart contract module schema, by allowing the contract to be built exporting getter functions for the concordium_contracts_common::schema::Type of Types for contract state and parameters. This special build is only intended to be used for generating the schema and is not meant to be deployed, since the build exports functions that do not conform to the expected API of smart contracts. The build is enabled by setting the feature build-schema.

Note This feature is used by cargo-concordium, when building with schema and for most cases this feature should not be set manually.

wasm-test: Build for testing in Wasm

WARNING Building with this feature enabled is meant for tooling, and the result is not intended to be deployed on chain.

The macros #[concordium_test] and #[concordium_cfg_test] are reduced to #[test] and #[cfg(test)] unless the wasm-test feature is enabled.

With the wasm-test feature enabled, the #[concordium_test] macro exports the test as an extern function, allowing tools such as cargo-concordium to call the test functions directly, when compiled to Wasm. Without the feature it falls back to #[test].

With the ‘wasm-test’ feature enabled, the #[concordium_cfg_test] macro allows the annotated code to be included in the build. Without the feature, it falls back to #[cfg(test)].

Note This feature is used by cargo-concordium, when building for testing and for most cases this feature should not be set manually.

crypto-primitives: For testing crypto with actual implementations

Build with this feature if you want to run smart contract tests with actual (i.e., not mock) implementations of the cryptographic primitives from HasCryptoPrimitives.

WARNING: It is not possible to build this crate on macOS with the crypto-primitives feature when targeting wasm32-unknown-unknown. The issue arises when compiling the secp256k1 crate.

Use a custom allocator

Some operations in concordium-std need to dynamically allocate memory. Rust programs compiled with default compiler settings have access to a standard allocator implemented in the Rust standard library. When using the no-std feature there is no default allocator provided by the Rust toolchain, and so one must be set explicitly.

In the past concordium-std hard-coded the use of wee_alloc however since version 5.2.0 this is no longer the case. Instead no allocator is set by default, however there is a wee_alloc feature (disabled by default) that can be enabled which sets the allocator to wee_alloc. This can be used both with and without the std feature.

The main reason for using wee_alloc instead of the default allocator, even in std builds, is that wee_alloc has a smaller code footprint, i.e, the resulting smart contracts are going to be smaller by about 6-10kB, which means they are cheaper to deploy and run. The downside is that this allocator is designed to be used in contexts where there are a few large allocations up-front, and the memory is afterward used by the program without many further allocations. Frequent small allocations will have bad performance, and should be avoided. Do note that this allocator is at present unmaintained. There are other allocators available, for example dlmalloc.

We only provide wee_alloc via a feature for backwards compatibility. Configuration of other allocators should follow their respective documentation, however note that there can only be one allocator set. See Rust allocator documentation for more context and details.

Traits

To support testing of smart contracts most of the functionality is accessible via traits. This library generally provides two implementations of most traits. The first one is supported by host functions, and this is the implementation that is used when contracts are executed by nodes. The second set of implementations supports testing of contracts and it is defined in the test_infrastructure module.

  • HasParameter for accessing the contract parameter
  • HasCommonData for accessing the data that is common to both init and receive methods
  • HasInitContext for all the context data available to the init functions (note that this includes all the common data)
  • HasReceiveContext for accessing all the context data available to the receive functions (note that this includes all the common data)
  • HasLogger for logging data during smart contract execution
  • HasPolicy for accessing the policy of the sender, either of the init or receive method
  • HasStateApi for operations possible on the contract state
  • HasHost for invoking operations on the host and accessing the state
  • HasCryptoPrimitives for using cryptographic primitives such as hashing and signature verification.

Signalling errors

On the Wasm level contracts can signal errors by returning a negative i32 value as a result of either initialization or invocation of the receive method. If the error is a logic error and the contract executes successfully then it can also produce a return value, which may provide additional detail of the error to the caller. To make error handling more pleasant we provide the Reject structure. The result type of a contract init or a receive method is assumed to be of the form Result<_, E> where Reject: From<E>.

Producing return values is in case of errors is not yet supported by this library, although smart contract writers can do this manually using the Write implementation of the ExternReturnValue type.

With respect to error codes, the intention is that smart contract writers will write their own custom, precise, error types and either manually implement Reject: From<E> for their type E, or use the Reject macro which supports the common use cases.

In addition to the custom errors that signal contract-specific error conditions this library provides some common error cases that most contracts will have to handle and their conversions to Reject. These are

VariantError code
()-2147483647
ParseError-2147483646
LogError::Full-2147483645
LogError::Malformed-2147483644
NewContractNameError::MissingInitPrefix-2147483643
NewContractNameError::TooLong-2147483642
NewContractNameError::ContainsDot-2147483639
NewContractNameError::InvalidCharacters-2147483638
NewReceiveNameError::MissingDotSeparator-2147483641
NewReceiveNameError::TooLong-2147483640
NewReceiveNameError::InvalidCharacters-2147483637
NotPayableError-2147483636
TransferError::AmountTooLarge-2147483635
TransferError::MissingAccount-2147483634
CallContractError::AmountTooLarge-2147483633
CallContractError::MissingAccount-2147483632
CallContractError::MissingContract-2147483631
CallContractError::MissingEntrypoint-2147483630
CallContractError::MessageFailed-2147483629
CallContractError::LogicReject-2147483628
CallContractError::Trap-2147483627
UpgradeError::MissingModule-2147483626
UpgradeError::MissingContract-2147483625
UpgradeError::UnsupportedModuleVersion-2147483624
QueryAccountBalanceError-2147483623
QueryContractBalanceError-2147483622

Other error codes may be added in the future and custom error codes should not use the range i32::MIN to i32::MIN + 100.

Modules

Currently defined attributes possible in a policy.
Re-export. The Box<T> type for heap allocation.
Re-export. Shareable mutable containers.
Re-export. Utilities for comparing and ordering values.
Re-export.
Chain constants that impose limits on various aspects of smart contract execution.
Re-export. Traits for conversions between types.
Re-export. Utilities for formatting and printing Strings.
Re-export. Generic hashing support.
Re-export. Hints to compiler that affects how code should be emitted or optimized. Hints may be compile time or runtime.
Re-export. Composable external iteration.
Re-export. Primitive traits and types representing basic properties of types.
Re-export. Basic functions for dealing with memory.
Re-export. Additional functionality for numerics.
Re-export. Overloadable operators.
This module provides the primitive interface to the chain. Functions here should be wrapped in safer wrappers when used from contracts. This module is provided for expert users who wish to optimize their smart contract to the utmost for space and size, and should not be used by the majority of users.
Re-export. Single-threaded reference-counting pointers. ‘Rc’ stands for ‘Reference Counted’.
Types related to contract schemas. These are optional annotations in modules that allow the users of smart contracts to interact with them in a way that is better than constructing raw bytes as parameters.
The test infrastructure module provides alternative implementations of HasInitContext, HasReceiveContext, HasParameter, HasStateApi, and HasHost traits intended for testing.

Macros

The bail macro can be used for cleaner error handling. If the function has result type Result invoking bail will terminate execution early with an error. If an argument is supplied, this will be used as the error, otherwise it requires the type E in Result<_, E> to implement the Default trait.
The claim macro is used for testing as a substitute for the assert macro. It checks the condition and if false it reports back an error. Used only in testing.
Ensure the first two arguments are equal, just like assert_eq!, otherwise reports an error. Used only in testing.
Ensure the first two arguments are not equal, just like assert_ne!, otherwise reports an error. Used only in testing.
The ensure macro can be used for cleaner error handling. It is analogous to assert, but instead of panicking it uses bail to terminate execution of the function early.
Variants of ensure for ease of use in certain contexts.
Ensure the first two arguments are not equal, using bail otherwise.
The fail macro is used for testing as a substitute for the panic macro. It reports back error information to the host. Used only in testing.

Structs

Address of an account, as raw bytes.
The current public balances of an account.
The type of amounts on the chain
Tag of an attribute. See the module attributes for the currently supported attributes.
An attribute value. The meaning of the bytes is dependent on the type of the attribute.
A type representing the attributes, lazily acquired from the host.
Re-export. A pointer type that uniquely owns a heap allocation of type T.
Chain metadata accessible to both receive and init methods. Information about the chain available to smart contracts.
Address of a contract.
A contract name. Expected format: “init_<contract_name>”.
Add offset tracking inside a data structure.
Duration of time in milliseconds.
An entrypoint name (borrowed version). Expected format: “<func_name>” where the name of the function consists solely of ASCII alphanumeric or punctuation characters.
An exchange rate between two quantities. This is never 0, and the exchange rate should also never be infinite.
The current exchange rates.
A type representing the return value of contract init or receive method. The intention is that this type is manipulated using methods of the Write trait. In particular it can be used as a sink to serialize values into.
Keccak digest with 256 bits (32 bytes).
Sha2 digest with 256 bits (32 bytes).
Sha3 digest with 256 bits (32 bytes).
A type representing the logger.
A reference to a smart contract module deployed on the chain.
Error triggered when a non-zero amount of CCD is sent to a contract init or receive function that is not marked as payable.
A view into an occupied entry in a StateMap. It can be obtained via the StateMap::entry method. This allows looking up or modifying the value at a give key in-place.
A view into an occupied entry in a HasStateApi type. It is part of the EntryRaw enum.
A contract name (owned version). Expected format: “init_<contract_name>”.
An entrypoint name (owned version). Expected format: “<func_name>”. Most methods on this type are available via the as_entrypoint_name and the methods on the EntrypointName type.
Parameter to the init function or entrypoint. Owned version.
A receive name (owned version). Expected format: “<contract_name>.<func_name>”. Most methods are available only on the ReceiveName type, the intention is to access those via the as_receive_name method.
Parameter to the init function or entrypoint.
Zero-sized type to represent an error when reading bytes and deserializing.
An iterator over policies using host functions to supply the data. The main interface to using this type is via the methods of the Iterator and ExactSizeIterator traits.
Policy on the credential of the account.
An iterator over the attributes of a policy. The iterator returns pairs of AttributeTag and AttributeValue.
Public key for ECDSA over Secp256k1. Must be 33 bytes long.
Public key for Ed25519. Must be 32 bytes long.
Error for querying the balance of an account. No account found for the provided account address.
Error for querying the balance of a smart contract instance. No instance found for the provided contract address.
A receive name. Expected format: “<contract_name>.<func_name>”.
An error message, signalling rejection of a smart contract invocation. The client will see the error code as a reject reason; if a schema is provided, the error message corresponding to the error code will be displayed. The valid range for an error code is from i32::MIN to -1. A return value can also be provided.
Signature for a ECDSA (over Secp256k1) message. Must be 64 bytes longs (serialized in compressed format).
Signature for a Ed25519 message. Must be 64 bytes long.
A pointer type for data in the state.
An state builder that allows the creation of StateMap, StateSet, and StateBox. It is parametrized by a parameter S that is assumed to implement HasStateApi.
Represents the data in a node in the state trie.
A high-level map based on the low-level key-value store, which is the interface provided by the chain.
An iterator over the entries of a StateMap.
A mutable iterator over the entries of a StateMap.
The StateRef behaves akin the type &'a V, except that it is not copyable. It should be used as MutexGuard or similar types which guard access to a resource.
The StateRefMut<_, V, _> behaves like &mut V, by analogy with other standard library RAII guards like RefMut. The type implements DerefMut which allows the value to be mutated. Additionally, the Drop implementation ensures that the value is properly stored in the contract state maintained by the node.
A high-level set of flat values based on the low-level key-value store, which is the interface provided by the chain.
An iterator over the entries of a StateMap.
Re-export. A UTF-8–encoded, growable string.
Timestamp represented as milliseconds since unix epoch.
A view into a vacant entry in a StateMap. It is part of the Entry enum.
A view into a vacant entry in a HasStateApi type. It is part of the EntryRaw enum.
Re-export. A contiguous growable array type, written as Vec<T>, short for ‘vector’.

Enums

Either an address of an account, or contract.
An error indicating why parsing of an amount failed. Since amount parsing is typically a user-facing activity this is fairly precise, so we can notify the user why we failed, and what they can do to fix it.
Errors that may occur when invoking a contract entrypoint.
A view into a single entry in a StateMap, which may either be vacant or occupied.
A view into a single entry in a HasStateApi type, which may either be vacant or occupied.
Errors that can occur during logging.
Errors that can occur when constructing a new AttributeValue.
This is essentially equivalent to the SeekFrom type from the rust standard library, but reproduced here to avoid dependency on std::io, as well as to use 32-bit integers to specify positions. This saves some computation and space, and is adequate for the kind of data sizes that are possible in smart contracts.
The error type which is returned by methods on HasStateApi.
Errors that may occur when transferring CCD to an account.
Errors that may occur when upgrading the smart contract module.

Constants

Size of an account address when serialized in binary. NB: This is different from the Base58 representation.

Traits

A type that can be deleted from the state. For simple types, such as u8 and String, the delete methods is a no-op. But for StateBox, StateMap, and StateSet, delete makes sure to the delete all the necessary data from the state.
The Deserial trait provides a means of reading structures from byte-sources (Read).
The DeserialCtx trait provides a means of reading structures from byte-sources (Read) using contextual information. The contextual information is:
The DeserialCtxWithState trait provides a means of reading structures from byte-sources (Read) using contextual information for types that also need a reference to a HasStateApi type. The trait is a combination of the DeserialCtx and DeserialWithState traits, which each has additional documentation.
The DeserialWithState trait provides a means of reading structures from byte-sources (Read) for types that also need a reference to a HasStateApi type.
Analogue of the expect_err methods on Result, but useful in a Wasm setting.
Analogue of the expect_none methods on Option, but useful in a Wasm setting.
Analogue of the expect methods on types such as Option, but useful in a Wasm setting.
A more convenient wrapper around Deserial that makes it easier to write deserialization code. It has a blanked implementation for any read and serialize pair. The key idea is that the type to deserialize is inferred from the context, enabling one to write, for example,
Objects which can access call responses from contract invocations.
Objects which can access chain metadata.
Common data accessible to both init and receive methods.
Objects which provide cryptographic primitives.
A type that can serve as the host, meaning that it supports interactions with the chain, such as querying balance of the contract, accessing its state, and invoking operations on other contracts and accounts.
Types which can act as init contexts.
Objects which can serve as loggers.
Objects which can access parameters to contracts.
A type which has access to a policy of a credential. Since policies can be large this is deliberately written in a relatively low-level style to enable efficient traversal of all the attributes without any allocations.
Types which can act as receive contexts.
The HasSize trait provides a function for getting the current byte size.
Types which can serve as the contract state.
A type that can serve as the contract state entry type.
The Read trait provides a means of reading from byte streams.
The Seek trait provides a cursor which can be moved within a stream of bytes. This is essentially a copy of std::io::Seek, but avoiding its dependency on std::io::Error, and the associated code size increase. Additionally, the positions are expressed in terms of 32-bit integers since this is adequate for the sizes of data in smart contracts.
The Serial trait provides a means of writing structures into byte-sinks (Write).
The SerialCtx trait provides a means of writing structures into byte-sinks (Write) using contextual information. The contextual information is:
The Serialize trait provides a means of writing structures into byte-sinks (Write) or reading structures from byte sources (Read).
Types that can be cloned along with the state.
Add optimized unwrap behaviour that aborts the process instead of panicking.
The Write trait provides functionality for writing to byte streams.

Functions

Read a HashMap as a list of key-value pairs given some length.
Read a HashSet as a list of keys, given some length. NB: This ensures there are no duplicates.
Read a BTreeMap as a list of key-value pairs given some length. NB: This ensures there are no duplicates, hence the specialized type. Moreover this will only succeed if keys are listed in order.
Read a BTreeMap as a list of key-value pairs given some length. Slightly faster version of deserial_map_no_length as it is skipping the order checking
Read a BTreeSet as a list of keys, given some length. NB: This ensures there are no duplicates, hence the specialized type. Moreover this will only succeed if keys are listed in order.
Read a BTreeSet as an list of key-value pairs given some length. Slightly faster version of deserial_set_no_length as it is skipping the order checking. The only check that is made to the set is that there are no duplicates.
Read a vector given a length.
Dual to to_bytes.
Check whether the given string is a valid contract entrypoint name. This is the case if and only if
Write a HashMap as a list of key-value pairs in to particular order, without the length information.
Write a HashSet as a list of keys in no particular order, without the length information.
Write a Map as a list of key-value pairs ordered by the key, without the length information.
Write a BTreeSet as an ascending list of keys, without the length information.
Write a slice of elements, without including length information. This is intended to be used either when the length is statically known, or when the length is serialized independently as part of a bigger structure.
Serialize the given value to a freshly allocated vector of bytes using the provided Serial instance.
Terminate execution immediately without panicking. When the std feature is enabled this is just std::process::abort. When std is not present and the target architecture is wasm32 this will simply emit the unreachable instruction. Terminates the process in an abnormal fashion.

Type Definitions

A wrapper around Result that fixes the error variant to CallContractError, and the result to (bool, Option<A>). If the result is Ok then the boolean indicates whether the state was modified or not, and the second item is the actual return value, which is present (i.e., Some) if and only if a V1 contract was invoked.
Contract address index. A contract address consists of an index and a subindex. This type is for the index.
Contract address subindex. A contract address consists of an index and a subindex. This type is for the subindex.
Reexport of the HashMap from hashbrown with the default hasher set to the fnv hash function.
Reexport of the HashSet from hashbrown with the default hasher set to the fnv hash function.
Index of the identity provider on the chain. An identity provider with the given index will not be replaced, so this is a stable identifier.
The expected return type of the init method of the smart contract, parametrized by the state type of the smart contract.
Type of keys that index into the contract state.
A policy with a vector of attributes, fully allocated and owned. This is in contrast to a policy which is lazily read from a read source. The latter is useful for efficiency, this type is more useful for testing since the values are easier to construct.
A type alias used to indicate that the value is a result of parsing from binary via the Serial instance.
A wrapper around Result that fixes the error variant to QueryAccountBalanceError and result to AccountBalance.
A wrapper around Result that fixes the error variant to QueryContractBalanceError and result to Amount.
A wrapper around Result that fixes the error variant to CallContractError, and the result to Option<A> If the result is Ok then the value is None if a V0 contract was invoked, and a return value returned by a V1 contract otherwise.
The expected return type of the receive method of a smart contract.
Time at the beginning of the current slot, in miliseconds since unix epoch.
A wrapper around Result that fixes the error variant to TransferError and result to ().
A wrapper around Result that fixes the error variant to UpgradeError and result to ().

Attribute Macros

If wasm-test feature of concordium-std is enabled ignore the item, this usually happens when executing tests with cargo-concordium utility. Otherwise this is equivalent to #[cfg(not(test))]. Use as a dual to #[concordium_cfg_test].
Sets the cfg for testing targeting either Wasm and native.
Derive the appropriate export for an annotated test function, when feature “wasm-test” is enabled, otherwise behaves like #[test].
Derive the appropriate export for an annotated init function.
Derive the appropriate export for an annotated receive function.

Derive Macros

Derive the Deletable trait. See the documentation of derive(Deletable) for details and limitations.
Derive the Deserial trait. See the documentation of derive(Serial) for details and limitations.
Derive the DeserialWithState trait. See the documentation of derive(Deserial) for details and limitations.
Derive the conversion of enums that represent error types into the Reject struct which can be used as the error type of init and receive functions. Creating custom enums for error types can provide meaningful error messages to the user of the smart contract.
Derive the SchemaType trait for a type. If the feature build-schema is not enabled this is a no-op, i.e., it does not produce any code.
Derive the Serial trait for the type.
A helper macro to derive both the Serial and Deserial traits. [derive(Serialize)] is equivalent to [derive(Serial, Deserial)], see documentation of the latter two for details and options: derive(Serial), derive(Deserial).
Derive the StateClone trait. See the documentation of derive(StateClone) for details and limitations.