ab_contracts_common/method.rs
1use crate::metadata::ContractMetadataKind;
2use ab_core_primitives::hashes::Blake3Hash;
3use ab_io_type::trivial_type::TrivialType;
4use const_sha1::sha1;
5use derive_more::Display;
6
7/// Hash of method's compact metadata, which uniquely represents method signature.
8///
9/// While nothing can be said about method implementation, matching method fingerprint means method
10/// name, inputs and outputs are what they are expected to be (struct and field names are ignored as
11/// explained in [`ContractMetadataKind::compact`].
12#[derive(Debug, Display, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, TrivialType)]
13#[repr(C)]
14pub struct MethodFingerprint(Blake3Hash);
15
16impl MethodFingerprint {
17 /// Create a new method fingerprint from its metadata.
18 ///
19 /// `None` is returned for invalid metadata (see
20 /// [`ContractMetadataKind::compact_external_args()`] for details).
21 pub const fn new(method_metadata: &[u8]) -> Option<Self> {
22 // `?` is not supported in `const` environment
23 let Some((compact_metadata_scratch, compact_metadata_size)) =
24 ContractMetadataKind::compact_external_args(method_metadata)
25 else {
26 return None;
27 };
28 // The same as `&compact_metadata_scratch[..compact_metadata_size]`, but it is not allowed
29 // in const environment yet
30 let compact_metadata = compact_metadata_scratch.split_at(compact_metadata_size).0;
31
32 let hash = sha1(compact_metadata).as_bytes();
33
34 Some(Self(Blake3Hash::new([
35 hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8],
36 hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], hash[16],
37 hash[17], hash[18], hash[19], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38 ])))
39 }
40
41 #[inline(always)]
42 pub const fn to_bytes(&self) -> &[u8; Blake3Hash::SIZE] {
43 self.0.as_bytes()
44 }
45}
46
47/// Marker trait for external arguments when calling methods.
48///
49/// # Safety
50/// Struct that implements this trait must be `#[repr(C)]` and valid `ExternalArgs` for the contract
51/// method being called.
52///
53/// **Do not implement this trait explicitly!** Implementation is automatically generated by the
54/// macro which generates contract implementation.
55pub unsafe trait ExternalArgs {
56 /// Fingerprint of the method being called
57 const FINGERPRINT: MethodFingerprint;
58 /// Metadata that corresponds to a method being called
59 const METADATA: &[u8];
60}