superfluid_executor/
envelope.rs1use superfluid_abi::{checksum_kind, StateEnvelope, TokenRange, Status, STATE_ENVELOPE_MAGIC};
4
5pub const ENVELOPE_VERSION: u32 = 1;
6pub const ENVELOPE_BYTES: usize = std::mem::size_of::<StateEnvelope>();
7
8pub fn compat_identity(kind: u32, version_tag: u64, runtime: &str, version: &str, weights: &[u8; 32]) -> [u8; 32] {
9 let mut input = Vec::with_capacity(64 + runtime.len() + version.len());
10 input.extend_from_slice(&kind.to_le_bytes());
11 input.extend_from_slice(&version_tag.to_le_bytes());
12 input.extend_from_slice(runtime.as_bytes());
13 input.push(0);
14 input.extend_from_slice(version.as_bytes());
15 input.push(0);
16 input.extend_from_slice(weights);
17 let h = superfluid_fingerprint::fnv1a64(&input, 0xCBF2_9CE4_8422_2325);
18 let mut out = [0u8; 32];
19 out[..8].copy_from_slice(&h.to_le_bytes());
20 out[8..16].copy_from_slice(&superfluid_fingerprint::fnv1a64(&input, h).to_le_bytes());
21 out
22}
23
24pub struct SealArgs<'a> {
25 pub kind: u32,
26 pub version_tag: u64,
27 pub compat: [u8; 32],
28 pub provenance: [u8; 32],
29 pub taint_bits: u32,
30 pub range: TokenRange,
31 pub encoding: u8,
32 pub payload: &'a [u8],
33}
34
35pub fn seal(a: SealArgs<'_>) -> Vec<u8> {
36 let env = StateEnvelope {
37 magic: STATE_ENVELOPE_MAGIC,
38 envelope_version: ENVELOPE_VERSION,
39 space_kind: a.kind,
40 compat_identity: a.compat,
41 version_tag: a.version_tag,
42 provenance_digest: a.provenance,
43 taint_bits: a.taint_bits,
44 _pad0: 0,
45 range: a.range,
46 encoding: a.encoding,
47 _pad1: [0; 3],
48 checksum_kind: checksum_kind::FNV1A64,
49 payload_len: a.payload.len() as u64,
50 content_checksum: superfluid_fingerprint::fnv1a64(a.payload, 0xCBF2_9CE4_8422_2325),
51 };
52 let mut out = Vec::with_capacity(ENVELOPE_BYTES + a.payload.len());
53 let env_bytes = unsafe { std::slice::from_raw_parts(&env as *const _ as *const u8, ENVELOPE_BYTES) };
56 out.extend_from_slice(env_bytes);
57 out.extend_from_slice(a.payload);
58 out
59}
60
61pub fn open<'a>(
62 bytes: &'a [u8],
63 kind: u32,
64 version_tag: u64,
65 compat: &[u8; 32],
66) -> Result<(StateEnvelope, &'a [u8]), Status> {
67 if bytes.len() < ENVELOPE_BYTES {
68 return Err(Status::EnvelopeMismatch);
69 }
70 let mut env = StateEnvelope::default();
71 unsafe { std::ptr::copy_nonoverlapping(bytes.as_ptr(), &mut env as *mut _ as *mut u8, ENVELOPE_BYTES) };
74 if env.magic != STATE_ENVELOPE_MAGIC || env.envelope_version != ENVELOPE_VERSION {
75 return Err(Status::EnvelopeMismatch);
76 }
77 if env.space_kind != kind {
78 return Err(Status::EnvelopeMismatch);
79 }
80 if env.compat_identity != *compat || env.version_tag != version_tag {
81 return Err(Status::IdentityMismatch);
82 }
83 let payload = &bytes[ENVELOPE_BYTES..];
84 if payload.len() as u64 != env.payload_len {
85 return Err(Status::EnvelopeMismatch);
86 }
87 match env.checksum_kind {
88 checksum_kind::FNV1A64 => {
89 if superfluid_fingerprint::fnv1a64(payload, 0xCBF2_9CE4_8422_2325) != env.content_checksum {
90 return Err(Status::Checksum);
91 }
92 }
93 _ => return Err(Status::EnvelopeMismatch),
94 }
95 Ok((env, payload))
96}