Skip to content

Commit

Permalink
Problem: A user cannot create a Confidential VM because we don't supp…
Browse files Browse the repository at this point in the history
…ort that kind of messages, that have a different schema from Instances and Programs.

Solution: Create a Confidential message schema with concrete fields.
  • Loading branch information
nesitor committed May 16, 2024
1 parent 3c0144a commit 4aaf12c
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Test with ruff in the Docker image
run: |
docker run aleph-message:${GITHUB_REF##*/} ruff aleph_message
docker run aleph-message:${GITHUB_REF##*/} ruff check aleph_message
- name: Pytest in the Docker image
run: |
Expand Down
16 changes: 14 additions & 2 deletions aleph_message/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .abstract import BaseContent
from .base import Chain, HashType, MessageType
from .execution.base import MachineType, Payment, PaymentType # noqa
from .execution.confidential import ConfidentialContent
from .execution.instance import InstanceContent
from .execution.program import ProgramContent
from .item_hash import ItemHash, ItemType
Expand Down Expand Up @@ -297,12 +298,18 @@ class InstanceMessage(BaseMessage):
content: InstanceContent


class ConfidentialMessage(BaseMessage):
type: Literal[MessageType.confidential]
content: ConfidentialContent


AlephMessage: TypeAlias = Union[
PostMessage,
AggregateMessage,
StoreMessage,
ProgramMessage,
InstanceMessage,
ConfidentialMessage,
ForgetMessage,
]

Expand All @@ -317,11 +324,16 @@ class InstanceMessage(BaseMessage):
StoreMessage,
ProgramMessage,
InstanceMessage,
ConfidentialMessage,
ForgetMessage,
]

ExecutableContent: TypeAlias = Union[InstanceContent, ProgramContent]
ExecutableMessage: TypeAlias = Union[InstanceMessage, ProgramMessage]
ExecutableContent: TypeAlias = Union[
InstanceContent, ProgramContent, ConfidentialContent
]
ExecutableMessage: TypeAlias = Union[
InstanceMessage, ProgramMessage, ConfidentialMessage
]


def parse_message(message_dict: Dict) -> AlephMessage:
Expand Down
1 change: 1 addition & 0 deletions aleph_message/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ class MessageType(str, Enum):
store = "STORE"
program = "PROGRAM"
instance = "INSTANCE"
confidential = "CONFIDENTIAL"
forget = "FORGET"
8 changes: 7 additions & 1 deletion aleph_message/models/execution/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from .abstract import BaseExecutableContent
from .confidential import ConfidentialContent
from .instance import InstanceContent
from .program import ProgramContent

__all__ = ["BaseExecutableContent", "InstanceContent", "ProgramContent"]
__all__ = [
"BaseExecutableContent",
"ConfidentialContent",
"InstanceContent",
"ProgramContent",
]
28 changes: 28 additions & 0 deletions aleph_message/models/execution/confidential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from __future__ import annotations

from pydantic import Field

from .abstract import BaseExecutableContent
from .base import Payment
from .volume import RootfsVolume
from ..item_hash import ItemHash


class ConfidentialPayment(Payment):
"""Payment information for a confidential instance execution."""

# Added node item hash required on the payment field
node_hash: ItemHash
"""Node item hash that execute the message"""


class ConfidentialContent(BaseExecutableContent):
"""Message content for scheduling a VM confidential instance on the network."""

# Make payment field required for confidential messages
payment: ConfidentialPayment = Field(
description="Payment details for the confidential execution"
)
rootfs: RootfsVolume = Field(
description="Root filesystem of the system, will be booted by the kernel"
)
18 changes: 1 addition & 17 deletions aleph_message/models/execution/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,8 @@

from pydantic import Field

from aleph_message.models.abstract import HashableModel

from .abstract import BaseExecutableContent
from .volume import ParentVolume, PersistentVolumeSizeMib, VolumePersistence


class RootfsVolume(HashableModel):
"""
Root file system of a VM instance.
The root file system of an instance is built as a copy of a reference image, named parent
image. The user determines a custom size and persistence model.
"""

parent: ParentVolume
persistence: VolumePersistence
# Use the same size constraint as persistent volumes for now
size_mib: PersistentVolumeSizeMib
from .volume import RootfsVolume


class InstanceContent(BaseExecutableContent):
Expand Down
14 changes: 14 additions & 0 deletions aleph_message/models/execution/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,18 @@ def is_read_only(self):
return False


class RootfsVolume(HashableModel):
"""
Root file system of a VM instance.
The root file system of an instance is built as a copy of a reference image, named parent
image. The user determines a custom size and persistence model.
"""

parent: ParentVolume
persistence: VolumePersistence
# Use the same size constraint as persistent volumes for now
size_mib: PersistentVolumeSizeMib


MachineVolume = Union[ImmutableVolume, EphemeralVolume, PersistentVolume]
100 changes: 100 additions & 0 deletions aleph_message/tests/messages/confidential_machine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"_id": {
"$oid": "6080402d7f44efefd611dc1e"
},
"chain": "ETH",
"sender": "0x9319Ad3B7A8E0eE24f2E639c40D8eD124C5520Ba",
"type": "CONFIDENTIAL",
"channel": "Fun-dApps",
"confirmed": true,
"content": {
"address": "0x9319Ad3B7A8E0eE24f2E639c40D8eD124C5520Ba",
"allow_amend": false,
"variables": {
"VM_CUSTOM_VARIABLE": "SOMETHING",
"VM_CUSTOM_VARIABLE_2": "32"
},
"environment": {
"reproducible": true,
"internet": false,
"aleph_api": false,
"shared_cache": false
},
"resources": {
"vcpus": 1,
"memory": 2048,
"seconds": 30
},
"requirements": {
"cpu": {
"architecture": "x86_64"
}
},
"rootfs": {
"parent": {
"ref": "549ec451d9b099cad112d4aaa2c00ac40fb6729a92ff252ff22eef0b5c3cb613",
"use_latest": true
},
"persistence": "host",
"size_mib": 20480
},
"payment": {
"chain": "AVAX",
"receiver": "0x4145f182EF2F06b45E50468519C1B92C60FBd4A0",
"type": "superfluid",
"node_hash": "589d81de8531bc8f9281ca43610d6640571228eae07cc879c675ffdb28ffaf3c"
},
"authorized_keys": [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGULT6A41Msmw2KEu0R9MvUjhuWNAsbdeZ0DOwYbt4Qt user@example",
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH0jqdc5dmt75QhTrWqeHDV9xN8vxbgFyOYs2fuQl7CI",
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDRsrQV1HVrcnskNhyH0may8TG9fHCPawpAi3ZgAWU6V/R7ezvZOHnZdaFeIsOpFbPbt/l67Fur3qniSXllI2kvuh2D4BBJ9PwwlB2sgWzFDF34ADsfLQf+C/vpwrWemEEE91Tpj0dWbnf219i3mZLxy/+5Sv6kUy9YJlzWnDEUbaMAZK2CXrlK90b9Ns7mT82h6h3x9dLF/oCjBAKOSxbH2X+KgsDEZT0soxyluDqKNgKflkav+pvKFyD4J9IWM4j36r80yW+OPGsHqWoWleEhprfNb60RJPwKAYCDiBiSg6wCq5P+kS15O79Ko45wPaYDUwhRoNTcrWeadvTaCZgz9X3KDHgrX6wzdKqzQwtQeabhCaIGLFRMNl1Oy/BR8VozPbIe/mY28IN84An50UYkbve7nOGJucKc4hKxZKEVPpnVpRtIoWGwBJY2fi6C6wy2pBa8UX4C4t9NLJjNQSwFBzYOrphLu3ZW9A+267nogQHGnsJ5xnQ/MXximP3BlwM= user@example"
],
"volumes": [
{
"comment": "Python libraries. Read-only since a 'ref' is specified.",
"mount": "/opt/venv",
"ref": "5f31b0706f59404fad3d0bff97ef89ddf24da4761608ea0646329362c662ba51",
"use_latest": false
},
{
"comment": "Ephemeral storage, read-write but will not persist after the VM stops",
"mount": "/var/cache",
"ephemeral": true,
"size_mib": 5
},
{
"comment": "Working data persisted on the VM supervisor, not available on other nodes",
"mount": "/var/lib/sqlite",
"name": "sqlite-data",
"persistence": "host",
"size_mib": 10
},
{
"comment": "Working data persisted on the Aleph network. New VMs will try to use the latest version of this volume, with no guarantee against conflicts",
"mount": "/var/lib/statistics",
"name": "statistics",
"persistence": "store",
"size_mib": 10
},
{
"comment": "Raw drive to use by a process, do not mount it",
"name": "raw-data",
"persistence": "host",
"size_mib": 10
}
],
"replaces": "0x9319Ad3B7A8E0eE24f2E639c40D8eD124C5520Ba",
"time": 1619017773.8950517
},
"item_type": "inline",
"signature": "0x372da8230552b8c3e65c05b31a0ff3a24666d66c575f8e11019f62579bf48c2b7fe2f0bbe907a2a5bf8050989cdaf8a59ff8a1cbcafcdef0656c54279b4aa0c71b",
"size": 749,
"time": 1619017773.8950577,
"confirmations": [
{
"chain": "ETH",
"height": 12284734,
"hash": "0x67f2f3cde5e94e70615c92629c70d22dc959a118f46e9411b29659c2fce87cdc"
}
]
}
11 changes: 11 additions & 0 deletions aleph_message/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from aleph_message.exceptions import UnknownHashError
from aleph_message.models import (
AggregateMessage,
ConfidentialMessage,
ForgetMessage,
InstanceMessage,
ItemType,
Expand Down Expand Up @@ -149,6 +150,16 @@ def test_instance_message_machine():
assert hash(message.content)


def test_confidential_message_machine():
path = Path(
os.path.abspath(os.path.join(__file__, "../messages/confidential_machine.json"))
)
message = create_message_from_file(path, factory=ConfidentialMessage)

assert isinstance(message, ConfidentialMessage)
assert hash(message.content)


def test_message_machine_port_mapping():
message_dict = {
"chain": "ETH",
Expand Down

0 comments on commit 4aaf12c

Please sign in to comment.