parent
9d34b80ed6
commit
e2c9d87d91
@ -20,16 +20,16 @@ serde_json = "1.0.40"
|
||||
solana-logger = { path = "../../logger", version = "0.17.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.17.0" }
|
||||
|
||||
bytecode_verifier = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_bytecode_verifier" }
|
||||
compiler = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_compiler" }
|
||||
failure = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_failure_ext" }
|
||||
language_e2e_tests = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3" , package = "solana_libra_language_e2e_tests" }
|
||||
state_view = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_state_view" }
|
||||
stdlib = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_stdlib" }
|
||||
types = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_types" }
|
||||
vm = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_vm" }
|
||||
vm_cache_map = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_vm_cache_map" }
|
||||
vm_runtime = { git = "https://github.com/solana-labs/libra", tag = "v0.0.0.3", package = "solana_libra_vm_runtime" }
|
||||
bytecode_verifier = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_bytecode_verifier" }
|
||||
compiler = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_compiler" }
|
||||
failure = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_failure_ext" }
|
||||
language_e2e_tests = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_language_e2e_tests" }
|
||||
state_view = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_state_view" }
|
||||
stdlib = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_stdlib" }
|
||||
types = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_types" }
|
||||
vm = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_vm" }
|
||||
vm_cache_map = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_vm_cache_map" }
|
||||
vm_runtime = { git = "https://github.com/solana-labs/libra", branch = "solana-0.0.0.3.1", package = "solana_libra_vm_runtime" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@ -8,7 +8,6 @@ use stdlib::stdlib_modules;
|
||||
use types::{
|
||||
account_address::AccountAddress,
|
||||
byte_array::ByteArray,
|
||||
transaction::Program,
|
||||
write_set::{WriteOp, WriteSet},
|
||||
};
|
||||
use vm::{
|
||||
@ -38,8 +37,16 @@ fn to_array_32(array: &[u8]) -> &[u8; 32] {
|
||||
pub enum LibraAccountState {
|
||||
/// No data for this account yet
|
||||
Unallocated,
|
||||
/// Program bits
|
||||
Program(Program),
|
||||
/// Serialized compiled program bytes
|
||||
CompiledProgram {
|
||||
script_bytes: Vec<u8>,
|
||||
modules_bytes: Vec<Vec<u8>>,
|
||||
},
|
||||
/// Serialized verified program bytes
|
||||
VerifiedProgram {
|
||||
script_bytes: Vec<u8>,
|
||||
modules_bytes: Vec<Vec<u8>>,
|
||||
},
|
||||
/// Write set containing a Libra account's data
|
||||
User(WriteSet),
|
||||
/// Write sets containing the mint and stdlib modules
|
||||
@ -80,20 +87,23 @@ impl LibraAccountState {
|
||||
};
|
||||
let compiled_program = compiler.into_compiled_program().expect("Failed to compile");
|
||||
|
||||
let mut script = vec![];
|
||||
let mut script_bytes = vec![];
|
||||
compiled_program
|
||||
.script
|
||||
.serialize(&mut script)
|
||||
.serialize(&mut script_bytes)
|
||||
.expect("Unable to serialize script");
|
||||
let mut modules = vec![];
|
||||
let mut modules_bytes = vec![];
|
||||
for module in compiled_program.modules.iter() {
|
||||
let mut buf = vec![];
|
||||
module
|
||||
.serialize(&mut buf)
|
||||
.expect("Unable to serialize module");
|
||||
modules.push(buf);
|
||||
modules_bytes.push(buf);
|
||||
}
|
||||
LibraAccountState::CompiledProgram {
|
||||
script_bytes,
|
||||
modules_bytes,
|
||||
}
|
||||
LibraAccountState::Program(Program::new(script, modules, vec![]))
|
||||
}
|
||||
|
||||
pub fn create_user(write_set: WriteSet) -> Self {
|
||||
|
@ -207,4 +207,4 @@ mod tests {
|
||||
assert_eq!(&before2, after2);
|
||||
assert_eq!(&before3, after3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use solana_sdk::{
|
||||
};
|
||||
use types::{
|
||||
account_address::AccountAddress,
|
||||
transaction::{Program, TransactionArgument, TransactionOutput},
|
||||
transaction::{TransactionArgument, TransactionOutput},
|
||||
};
|
||||
use vm::{
|
||||
access::ModuleAccess,
|
||||
@ -24,7 +24,6 @@ use vm_runtime::{
|
||||
module_adapter::ModuleFetcherImpl,
|
||||
module_cache::{BlockModuleCache, ModuleCache, VMModuleCache},
|
||||
},
|
||||
static_verify_program,
|
||||
txn_executor::TransactionExecutor,
|
||||
value::Local,
|
||||
};
|
||||
@ -88,17 +87,21 @@ impl MoveProcessor {
|
||||
debug!("Error: Script deserialize failed: {:?}", err);
|
||||
InstructionError::InvalidInstructionData
|
||||
}
|
||||
fn map_vm_verification_error(
|
||||
err: std::vec::Vec<vm::errors::VerificationStatus>,
|
||||
) -> InstructionError {
|
||||
debug!("Error: Script verification 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)]
|
||||
fn missing_account() -> InstructionError {
|
||||
debug!("Error: Missing account");
|
||||
@ -118,19 +121,81 @@ impl MoveProcessor {
|
||||
locals
|
||||
}
|
||||
|
||||
fn deserialize_program(
|
||||
program: &Program,
|
||||
) -> Result<(CompiledScript, Vec<CompiledModule>), InstructionError> {
|
||||
let compiled_script =
|
||||
CompiledScript::deserialize(program.code()).map_err(Self::map_vm_binary_error)?;
|
||||
let mut compiled_modules = vec![];
|
||||
for module_bytes in program.modules().iter() {
|
||||
let compiled_module =
|
||||
CompiledModule::deserialize(module_bytes).map_err(Self::map_vm_binary_error)?;
|
||||
compiled_modules.push(compiled_module);
|
||||
fn serialize_verified_program(
|
||||
script: &VerifiedScript,
|
||||
modules: &[VerifiedModule],
|
||||
) -> Result<(Vec<u8>), InstructionError> {
|
||||
let mut script_bytes = vec![];
|
||||
script
|
||||
.as_inner()
|
||||
.serialize(&mut script_bytes)
|
||||
.map_err(Self::map_failure_error)?;
|
||||
let mut modules_bytes = vec![];
|
||||
for module in modules.iter() {
|
||||
let mut buf = vec![];
|
||||
module
|
||||
.as_inner()
|
||||
.serialize(&mut buf)
|
||||
.map_err(Self::map_failure_error)?;
|
||||
modules_bytes.push(buf);
|
||||
}
|
||||
bincode::serialize(&LibraAccountState::VerifiedProgram {
|
||||
script_bytes,
|
||||
modules_bytes,
|
||||
})
|
||||
.map_err(Self::map_data_error)
|
||||
}
|
||||
|
||||
Ok((compiled_script, compiled_modules))
|
||||
fn deserialize_compiled_program(
|
||||
data: &[u8],
|
||||
) -> Result<(CompiledScript, Vec<CompiledModule>), InstructionError> {
|
||||
let (script_bytes, modules_bytes) =
|
||||
match bincode::deserialize(data).map_err(Self::map_data_error)? {
|
||||
LibraAccountState::CompiledProgram {
|
||||
script_bytes,
|
||||
modules_bytes,
|
||||
} => (script_bytes, modules_bytes),
|
||||
_ => {
|
||||
debug!("Error: Program account does not contain a program");
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
};
|
||||
|
||||
let script =
|
||||
CompiledScript::deserialize(&script_bytes).map_err(Self::map_vm_binary_error)?;
|
||||
let modules = modules_bytes
|
||||
.iter()
|
||||
.map(|bytes| CompiledModule::deserialize(&bytes))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(Self::map_vm_binary_error)?;
|
||||
|
||||
Ok((script, modules))
|
||||
}
|
||||
|
||||
fn deserialize_verified_program(
|
||||
data: &[u8],
|
||||
) -> Result<(VerifiedScript, Vec<VerifiedModule>), InstructionError> {
|
||||
let (script_bytes, modules_bytes) =
|
||||
match bincode::deserialize(data).map_err(Self::map_data_error)? {
|
||||
LibraAccountState::VerifiedProgram {
|
||||
script_bytes,
|
||||
modules_bytes,
|
||||
} => (script_bytes, modules_bytes),
|
||||
_ => {
|
||||
debug!("Error: Program account does not contain a program");
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
};
|
||||
|
||||
let script =
|
||||
VerifiedScript::deserialize(&script_bytes).map_err(Self::map_vm_binary_error)?;
|
||||
let modules = modules_bytes
|
||||
.iter()
|
||||
.map(|bytes| VerifiedModule::deserialize(&bytes))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(Self::map_vm_binary_error)?;
|
||||
|
||||
Ok((script, modules))
|
||||
}
|
||||
|
||||
fn execute(
|
||||
@ -221,7 +286,21 @@ impl MoveProcessor {
|
||||
debug!("Error: key[0] did not sign the transaction");
|
||||
return Err(InstructionError::GenericError);
|
||||
}
|
||||
|
||||
let (compiled_script, compiled_modules) =
|
||||
Self::deserialize_compiled_program(&keyed_accounts[PROGRAM_INDEX].account.data)?;
|
||||
|
||||
let verified_script = VerifiedScript::new(compiled_script).unwrap();
|
||||
let verified_modules = compiled_modules
|
||||
.into_iter()
|
||||
.map(VerifiedModule::new)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(Self::map_vm_verification_error)?;
|
||||
|
||||
keyed_accounts[PROGRAM_INDEX].account.data =
|
||||
Self::serialize_verified_program(&verified_script, &verified_modules)?;
|
||||
keyed_accounts[PROGRAM_INDEX].account.executable = true;
|
||||
|
||||
info!(
|
||||
"Finalize: {:?}",
|
||||
keyed_accounts[PROGRAM_INDEX]
|
||||
@ -249,27 +328,11 @@ impl MoveProcessor {
|
||||
}
|
||||
|
||||
let invoke_info: InvokeInfo = bincode::deserialize(&data).map_err(Self::map_data_error)?;
|
||||
|
||||
let program = match bincode::deserialize(&keyed_accounts[0].account.data)
|
||||
.map_err(Self::map_data_error)?
|
||||
{
|
||||
LibraAccountState::Program(program) => program,
|
||||
_ => {
|
||||
debug!("Error: First account must contain the program bits");
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
};
|
||||
|
||||
let mut data_store = Self::keyed_accounts_to_data_store(&keyed_accounts[GENESIS_INDEX..])?;
|
||||
let (verified_script, verified_modules) =
|
||||
Self::deserialize_verified_program(&keyed_accounts[PROGRAM_INDEX].account.data)?;
|
||||
|
||||
let (compiled_script, compiled_modules) = Self::deserialize_program(&program)?;
|
||||
let (script, modules) = static_verify_program(
|
||||
&invoke_info.sender_address,
|
||||
compiled_script,
|
||||
compiled_modules,
|
||||
)
|
||||
.map_err(Self::map_vm_verification_error)?;
|
||||
let output = Self::execute(invoke_info, script, modules, &data_store)?;
|
||||
let output = Self::execute(invoke_info, verified_script, verified_modules, &data_store)?;
|
||||
for event in output.events() {
|
||||
trace!("Event: {:?}", event);
|
||||
}
|
||||
@ -314,6 +377,18 @@ mod tests {
|
||||
use language_e2e_tests::account::AccountResource;
|
||||
use solana_sdk::account::Account;
|
||||
|
||||
#[test]
|
||||
fn test_finalize() {
|
||||
solana_logger::setup();
|
||||
|
||||
let code = "main() { return; }";
|
||||
let sender_address = AccountAddress::default();
|
||||
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
||||
let mut keyed_accounts = vec![KeyedAccount::new(&program.key, true, &mut program.account)];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
let (_, _) = MoveProcessor::deserialize_verified_program(&program.account.data).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invoke_main() {
|
||||
solana_logger::setup();
|
||||
@ -324,9 +399,10 @@ mod tests {
|
||||
let mut genesis = LibraAccount::create_genesis();
|
||||
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
let invoke_info = InvokeInfo {
|
||||
sender_address,
|
||||
function_name: "main".to_string(),
|
||||
@ -354,9 +430,11 @@ mod tests {
|
||||
let mut genesis = LibraAccount::create_genesis();
|
||||
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
|
||||
let invoke_info = InvokeInfo {
|
||||
sender_address,
|
||||
function_name: "main".to_string(),
|
||||
@ -413,11 +491,12 @@ mod tests {
|
||||
let genesis = &mut genesis[1];
|
||||
let sender = &mut sender[0];
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
KeyedAccount::new(&sender.key, false, &mut sender.account),
|
||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
|
||||
let amount = 2;
|
||||
let invoke_info = InvokeInfo {
|
||||
@ -475,10 +554,11 @@ mod tests {
|
||||
let mut program = LibraAccount::create_program(&payee.address, code, vec![]);
|
||||
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
let invoke_info = InvokeInfo {
|
||||
sender_address: payee.address,
|
||||
function_name: "main".to_string(),
|
||||
@ -509,10 +589,11 @@ mod tests {
|
||||
let mut genesis = LibraAccount::create_genesis();
|
||||
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
KeyedAccount::new(&module.key, false, &mut module.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
let invoke_info = InvokeInfo {
|
||||
sender_address: module.address,
|
||||
function_name: "main".to_string(),
|
||||
@ -541,10 +622,11 @@ mod tests {
|
||||
LibraAccount::create_program(&module.address, &code, vec![&module.account.data]);
|
||||
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
KeyedAccount::new(&module.key, false, &mut module.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
let invoke_info = InvokeInfo {
|
||||
sender_address: program.address,
|
||||
function_name: "main".to_string(),
|
||||
@ -573,10 +655,11 @@ mod tests {
|
||||
let mut payee = LibraAccount::create_unallocated();
|
||||
|
||||
let mut keyed_accounts = vec![
|
||||
KeyedAccount::new(&program.key, false, &mut program.account),
|
||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||
];
|
||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||
let invoke_info = InvokeInfo {
|
||||
sender_address: genesis.address.clone(),
|
||||
function_name: "main".to_string(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user