Add command to create genesis accounts (#5343)
This commit is contained in:
parent
bd7e269280
commit
6d7cb23c61
|
@ -827,7 +827,7 @@ mod tests {
|
||||||
use solana::validator::ValidatorConfig;
|
use solana::validator::ValidatorConfig;
|
||||||
use solana_client::thin_client::create_client;
|
use solana_client::thin_client::create_client;
|
||||||
use solana_drone::drone::run_local_drone;
|
use solana_drone::drone::run_local_drone;
|
||||||
use solana_librapay_api::{upload_mint_program, upload_payment_program};
|
use solana_librapay_api::{create_genesis, upload_mint_program, upload_payment_program};
|
||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_runtime::bank_client::BankClient;
|
use solana_runtime::bank_client::BankClient;
|
||||||
use solana_sdk::client::SyncClient;
|
use solana_sdk::client::SyncClient;
|
||||||
|
@ -872,12 +872,21 @@ mod tests {
|
||||||
FULLNODE_PORT_RANGE,
|
FULLNODE_PORT_RANGE,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (libra_mint_id, libra_pay_program_id) = if config.use_move {
|
let (libra_genesis_keypair, libra_mint_id, libra_pay_program_id) = if config.use_move {
|
||||||
|
let libra_genesis_keypair = create_genesis(&drone_keypair, &client, 1_000_000);
|
||||||
let libra_mint_id = upload_mint_program(&drone_keypair, &client);
|
let libra_mint_id = upload_mint_program(&drone_keypair, &client);
|
||||||
let libra_pay_program_id = upload_payment_program(&drone_keypair, &client);
|
let libra_pay_program_id = upload_payment_program(&drone_keypair, &client);
|
||||||
(libra_mint_id, libra_pay_program_id)
|
(
|
||||||
|
Arc::new(libra_genesis_keypair),
|
||||||
|
libra_mint_id,
|
||||||
|
libra_pay_program_id,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
(Pubkey::default(), Pubkey::default())
|
(
|
||||||
|
Arc::new(Keypair::new()),
|
||||||
|
Pubkey::default(),
|
||||||
|
Pubkey::default(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (addr_sender, addr_receiver) = channel();
|
let (addr_sender, addr_receiver) = channel();
|
||||||
|
@ -890,7 +899,7 @@ mod tests {
|
||||||
Some((
|
Some((
|
||||||
&libra_pay_program_id,
|
&libra_pay_program_id,
|
||||||
&libra_mint_id,
|
&libra_mint_id,
|
||||||
&cluster.libra_mint_keypair,
|
&libra_genesis_keypair,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -912,7 +921,7 @@ mod tests {
|
||||||
keypairs,
|
keypairs,
|
||||||
0,
|
0,
|
||||||
&libra_pay_program_id,
|
&libra_pay_program_id,
|
||||||
&cluster.libra_mint_keypair.pubkey(),
|
&libra_genesis_keypair.pubkey(),
|
||||||
);
|
);
|
||||||
assert!(total > 100);
|
assert!(total > 100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ use std::io::{Error, ErrorKind, Result};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use solana_librapay_api::librapay_transaction;
|
|
||||||
use solana_move_loader_api;
|
use solana_move_loader_api;
|
||||||
|
|
||||||
pub struct ValidatorInfo {
|
pub struct ValidatorInfo {
|
||||||
|
@ -119,7 +118,6 @@ pub struct LocalCluster {
|
||||||
pub genesis_block: GenesisBlock,
|
pub genesis_block: GenesisBlock,
|
||||||
replicators: Vec<Replicator>,
|
replicators: Vec<Replicator>,
|
||||||
pub replicator_infos: HashMap<Pubkey, ReplicatorInfo>,
|
pub replicator_infos: HashMap<Pubkey, ReplicatorInfo>,
|
||||||
pub libra_mint_keypair: Arc<Keypair>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalCluster {
|
impl LocalCluster {
|
||||||
|
@ -166,11 +164,6 @@ impl LocalCluster {
|
||||||
storage_keypair.pubkey(),
|
storage_keypair.pubkey(),
|
||||||
storage_contract::create_validator_storage_account(leader_pubkey, 1),
|
storage_contract::create_validator_storage_account(leader_pubkey, 1),
|
||||||
));
|
));
|
||||||
let libra_mint_keypair = Keypair::new();
|
|
||||||
genesis_block.accounts.push((
|
|
||||||
libra_mint_keypair.pubkey(),
|
|
||||||
librapay_transaction::create_libra_genesis_account(10_000),
|
|
||||||
));
|
|
||||||
genesis_block
|
genesis_block
|
||||||
.native_instruction_processors
|
.native_instruction_processors
|
||||||
.push(solana_storage_program!());
|
.push(solana_storage_program!());
|
||||||
|
@ -181,7 +174,6 @@ impl LocalCluster {
|
||||||
let (leader_ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block);
|
let (leader_ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block);
|
||||||
let leader_contact_info = leader_node.info.clone();
|
let leader_contact_info = leader_node.info.clone();
|
||||||
let leader_storage_keypair = Arc::new(storage_keypair);
|
let leader_storage_keypair = Arc::new(storage_keypair);
|
||||||
let libra_mint_keypair = Arc::new(libra_mint_keypair);
|
|
||||||
let leader_voting_keypair = Arc::new(voting_keypair);
|
let leader_voting_keypair = Arc::new(voting_keypair);
|
||||||
let leader_server = Validator::new(
|
let leader_server = Validator::new(
|
||||||
leader_node,
|
leader_node,
|
||||||
|
@ -220,7 +212,6 @@ impl LocalCluster {
|
||||||
fullnode_infos,
|
fullnode_infos,
|
||||||
replicator_infos: HashMap::new(),
|
replicator_infos: HashMap::new(),
|
||||||
listener_infos: HashMap::new(),
|
listener_infos: HashMap::new(),
|
||||||
libra_mint_keypair,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (stake, validator_config) in (&config.node_stakes[1..])
|
for (stake, validator_config) in (&config.node_stakes[1..])
|
||||||
|
|
|
@ -18,11 +18,36 @@ use solana_runtime::loader_utils::load_program;
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::account::KeyedAccount;
|
||||||
use solana_sdk::client::Client;
|
use solana_sdk::client::Client;
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
|
use solana_sdk::message::Message;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::Keypair;
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
|
use solana_sdk::system_instruction;
|
||||||
|
|
||||||
use types::account_address::AccountAddress;
|
use types::account_address::AccountAddress;
|
||||||
|
|
||||||
|
pub fn create_genesis<T: Client>(from_key: &Keypair, client: &T, amount: u64) -> Keypair {
|
||||||
|
let libra_genesis_key = Keypair::new();
|
||||||
|
|
||||||
|
let instruction = system_instruction::create_account(
|
||||||
|
&from_key.pubkey(),
|
||||||
|
&libra_genesis_key.pubkey(),
|
||||||
|
1,
|
||||||
|
bincode::serialize(&LibraAccountState::create_genesis(1))
|
||||||
|
.unwrap()
|
||||||
|
.len() as u64,
|
||||||
|
&solana_move_loader_api::id(),
|
||||||
|
);
|
||||||
|
client.send_instruction(&from_key, instruction).unwrap();
|
||||||
|
|
||||||
|
let instruction = librapay_instruction::genesis(&libra_genesis_key.pubkey(), amount);
|
||||||
|
let message = Message::new_with_payer(vec![instruction], Some(&from_key.pubkey()));
|
||||||
|
client
|
||||||
|
.send_message(&[from_key, &libra_genesis_key], message)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
libra_genesis_key
|
||||||
|
}
|
||||||
|
|
||||||
pub fn upload_move_program<T: Client>(from: &Keypair, client: &T, code: &str) -> Pubkey {
|
pub fn upload_move_program<T: Client>(from: &Keypair, client: &T, code: &str) -> Pubkey {
|
||||||
let address = AccountAddress::default();
|
let address = AccountAddress::default();
|
||||||
let account_state = LibraAccountState::create_program(&address, code, vec![]);
|
let account_state = LibraAccountState::create_program(&address, code, vec![]);
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
use bincode;
|
use bincode;
|
||||||
use solana_move_loader_api::account_state::pubkey_to_address;
|
use solana_move_loader_api::account_state::pubkey_to_address;
|
||||||
use solana_move_loader_api::processor::InvokeInfo;
|
use solana_move_loader_api::processor::InvokeCommand;
|
||||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||||
use solana_sdk::loader_instruction::LoaderInstruction;
|
use solana_sdk::loader_instruction::LoaderInstruction;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use types::account_address::AccountAddress;
|
use types::account_address::AccountAddress;
|
||||||
use types::transaction::TransactionArgument;
|
use types::transaction::TransactionArgument;
|
||||||
|
|
||||||
|
pub fn genesis(genesis_pubkey: &Pubkey, microlibras: u64) -> Instruction {
|
||||||
|
let data = bincode::serialize(&InvokeCommand::CreateGenesis(microlibras)).unwrap();
|
||||||
|
let ix_data = LoaderInstruction::InvokeMain { data };
|
||||||
|
|
||||||
|
let accounts = vec![AccountMeta::new(*genesis_pubkey, true)];
|
||||||
|
|
||||||
|
Instruction::new(solana_move_loader_api::id(), &ix_data, accounts)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mint(
|
pub fn mint(
|
||||||
program_id: &Pubkey,
|
program_pubkey: &Pubkey,
|
||||||
from_pubkey: &Pubkey,
|
from_pubkey: &Pubkey,
|
||||||
to_pubkey: &Pubkey,
|
to_pubkey: &Pubkey,
|
||||||
microlibras: u64,
|
microlibras: u64,
|
||||||
|
@ -18,16 +27,16 @@ pub fn mint(
|
||||||
TransactionArgument::U64(microlibras),
|
TransactionArgument::U64(microlibras),
|
||||||
];
|
];
|
||||||
|
|
||||||
let invoke_info = InvokeInfo {
|
let data = bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
sender_address: AccountAddress::default(),
|
sender_address: AccountAddress::default(),
|
||||||
function_name: "main".to_string(),
|
function_name: "main".to_string(),
|
||||||
args,
|
args,
|
||||||
};
|
})
|
||||||
let data = bincode::serialize(&invoke_info).unwrap();
|
.unwrap();
|
||||||
let ix_data = LoaderInstruction::InvokeMain { data };
|
let ix_data = LoaderInstruction::InvokeMain { data };
|
||||||
|
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new_credit_only(*program_id, false),
|
AccountMeta::new_credit_only(*program_pubkey, false),
|
||||||
AccountMeta::new(*from_pubkey, true),
|
AccountMeta::new(*from_pubkey, true),
|
||||||
AccountMeta::new(*to_pubkey, false),
|
AccountMeta::new(*to_pubkey, false),
|
||||||
];
|
];
|
||||||
|
@ -36,7 +45,7 @@ pub fn mint(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transfer(
|
pub fn transfer(
|
||||||
program_id: &Pubkey,
|
program_pubkey: &Pubkey,
|
||||||
mint_pubkey: &Pubkey,
|
mint_pubkey: &Pubkey,
|
||||||
from_pubkey: &Pubkey,
|
from_pubkey: &Pubkey,
|
||||||
to_pubkey: &Pubkey,
|
to_pubkey: &Pubkey,
|
||||||
|
@ -47,16 +56,16 @@ pub fn transfer(
|
||||||
TransactionArgument::U64(microlibras),
|
TransactionArgument::U64(microlibras),
|
||||||
];
|
];
|
||||||
|
|
||||||
let invoke_info = InvokeInfo {
|
let data = bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
sender_address: pubkey_to_address(from_pubkey),
|
sender_address: pubkey_to_address(from_pubkey),
|
||||||
function_name: "main".to_string(),
|
function_name: "main".to_string(),
|
||||||
args,
|
args,
|
||||||
};
|
})
|
||||||
let data = bincode::serialize(&invoke_info).unwrap();
|
.unwrap();
|
||||||
let ix_data = LoaderInstruction::InvokeMain { data };
|
let ix_data = LoaderInstruction::InvokeMain { data };
|
||||||
|
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
AccountMeta::new_credit_only(*program_id, false),
|
AccountMeta::new_credit_only(*program_pubkey, false),
|
||||||
AccountMeta::new_credit_only(*mint_pubkey, false),
|
AccountMeta::new_credit_only(*mint_pubkey, false),
|
||||||
AccountMeta::new(*from_pubkey, true),
|
AccountMeta::new(*from_pubkey, true),
|
||||||
AccountMeta::new(*to_pubkey, false),
|
AccountMeta::new(*to_pubkey, false),
|
||||||
|
|
|
@ -3,7 +3,6 @@ use language_e2e_tests::account::AccountResource;
|
||||||
use log::*;
|
use log::*;
|
||||||
use solana_move_loader_api::account_state::{pubkey_to_address, LibraAccountState};
|
use solana_move_loader_api::account_state::{pubkey_to_address, LibraAccountState};
|
||||||
use solana_move_loader_api::data_store::DataStore;
|
use solana_move_loader_api::data_store::DataStore;
|
||||||
use solana_sdk::account::Account;
|
|
||||||
use solana_sdk::client::Client;
|
use solana_sdk::client::Client;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
@ -14,6 +13,20 @@ use std::boxed::Box;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
pub fn create_genesis(
|
||||||
|
genesis_keypair: &Keypair,
|
||||||
|
microlibras: u64,
|
||||||
|
recent_blockhash: Hash,
|
||||||
|
) -> Transaction {
|
||||||
|
let ix = librapay_instruction::genesis(&genesis_keypair.pubkey(), microlibras);
|
||||||
|
Transaction::new_signed_with_payer(
|
||||||
|
vec![ix],
|
||||||
|
Some(&genesis_keypair.pubkey()),
|
||||||
|
&[genesis_keypair],
|
||||||
|
recent_blockhash,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mint_tokens(
|
pub fn mint_tokens(
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
payer: &Keypair,
|
payer: &Keypair,
|
||||||
|
@ -100,7 +113,7 @@ pub fn get_libra_balance<T: Client>(
|
||||||
if let Some(account) = account {
|
if let Some(account) = account {
|
||||||
let mut data_store = DataStore::default();
|
let mut data_store = DataStore::default();
|
||||||
match bincode::deserialize(&account)? {
|
match bincode::deserialize(&account)? {
|
||||||
LibraAccountState::User(write_set) => {
|
LibraAccountState::User(_, write_set) => {
|
||||||
data_store.apply_write_set(&write_set);
|
data_store.apply_write_set(&write_set);
|
||||||
}
|
}
|
||||||
LibraAccountState::Unallocated => {
|
LibraAccountState::Unallocated => {
|
||||||
|
@ -122,45 +135,18 @@ pub fn get_libra_balance<T: Client>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_libra_genesis_account(microlibras: u64) -> Account {
|
|
||||||
let libra_genesis_data =
|
|
||||||
bincode::serialize(&LibraAccountState::create_genesis(microlibras)).unwrap();
|
|
||||||
Account {
|
|
||||||
lamports: 1,
|
|
||||||
data: libra_genesis_data,
|
|
||||||
owner: solana_move_loader_api::id(),
|
|
||||||
executable: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{upload_mint_program, upload_payment_program};
|
use crate::{create_genesis, upload_mint_program, upload_payment_program};
|
||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_runtime::bank_client::BankClient;
|
use solana_runtime::bank_client::BankClient;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::genesis_block::create_genesis_block;
|
||||||
use solana_sdk::genesis_block::GenesisBlock;
|
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_program;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn create_bank(lamports: u64) -> (Arc<Bank>, Keypair, Keypair, Pubkey, Pubkey) {
|
fn create_bank(lamports: u64) -> (Arc<Bank>, Keypair, Keypair, Pubkey, Pubkey) {
|
||||||
let libra_genesis_account = create_libra_genesis_account(lamports);
|
let (genesis_block, mint_keypair) = create_genesis_block(lamports);
|
||||||
//let (genesis_block, mint_keypair) = create_genesis_block(lamports);
|
|
||||||
let mint_keypair = Keypair::new();
|
|
||||||
let libra_mint_keypair = Keypair::new();
|
|
||||||
let genesis_block = GenesisBlock::new(
|
|
||||||
&[
|
|
||||||
(
|
|
||||||
mint_keypair.pubkey(),
|
|
||||||
Account::new(lamports, 0, &system_program::id()),
|
|
||||||
),
|
|
||||||
(libra_mint_keypair.pubkey(), libra_genesis_account),
|
|
||||||
],
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut bank = Bank::new(&genesis_block);
|
let mut bank = Bank::new(&genesis_block);
|
||||||
bank.add_instruction_processor(
|
bank.add_instruction_processor(
|
||||||
solana_move_loader_api::id(),
|
solana_move_loader_api::id(),
|
||||||
|
@ -168,12 +154,13 @@ mod tests {
|
||||||
);
|
);
|
||||||
let shared_bank = Arc::new(bank);
|
let shared_bank = Arc::new(bank);
|
||||||
let bank_client = BankClient::new_shared(&shared_bank);
|
let bank_client = BankClient::new_shared(&shared_bank);
|
||||||
|
let genesis_keypair = create_genesis(&mint_keypair, &bank_client, 1_000_000);
|
||||||
let mint_program_pubkey = upload_mint_program(&mint_keypair, &bank_client);
|
let mint_program_pubkey = upload_mint_program(&mint_keypair, &bank_client);
|
||||||
let program_pubkey = upload_payment_program(&mint_keypair, &bank_client);
|
let program_pubkey = upload_payment_program(&mint_keypair, &bank_client);
|
||||||
(
|
(
|
||||||
shared_bank,
|
shared_bank,
|
||||||
mint_keypair,
|
mint_keypair,
|
||||||
libra_mint_keypair,
|
genesis_keypair,
|
||||||
mint_program_pubkey,
|
mint_program_pubkey,
|
||||||
program_pubkey,
|
program_pubkey,
|
||||||
)
|
)
|
||||||
|
@ -181,7 +168,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_transfer() {
|
fn test_transfer() {
|
||||||
let (bank, mint_keypair, libra_mint_keypair, mint_program_id, program_id) =
|
let (bank, mint_keypair, libra_genesis_keypair, mint_program_id, program_id) =
|
||||||
create_bank(10_000);
|
create_bank(10_000);
|
||||||
let from = Keypair::new();
|
let from = Keypair::new();
|
||||||
let to = Keypair::new();
|
let to = Keypair::new();
|
||||||
|
@ -197,14 +184,14 @@ mod tests {
|
||||||
info!(
|
info!(
|
||||||
"created accounts: mint: {} libra_mint: {}",
|
"created accounts: mint: {} libra_mint: {}",
|
||||||
mint_keypair.pubkey(),
|
mint_keypair.pubkey(),
|
||||||
libra_mint_keypair.pubkey()
|
libra_genesis_keypair.pubkey()
|
||||||
);
|
);
|
||||||
info!(" from: {} to: {}", from.pubkey(), to.pubkey());
|
info!(" from: {} to: {}", from.pubkey(), to.pubkey());
|
||||||
|
|
||||||
let tx = mint_tokens(
|
let tx = mint_tokens(
|
||||||
&mint_program_id,
|
&mint_program_id,
|
||||||
&mint_keypair,
|
&mint_keypair,
|
||||||
&libra_mint_keypair,
|
&libra_genesis_keypair,
|
||||||
&from.pubkey(),
|
&from.pubkey(),
|
||||||
1,
|
1,
|
||||||
bank.last_blockhash(),
|
bank.last_blockhash(),
|
||||||
|
@ -217,7 +204,7 @@ mod tests {
|
||||||
|
|
||||||
let tx = transfer(
|
let tx = transfer(
|
||||||
&program_id,
|
&program_id,
|
||||||
&libra_mint_keypair.pubkey(),
|
&libra_genesis_keypair.pubkey(),
|
||||||
&mint_keypair,
|
&mint_keypair,
|
||||||
&from,
|
&from,
|
||||||
&to.pubkey(),
|
&to.pubkey(),
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::data_store::DataStore;
|
use crate::data_store::DataStore;
|
||||||
|
use crate::error_mappers::*;
|
||||||
use bytecode_verifier::VerifiedModule;
|
use bytecode_verifier::VerifiedModule;
|
||||||
use compiler::Compiler;
|
use compiler::Compiler;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use stdlib::stdlib_modules;
|
use stdlib::stdlib_modules;
|
||||||
use types::{
|
use types::{
|
||||||
|
@ -47,8 +48,8 @@ pub enum LibraAccountState {
|
||||||
script_bytes: Vec<u8>,
|
script_bytes: Vec<u8>,
|
||||||
modules_bytes: Vec<Vec<u8>>,
|
modules_bytes: Vec<Vec<u8>>,
|
||||||
},
|
},
|
||||||
/// Write set containing a Libra account's data
|
/// Associated genesis account and the write set containing the Libra account data
|
||||||
User(WriteSet),
|
User(Pubkey, WriteSet),
|
||||||
/// Write sets containing the mint and stdlib modules
|
/// Write sets containing the mint and stdlib modules
|
||||||
Genesis(WriteSet),
|
Genesis(WriteSet),
|
||||||
}
|
}
|
||||||
|
@ -62,12 +63,12 @@ impl LibraAccountState {
|
||||||
code: &str,
|
code: &str,
|
||||||
deps: Vec<&Vec<u8>>,
|
deps: Vec<&Vec<u8>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Compiler needs all the dependencies all the dependency module's account's
|
// Compiler needs all the dependencies and the dependency module's account's
|
||||||
// data into `VerifiedModules`
|
// data into `VerifiedModules`
|
||||||
let mut extra_deps: Vec<VerifiedModule> = vec![];
|
let mut extra_deps: Vec<VerifiedModule> = vec![];
|
||||||
for dep in deps {
|
for dep in deps {
|
||||||
let state: LibraAccountState = bincode::deserialize(&dep).unwrap();
|
let state: Self = bincode::deserialize(&dep).unwrap();
|
||||||
if let LibraAccountState::User(write_set) = state {
|
if let LibraAccountState::User(_, write_set) = state {
|
||||||
for (_, write_op) in write_set.iter() {
|
for (_, write_op) in write_set.iter() {
|
||||||
if let WriteOp::Value(raw_bytes) = write_op {
|
if let WriteOp::Value(raw_bytes) = write_op {
|
||||||
extra_deps.push(
|
extra_deps.push(
|
||||||
|
@ -93,7 +94,7 @@ impl LibraAccountState {
|
||||||
.serialize(&mut script_bytes)
|
.serialize(&mut script_bytes)
|
||||||
.expect("Unable to serialize script");
|
.expect("Unable to serialize script");
|
||||||
let mut modules_bytes = vec![];
|
let mut modules_bytes = vec![];
|
||||||
for module in compiled_program.modules.iter() {
|
for module in &compiled_program.modules {
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
module
|
module
|
||||||
.serialize(&mut buf)
|
.serialize(&mut buf)
|
||||||
|
@ -106,11 +107,11 @@ impl LibraAccountState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_user(write_set: WriteSet) -> Self {
|
pub fn create_user(owner: &Pubkey, write_set: WriteSet) -> Self {
|
||||||
LibraAccountState::User(write_set)
|
LibraAccountState::User(*owner, write_set)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_genesis(mint_balance: u64) -> Self {
|
pub fn create_genesis(mint_balance: u64) -> Result<(Self), InstructionError> {
|
||||||
let modules = stdlib_modules();
|
let modules = stdlib_modules();
|
||||||
let arena = Arena::new();
|
let arena = Arena::new();
|
||||||
let state_view = DataStore::default();
|
let state_view = DataStore::default();
|
||||||
|
@ -130,11 +131,14 @@ impl LibraAccountState {
|
||||||
txn_data.sender = mint_address;
|
txn_data.sender = mint_address;
|
||||||
|
|
||||||
let mut txn_executor = TransactionExecutor::new(&block_cache, &data_cache, txn_data);
|
let mut txn_executor = TransactionExecutor::new(&block_cache, &data_cache, txn_data);
|
||||||
txn_executor.create_account(mint_address).unwrap().unwrap();
|
txn_executor
|
||||||
|
.create_account(mint_address)
|
||||||
|
.map_err(map_vm_invariant_violation_error)?
|
||||||
|
.map_err(map_vm_runtime_error)?;
|
||||||
txn_executor
|
txn_executor
|
||||||
.execute_function(&COIN_MODULE, "initialize", vec![])
|
.execute_function(&COIN_MODULE, "initialize", vec![])
|
||||||
.unwrap()
|
.map_err(map_vm_invariant_violation_error)?
|
||||||
.unwrap();
|
.map_err(map_vm_runtime_error)?;
|
||||||
|
|
||||||
txn_executor
|
txn_executor
|
||||||
.execute_function(
|
.execute_function(
|
||||||
|
@ -142,8 +146,8 @@ impl LibraAccountState {
|
||||||
"mint_to_address",
|
"mint_to_address",
|
||||||
vec![Local::address(mint_address), Local::u64(mint_balance)],
|
vec![Local::address(mint_address), Local::u64(mint_balance)],
|
||||||
)
|
)
|
||||||
.unwrap()
|
.map_err(map_vm_invariant_violation_error)?
|
||||||
.unwrap();
|
.map_err(map_vm_runtime_error)?;
|
||||||
|
|
||||||
txn_executor
|
txn_executor
|
||||||
.execute_function(
|
.execute_function(
|
||||||
|
@ -151,28 +155,26 @@ impl LibraAccountState {
|
||||||
"rotate_authentication_key",
|
"rotate_authentication_key",
|
||||||
vec![Local::bytearray(genesis_auth_key)],
|
vec![Local::bytearray(genesis_auth_key)],
|
||||||
)
|
)
|
||||||
.unwrap()
|
.map_err(map_vm_invariant_violation_error)?
|
||||||
.unwrap();
|
.map_err(map_vm_runtime_error)?;
|
||||||
|
|
||||||
let stdlib_modules = modules
|
let mut stdlib_modules = vec![];
|
||||||
.iter()
|
for module in modules.iter() {
|
||||||
.map(|m| {
|
let mut buf = vec![];
|
||||||
let mut module_vec = vec![];
|
module.serialize(&mut buf).map_err(map_failure_error)?;
|
||||||
m.serialize(&mut module_vec).unwrap();
|
stdlib_modules.push((module.self_id(), buf));
|
||||||
(m.self_id(), module_vec)
|
}
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
txn_executor
|
txn_executor
|
||||||
.make_write_set(stdlib_modules, Ok(Ok(())))
|
.make_write_set(stdlib_modules, Ok(Ok(())))
|
||||||
.unwrap()
|
.map_err(map_vm_runtime_error)?
|
||||||
.write_set()
|
.write_set()
|
||||||
.clone()
|
.clone()
|
||||||
.into_mut()
|
.into_mut()
|
||||||
}
|
}
|
||||||
.freeze()
|
.freeze()
|
||||||
.unwrap();
|
.map_err(map_failure_error)?;
|
||||||
|
|
||||||
LibraAccountState::Genesis(write_set)
|
Ok(LibraAccountState::Genesis(write_set))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub struct DataStore {
|
||||||
impl DataStore {
|
impl DataStore {
|
||||||
/// Creates a new `DataStore` with the provided initial data.
|
/// Creates a new `DataStore` with the provided initial data.
|
||||||
pub fn new(data: IndexMap<AccessPath, Vec<u8>>) -> Self {
|
pub fn new(data: IndexMap<AccessPath, Vec<u8>>) -> Self {
|
||||||
DataStore { data }
|
Self { data }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies a [`WriteSet`] to this data store.
|
/// Applies a [`WriteSet`] to this data store.
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
//! Mapping functions to Instruction errors
|
||||||
|
|
||||||
|
use log::*;
|
||||||
|
use solana_sdk::instruction::InstructionError;
|
||||||
|
use vm::file_format::CompiledModule;
|
||||||
|
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
|
pub fn map_vm_runtime_error(err: vm::errors::VMRuntimeError) -> InstructionError {
|
||||||
|
debug!("Execution failed: {:?}", err);
|
||||||
|
match err.err {
|
||||||
|
vm::errors::VMErrorKind::OutOfGasError => InstructionError::InsufficientFunds,
|
||||||
|
_ => InstructionError::GenericError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn map_vm_invariant_violation_error(err: vm::errors::VMInvariantViolation) -> InstructionError {
|
||||||
|
debug!("Error: Execution failed: {:?}", err);
|
||||||
|
InstructionError::GenericError
|
||||||
|
}
|
||||||
|
pub fn map_vm_binary_error(err: vm::errors::BinaryError) -> InstructionError {
|
||||||
|
debug!("Error: Script deserialize failed: {:?}", err);
|
||||||
|
InstructionError::InvalidInstructionData
|
||||||
|
}
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
|
pub fn map_data_error(err: std::boxed::Box<bincode::ErrorKind>) -> InstructionError {
|
||||||
|
debug!("Error: Account data: {:?}", err);
|
||||||
|
InstructionError::InvalidAccountData
|
||||||
|
}
|
||||||
|
pub fn map_vm_verification_error(
|
||||||
|
err: (CompiledModule, Vec<vm::errors::VerificationError>),
|
||||||
|
) -> InstructionError {
|
||||||
|
debug!("Error: Script verification failed: {:?}", err.1);
|
||||||
|
InstructionError::InvalidInstructionData
|
||||||
|
}
|
||||||
|
pub fn map_failure_error(err: failure::Error) -> InstructionError {
|
||||||
|
debug!("Error: Script verification failed: {:?}", err);
|
||||||
|
InstructionError::InvalidInstructionData
|
||||||
|
}
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
|
pub fn missing_account() -> InstructionError {
|
||||||
|
debug!("Error: Missing account");
|
||||||
|
InstructionError::InvalidAccountData
|
||||||
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
pub mod account_state;
|
pub mod account_state;
|
||||||
pub mod data_store;
|
pub mod data_store;
|
||||||
|
pub mod error_mappers;
|
||||||
pub mod processor;
|
pub mod processor;
|
||||||
|
|
||||||
const MOVE_LOADER_PROGRAM_ID: [u8; 32] = [
|
const MOVE_LOADER_PROGRAM_ID: [u8; 32] = [
|
||||||
5, 91, 237, 31, 90, 253, 197, 145, 157, 236, 147, 43, 6, 5, 157, 238, 63, 151, 181, 165, 118,
|
5, 84, 172, 160, 172, 5, 64, 41, 134, 4, 81, 31, 45, 11, 30, 64, 219, 238, 140, 38, 194, 100,
|
||||||
224, 198, 97, 103, 136, 113, 64, 0, 0, 0, 0,
|
192, 219, 156, 94, 62, 208, 0, 0, 0, 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
solana_sdk::solana_name_id!(
|
solana_sdk::solana_name_id!(
|
||||||
MOVE_LOADER_PROGRAM_ID,
|
MOVE_LOADER_PROGRAM_ID,
|
||||||
"MvLdr11111111111111111111111111111111111111"
|
"MoveLdr111111111111111111111111111111111111"
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::account_state::{pubkey_to_address, LibraAccountState};
|
use crate::account_state::{pubkey_to_address, LibraAccountState};
|
||||||
use crate::data_store::DataStore;
|
use crate::data_store::DataStore;
|
||||||
|
use crate::error_mappers::*;
|
||||||
use crate::id;
|
use crate::id;
|
||||||
use bytecode_verifier::{VerifiedModule, VerifiedScript};
|
use bytecode_verifier::{VerifiedModule, VerifiedScript};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
@ -44,11 +45,11 @@ pub fn process_instruction(
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
LoaderInstruction::Write { offset, bytes } => {
|
LoaderInstruction::Write { offset, bytes } => {
|
||||||
MoveProcessor::do_write(keyed_accounts, offset, bytes)
|
MoveProcessor::do_write(keyed_accounts, offset, &bytes)
|
||||||
}
|
}
|
||||||
LoaderInstruction::Finalize => MoveProcessor::do_finalize(keyed_accounts),
|
LoaderInstruction::Finalize => MoveProcessor::do_finalize(keyed_accounts),
|
||||||
LoaderInstruction::InvokeMain { data } => {
|
LoaderInstruction::InvokeMain { data } => {
|
||||||
MoveProcessor::do_invoke_main(keyed_accounts, data)
|
MoveProcessor::do_invoke_main(keyed_accounts, &data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,52 +57,25 @@ pub fn process_instruction(
|
||||||
pub const PROGRAM_INDEX: usize = 0;
|
pub const PROGRAM_INDEX: usize = 0;
|
||||||
pub const GENESIS_INDEX: usize = 1;
|
pub const GENESIS_INDEX: usize = 1;
|
||||||
|
|
||||||
// TODO: Not quite right yet
|
/// Command to invoke
|
||||||
/// Invoke information passed via the Invoke Instruction
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[derive(Default, Debug, Serialize, Deserialize)]
|
pub enum InvokeCommand {
|
||||||
pub struct InvokeInfo {
|
/// Create a new genesis account
|
||||||
/// Sender of the "transaction", the "sender" who is calling this program
|
CreateGenesis(u64),
|
||||||
pub sender_address: AccountAddress,
|
/// Run a Move program
|
||||||
/// Name of the function to call
|
RunProgram {
|
||||||
pub function_name: String,
|
/// Sender of the "transaction", the "sender" who is running this program
|
||||||
/// Arguments to pass to the program being invoked
|
sender_address: AccountAddress,
|
||||||
pub args: Vec<TransactionArgument>,
|
/// Name of the program's function to call
|
||||||
|
function_name: String,
|
||||||
|
/// Arguments to pass to the program being called
|
||||||
|
args: Vec<TransactionArgument>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MoveProcessor {}
|
pub struct MoveProcessor {}
|
||||||
|
|
||||||
impl MoveProcessor {
|
impl MoveProcessor {
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
|
||||||
fn map_vm_runtime_error(err: vm::errors::VMRuntimeError) -> InstructionError {
|
|
||||||
debug!("Execution failed: {:?}", err);
|
|
||||||
match err.err {
|
|
||||||
vm::errors::VMErrorKind::OutOfGasError => InstructionError::InsufficientFunds,
|
|
||||||
_ => InstructionError::GenericError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn map_vm_invariant_violation_error(err: vm::errors::VMInvariantViolation) -> InstructionError {
|
|
||||||
debug!("Error: Execution failed: {:?}", err);
|
|
||||||
InstructionError::GenericError
|
|
||||||
}
|
|
||||||
fn map_vm_binary_error(err: vm::errors::BinaryError) -> InstructionError {
|
|
||||||
debug!("Error: Script deserialize failed: {:?}", err);
|
|
||||||
InstructionError::InvalidInstructionData
|
|
||||||
}
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
|
||||||
fn map_data_error(err: std::boxed::Box<bincode::ErrorKind>) -> InstructionError {
|
|
||||||
debug!("Error: Account data: {:?}", err);
|
|
||||||
InstructionError::InvalidAccountData
|
|
||||||
}
|
|
||||||
fn map_vm_verification_error(
|
|
||||||
err: (CompiledModule, Vec<vm::errors::VerificationError>),
|
|
||||||
) -> InstructionError {
|
|
||||||
debug!("Error: Script verification failed: {:?}", err.1);
|
|
||||||
InstructionError::InvalidInstructionData
|
|
||||||
}
|
|
||||||
fn map_failure_error(err: failure::Error) -> InstructionError {
|
|
||||||
debug!("Error: Script verification failed: {:?}", err);
|
|
||||||
InstructionError::InvalidInstructionData
|
|
||||||
}
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
fn missing_account() -> InstructionError {
|
fn missing_account() -> InstructionError {
|
||||||
debug!("Error: Missing account");
|
debug!("Error: Missing account");
|
||||||
|
@ -110,7 +84,7 @@ impl MoveProcessor {
|
||||||
|
|
||||||
fn arguments_to_locals(args: Vec<TransactionArgument>) -> Vec<Local> {
|
fn arguments_to_locals(args: Vec<TransactionArgument>) -> Vec<Local> {
|
||||||
let mut locals = vec![];
|
let mut locals = vec![];
|
||||||
for arg in args.into_iter() {
|
for arg in args {
|
||||||
locals.push(match arg {
|
locals.push(match arg {
|
||||||
TransactionArgument::U64(i) => Local::u64(i),
|
TransactionArgument::U64(i) => Local::u64(i),
|
||||||
TransactionArgument::Address(a) => Local::address(a),
|
TransactionArgument::Address(a) => Local::address(a),
|
||||||
|
@ -129,28 +103,28 @@ impl MoveProcessor {
|
||||||
script
|
script
|
||||||
.as_inner()
|
.as_inner()
|
||||||
.serialize(&mut script_bytes)
|
.serialize(&mut script_bytes)
|
||||||
.map_err(Self::map_failure_error)?;
|
.map_err(map_failure_error)?;
|
||||||
let mut modules_bytes = vec![];
|
let mut modules_bytes = vec![];
|
||||||
for module in modules.iter() {
|
for module in modules.iter() {
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
module
|
module
|
||||||
.as_inner()
|
.as_inner()
|
||||||
.serialize(&mut buf)
|
.serialize(&mut buf)
|
||||||
.map_err(Self::map_failure_error)?;
|
.map_err(map_failure_error)?;
|
||||||
modules_bytes.push(buf);
|
modules_bytes.push(buf);
|
||||||
}
|
}
|
||||||
bincode::serialize(&LibraAccountState::VerifiedProgram {
|
bincode::serialize(&LibraAccountState::VerifiedProgram {
|
||||||
script_bytes,
|
script_bytes,
|
||||||
modules_bytes,
|
modules_bytes,
|
||||||
})
|
})
|
||||||
.map_err(Self::map_data_error)
|
.map_err(map_data_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_compiled_program(
|
fn deserialize_compiled_program(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(CompiledScript, Vec<CompiledModule>), InstructionError> {
|
) -> Result<(CompiledScript, Vec<CompiledModule>), InstructionError> {
|
||||||
let (script_bytes, modules_bytes) =
|
let (script_bytes, modules_bytes) =
|
||||||
match bincode::deserialize(data).map_err(Self::map_data_error)? {
|
match bincode::deserialize(data).map_err(map_data_error)? {
|
||||||
LibraAccountState::CompiledProgram {
|
LibraAccountState::CompiledProgram {
|
||||||
script_bytes,
|
script_bytes,
|
||||||
modules_bytes,
|
modules_bytes,
|
||||||
|
@ -161,13 +135,12 @@ impl MoveProcessor {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let script =
|
let script = CompiledScript::deserialize(&script_bytes).map_err(map_vm_binary_error)?;
|
||||||
CompiledScript::deserialize(&script_bytes).map_err(Self::map_vm_binary_error)?;
|
|
||||||
let modules = modules_bytes
|
let modules = modules_bytes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|bytes| CompiledModule::deserialize(&bytes))
|
.map(|bytes| CompiledModule::deserialize(&bytes))
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.map_err(Self::map_vm_binary_error)?;
|
.map_err(map_vm_binary_error)?;
|
||||||
|
|
||||||
Ok((script, modules))
|
Ok((script, modules))
|
||||||
}
|
}
|
||||||
|
@ -176,7 +149,7 @@ impl MoveProcessor {
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(VerifiedScript, Vec<VerifiedModule>), InstructionError> {
|
) -> Result<(VerifiedScript, Vec<VerifiedModule>), InstructionError> {
|
||||||
let (script_bytes, modules_bytes) =
|
let (script_bytes, modules_bytes) =
|
||||||
match bincode::deserialize(data).map_err(Self::map_data_error)? {
|
match bincode::deserialize(data).map_err(map_data_error)? {
|
||||||
LibraAccountState::VerifiedProgram {
|
LibraAccountState::VerifiedProgram {
|
||||||
script_bytes,
|
script_bytes,
|
||||||
modules_bytes,
|
modules_bytes,
|
||||||
|
@ -187,19 +160,20 @@ impl MoveProcessor {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let script =
|
let script = VerifiedScript::deserialize(&script_bytes).map_err(map_vm_binary_error)?;
|
||||||
VerifiedScript::deserialize(&script_bytes).map_err(Self::map_vm_binary_error)?;
|
|
||||||
let modules = modules_bytes
|
let modules = modules_bytes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|bytes| VerifiedModule::deserialize(&bytes))
|
.map(|bytes| VerifiedModule::deserialize(&bytes))
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.map_err(Self::map_vm_binary_error)?;
|
.map_err(map_vm_binary_error)?;
|
||||||
|
|
||||||
Ok((script, modules))
|
Ok((script, modules))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(
|
fn execute(
|
||||||
invoke_info: InvokeInfo,
|
sender_address: AccountAddress,
|
||||||
|
function_name: String,
|
||||||
|
args: Vec<TransactionArgument>,
|
||||||
script: VerifiedScript,
|
script: VerifiedScript,
|
||||||
modules: Vec<VerifiedModule>,
|
modules: Vec<VerifiedModule>,
|
||||||
data_store: &DataStore,
|
data_store: &DataStore,
|
||||||
|
@ -217,38 +191,41 @@ impl MoveProcessor {
|
||||||
verified_module
|
verified_module
|
||||||
.as_inner()
|
.as_inner()
|
||||||
.serialize(&mut raw_bytes)
|
.serialize(&mut raw_bytes)
|
||||||
.expect("Unable to serialize module"); // TODO remove expect
|
.map_err(map_failure_error)?;
|
||||||
modules_to_publish.push((verified_module.self_id(), raw_bytes));
|
modules_to_publish.push((verified_module.self_id(), raw_bytes));
|
||||||
module_cache.cache_module(verified_module);
|
module_cache.cache_module(verified_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut txn_metadata = TransactionMetadata::default();
|
let mut txn_metadata = TransactionMetadata::default();
|
||||||
txn_metadata.sender = invoke_info.sender_address;
|
txn_metadata.sender = sender_address;
|
||||||
|
|
||||||
// Caps execution to the Libra prescribed 10 milliseconds
|
// Caps execution to the Libra prescribed 10 milliseconds
|
||||||
txn_metadata.max_gas_amount = *MAXIMUM_NUMBER_OF_GAS_UNITS;
|
txn_metadata.max_gas_amount = *MAXIMUM_NUMBER_OF_GAS_UNITS;
|
||||||
txn_metadata.gas_unit_price = *MAX_PRICE_PER_GAS_UNIT;
|
txn_metadata.gas_unit_price = *MAX_PRICE_PER_GAS_UNIT;
|
||||||
|
|
||||||
let mut vm = TransactionExecutor::new(&module_cache, data_store, txn_metadata);
|
let mut vm = TransactionExecutor::new(&module_cache, data_store, txn_metadata);
|
||||||
vm.execute_function(
|
vm.execute_function(&module_id, &function_name, Self::arguments_to_locals(args))
|
||||||
&module_id,
|
.map_err(map_vm_invariant_violation_error)?
|
||||||
&invoke_info.function_name,
|
.map_err(map_vm_runtime_error)?;
|
||||||
Self::arguments_to_locals(invoke_info.args),
|
|
||||||
)
|
|
||||||
.map_err(Self::map_vm_invariant_violation_error)?
|
|
||||||
.map_err(Self::map_vm_runtime_error)?;
|
|
||||||
|
|
||||||
Ok(vm
|
Ok(vm
|
||||||
.make_write_set(modules_to_publish, Ok(Ok(())))
|
.make_write_set(modules_to_publish, Ok(Ok(())))
|
||||||
.map_err(Self::map_vm_runtime_error)?)
|
.map_err(map_vm_runtime_error)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyed_accounts_to_data_store(
|
fn keyed_accounts_to_data_store(
|
||||||
|
genesis_key: &Pubkey,
|
||||||
keyed_accounts: &[KeyedAccount],
|
keyed_accounts: &[KeyedAccount],
|
||||||
) -> Result<DataStore, InstructionError> {
|
) -> Result<DataStore, InstructionError> {
|
||||||
let mut data_store = DataStore::default();
|
let mut data_store = DataStore::default();
|
||||||
for keyed_account in keyed_accounts {
|
for keyed_account in keyed_accounts {
|
||||||
match bincode::deserialize(&keyed_account.account.data).map_err(Self::map_data_error)? {
|
match bincode::deserialize(&keyed_account.account.data).map_err(map_data_error)? {
|
||||||
LibraAccountState::Genesis(write_set) | LibraAccountState::User(write_set) => {
|
LibraAccountState::Genesis(write_set) => data_store.apply_write_set(&write_set),
|
||||||
|
LibraAccountState::User(owner, write_set) => {
|
||||||
|
if owner != *genesis_key {
|
||||||
|
debug!("All user accounts must be owned by the genesis");
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
data_store.apply_write_set(&write_set)
|
data_store.apply_write_set(&write_set)
|
||||||
}
|
}
|
||||||
_ => (), // ignore unallocated accounts
|
_ => (), // ignore unallocated accounts
|
||||||
|
@ -257,10 +234,45 @@ impl MoveProcessor {
|
||||||
Ok(data_store)
|
Ok(data_store)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn data_store_to_keyed_accounts(
|
||||||
|
data_store: DataStore,
|
||||||
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
|
) -> Result<(), InstructionError> {
|
||||||
|
let mut write_sets = data_store
|
||||||
|
.into_write_sets()
|
||||||
|
.map_err(|_| InstructionError::GenericError)?;
|
||||||
|
|
||||||
|
// Genesis account holds both mint and stdlib under address 0x0
|
||||||
|
let genesis_key = *keyed_accounts[GENESIS_INDEX].unsigned_key();
|
||||||
|
let write_set = write_sets
|
||||||
|
.remove(&AccountAddress::default())
|
||||||
|
.ok_or_else(Self::missing_account)?;
|
||||||
|
keyed_accounts[GENESIS_INDEX].account.data.clear();
|
||||||
|
let writer = std::io::BufWriter::new(&mut keyed_accounts[GENESIS_INDEX].account.data);
|
||||||
|
bincode::serialize_into(writer, &LibraAccountState::Genesis(write_set))
|
||||||
|
.map_err(map_data_error)?;
|
||||||
|
|
||||||
|
// Now do the rest of the accounts
|
||||||
|
for keyed_account in keyed_accounts[GENESIS_INDEX + 1..].iter_mut() {
|
||||||
|
let write_set = write_sets
|
||||||
|
.remove(&pubkey_to_address(keyed_account.unsigned_key()))
|
||||||
|
.ok_or_else(Self::missing_account)?;
|
||||||
|
keyed_account.account.data.clear();
|
||||||
|
let writer = std::io::BufWriter::new(&mut keyed_account.account.data);
|
||||||
|
bincode::serialize_into(writer, &LibraAccountState::User(genesis_key, write_set))
|
||||||
|
.map_err(map_data_error)?;
|
||||||
|
}
|
||||||
|
if !write_sets.is_empty() {
|
||||||
|
debug!("Error: Missing keyed accounts");
|
||||||
|
return Err(InstructionError::GenericError);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn do_write(
|
pub fn do_write(
|
||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
offset: u32,
|
offset: u32,
|
||||||
bytes: Vec<u8>,
|
bytes: &[u8],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if keyed_accounts[PROGRAM_INDEX].signer_key().is_none() {
|
if keyed_accounts[PROGRAM_INDEX].signer_key().is_none() {
|
||||||
debug!("Error: key[0] did not sign the transaction");
|
debug!("Error: key[0] did not sign the transaction");
|
||||||
|
@ -295,7 +307,7 @@ impl MoveProcessor {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(VerifiedModule::new)
|
.map(VerifiedModule::new)
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.map_err(Self::map_vm_verification_error)?;
|
.map_err(map_vm_verification_error)?;
|
||||||
|
|
||||||
keyed_accounts[PROGRAM_INDEX].account.data =
|
keyed_accounts[PROGRAM_INDEX].account.data =
|
||||||
Self::serialize_verified_program(&verified_script, &verified_modules)?;
|
Self::serialize_verified_program(&verified_script, &verified_modules)?;
|
||||||
|
@ -312,62 +324,76 @@ impl MoveProcessor {
|
||||||
|
|
||||||
pub fn do_invoke_main(
|
pub fn do_invoke_main(
|
||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
data: Vec<u8>,
|
data: &[u8],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if keyed_accounts.len() < 2 {
|
match bincode::deserialize(&data).map_err(map_data_error)? {
|
||||||
debug!("Error: Requires at least a program and a genesis accounts");
|
InvokeCommand::CreateGenesis(amount) => {
|
||||||
return Err(InstructionError::InvalidArgument);
|
if keyed_accounts.is_empty() {
|
||||||
}
|
debug!("Error: Requires an unallocated account");
|
||||||
if keyed_accounts[PROGRAM_INDEX].account.owner != id() {
|
return Err(InstructionError::InvalidArgument);
|
||||||
debug!("Error: Move program account not owned by Move loader");
|
}
|
||||||
return Err(InstructionError::InvalidArgument);
|
if keyed_accounts[0].account.owner != id() {
|
||||||
}
|
debug!("Error: Move program account not owned by Move loader");
|
||||||
if !keyed_accounts[PROGRAM_INDEX].account.executable {
|
return Err(InstructionError::InvalidArgument);
|
||||||
debug!("Error: Move program account not executable");
|
}
|
||||||
return Err(InstructionError::InvalidArgument);
|
|
||||||
}
|
|
||||||
|
|
||||||
let invoke_info: InvokeInfo = bincode::deserialize(&data).map_err(Self::map_data_error)?;
|
match bincode::deserialize(&keyed_accounts[0].account.data)
|
||||||
let mut data_store = Self::keyed_accounts_to_data_store(&keyed_accounts[GENESIS_INDEX..])?;
|
.map_err(map_data_error)?
|
||||||
let (verified_script, verified_modules) =
|
{
|
||||||
Self::deserialize_verified_program(&keyed_accounts[PROGRAM_INDEX].account.data)?;
|
LibraAccountState::Unallocated => {
|
||||||
|
keyed_accounts[0].account.data.clear();
|
||||||
|
let writer = std::io::BufWriter::new(&mut keyed_accounts[0].account.data);
|
||||||
|
bincode::serialize_into(writer, &LibraAccountState::create_genesis(amount)?)
|
||||||
|
.map_err(map_data_error)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug!("Error: Must provide an unallocated account");
|
||||||
|
Err(InstructionError::InvalidArgument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InvokeCommand::RunProgram {
|
||||||
|
sender_address,
|
||||||
|
function_name,
|
||||||
|
args,
|
||||||
|
} => {
|
||||||
|
if keyed_accounts.len() < 2 {
|
||||||
|
debug!("Error: Requires at least a program and a genesis accounts");
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
|
if keyed_accounts[PROGRAM_INDEX].account.owner != id() {
|
||||||
|
debug!("Error: Move program account not owned by Move loader");
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
|
if !keyed_accounts[PROGRAM_INDEX].account.executable {
|
||||||
|
debug!("Error: Move program account not executable");
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
let output = Self::execute(invoke_info, verified_script, verified_modules, &data_store)?;
|
let mut data_store = Self::keyed_accounts_to_data_store(
|
||||||
for event in output.events() {
|
keyed_accounts[GENESIS_INDEX].unsigned_key(),
|
||||||
trace!("Event: {:?}", event);
|
&keyed_accounts[GENESIS_INDEX..],
|
||||||
|
)?;
|
||||||
|
let (verified_script, verified_modules) = Self::deserialize_verified_program(
|
||||||
|
&keyed_accounts[PROGRAM_INDEX].account.data,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let output = Self::execute(
|
||||||
|
sender_address,
|
||||||
|
function_name,
|
||||||
|
args,
|
||||||
|
verified_script,
|
||||||
|
verified_modules,
|
||||||
|
&data_store,
|
||||||
|
)?;
|
||||||
|
for event in output.events() {
|
||||||
|
trace!("Event: {:?}", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_store.apply_write_set(&output.write_set());
|
||||||
|
Self::data_store_to_keyed_accounts(data_store, keyed_accounts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data_store.apply_write_set(&output.write_set());
|
|
||||||
|
|
||||||
// Break data store into a list of address keyed WriteSets
|
|
||||||
let mut write_sets = data_store
|
|
||||||
.into_write_sets()
|
|
||||||
.map_err(|_| InstructionError::GenericError)?;
|
|
||||||
|
|
||||||
// Genesis account holds both mint and stdlib under address 0x0
|
|
||||||
let write_set = write_sets
|
|
||||||
.remove(&AccountAddress::default())
|
|
||||||
.ok_or_else(Self::missing_account)?;
|
|
||||||
keyed_accounts[GENESIS_INDEX].account.data.clear();
|
|
||||||
let writer = std::io::BufWriter::new(&mut keyed_accounts[GENESIS_INDEX].account.data);
|
|
||||||
bincode::serialize_into(writer, &LibraAccountState::Genesis(write_set))
|
|
||||||
.map_err(Self::map_data_error)?;
|
|
||||||
|
|
||||||
// Now do the rest of the accounts
|
|
||||||
for keyed_account in keyed_accounts[GENESIS_INDEX + 1..].iter_mut() {
|
|
||||||
let write_set = write_sets
|
|
||||||
.remove(&pubkey_to_address(keyed_account.unsigned_key()))
|
|
||||||
.ok_or_else(Self::missing_account)?;
|
|
||||||
keyed_account.account.data.clear();
|
|
||||||
let writer = std::io::BufWriter::new(&mut keyed_account.account.data);
|
|
||||||
bincode::serialize_into(writer, &LibraAccountState::User(write_set))
|
|
||||||
.map_err(Self::map_data_error)?;
|
|
||||||
}
|
|
||||||
if !write_sets.is_empty() {
|
|
||||||
debug!("Error: Missing keyed accounts");
|
|
||||||
return Err(InstructionError::GenericError);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,6 +415,33 @@ mod tests {
|
||||||
let (_, _) = MoveProcessor::deserialize_verified_program(&program.account.data).unwrap();
|
let (_, _) = MoveProcessor::deserialize_verified_program(&program.account.data).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_genesis_account() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let amount = 10_000_000;
|
||||||
|
let mut unallocated = LibraAccount::create_unallocated();
|
||||||
|
|
||||||
|
let mut keyed_accounts = vec![KeyedAccount::new(
|
||||||
|
&unallocated.key,
|
||||||
|
false,
|
||||||
|
&mut unallocated.account,
|
||||||
|
)];
|
||||||
|
MoveProcessor::do_invoke_main(
|
||||||
|
&mut keyed_accounts,
|
||||||
|
&bincode::serialize(&InvokeCommand::CreateGenesis(amount)).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
bincode::deserialize::<LibraAccountState>(
|
||||||
|
&LibraAccount::create_genesis(amount).account.data
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
bincode::deserialize::<LibraAccountState>(&keyed_accounts[0].account.data).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invoke_main() {
|
fn test_invoke_main() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
@ -396,21 +449,21 @@ mod tests {
|
||||||
let code = "main() { return; }";
|
let code = "main() { return; }";
|
||||||
let sender_address = AccountAddress::default();
|
let sender_address = AccountAddress::default();
|
||||||
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
||||||
let mut genesis = LibraAccount::create_genesis();
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address,
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![],
|
|
||||||
};
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address,
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -427,23 +480,22 @@ mod tests {
|
||||||
";
|
";
|
||||||
let sender_address = AccountAddress::default();
|
let sender_address = AccountAddress::default();
|
||||||
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
||||||
let mut genesis = LibraAccount::create_genesis();
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address,
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![],
|
|
||||||
};
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address,
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
),
|
),
|
||||||
Err(InstructionError::InsufficientFunds)
|
Err(InstructionError::InsufficientFunds)
|
||||||
);
|
);
|
||||||
|
@ -458,7 +510,12 @@ mod tests {
|
||||||
|
|
||||||
let mut data_store = DataStore::default();
|
let mut data_store = DataStore::default();
|
||||||
match bincode::deserialize(&accounts[GENESIS_INDEX + 1].account.data).unwrap() {
|
match bincode::deserialize(&accounts[GENESIS_INDEX + 1].account.data).unwrap() {
|
||||||
LibraAccountState::User(write_set) => data_store.apply_write_set(&write_set),
|
LibraAccountState::User(owner, write_set) => {
|
||||||
|
if owner != accounts[GENESIS_INDEX].key {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
data_store.apply_write_set(&write_set)
|
||||||
|
}
|
||||||
_ => panic!("Invalid account state"),
|
_ => panic!("Invalid account state"),
|
||||||
}
|
}
|
||||||
let payee_resource = data_store
|
let payee_resource = data_store
|
||||||
|
@ -497,24 +554,24 @@ mod tests {
|
||||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let amount = 2;
|
let amount = 2;
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address: sender.address.clone(),
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![
|
|
||||||
TransactionArgument::Address(payee.address.clone()),
|
|
||||||
TransactionArgument::U64(amount),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address: sender.address.clone(),
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![
|
||||||
|
TransactionArgument::Address(payee.address.clone()),
|
||||||
|
TransactionArgument::U64(amount),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let data_store = MoveProcessor::keyed_accounts_to_data_store(&keyed_accounts[1..]).unwrap();
|
let data_store =
|
||||||
|
MoveProcessor::keyed_accounts_to_data_store(&genesis.key, &keyed_accounts[1..])
|
||||||
|
.unwrap();
|
||||||
let sender_resource = data_store.read_account_resource(&sender.address).unwrap();
|
let sender_resource = data_store.read_account_resource(&sender.address).unwrap();
|
||||||
let payee_resource = data_store.read_account_resource(&payee.address).unwrap();
|
let payee_resource = data_store.read_account_resource(&payee.address).unwrap();
|
||||||
|
|
||||||
|
@ -549,7 +606,7 @@ mod tests {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
let mut genesis = LibraAccount::create_genesis();
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
let mut payee = LibraAccount::create_unallocated();
|
let mut payee = LibraAccount::create_unallocated();
|
||||||
let mut program = LibraAccount::create_program(&payee.address, code, vec![]);
|
let mut program = LibraAccount::create_program(&payee.address, code, vec![]);
|
||||||
|
|
||||||
|
@ -559,14 +616,14 @@ mod tests {
|
||||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address: payee.address,
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![],
|
|
||||||
};
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address: payee.address,
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -586,7 +643,7 @@ mod tests {
|
||||||
";
|
";
|
||||||
let mut module = LibraAccount::create_unallocated();
|
let mut module = LibraAccount::create_unallocated();
|
||||||
let mut program = LibraAccount::create_program(&module.address, code, vec![]);
|
let mut program = LibraAccount::create_program(&module.address, code, vec![]);
|
||||||
let mut genesis = LibraAccount::create_genesis();
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
@ -594,14 +651,14 @@ mod tests {
|
||||||
KeyedAccount::new(&module.key, false, &mut module.account),
|
KeyedAccount::new(&module.key, false, &mut module.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address: module.address,
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![],
|
|
||||||
};
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address: module.address,
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -627,14 +684,14 @@ mod tests {
|
||||||
KeyedAccount::new(&module.key, false, &mut module.account),
|
KeyedAccount::new(&module.key, false, &mut module.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address: program.address,
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![],
|
|
||||||
};
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address: program.address,
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -650,7 +707,7 @@ mod tests {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
let mut genesis = LibraAccount::create_genesis();
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
let mut program = LibraAccount::create_program(&genesis.address, code, vec![]);
|
let mut program = LibraAccount::create_program(&genesis.address, code, vec![]);
|
||||||
let mut payee = LibraAccount::create_unallocated();
|
let mut payee = LibraAccount::create_unallocated();
|
||||||
|
|
||||||
|
@ -660,18 +717,17 @@ mod tests {
|
||||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
let invoke_info = InvokeInfo {
|
|
||||||
sender_address: genesis.address.clone(),
|
|
||||||
function_name: "main".to_string(),
|
|
||||||
args: vec![
|
|
||||||
TransactionArgument::Address(pubkey_to_address(&payee.key)),
|
|
||||||
TransactionArgument::U64(amount),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
bincode::serialize(&invoke_info).unwrap(),
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
sender_address: genesis.address.clone(),
|
||||||
|
function_name: "main".to_string(),
|
||||||
|
args: vec![
|
||||||
|
TransactionArgument::Address(pubkey_to_address(&payee.key)),
|
||||||
|
TransactionArgument::U64(amount),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -682,6 +738,7 @@ mod tests {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Debug, Default)]
|
||||||
struct LibraAccount {
|
struct LibraAccount {
|
||||||
pub key: Pubkey,
|
pub key: Pubkey,
|
||||||
pub address: AccountAddress,
|
pub address: AccountAddress,
|
||||||
|
@ -708,7 +765,7 @@ mod tests {
|
||||||
Self::new(key, account)
|
Self::new(key, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_genesis() -> Self {
|
pub fn create_genesis(amount: u64) -> Self {
|
||||||
let account = Account {
|
let account = Account {
|
||||||
lamports: 1,
|
lamports: 1,
|
||||||
data: vec![],
|
data: vec![],
|
||||||
|
@ -717,7 +774,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut genesis = Self::new(Pubkey::default(), account);
|
let mut genesis = Self::new(Pubkey::default(), account);
|
||||||
genesis.account.data =
|
genesis.account.data =
|
||||||
bincode::serialize(&LibraAccountState::create_genesis(1_000_000_000)).unwrap();
|
bincode::serialize(&LibraAccountState::create_genesis(amount).unwrap()).unwrap();
|
||||||
genesis
|
genesis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue