aleph_types/message/
instance.rs1use crate::message::execution::base::ExecutableContent;
2use crate::message::execution::environment::InstanceEnvironment;
3use crate::message::execution::volume::RootfsVolume;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub struct InstanceContent {
8 #[serde(flatten)]
9 base: ExecutableContent,
10 environment: InstanceEnvironment,
12 rootfs: RootfsVolume,
14}
15
16#[cfg(test)]
17mod test {
18 use super::*;
19 use crate::chain::Chain;
20 use crate::message::base_message::{MessageConfirmation, MessageContentEnum};
21 use crate::message::execution::base::{Payment, PaymentType};
22 use crate::message::execution::environment::{
23 GpuDeviceClass, GpuProperties, HostRequirements, Hypervisor, MachineResources,
24 NodeRequirements,
25 };
26 use crate::message::execution::volume::{ParentVolume, VolumePersistence};
27 use crate::message::{ContentSource, Message, MessageType};
28 use crate::storage_size::{MemorySize, MiB};
29 use crate::timestamp::Timestamp;
30 use crate::{address, channel, item_hash, signature};
31 use assert_matches::assert_matches;
32 use std::collections::HashMap;
33
34 const INSTANCE_PAYG_FIXTURE: &str = include_str!(concat!(
35 env!("CARGO_MANIFEST_DIR"),
36 "/../../fixtures/messages/instance/instance-gpu-payg.json"
37 ));
38
39 #[test]
40 fn test_deserialize_instance_message() {
41 let message: Message = serde_json::from_str(INSTANCE_PAYG_FIXTURE).unwrap();
42
43 assert_eq!(
44 message.sender,
45 address!("0x238224C744F4b90b4494516e074D2676ECfC6803")
46 );
47 assert_eq!(message.chain, Chain::Ethereum);
48 assert_eq!(
49 message.signature,
50 signature!(
51 "0x4f7250efd67d989ac3067358ee657e301cd437fd0b4acb38342402e60125a0a209818f555386cd17b82080aba0a7a5cd83e4e1d8875c58b38f2e64cbe5dd308f1c"
52 )
53 );
54 assert_matches!(message.message_type, MessageType::Instance);
55 assert_matches!(
56 message.content_source,
57 ContentSource::Inline { item_content: _ }
58 );
59 assert_eq!(
60 message.item_hash,
61 item_hash!("a41fb91c3e68370759b72338dd1947f18e2ed883837aec5dc731d5f427f90564")
62 );
63 assert_eq!(message.time, Timestamp::from(1762349117.833245));
64 assert_eq!(message.channel, Some(channel!("ALEPH-CLOUDSOLUTIONS")));
65
66 assert_eq!(
68 &message.content.address,
69 &address!("0x238224C744F4b90b4494516e074D2676ECfC6803")
70 );
71 assert_eq!(&message.content.time, &Timestamp::from(1762349117.833176));
72
73 let instance_content = match message.content() {
75 MessageContentEnum::Instance(content) => content,
76 other => {
77 panic!("Expected MessageContentEnum::Instance, got {:?}", other);
78 }
79 };
80
81 assert!(!instance_content.base.allow_amend);
82 assert_eq!(
83 instance_content.base.metadata,
84 Some(HashMap::from([(
85 "name".to_string(),
86 serde_json::Value::String("gpu-l40s-2".to_string())
87 )]))
88 );
89 assert_eq!(instance_content.base.variables, None);
90 assert_eq!(
91 instance_content.base.resources,
92 MachineResources {
93 vcpus: 12,
94 memory: MiB::from_units(73728),
95 seconds: 30,
96 published_ports: None,
97 }
98 );
99 assert_eq!(
100 instance_content.base.authorized_keys,
101 Some(vec![
102 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC068SD08xlTtMxTdmCe3rPVM/uA7SvgDUiQwP0FrIGS Libertai".to_string()
103 ])
104 );
105 assert_eq!(
106 instance_content.environment,
107 InstanceEnvironment {
108 internet: true,
109 aleph_api: true,
110 hypervisor: Some(Hypervisor::Qemu),
111 trusted_execution: None,
112 reproducible: false,
113 shared_cache: false,
114 }
115 );
116
117 let expected_requirements = HostRequirements {
118 cpu: None,
119 node: Some(NodeRequirements {
120 owner: None,
121 address_regex: None,
122 node_hash: Some(
123 "dc3d1d194a990b5c54380c3c0439562fefa42f5a46807cba1c500ec3affecf04".to_string(),
124 ),
125 terms_and_conditions: None,
126 }),
127 gpu: Some(vec![GpuProperties {
128 vendor: "NVIDIA".to_string(),
129 device_name: "AD102GL [L40S]".to_string(),
130 device_class: GpuDeviceClass::_3DController,
131 device_id: "10de:26b9".to_string(),
132 }]),
133 };
134
135 assert_eq!(
136 instance_content.base.payment,
137 Some(Payment {
138 chain: Some(Chain::Base),
139 receiver: Some(address!("0xf0c0ddf11a0dCE6618B5DF8d9fAE3D95e72E04a9")),
140 payment_type: PaymentType::Superfluid,
141 })
142 );
143 assert_eq!(
144 instance_content.base.requirements,
145 Some(expected_requirements)
146 );
147 assert!(instance_content.base.volumes.is_empty());
148 assert_eq!(instance_content.base.replaces, None);
149 assert_eq!(
150 instance_content.rootfs,
151 RootfsVolume {
152 parent: ParentVolume {
153 reference: item_hash!(
154 "b6ff5c3a8205d1ca4c7c3369300eeafff498b558f71b851aa2114afd0a532717"
155 ),
156 use_latest: true
157 },
158 persistence: VolumePersistence::Host,
159 size_mib: MiB::from_units(737280).into(),
160 forgotten_by: None,
161 }
162 );
163
164 assert!(message.confirmed());
165 assert_eq!(
166 message.confirmations,
167 vec![MessageConfirmation {
168 chain: Chain::Ethereum,
169 height: 23733404,
170 hash: "0xda1dd1676b5f08cef019172a7b31de303c86aafe8cb209916cf5ffa2bc5871dc"
171 .to_string(),
172 time: None,
173 publisher: None,
174 }]
175 );
176 }
177}