Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Prepare Entrypoint #48

Draft
wants to merge 4 commits into
base: solana
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions external-crates/move/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,12 @@ fn run_rbpf(test_plan: &tc::TestPlan, exe: &Path) -> anyhow::Result<()> {
.directives
.iter()
.find(|&x| matches!(x, tc::TestDirective::Input(_x)));
let input_directive = input_directive.or(
test_plan
.directives
.iter()
.find(|&x| matches!(x, tc::TestDirective::Input2(_x)))
);
if let Some(tc::TestDirective::Input(input)) = input_directive {
instruction_data = input.instruction_data.clone();
program_id = input.program_id.parse::<Pubkey>().unwrap_or_else(|err| {
Expand Down Expand Up @@ -459,6 +465,17 @@ fn run_rbpf(test_plan: &tc::TestPlan, exe: &Path) -> anyhow::Result<()> {
});
}
}
if let Some(tc::TestDirective::Input2(input)) = input_directive {
program_id = input.program_id.parse::<Pubkey>().expect("program_id");
let message = move_to_solana::entry_codec::generate_move_call_message(
program_id.clone(),
&Hash::new_unique(),
None,
&input.entry_fn,
&[],
)?;
instruction_data = message.instructions[0].data.clone();
}
transaction_accounts.push((
loader_id,
AccountSharedData::new(0, 0, &solana_sdk::native_loader::id()),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "basic2"
version = "1.0.0"

[addresses]
basic = "0xba31"

[dependencies]
MoveStdlib = { local = "../../../../../crates/move-stdlib", addr_subst = { "std" = "0x1" } }
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"program_id": "DozgQiYtGbdyniV2T74xMdmjZJvYDzoRFFqw7UR5MwPK",
"entry_fn": "basic__bar"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// input2 ../input.json
// log 19

module 0x10::debug {
native public fun print<T>(x: &T);
}

module basic::basic {
use 0x10::debug;
use std::signer;

public entry fun bar(): u64 {
let rv = 19;
debug::print(&rv);
rv
}

public entry fun foo(account: &signer): u64 {
let rv = 17;
debug::print(&rv);
debug::print(&signer::address_of(account));
rv
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ pub enum TestDirective {
Xfail(String), // The test is expected to fail with the `String` message. It is an error if test passes.
Abort(u64), // The test should abort.
Log(String), // Test should pass.
Input(Input),
Input(Input), // Input file with program_id, accounts, instruction_data
Input2(Input2),// Input file with program_id, entry_fn. // TODO: Single input.json should be used.
UseStdlib, // Build and link the move stdlib as bytecode
}

Expand All @@ -167,6 +168,13 @@ pub struct Input {
pub instruction_data: Vec<u8>,
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Input2 {
// FIXME: We should have single input.json loader with appropriate discriminators.
pub program_id: String,
pub entry_fn: String,
}

impl TestPlan {
pub fn should_ignore(&self) -> bool {
self.directives.contains(&TestDirective::Ignore)
Expand Down Expand Up @@ -264,6 +272,13 @@ fn load_accounts(path: PathBuf) -> Result<Input> {
Ok(input)
}

fn load_accounts2(path: PathBuf) -> Result<Input2> {
debug!("Reading input file {path:?}");
let file = fs::File::open(path).unwrap();
let input: Input2 = serde_json::from_reader(file)?;
Ok(input)
}

fn load_directives(test_path: &Path) -> anyhow::Result<Vec<TestDirective>> {
let mut directives = Vec::new();
let source = std::fs::read_to_string(test_path)?;
Expand Down Expand Up @@ -297,6 +312,12 @@ fn load_directives(test_path: &Path) -> anyhow::Result<Vec<TestDirective>> {
let input = load_accounts(filename).unwrap();
directives.push(TestDirective::Input(input));
}
if line.starts_with("input2 ") {
let filename = line.split(' ').nth(1).expect("input file name");
let filename = test_path.parent().unwrap().join(filename);
let input = load_accounts2(filename).unwrap();
directives.push(TestDirective::Input2(input));
}
if line.starts_with("signers ") {
let s = line.split(' ').nth(1).expect("signer list");
directives.push(TestDirective::Signers(s.to_string()));
Expand Down
68 changes: 68 additions & 0 deletions external-crates/move/solana/move-to-solana/src/entry_codec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use anyhow::Result;
use solana_sdk::message::Message;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::instruction::Instruction;
use move_core_types::annotated_value::MoveValue;

pub fn generate_move_call_message(
program_id: Pubkey,
recent_block_hash: &Hash,
payer: Option<&Pubkey>,
entry_fn_name: &str,
args: &[MoveValue],
) -> Result<Message> {
let insn_data = encode_instruction_data(
entry_fn_name,
args,
)?;

let insn = Instruction::new_with_bytes(
program_id,
&insn_data,
vec![],
);

let msg = Message::new_with_blockhash(
&[insn],
payer,
recent_block_hash,
);

Ok(msg)
}

fn encode_instruction_data(
entry_fn_name: &str,
args: &[MoveValue],
) -> Result<Vec<u8>> {
let mut insn_data: Vec<u8> = vec![];

// Encode the data in borsch or bincode format.

// First encode the entry function name
{
let entry_fn_len: u64 = entry_fn_name.len() as u64;
insn_data.extend(&entry_fn_len.to_le_bytes());
insn_data.extend(entry_fn_name.as_bytes());
}

// encode remaining args of the function
if !args.is_empty() {
let arglen = args.len() as u64;
insn_data.extend(&arglen.to_le_bytes());
for a in args {
// serialize each move value.
// TODO: sui-graphql-rpc/src/types/move_value.rs has more
// advanced serialization methods to convert to json etc.
let argstring = match a.simple_serialize() {
Some(bytes) => bytes,
None => panic!("Error"),
};
insn_data.extend(std::str::from_utf8(&argstring)?.as_bytes());
}
}
// todo

Ok(insn_data)
}
1 change: 1 addition & 0 deletions external-crates/move/solana/move-to-solana/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod cstr;
pub mod options;
pub mod runner;
pub mod stackless;
pub mod entry_codec;

use crate::{
options::Options,
Expand Down
49 changes: 49 additions & 0 deletions external-crates/move/solana/solana-move-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[package]
name = "solana-move-cli"
version = "0.1.0"
authors = ["Diem Association <[email protected]>"]
description = "Generate An Instruction Set code from Move"
license = "Apache-2.0"
publish = false
edition = "2021"

[dependencies]
anyhow = "1.0.52"
atty = "0.2.14"
blake3 = "0.1.5"
bs58 = "0.5.0"
chrono = "0.4"
clap = { version = "3.1.8", features = ["derive"] }
codespan = "0.11.1"
codespan-reporting = "0.11.1"
colored = "2.0.0"
env_logger = "0.8.3"
extension-trait = "1.0.1"
itertools = "0.10"
libc = "0.2"
llvm-sys = "170.0.1"
log = "0.4.14"
move-binary-format.workspace = true
move-bytecode-source-map.workspace = true
move-command-line-common.workspace = true
move-compiler.workspace = true
move-core-types.workspace = true
move-ir-types.workspace = true
move-model.workspace = true
move-native.workspace = true
move-stackless-bytecode.workspace = true
move-symbol-pool.workspace = true
move-to-solana.workspace = true
num = "0.4.0"
num-traits = "0.2"
once_cell = "1.10"
parking_lot = "0.11"
regex = "1.1.9"
semver = "1.0.13"
serde = { version = "1.0.124", features = ["derive"] }
serde_json = "1.0.64"
solana-bpf-loader-program = { git = "https://github.com/solana-labs/solana", rev = "5d1538013206c1afe6f9d3c8a1a870cb0bfa9dcd" }
solana-program-runtime = { git = "https://github.com/solana-labs/solana", rev = "5d1538013206c1afe6f9d3c8a1a870cb0bfa9dcd" }
solana-sdk = { git = "https://github.com/solana-labs/solana", rev = "5d1538013206c1afe6f9d3c8a1a870cb0bfa9dcd" }
solana_rbpf = "=0.7.1"
tempfile = "3.2"
49 changes: 49 additions & 0 deletions external-crates/move/solana/solana-move-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use solana_sdk::pubkey::Pubkey;
use anyhow::Result;
use clap::Parser;

#[derive(clap::Parser)]
struct Args {
#[clap(subcommand)]
cmd: Command,
}

#[derive(clap::Subcommand)]
enum Command {
Call(CallCommand),
}

#[derive(clap::Args)]
struct CallCommand {
program_id: String,
payer: String,
function: String,
}

fn main() -> Result<()> {
let args = Args::parse();

match args.cmd {
Command::Call(cmd) => {
cmd.run()
}
}
}

impl CallCommand {
fn run(&self) -> Result<()> {
let recent_block_hash = {
todo!()
};
let program_id = self.program_id.parse::<Pubkey>()?;
let payer = self.program_id.parse::<Pubkey>()?;
let message = move_to_solana::entry_codec::generate_move_call_message(
program_id,
&recent_block_hash,
Some(&payer),
&self.function,
&[],
)?;
}
}

Loading