Skip to main content

ab_contracts_common/
lib.rs

1#![feature(
2    const_convert,
3    const_index,
4    const_result_trait_fn,
5    const_split_off_first_last,
6    const_trait_impl,
7    const_try,
8    mut_restriction
9)]
10#![no_std]
11
12pub mod env;
13mod error;
14pub mod metadata;
15pub mod method;
16
17use crate::method::MethodFingerprint;
18use ab_io_type::IoType;
19use ab_io_type::variable_bytes::VariableBytes;
20use core::ffi::c_void;
21use core::ops::Deref;
22use core::ptr::NonNull;
23pub use error::{ContractError, CustomContractErrorCode, ExitCode};
24
25/// Function name used to make calls from guest to host
26pub const HOST_CALL_FN: &str = "__ab_host_call";
27/// Import function name used to make calls from guest to host
28pub const HOST_CALL_FN_IMPORT: &str = "__ab_host_call_import";
29/// The name of the static variable that contains contract metadata
30pub const METADATA_STATIC_NAME_PREFIX: &str = "__ab_metadata_";
31/// Max allowed size of the contract code
32pub const MAX_CODE_SIZE: u32 = 1024 * 1024;
33/// Max number of arguments in a method.
34///
35/// NOTE: Both `self` and return type that is not `()` or `Result<(), ContractError>` count towards
36/// the total number of method arguments.
37pub const MAX_TOTAL_METHOD_ARGS: u8 = 8;
38
39/// Method details used by the native execution environment.
40///
41/// `ffi_fn`'s argument is actually `NonNull<InternalArgs>` of a corresponding method and must have
42/// corresponding ABI.
43///
44/// NOTE: It is unlikely to be necessary to interact with this directly.
45#[derive(Debug, Copy, Clone)]
46#[doc(hidden)]
47pub struct NativeExecutorContactMethod {
48    pub method_fingerprint: &'static MethodFingerprint,
49    pub method_metadata: &'static [u8],
50    pub ffi_fn: unsafe extern "C" fn(NonNull<c_void>) -> ExitCode,
51}
52
53/// A trait that indicates the struct is a contact.
54///
55/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
56/// macro which generates contract implementation. This trait is required, but not sufficient for
57/// proper contract implementation, use `#[contract]` attribute macro instead.
58pub trait Contract: IoType {
59    /// Main contract metadata, see [`ContractMetadataKind`] for encoding details.
60    ///
61    /// More metadata can be contributed by trait implementations.
62    ///
63    /// [`ContractMetadataKind`]: crate::metadata::ContractMetadataKind
64    const MAIN_CONTRACT_METADATA: &[u8];
65    /// Something that can be used as "code" in native execution environment.
66    ///
67    /// NOTE: It is unlikely to be necessary to interact with this directly.
68    #[doc(hidden)]
69    const CODE: &str;
70    /// Methods of a contract used in native execution environment.
71    ///
72    /// NOTE: It is unlikely to be necessary to interact with this directly.
73    #[doc(hidden)]
74    const NATIVE_EXECUTOR_METHODS: &[NativeExecutorContactMethod];
75    // Default value is provided to only fail to compile when contract that uses
76    // `ab-contracts-common` has feature specified, but `ab-contracts-common` does not, but not the
77    // other way around (as will be the case with dependencies where `guest` feature must not be
78    // enabled)
79    #[cfg(feature = "guest")]
80    #[doc(hidden)]
81    const GUEST_FEATURE_ENABLED: () = ();
82    /// Slot type used by this contract
83    type Slot: IoType;
84    /// Tmp type used by this contract
85    type Tmp: IoType;
86    /// Something that can be used as "code" in native execution environment and primarily used for
87    /// testing.
88    ///
89    /// This is NOT the code compiled for guest architecture!
90    // TODO: Make `const` when possible
91    fn code() -> impl Deref<Target = VariableBytes<MAX_CODE_SIZE>>;
92}
93
94/// A trait that indicates the implementation of a contract trait by a contract.
95///
96/// `DynTrait` here is `dyn ContractTrait`, which is a bit of a hack that allows treating a trait as
97/// a type for convenient API in native execution environment.
98///
99/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
100/// macro which generates contract trait implementation. This trait is required, but not sufficient
101/// for proper trait implementation, use `#[contract]` attribute macro instead.
102///
103/// NOTE: It is unlikely to be necessary to interact with this directly.
104pub trait ContractTrait<DynTrait>
105where
106    DynTrait: ?Sized,
107{
108    /// Methods of a trait used in native execution environment
109    #[doc(hidden)]
110    const NATIVE_EXECUTOR_METHODS: &[NativeExecutorContactMethod];
111}
112
113/// A trait that is implemented for `dyn ContractTrait` and includes constants related to trait
114/// definition.
115///
116/// `dyn ContractTrait` here is a bit of a hack that allows treating a trait as a type. These
117/// constants specifically can't be implemented on a trait itself because that'll make trait
118/// not object safe, which is needed for [`ContractTrait`] that uses a similar hack with
119/// `dyn ContractTrait`.
120///
121/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
122/// macro which generates trait definition. This trait is required, but not sufficient for
123/// proper trait implementation, use `#[contract]` attribute macro instead.
124///
125/// NOTE: It is unlikely to be necessary to interact with this directly.
126pub trait ContractTraitDefinition {
127    // Default value is provided to only fail to compile when trait that uses
128    // `ab-contracts-common` has feature specified, but `ab-contracts-common` does not, but not the
129    // other way around (as will be the case with dependencies where `guest` feature must not be
130    // enabled)
131    #[cfg(feature = "guest")]
132    #[doc(hidden)]
133    const GUEST_FEATURE_ENABLED: () = ();
134    /// Trait metadata, see [`ContractMetadataKind`] for encoding details"]
135    /// Trait metadata, see [`ContractMetadataKind`] for encoding details"]
136    ///
137    /// [`ContractMetadataKind`]: crate::metadata::ContractMetadataKind
138    const METADATA: &[::core::primitive::u8];
139}