ab_contracts_common/
lib.rs

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