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