Skip to content

Commit

Permalink
implement wallet example proxy method
Browse files Browse the repository at this point in the history
  • Loading branch information
poszu committed Jan 3, 2025
1 parent b048267 commit ecc6714
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 10 deletions.
4 changes: 2 additions & 2 deletions core/src/syscall/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ impl SyscallHostCall {
}

if !chunks.remainder().is_empty() {
let mut value = [0u8; 4];
value.copy_from_slice(chunks.remainder());
let mut value = ctx.rt.mr(output_ptr).to_le_bytes();
value[..chunks.remainder().len()].copy_from_slice(chunks.remainder());
ctx.rt.mw(output_ptr, u32::from_le_bytes(value));
}
};
Expand Down
7 changes: 4 additions & 3 deletions examples/wallet/program/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extern crate alloc;
use athena_interface::Address;
use athena_vm::entrypoint;
use athena_vm_declare::{callable, template};
use athena_vm_sdk::wallet::{SpendArguments, WalletProgram};
use athena_vm_sdk::wallet::{ProxyArguments, SpendArguments, WalletProgram};
use athena_vm_sdk::{call, spawn, Pubkey, VerifiableTemplate};
use parity_scale_codec::{Decode, Encode};

Expand Down Expand Up @@ -39,8 +39,9 @@ impl WalletProgram for Wallet {
call(args.recipient, None, None, args.amount);
}

fn proxy(&self, _destination: Address, _args: &[u8]) {
unimplemented!();
#[callable]
fn proxy(&self, args: ProxyArguments) -> alloc::vec::Vec<u8> {
call(args.destination, args.args, args.method, args.amount)
}

#[callable]
Expand Down
51 changes: 51 additions & 0 deletions examples/wallet/script/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,19 @@ mod tests {
payload::ExecutionPayloadBuilder, payload::Payload, Address, AthenaMessage, Balance, Encode,
MessageKind, MethodSelector, StatusCode,
};
use athena_interface::{AthenaContext, Decode, ExecutionResult};
use athena_runner::vm::AthenaRevision;
use athena_runner::AthenaVm;
use athena_sdk::host::MockHostInterface;
use athena_sdk::{AthenaStdin, ExecutionClient};
use athena_vm_sdk::wallet::ProxyArguments;
use athena_vm_sdk::Pubkey;
use ed25519_dalek::ed25519::signature::Signer;
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;

use crate::{ADDRESS_ALICE, ADDRESS_CHARLIE};

fn setup_logger() {
let _ = tracing_subscriber::fmt()
.with_test_writer()
Expand Down Expand Up @@ -306,4 +310,51 @@ mod tests {
assert!(gas_cost.is_some());
assert_eq!(result.read::<u64>(), amount);
}

#[test]
fn proxying_calls() {
setup_logger();

let mut stdin = AthenaStdin::new();
let owner = Pubkey::default();
stdin.write_slice(&owner.0);
let args = ProxyArguments {
destination: ADDRESS_CHARLIE,
method: Some(MethodSelector::from("athexp_fibonacci")),
args: Some(vec![1, 2, 3, 4]),
amount: 100,
};
stdin.write_vec(args.encode());

let sender = ADDRESS_ALICE;
let context = AthenaContext::new(sender, Address::default(), 0);
let mut host = MockHostInterface::new();
host.expect_call().returning(move |msg| {
assert_eq!(sender, msg.sender);
assert_eq!(args.destination, msg.recipient);
assert_eq!(args.amount, msg.value);

let input = msg.input_data.unwrap();
let payload = Payload::decode(&mut input.as_slice()).unwrap();
assert_eq!(args.method, payload.selector);
assert_eq!(args.args, Some(payload.input));

ExecutionResult::new(StatusCode::Success, 1_000_000, Some(vec![5, 6, 7, 8, 9]))
});

let selector = MethodSelector::from("athexp_proxy");
let result = ExecutionClient::new().execute_function(
super::ELF,
&selector,
stdin,
Some(&mut host),
Some(25000000),
Some(context),
);
let (result, gas_cost) = result.unwrap();
assert!(gas_cost.is_some());

let output = Vec::<u8>::decode(&mut result.as_slice()).unwrap();
assert_eq!(vec![5, 6, 7, 8, 9], output);
}
}
7 changes: 5 additions & 2 deletions tests/entrypoint/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#![no_main]
use athena_vm::{entrypoint, types::Address};
use athena_vm::{
entrypoint,
types::{Address, MethodSelector},
};
use athena_vm_declare::{callable, template};
use athena_vm_sdk::call;
use std::io::Read;
Expand All @@ -22,7 +25,7 @@ impl EntrypointTest {
let address = Address::from(address);

// recursive call to self
call(address, None, Some("athexp_test2"), 0);
call(address, None, Some(MethodSelector::from("athexp_test2")), 0);
}

#[callable]
Expand Down
4 changes: 2 additions & 2 deletions vm/sdk/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use athena_interface::{payload::Payload, Address, Balance, Encode, MethodSelecto
pub fn call(
address: Address,
input: Option<Vec<u8>>,
method: Option<&str>,
method: Option<MethodSelector>,
amount: Balance,
) -> Vec<u8> {
let payload = Payload {
selector: method.map(MethodSelector::from),
selector: method,
input: input.unwrap_or_default(),
};
let input_payload = payload.encode();
Expand Down
10 changes: 9 additions & 1 deletion vm/sdk/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ pub struct SpendArguments {
pub amount: u64,
}

#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
pub struct ProxyArguments {
pub destination: Address,
pub method: Option<MethodSelector>,
pub args: Option<Vec<u8>>,
pub amount: u64,
}

pub trait WalletProgram {
fn spawn(owner: Pubkey) -> Address;
fn spend(&self, args: SpendArguments);
fn proxy(&self, destination: Address, args: &[u8]);
fn proxy(&self, args: ProxyArguments) -> Vec<u8>;
fn deploy(&self, code: Vec<u8>) -> Address;
fn max_spend(&self, args: SpendArguments) -> u64;
}
Expand Down

0 comments on commit ecc6714

Please sign in to comment.