diff --git a/Cargo.lock b/Cargo.lock index 047220590322e0..16f8fe672b0895 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2386,7 +2386,9 @@ dependencies = [ name = "solana-bench-tps" version = "0.17.0" dependencies = [ + "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler 0.1.0 (git+https://github.com/solana-labs/libra?branch=solana-0.0.0)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2401,6 +2403,7 @@ dependencies = [ "solana-netutil 0.17.0", "solana-runtime 0.17.0", "solana-sdk 0.17.0", + "types 0.1.0 (git+https://github.com/solana-labs/libra?branch=solana-0.0.0)", ] [[package]] diff --git a/bench-tps/Cargo.toml b/bench-tps/Cargo.toml index c89d1f85f73a93..9daad9413a4c5b 100644 --- a/bench-tps/Cargo.toml +++ b/bench-tps/Cargo.toml @@ -23,6 +23,10 @@ solana-metrics = { path = "../metrics", version = "0.17.0" } solana-netutil = { path = "../netutil", version = "0.17.0" } solana-runtime = { path = "../runtime", version = "0.17.0" } solana-sdk = { path = "../sdk", version = "0.17.0" } +types = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0" } +compiler = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0" } +bincode = "1.1.4" +solana-move-loader-api = { path = "../programs/move_loader_api", version = "0.17.0" } [features] cuda = ["solana/cuda"] diff --git a/bench-tps/src/bench.rs b/bench-tps/src/bench.rs index f746f87141970c..aac9142b65cf5a 100644 --- a/bench-tps/src/bench.rs +++ b/bench-tps/src/bench.rs @@ -1,5 +1,8 @@ use solana_metrics; +#[macro_use] +extern crate solana_move_loader_api; + use log::*; use rayon::prelude::*; use solana::gen_keys::GenKeys; @@ -24,6 +27,15 @@ use std::thread::Builder; use std::time::Duration; use std::time::Instant; +use bincode; +use compiler::Compiler; +use solana_runtime::loader_utils::load_program; +use solana_sdk::instruction::{AccountMeta, Instruction}; +use solana_sdk::loader_instruction::LoaderInstruction; +use solana_sdk::pubkey::Pubkey; +use types::account_address::AccountAddress; +use types::transaction::{Program, TransactionArgument}; + pub const MAX_SPENDS_PER_TX: u64 = 4; pub const NUM_LAMPORTS_PER_ACCOUNT: u64 = 128; @@ -32,6 +44,79 @@ pub enum BenchTpsError { AirdropFailure, } +const USE_MOVE: bool = true; + +fn new_move_transaction( + program_id: &Pubkey, + from: &Keypair, + recent_blockhash: Hash, + args: Vec, +) -> Transaction { + let data = bincode::serialize(&args).unwrap(); + let ix = LoaderInstruction::InvokeMain { data }; + let ix_data = bincode::serialize(&ix).unwrap(); + + let accounts = vec![AccountMeta::new(from.pubkey(), true)]; + + let ixs = vec![Instruction::new(*program_id, &ix_data, accounts)]; + Transaction::new_signed_instructions(&[from], ixs, recent_blockhash) +} + +fn upload_move_program(from: &Keypair, client: &Arc) -> Pubkey { + let code = "//! no-execute + + // A small variant of the peer-peer payment example that creates a fresh + // account if one does not already exist. + + import 0x0.LibraAccount; + import 0x0.LibraCoin; + main(payee: address, amount: u64) { + let coin: R#LibraCoin.T; + let account_exists: bool; + + // Acquire a LibraCoin.T resource with value `amount` from the sender's + // account. This will fail if the sender's balance is less than `amount`. + coin = LibraAccount.withdraw_from_sender(move(amount)); + + account_exists = LibraAccount.exists(copy(payee)); + + if (!move(account_exists)) { + // Creates a fresh account at the address `payee` by publishing a + // LibraAccount.T resource under this address. If there is already a + // LibraAccount.T resource under the address, this will fail. + create_account(copy(payee)); + } + + LibraAccount.deposit(move(payee), move(coin)); + return; + }"; + + let address = AccountAddress::default(); + let compiler = Compiler { + code, + address, + ..Compiler::default() + }; + let compiled_program = compiler.into_compiled_program().expect("Failed to compile"); + + let mut script = vec![]; + compiled_program + .script + .serialize(&mut script) + .expect("Unable to serialize script"); + let mut modules = vec![]; + for m in compiled_program.modules.iter() { + let mut buf = vec![]; + m.serialize(&mut buf).expect("Unable to serialize module"); + modules.push(buf); + } + + let program = Program::new(script, modules, vec![]); + let program_bytes = serde_json::to_vec(&program).unwrap(); + + load_program(client, &from, &solana_move_loader_api::id(), program_bytes) +} + pub type Result = std::result::Result; pub type SharedTransactions = Arc>>>; @@ -87,6 +172,12 @@ where let exit_signal = Arc::new(AtomicBool::new(false)); + let program_id = if USE_MOVE { + upload_move_program(&keypairs[0], client) + } else { + Pubkey::default() + }; + // Setup a thread per validator to sample every period // collect the max transaction rate and total tx count seen let maxes = Arc::new(RwLock::new(Vec::new())); @@ -165,6 +256,7 @@ where &keypairs[len..], threads, reclaim_lamports_back_to_source_account, + &program_id, ); // In sustained mode overlap the transfers with generation // this has higher average performance but lower peak performance @@ -228,6 +320,7 @@ fn generate_txs( dest: &[Keypair], threads: usize, reclaim: bool, + program_id: &Pubkey, ) { let tx_count = source.len(); println!("Signing transactions... {} (reclaim={})", tx_count, reclaim); @@ -241,10 +334,23 @@ fn generate_txs( let transactions: Vec<_> = pairs .par_iter() .map(|(id, keypair)| { - ( - system_transaction::create_user_account(id, &keypair.pubkey(), 1, *blockhash), - timestamp(), - ) + if USE_MOVE { + let mut pubkey = [0u8; 32]; + pubkey.copy_from_slice(&id.pubkey().as_ref()); + let args = vec![ + TransactionArgument::Address(AccountAddress::new(pubkey)), + TransactionArgument::U64(1), + ]; + ( + new_move_transaction(program_id, &keypair, *blockhash, args), + timestamp(), + ) + } else { + ( + system_transaction::create_user_account(id, &keypair.pubkey(), 1, *blockhash), + timestamp(), + ) + } }) .collect(); @@ -695,7 +801,7 @@ mod tests { let mut config = Config::default(); config.tx_count = 100; - config.duration = Duration::from_secs(5); + config.duration = Duration::from_secs(10); let client = create_client( (cluster.entry_point_info.rpc, cluster.entry_point_info.tpu), diff --git a/core/Cargo.toml b/core/Cargo.toml index 5db4002aa1d5c2..9ddf24bfcb00d1 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -66,6 +66,8 @@ solana-stake-api = { path = "../programs/stake_api", version = "0.17.0" } solana-stake-program = { path = "../programs/stake_program", version = "0.17.0" } solana-storage-api = { path = "../programs/storage_api", version = "0.17.0" } solana-storage-program = { path = "../programs/storage_program", version = "0.17.0" } +solana-move-loader-program = { path = "../programs/move_loader_program", version = "0.17.0" } +solana-move-loader-api = { path = "../programs/move_loader_api", version = "0.17.0" } solana-vote-api = { path = "../programs/vote_api", version = "0.17.0" } solana-vote-program = { path = "../programs/vote_program", version = "0.17.0" } solana-vote-signer = { path = "../vote-signer", version = "0.17.0" } diff --git a/core/src/lib.rs b/core/src/lib.rs index 9b83c84d5b84b6..79d87f311a6cc9 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -101,3 +101,6 @@ extern crate solana_metrics; extern crate matches; extern crate crossbeam_channel; + +#[macro_use] +extern crate solana_move_loader_program; diff --git a/core/src/local_cluster.rs b/core/src/local_cluster.rs index efad9372000463..20d19431f2b8b5 100644 --- a/core/src/local_cluster.rs +++ b/core/src/local_cluster.rs @@ -29,6 +29,8 @@ use std::fs::remove_dir_all; use std::io::{Error, ErrorKind, Result}; use std::sync::Arc; +use solana_move_loader_api; + pub struct ValidatorInfo { pub keypair: Arc, pub voting_keypair: Arc, @@ -164,6 +166,9 @@ impl LocalCluster { genesis_block .native_instruction_processors .push(solana_storage_program!()); + genesis_block + .native_instruction_processors + .push(solana_move_loader_program!()); let (leader_ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block); let leader_contact_info = leader_node.info.clone(); diff --git a/runtime/src/loader_utils.rs b/runtime/src/loader_utils.rs index f252cfad11c5b9..c3a3a574fa5795 100644 --- a/runtime/src/loader_utils.rs +++ b/runtime/src/loader_utils.rs @@ -1,15 +1,16 @@ -use crate::bank_client::BankClient; +use log::*; use serde::Serialize; -use solana_sdk::client::SyncClient; +use solana_sdk::client::Client; use solana_sdk::instruction::{AccountMeta, Instruction}; use solana_sdk::loader_instruction; use solana_sdk::message::Message; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction; +use std::sync::Arc; -pub fn load_program( - bank_client: &BankClient, +pub fn load_program( + bank_client: &Arc, from_keypair: &Keypair, loader_pubkey: &Pubkey, program: Vec,