ab_contracts_common/
lib.rs

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