Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronc committed Sep 27, 2024
1 parent afd0de8 commit d850af3
Show file tree
Hide file tree
Showing 13 changed files with 285 additions and 35 deletions.
1 change: 1 addition & 0 deletions rust/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ workspace = true
[dependencies]
ixc_message_api = { path = "../message_api", version = "0.0.2" }
ixc_schema = { path = "../schema", version = "0.0.2" }
ixc_core_macros = { path = "../core_macros" }
bump-scope = "0.9.1"

[features]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Self-destruct functionality for accounts.

use ixc_core_macros::message_selector;
use crate::context::Context;
use crate::response::Response;

Expand All @@ -9,3 +10,6 @@ use crate::response::Response;
pub unsafe fn self_destruct<'a, 'b>(ctx: &mut Context<'a>) -> Response<'b, ()> {
unimplemented!()
}


pub const CREATE_SELECTOR: u64 = message_selector!("ixc.account.v1.create");
21 changes: 11 additions & 10 deletions rust/core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bump_scope::BumpScope;
use crate::handler::{AccountAPI, AccountClientFactory, AccountHandler, ModuleAPI};
use crate::message::Message;
use crate::response::Response;
use ixc_message_api::Address;
use ixc_message_api::AccountID;
use ixc_message_api::handler::HostBackend;
use ixc_message_api::header::MessageHeader;
use ixc_message_api::packet::MessagePacket;
Expand All @@ -13,19 +13,19 @@ use ixc_schema::mem::MemoryManager;
/// the router callbacks necessary for making nested message calls.
pub struct Context<'a> {
message_packet: &'a mut MessagePacket,
host_callbacks: &'a HostBackend,
host_callbacks: &'a dyn HostBackend,
memory_manager: &'a MemoryManager<'a, 'a>,
}

impl<'a> Context<'a> {
/// This is the address of the account that is getting called.
/// In a receiving account, this is the account's own address.
pub fn address(&self) -> &Address {
pub fn account_id(&self) -> &AccountID {
unimplemented!()
}

/// This is the address of the account which is making the message call.
pub fn caller(&self) -> &Address {
pub fn caller(&self) -> &AccountID {
unimplemented!()
}

Expand All @@ -45,16 +45,17 @@ impl<'a> Context<'a> {
/// Dynamically invokes an account message.
/// Static account client instances should be preferred wherever possible,
/// so that static dependency analysis can be performed.
pub fn dynamic_invoke_account<'b, M: Message<'b, false>>(&self, account: &Address, message: M) -> Response<M::Response, M::Error> {
pub fn dynamic_invoke_account<'b, M: Message<'b, false>>(&self, account: &AccountID, message: M) -> Response<M::Response, M::Error> {
// TODO allocate packet
let mut guard = self.memory_manager.scope().scope_guard();
let new_scope = guard.scope();
let mut header = new_scope.alloc_default::<MessageHeader>();
let mut packet = unsafe { MessagePacket::new(header.as_mut_ptr(), 0) };
let new_mem_mgr = MemoryManager::new(&new_scope);
let msg_body = M::Codec::encode_value(&message, new_mem_mgr.scope())?;
packet.in1().set_slice(msg_body);
self.host_callbacks.invoke(&mut packet);
// let mut packet = unsafe { MessagePacket::new(header.as_mut_ptr(), 0) };
// let new_mem_mgr = MemoryManager::new(&new_scope);
// let msg_body = M::Codec::encode_value(&message, new_mem_mgr.scope())?;
// packet.in1().set_slice(msg_body);
// self.host_callbacks.invoke(&mut packet);
todo!()
// TODO call self.host_callbacks.invoke
// let code = self.host_callbacks.invoke(&mut packet);
// if code != Code::Ok {
Expand Down
2 changes: 1 addition & 1 deletion rust/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod context;
mod response;
mod events;
mod message;
pub mod self_destruct;
pub mod account_api;
pub mod handler;
pub mod resource;
pub mod error;
Expand Down
3 changes: 2 additions & 1 deletion rust/core_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ quote = "1.0.37"
proc-macro2 = "1.0.86"
deluxe = "0.5.0"
manyhow = "0.11.4"
heck = "0.5.0"
heck = "0.5.0"
blake2 = "0.10.6"
20 changes: 19 additions & 1 deletion rust/core_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use std::default::Default;
use proc_macro2::TokenStream as TokenStream2;
use manyhow::{bail, error_message, manyhow};
use quote::{format_ident, quote, ToTokens};
use syn::{parse2, parse_macro_input, parse_quote, token, Attribute, File, Item, ItemImpl, ItemMod, Type};
use syn::{parse2, parse_macro_input, parse_quote, token, Attribute, File, Item, ItemImpl, ItemMod, LitStr, Type};
use std::borrow::Borrow;
use blake2::{Blake2b512, Digest};
use deluxe::ExtractAttributes;
use heck::{AsUpperCamelCase, ToUpperCamelCase};
use syn::token::Impl;
Expand Down Expand Up @@ -272,3 +273,20 @@ pub fn package_root(item: TokenStream) -> TokenStream {
// expanded.into()
TokenStream::default()
}



/// Creates the message selector for the given message name.
#[proc_macro]
pub fn message_selector(item: TokenStream) -> TokenStream {
let input_str = parse_macro_input!(item as LitStr);
let mut hasher = Blake2b512::new(); // TODO should we use 256 or 512?
hasher.update(input_str.value().as_bytes());
let res = hasher.finalize();
// take first 8 bytes and convert to u64
let hash = u64::from_le_bytes(res[..8].try_into().unwrap());
let expanded = quote! {
#hash
};
expanded.into()
}
2 changes: 2 additions & 0 deletions rust/message_api/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub enum SystemErrorCode {
FatalExecutionError,
/// Account not-found error.
AccountNotFound,
/// Message handler not-found error.
HandlerNotFound,
/// The caller attempted to impersonate another caller and was not authorized.
UnauthorizedCallerAccess,
/// The handler code was invalid or failed to execute properly within its virtual machine.
Expand Down
3 changes: 3 additions & 0 deletions rust/message_api/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use crate::packet::MessagePacket;

/// A handler for an account.
pub trait Handler {
/// The name of the handler.
fn name(&self) -> &'static str;

/// Handle a message packet.
fn handle(&self, message_packet: &mut MessagePacket, callbacks: &dyn HostBackend) -> HandlerCode;
}
Expand Down
1 change: 1 addition & 0 deletions rust/testing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ license.workspace = true
ixc = { path = "..", version = "0.0.2" }
ixc_core = { path = "../core", version = "0.0.2" }
ixc_message_api = { path = "../message_api", version = "0.0.2" }
ixc_vm_api = { path = "../vm/api" }
imbl = "3.0.0"
arc-swap = "1.7.1"
thiserror = "1.0.64"
Expand Down
38 changes: 28 additions & 10 deletions rust/testing/src/vm.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
use ixc_core::Context;
use ixc_message_api::handler::Handler;
use std::collections::HashMap;
use ixc_message_api::code::{Code, SystemErrorCode};
use ixc_message_api::handler::{Handler, HandlerCode, HostBackend};
use ixc_message_api::packet::MessagePacket;
use ixc_vm_api::{VMHandlerID, VM};

pub struct HandlerID {
vm: u32,
vm_handler_id: VMHandlerID,
struct NativeVM {
next_handler_id: u64,
handlers: HashMap<u64, Box<dyn Handler>>,
handler_names: HashMap<u64, &'static str>,
}

pub struct VMHandlerID {
package: u64,
handler: u32,
impl NativeVM {
fn register_handler<H: Handler>(&mut self, handler: H) {
let id = self.next_handler_id;
self.next_handler_id += 1;
self.handler_names.insert(id, handler.name());
self.handlers.insert(id, Box::new(handler));
}
}

pub trait VM {
fn get_handler(&self, ctx: &Context, vm_handler_id: VMHandlerID) -> &dyn Handler;
impl VM for NativeVM {
fn run_handler(&self, vm_handler_id: VMHandlerID, message_packet: &mut MessagePacket, callbacks: &dyn HostBackend) -> Code {
if let Some(handler) = self.handlers.get(&vm_handler_id.package) {
let code = handler.handle(message_packet, callbacks);
match code {
HandlerCode::Ok => Code::Ok,
HandlerCode::HandlerError(code) => Code::HandlerError(code),
}
} else {
Code::SystemError(SystemErrorCode::HandlerNotFound)
}
}
}
15 changes: 4 additions & 11 deletions rust/vm/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,15 @@ use ixc_message_api::packet::MessagePacket;

/// A unique identifier for a handler implementation.
pub struct HandlerID {
// NOTE: encoding these as strings should be considered a temporary
/// The unique identifier for the virtual machine that the handler is implemented in.
pub vm: u32,
pub vm: String,
/// The unique identifier for the handler within the virtual machine.
pub vm_handler_id: VMHandlerID,
}

/// A unique identifier for a handler implementation within a virtual machine.
pub struct VMHandlerID {
/// The unique package within the virtual machine that the handler is implemented in.
pub package: u64,
/// The unique identifier for the handler within the package.
pub handler: u32,
pub vm_handler_id: String,
}

/// A virtual machine that can run message handlers.
pub trait VM {
/// Run a message handler within the virtual machine.
fn run_handler(&self, vm_handler_id: VMHandlerID, message_packet: &mut MessagePacket, callbacks: &dyn HostBackend) -> Code;
fn run_handler(&self, vm_handler_id: &str, message_packet: &mut MessagePacket, callbacks: &dyn HostBackend) -> Code;
}
2 changes: 2 additions & 0 deletions rust/vm/hypervisor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ publish = false

[dependencies]
ixc_message_api = { path = "../../message_api" }
ixc_vm_api = { path = "../../vm/api" }
ixc_core_macros = { path = "../../core_macros" }

[lints]
workspace = true
Loading

0 comments on commit d850af3

Please sign in to comment.