Update libra to new fork (#6523) (#6601)

automerge
This commit is contained in:
mergify[bot]
2019-10-29 14:04:02 -07:00
committed by Grimes
parent 22d60d496b
commit c5a98a5b57
11 changed files with 838 additions and 978 deletions

1532
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -76,7 +76,7 @@ fn test_bench_tps_local_cluster_solana() {
fn test_bench_tps_local_cluster_move() {
let mut config = Config::default();
config.tx_count = 100;
config.duration = Duration::from_secs(20);
config.duration = Duration::from_secs(30);
config.use_move = true;
test_bench_tps_local_cluster(config);

View File

@ -14,8 +14,8 @@ log = "0.4.8"
solana-logger = { path = "../../logger", version = "0.20.1" }
solana-sdk = { path = "../../sdk", version = "0.20.1" }
solana-runtime = { path = "../../runtime", version = "0.20.1" }
types = { version = "0.0.0", package = "solana_libra_types" }
language_e2e_tests = { version = "0.0.0", package = "solana_libra_language_e2e_tests" }
types = { version = "0.0.1-sol4", package = "solana_libra_types" }
language_e2e_tests = { version = "0.0.1-sol4", package = "solana_libra_language_e2e_tests" }
solana-move-loader-api = { path = "../move_loader_api", version = "0.20.1" }
[lib]

View File

@ -23,7 +23,7 @@ use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_instruction;
use types::account_address::AccountAddress;
use types::account_config;
pub fn create_genesis<T: Client>(from_key: &Keypair, client: &T, amount: u64) -> Keypair {
let libra_genesis_key = Keypair::new();
@ -48,7 +48,7 @@ pub fn create_genesis<T: Client>(from_key: &Keypair, client: &T, amount: u64) ->
}
pub fn upload_move_program<T: Client>(from: &Keypair, client: &T, code: &str) -> Pubkey {
let address = AccountAddress::default();
let address = account_config::association_address();
let account_state = LibraAccountState::create_program(&address, code, vec![]);
let program_bytes = bincode::serialize(&account_state).unwrap();

View File

@ -4,7 +4,7 @@ use solana_move_loader_api::processor::InvokeCommand;
use solana_sdk::instruction::{AccountMeta, Instruction};
use solana_sdk::loader_instruction::LoaderInstruction;
use solana_sdk::pubkey::Pubkey;
use types::account_address::AccountAddress;
use types::account_config;
use types::transaction::TransactionArgument;
pub fn genesis(genesis_pubkey: &Pubkey, microlibras: u64) -> Instruction {
@ -28,7 +28,7 @@ pub fn mint(
];
let data = bincode::serialize(&InvokeCommand::RunProgram {
sender_address: AccountAddress::default(),
sender_address: account_config::association_address(),
function_name: "main".to_string(),
args,
})

View File

@ -1,5 +1,4 @@
use crate::librapay_instruction;
use language_e2e_tests::account::AccountResource;
use log::*;
use solana_move_loader_api::account_state::{pubkey_to_address, LibraAccountState};
use solana_move_loader_api::data_store::DataStore;
@ -75,7 +74,7 @@ pub fn create_accounts(
&from.pubkey(),
to,
lamports,
200,
400,
&solana_move_loader_api::id(),
)
})
@ -128,7 +127,7 @@ pub fn get_libra_balance<T: Client>(
.read_account_resource(&pubkey_to_address(account_address))
.unwrap();
let res = AccountResource::read_balance(&resource);
let res = resource.balance();
Ok(res)
} else {
Ok(0)

View File

@ -21,16 +21,18 @@ serde_json = "1.0.41"
solana-logger = { path = "../../logger", version = "0.20.1" }
solana-sdk = { path = "../../sdk", version = "0.20.1" }
bytecode_verifier = { version = "0.0.0", package = "solana_libra_bytecode_verifier" }
compiler = { version = "0.0.0", package = "solana_libra_compiler" }
failure = { version = "0.0.0", package = "solana_libra_failure_ext" }
language_e2e_tests = { version = "0.0.0", package = "solana_libra_language_e2e_tests" }
state_view = { version = "0.0.0", package = "solana_libra_state_view" }
stdlib = { version = "0.0.0", package = "solana_libra_stdlib" }
types = { version = "0.0.0", package = "solana_libra_types" }
vm = { version = "0.0.0", package = "solana_libra_vm" }
vm_cache_map = { version = "0.0.0", package = "solana_libra_vm_cache_map" }
vm_runtime = { version = "0.0.0", package = "solana_libra_vm_runtime" }
bytecode_verifier = { version = "0.0.1-sol4", package = "solana_libra_bytecode_verifier" }
canonical_serialization = { version = "0.0.1-sol4", package = "solana_libra_canonical_serialization" }
compiler = { version = "0.0.1-sol4", package = "solana_libra_compiler" }
failure = { version = "0.0.1-sol4", package = "solana_libra_failure_ext" }
language_e2e_tests = { version = "0.0.1-sol4", package = "solana_libra_language_e2e_tests" }
state_view = { version = "0.0.1-sol4", package = "solana_libra_state_view" }
stdlib = { version = "0.0.1-sol4", package = "solana_libra_stdlib" }
types = { version = "0.0.1-sol4", package = "solana_libra_types" }
vm = { version = "0.0.1-sol4", package = "solana_libra_vm" }
vm_cache_map = { version = "0.0.1-sol4", package = "solana_libra_vm_cache_map" }
vm_runtime = { version = "0.0.1-sol4", package = "solana_libra_vm_runtime" }
vm_runtime_types = { version = "0.0.1-sol4", package = "solana_libra_vm_runtime_types" }
[lib]
crate-type = ["lib"]

View File

@ -8,7 +8,9 @@ use std::convert::TryInto;
use stdlib::stdlib_modules;
use types::{
account_address::AccountAddress,
account_config,
byte_array::ByteArray,
identifier::Identifier,
transaction::Program,
write_set::{WriteOp, WriteSet},
};
@ -22,9 +24,9 @@ use vm_runtime::{
module_cache::{BlockModuleCache, VMModuleCache},
},
data_cache::BlockDataCache,
txn_executor::{TransactionExecutor, ACCOUNT_MODULE, COIN_MODULE},
value::Local,
txn_executor::{TransactionExecutor, ACCOUNT_MODULE, BLOCK_MODULE, COIN_MODULE},
};
use vm_runtime_types::value::Value;
// Helper function that converts a Solana Pubkey to a Libra AccountAddress (WIP)
pub fn pubkey_to_address(key: &Pubkey) -> AccountAddress {
@ -87,11 +89,12 @@ impl LibraAccountState {
let compiler = Compiler {
address: *sender_address,
code,
extra_deps,
..Compiler::default()
};
let compiled_program = compiler.into_compiled_program().expect("Failed to compile");
let compiled_program = compiler
.into_compiled_program(code)
.expect("Failed to compile");
let mut script_bytes = vec![];
compiled_program
@ -120,10 +123,9 @@ impl LibraAccountState {
let arena = Arena::new();
let state_view = DataStore::default();
let vm_cache = VMModuleCache::new(&arena);
// Libra enforces the mint address to be 0x0 (see Libra's `mint_to_address` function)
let mint_address = AccountAddress::default();
let genesis_addr = account_config::association_address();
// TODO: Need this?
let genesis_auth_key = ByteArray::new(mint_address.to_vec());
let genesis_auth_key = ByteArray::new(genesis_addr.to_vec());
let write_set = {
let fake_fetcher =
@ -132,35 +134,55 @@ impl LibraAccountState {
let block_cache = BlockModuleCache::new(&vm_cache, fake_fetcher);
let mut txn_data = TransactionMetadata::default();
txn_data.sender = mint_address;
txn_data.sender = genesis_addr;
let mut txn_executor = TransactionExecutor::new(&block_cache, &data_cache, txn_data);
txn_executor.create_account(genesis_addr).unwrap();
txn_executor
.create_account(mint_address)
.map_err(map_vm_invariant_violation_error)?
.map_err(map_vm_runtime_error)?;
.create_account(account_config::core_code_address())
.map_err(map_err_vm_status)?;
txn_executor
.execute_function(&COIN_MODULE, "initialize", vec![])
.map_err(map_vm_invariant_violation_error)?
.map_err(map_vm_runtime_error)?;
.execute_function(
&BLOCK_MODULE,
&Identifier::new("initialize").unwrap(),
vec![],
)
.map_err(map_err_vm_status)?;
txn_executor
.execute_function(
&COIN_MODULE,
&Identifier::new("initialize").unwrap(),
vec![],
)
.map_err(map_err_vm_status)?;
txn_executor
.execute_function(
&ACCOUNT_MODULE,
"mint_to_address",
vec![Local::address(mint_address), Local::u64(mint_balance)],
&Identifier::new("mint_to_address").unwrap(),
vec![Value::address(genesis_addr), Value::u64(mint_balance)],
)
.map_err(map_vm_invariant_violation_error)?
.map_err(map_vm_runtime_error)?;
.map_err(map_err_vm_status)?;
txn_executor
.execute_function(
&ACCOUNT_MODULE,
"rotate_authentication_key",
vec![Local::bytearray(genesis_auth_key)],
&Identifier::new("rotate_authentication_key").unwrap(),
vec![Value::byte_array(genesis_auth_key)],
)
.map_err(map_vm_invariant_violation_error)?
.map_err(map_vm_runtime_error)?;
.map_err(map_err_vm_status)?;
// Bump the sequence number for the Association account. If we don't do this and a
// subsequent transaction (e.g., minting) is sent from the Association account, a problem
// arises: both the genesis transaction and the subsequent transaction have sequence
// number 0
txn_executor
.execute_function(
&ACCOUNT_MODULE,
&Identifier::new("epilogue").unwrap(),
vec![],
)
.map_err(map_err_vm_status)?;
let mut stdlib_modules = vec![];
for module in modules.iter() {
@ -170,8 +192,8 @@ impl LibraAccountState {
}
txn_executor
.make_write_set(stdlib_modules, Ok(Ok(())))
.map_err(map_vm_runtime_error)?
.make_write_set(stdlib_modules, Ok(()))
.map_err(map_err_vm_status)?
.write_set()
.clone()
.into_mut()

View File

@ -1,3 +1,4 @@
use canonical_serialization::SimpleDeserializer;
use failure::prelude::*;
use indexmap::IndexMap;
use log::*;
@ -5,17 +6,12 @@ use state_view::StateView;
use types::{
access_path::AccessPath,
account_address::AccountAddress,
account_config,
account_config::{self, AccountResource},
language_storage::ModuleId,
write_set::{WriteOp, WriteSet, WriteSetMut},
};
use vm::{errors::VMInvariantViolation, CompiledModule};
use vm_runtime::{
data_cache::RemoteCache,
identifier::create_access_path,
loaded_data::{struct_def::StructDef, types::Type},
value::Value,
};
use vm::{errors::VMResult, CompiledModule};
use vm_runtime::{data_cache::RemoteCache, identifier::create_access_path};
/// An in-memory implementation of [`StateView`] and [`RemoteCache`] for the VM.
#[derive(Debug, Default)]
@ -66,17 +62,11 @@ impl DataStore {
}
/// Read an account's resource
pub fn read_account_resource(&self, addr: &AccountAddress) -> Option<Value> {
pub fn read_account_resource(&self, addr: &AccountAddress) -> Option<AccountResource> {
let access_path = create_access_path(&addr, account_config::account_struct_tag());
match self.data.get(&access_path) {
None => None,
Some(blob) => {
let account_type = get_account_struct_def();
match Value::simple_deserialize(blob, account_type) {
Ok(account) => Some(account),
Err(_) => None,
}
}
Some(blob) => SimpleDeserializer::deserialize(blob).ok(),
}
}
@ -134,32 +124,11 @@ impl StateView for DataStore {
}
impl RemoteCache for DataStore {
fn get(
&self,
access_path: &AccessPath,
) -> ::std::result::Result<Option<Vec<u8>>, VMInvariantViolation> {
fn get(&self, access_path: &AccessPath) -> VMResult<Option<Vec<u8>>> {
Ok(StateView::get(self, access_path).expect("it should not error"))
}
}
// TODO: internal Libra function and very likely to break soon, need something better
fn get_account_struct_def() -> StructDef {
// STRUCT DEF StructDef(StructDefInner { field_definitions: [ByteArray,
// Struct(StructDef(StructDefInner { field_definitions: [U64] })), U64, U64,
// U64] }) let coin = StructDef(StructDefInner { field_definitions:
// [Type::U64] })
let int_type = Type::U64;
let byte_array_type = Type::ByteArray;
let coin = Type::Struct(StructDef::new(vec![int_type.clone()]));
StructDef::new(vec![
byte_array_type,
coin,
int_type.clone(),
int_type.clone(),
int_type.clone(),
])
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -2,24 +2,10 @@
use log::*;
use solana_sdk::instruction::InstructionError;
use std::convert::TryInto;
use types::vm_error::{StatusCode, VMStatus};
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);
@ -28,23 +14,34 @@ pub fn map_data_error(err: std::boxed::Box<bincode::ErrorKind>) -> InstructionEr
_ => InstructionError::InvalidAccountData,
}
}
#[allow(clippy::needless_pass_by_value)]
pub fn map_json_error(err: serde_json::error::Error) -> InstructionError {
debug!("Error: serde_json: {:?}", err);
InstructionError::InvalidAccountData
}
pub fn map_vm_verification_error(
err: (CompiledModule, Vec<vm::errors::VerificationError>),
) -> InstructionError {
pub fn map_vm_verification_error(err: (CompiledModule, Vec<VMStatus>)) -> 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
}
pub fn map_failure_error(err: failure::Error) -> InstructionError {
debug!("Error: Script verification failed: {:?}", err);
InstructionError::InvalidInstructionData
}
pub fn map_err_vm_status(status: VMStatus) -> InstructionError {
// Attempt to map the StatusCode (repr(u64)) to a u32 for CustomError.
// The only defined StatusCode that fails is StatusCode::UNKNOWN_ERROR
match <StatusCode as Into<u64>>::into(status.major_status).try_into() {
Ok(u) => InstructionError::CustomError(u),
Err(_) => InstructionError::GenericError,
}
}

View File

@ -2,7 +2,7 @@ use crate::account_state::{pubkey_to_address, LibraAccountState, ModuleBytes};
use crate::data_store::DataStore;
use crate::error_mappers::*;
use crate::id;
use bytecode_verifier::{VerifiedModule, VerifiedScript};
use bytecode_verifier::verifier::{VerifiedModule, VerifiedScript};
use log::*;
use serde_derive::{Deserialize, Serialize};
use solana_sdk::{
@ -12,6 +12,8 @@ use solana_sdk::{
};
use types::{
account_address::AccountAddress,
account_config,
identifier::Identifier,
transaction::{Program, TransactionArgument, TransactionOutput},
};
use vm::{
@ -19,6 +21,7 @@ use vm::{
file_format::{CompiledModule, CompiledScript},
gas_schedule::{MAXIMUM_NUMBER_OF_GAS_UNITS, MAX_PRICE_PER_GAS_UNIT},
transaction_metadata::TransactionMetadata,
vm_string::VMString,
};
use vm_cache_map::Arena;
use vm_runtime::{
@ -27,8 +30,8 @@ use vm_runtime::{
module_cache::{BlockModuleCache, ModuleCache, VMModuleCache},
},
txn_executor::TransactionExecutor,
value::Local,
};
use vm_runtime_types::value::Value;
pub fn process_instruction(
_program_id: &Pubkey,
@ -76,14 +79,14 @@ impl MoveProcessor {
InstructionError::InvalidAccountData
}
fn arguments_to_locals(args: Vec<TransactionArgument>) -> Vec<Local> {
fn arguments_to_values(args: Vec<TransactionArgument>) -> Vec<Value> {
let mut locals = vec![];
for arg in args {
locals.push(match arg {
TransactionArgument::U64(i) => Local::u64(i),
TransactionArgument::Address(a) => Local::address(a),
TransactionArgument::ByteArray(b) => Local::bytearray(b),
TransactionArgument::String(s) => Local::string(s),
TransactionArgument::U64(i) => Value::u64(i),
TransactionArgument::Address(a) => Value::address(a),
TransactionArgument::ByteArray(b) => Value::byte_array(b),
TransactionArgument::String(s) => Value::string(VMString::new(s)),
});
}
locals
@ -137,13 +140,13 @@ impl MoveProcessor {
let program: Program = serde_json::from_str(&string).map_err(map_json_error)?;
let script =
CompiledScript::deserialize(&program.code()).map_err(map_vm_binary_error)?;
CompiledScript::deserialize(&program.code()).map_err(map_err_vm_status)?;
let modules = program
.modules()
.iter()
.map(|bytes| CompiledModule::deserialize(&bytes))
.collect::<Result<Vec<_>, _>>()
.map_err(map_vm_binary_error)?;
.map_err(map_err_vm_status)?;
Ok((script, modules))
}
@ -163,12 +166,12 @@ impl MoveProcessor {
modules_bytes,
} => {
let script =
VerifiedScript::deserialize(&script_bytes).map_err(map_vm_binary_error)?;
VerifiedScript::deserialize(&script_bytes).map_err(map_err_vm_status)?;
let modules = modules_bytes
.iter()
.map(|module_bytes| VerifiedModule::deserialize(&module_bytes.bytes))
.collect::<Result<Vec<_>, _>>()
.map_err(map_vm_binary_error)?;
.map_err(map_err_vm_status)?;
Ok((script, modules))
}
@ -213,13 +216,16 @@ impl MoveProcessor {
txn_metadata.gas_unit_price = *MAX_PRICE_PER_GAS_UNIT;
let mut vm = TransactionExecutor::new(&module_cache, data_store, txn_metadata);
vm.execute_function(&module_id, &function_name, Self::arguments_to_locals(args))
.map_err(map_vm_invariant_violation_error)?
.map_err(map_vm_runtime_error)?;
vm.execute_function(
&module_id,
&Identifier::new(function_name).unwrap(),
Self::arguments_to_values(args),
)
.map_err(map_err_vm_status)?;
Ok(vm
.make_write_set(modules_to_publish, Ok(Ok(())))
.map_err(map_vm_runtime_error)?)
.make_write_set(modules_to_publish, Ok(()))
.map_err(map_err_vm_status)?)
}
fn keyed_accounts_to_data_store(
@ -251,11 +257,20 @@ impl MoveProcessor {
.into_write_sets()
.map_err(|_| InstructionError::GenericError)?;
// Genesis account holds both mint and stdlib under address 0x0
// Genesis account holds both mint and stdlib
let genesis_key = *keyed_accounts[GENESIS_INDEX].unsigned_key();
let write_set = write_sets
.remove(&AccountAddress::default())
.ok_or_else(Self::missing_account)?;
let mut write_set = write_sets
.remove(&account_config::association_address())
.ok_or_else(Self::missing_account)?
.into_mut();
for (access_path, write_op) in write_sets
.remove(&account_config::core_code_address())
.ok_or_else(Self::missing_account)?
.into_iter()
{
write_set.push((access_path, write_op));
}
let write_set = write_set.freeze().unwrap();
Self::serialize_and_enforce_length(
&LibraAccountState::Genesis(write_set),
&mut keyed_accounts[GENESIS_INDEX].account.data,
@ -413,12 +428,11 @@ impl MoveProcessor {
#[cfg(test)]
mod tests {
use super::*;
use language_e2e_tests::account::AccountResource;
use solana_sdk::account::Account;
use solana_sdk::rent_calculator::RentCalculator;
use solana_sdk::sysvar::rent;
const BIG_ENOUGH: usize = 6_000;
const BIG_ENOUGH: usize = 10_000;
#[test]
fn test_account_size() {
@ -564,7 +578,7 @@ mod tests {
})
.unwrap(),
),
Err(InstructionError::InsufficientFunds)
Err(InstructionError::CustomError(4002))
);
}
@ -589,8 +603,8 @@ mod tests {
.read_account_resource(&accounts[GENESIS_INDEX + 1].address)
.unwrap();
assert_eq!(amount, AccountResource::read_balance(&payee_resource));
assert_eq!(0, AccountResource::read_sequence_number(&payee_resource));
assert_eq!(amount, payee_resource.balance());
assert_eq!(0, payee_resource.sequence_number());
}
#[test]
@ -655,13 +669,10 @@ mod tests {
let sender_resource = data_store.read_account_resource(&sender.address).unwrap();
let payee_resource = data_store.read_account_resource(&payee.address).unwrap();
assert_eq!(
amount_to_mint - amount,
AccountResource::read_balance(&sender_resource)
);
assert_eq!(0, AccountResource::read_sequence_number(&sender_resource));
assert_eq!(amount, AccountResource::read_balance(&payee_resource));
assert_eq!(0, AccountResource::read_sequence_number(&payee_resource));
assert_eq!(amount_to_mint - amount, sender_resource.balance());
assert_eq!(0, sender_resource.sequence_number());
assert_eq!(amount, payee_resource.balance());
assert_eq!(0, payee_resource.sequence_number());
}
#[test]
@ -893,9 +904,13 @@ mod tests {
owner: id(),
..Account::default()
};
let mut genesis = Self::new(Pubkey::default(), account);
genesis.account.data =
bincode::serialize(&LibraAccountState::create_genesis(amount).unwrap()).unwrap();
let mut genesis = Self::new(
Pubkey::new(&account_config::association_address().to_vec()),
account,
);
let pre_data = LibraAccountState::create_genesis(amount).unwrap();
let _hi = "hello";
genesis.account.data = bincode::serialize(&pre_data).unwrap();
genesis
}