2019-07-23 21:34:17 -07:00
|
|
|
use crate::data_store::DataStore;
|
2019-07-30 23:43:12 -07:00
|
|
|
use crate::error_mappers::*;
|
2019-07-25 09:30:24 -07:00
|
|
|
use bytecode_verifier::VerifiedModule;
|
2019-07-23 21:34:17 -07:00
|
|
|
use compiler::Compiler;
|
|
|
|
use serde_derive::{Deserialize, Serialize};
|
2019-07-30 23:43:12 -07:00
|
|
|
use solana_sdk::{instruction::InstructionError, pubkey::Pubkey};
|
2019-07-23 21:34:17 -07:00
|
|
|
use std::convert::TryInto;
|
|
|
|
use stdlib::stdlib_modules;
|
|
|
|
use types::{
|
2019-07-25 09:30:24 -07:00
|
|
|
account_address::AccountAddress,
|
2019-10-29 10:39:10 -07:00
|
|
|
account_config,
|
|
|
|
identifier::Identifier,
|
2019-08-07 17:16:42 -07:00
|
|
|
transaction::Program,
|
2019-07-25 09:30:24 -07:00
|
|
|
write_set::{WriteOp, WriteSet},
|
|
|
|
};
|
|
|
|
use vm::{
|
|
|
|
access::ModuleAccess, file_format::CompiledModule, transaction_metadata::TransactionMetadata,
|
2019-07-23 21:34:17 -07:00
|
|
|
};
|
|
|
|
use vm_cache_map::Arena;
|
|
|
|
use vm_runtime::{
|
|
|
|
code_cache::{
|
|
|
|
module_adapter::FakeFetcher,
|
|
|
|
module_cache::{BlockModuleCache, VMModuleCache},
|
|
|
|
},
|
|
|
|
data_cache::BlockDataCache,
|
2019-10-29 10:39:10 -07:00
|
|
|
txn_executor::{TransactionExecutor, ACCOUNT_MODULE, BLOCK_MODULE, COIN_MODULE},
|
2019-07-23 21:34:17 -07:00
|
|
|
};
|
2019-10-29 10:39:10 -07:00
|
|
|
use vm_runtime_types::value::Value;
|
2019-07-23 21:34:17 -07:00
|
|
|
|
|
|
|
// Helper function that converts a Solana Pubkey to a Libra AccountAddress (WIP)
|
|
|
|
pub fn pubkey_to_address(key: &Pubkey) -> AccountAddress {
|
|
|
|
AccountAddress::new(*to_array_32(key.as_ref()))
|
|
|
|
}
|
|
|
|
fn to_array_32(array: &[u8]) -> &[u8; 32] {
|
|
|
|
array.try_into().expect("slice with incorrect length")
|
|
|
|
}
|
|
|
|
|
2019-10-18 17:18:06 -07:00
|
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
|
|
pub struct ModuleBytes {
|
|
|
|
#[serde(with = "serde_bytes")]
|
|
|
|
pub bytes: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
2019-07-23 21:34:17 -07:00
|
|
|
/// Type of Libra account held by a Solana account
|
|
|
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
|
|
|
pub enum LibraAccountState {
|
|
|
|
/// No data for this account yet
|
|
|
|
Unallocated,
|
2019-08-07 17:16:42 -07:00
|
|
|
/// Json string representation of types::transaction::Program
|
|
|
|
CompiledProgram(String),
|
2019-07-26 17:51:07 -07:00
|
|
|
/// Serialized verified program bytes
|
|
|
|
VerifiedProgram {
|
2019-10-18 17:18:06 -07:00
|
|
|
#[serde(with = "serde_bytes")]
|
2019-07-26 17:51:07 -07:00
|
|
|
script_bytes: Vec<u8>,
|
2019-10-18 17:18:06 -07:00
|
|
|
modules_bytes: Vec<ModuleBytes>,
|
2019-07-26 17:51:07 -07:00
|
|
|
},
|
2019-07-30 23:43:12 -07:00
|
|
|
/// Associated genesis account and the write set containing the Libra account data
|
|
|
|
User(Pubkey, WriteSet),
|
2019-07-23 21:34:17 -07:00
|
|
|
/// Write sets containing the mint and stdlib modules
|
|
|
|
Genesis(WriteSet),
|
|
|
|
}
|
|
|
|
impl LibraAccountState {
|
|
|
|
pub fn create_unallocated() -> Self {
|
2019-10-15 18:30:45 -07:00
|
|
|
Self::Unallocated
|
2019-07-23 21:34:17 -07:00
|
|
|
}
|
|
|
|
|
2019-07-25 09:30:24 -07:00
|
|
|
pub fn create_program(
|
|
|
|
sender_address: &AccountAddress,
|
|
|
|
code: &str,
|
|
|
|
deps: Vec<&Vec<u8>>,
|
|
|
|
) -> Self {
|
2019-07-30 23:43:12 -07:00
|
|
|
// Compiler needs all the dependencies and the dependency module's account's
|
2019-07-25 09:30:24 -07:00
|
|
|
// data into `VerifiedModules`
|
|
|
|
let mut extra_deps: Vec<VerifiedModule> = vec![];
|
|
|
|
for dep in deps {
|
2019-07-30 23:43:12 -07:00
|
|
|
let state: Self = bincode::deserialize(&dep).unwrap();
|
2019-10-15 18:30:45 -07:00
|
|
|
if let Self::User(_, write_set) = state {
|
2019-07-25 09:30:24 -07:00
|
|
|
for (_, write_op) in write_set.iter() {
|
|
|
|
if let WriteOp::Value(raw_bytes) = write_op {
|
|
|
|
extra_deps.push(
|
|
|
|
VerifiedModule::new(CompiledModule::deserialize(&raw_bytes).unwrap())
|
|
|
|
.unwrap(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-23 21:34:17 -07:00
|
|
|
let compiler = Compiler {
|
|
|
|
address: *sender_address,
|
2019-07-25 09:30:24 -07:00
|
|
|
extra_deps,
|
2019-07-23 21:34:17 -07:00
|
|
|
..Compiler::default()
|
|
|
|
};
|
2019-10-29 10:39:10 -07:00
|
|
|
let compiled_program = compiler
|
|
|
|
.into_compiled_program(code)
|
|
|
|
.expect("Failed to compile");
|
2019-07-23 21:34:17 -07:00
|
|
|
|
2019-07-26 17:51:07 -07:00
|
|
|
let mut script_bytes = vec![];
|
2019-07-23 21:34:17 -07:00
|
|
|
compiled_program
|
|
|
|
.script
|
2019-07-26 17:51:07 -07:00
|
|
|
.serialize(&mut script_bytes)
|
2019-07-23 21:34:17 -07:00
|
|
|
.expect("Unable to serialize script");
|
2019-07-26 17:51:07 -07:00
|
|
|
let mut modules_bytes = vec![];
|
2019-07-30 23:43:12 -07:00
|
|
|
for module in &compiled_program.modules {
|
2019-07-23 21:34:17 -07:00
|
|
|
let mut buf = vec![];
|
2019-07-25 09:30:24 -07:00
|
|
|
module
|
|
|
|
.serialize(&mut buf)
|
|
|
|
.expect("Unable to serialize module");
|
2019-07-26 17:51:07 -07:00
|
|
|
modules_bytes.push(buf);
|
|
|
|
}
|
2019-10-15 18:30:45 -07:00
|
|
|
Self::CompiledProgram(
|
2019-08-07 17:16:42 -07:00
|
|
|
serde_json::to_string(&Program::new(script_bytes, modules_bytes, vec![])).unwrap(),
|
|
|
|
)
|
2019-07-23 21:34:17 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 23:43:12 -07:00
|
|
|
pub fn create_user(owner: &Pubkey, write_set: WriteSet) -> Self {
|
2019-10-15 18:30:45 -07:00
|
|
|
Self::User(*owner, write_set)
|
2019-07-23 21:34:17 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 23:43:12 -07:00
|
|
|
pub fn create_genesis(mint_balance: u64) -> Result<(Self), InstructionError> {
|
2019-07-23 21:34:17 -07:00
|
|
|
let modules = stdlib_modules();
|
|
|
|
let arena = Arena::new();
|
|
|
|
let state_view = DataStore::default();
|
|
|
|
let vm_cache = VMModuleCache::new(&arena);
|
2019-10-29 10:39:10 -07:00
|
|
|
let genesis_addr = account_config::association_address();
|
2019-07-23 21:34:17 -07:00
|
|
|
|
|
|
|
let write_set = {
|
|
|
|
let fake_fetcher =
|
|
|
|
FakeFetcher::new(modules.iter().map(|m| m.as_inner().clone()).collect());
|
|
|
|
let data_cache = BlockDataCache::new(&state_view);
|
|
|
|
let block_cache = BlockModuleCache::new(&vm_cache, fake_fetcher);
|
|
|
|
|
|
|
|
let mut txn_data = TransactionMetadata::default();
|
2019-10-29 10:39:10 -07:00
|
|
|
txn_data.sender = genesis_addr;
|
2019-07-23 21:34:17 -07:00
|
|
|
|
|
|
|
let mut txn_executor = TransactionExecutor::new(&block_cache, &data_cache, txn_data);
|
2019-10-29 10:39:10 -07:00
|
|
|
txn_executor.create_account(genesis_addr).unwrap();
|
2019-07-30 23:43:12 -07:00
|
|
|
txn_executor
|
2019-10-29 10:39:10 -07:00
|
|
|
.create_account(account_config::core_code_address())
|
|
|
|
.map_err(map_err_vm_status)?;
|
2019-07-23 21:34:17 -07:00
|
|
|
txn_executor
|
2019-10-29 10:39:10 -07:00
|
|
|
.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,
|
|
|
|
&Identifier::new("mint_to_address").unwrap(),
|
|
|
|
vec![Value::address(genesis_addr), Value::u64(mint_balance)],
|
|
|
|
)
|
|
|
|
.map_err(map_err_vm_status)?;
|
2019-07-23 21:34:17 -07:00
|
|
|
|
2019-10-29 10:39:10 -07:00
|
|
|
// 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
|
2019-07-23 21:34:17 -07:00
|
|
|
txn_executor
|
|
|
|
.execute_function(
|
|
|
|
&ACCOUNT_MODULE,
|
2019-10-29 10:39:10 -07:00
|
|
|
&Identifier::new("epilogue").unwrap(),
|
|
|
|
vec![],
|
2019-07-23 21:34:17 -07:00
|
|
|
)
|
2019-10-29 10:39:10 -07:00
|
|
|
.map_err(map_err_vm_status)?;
|
2019-07-23 21:34:17 -07:00
|
|
|
|
2019-07-30 23:43:12 -07:00
|
|
|
let mut stdlib_modules = vec![];
|
|
|
|
for module in modules.iter() {
|
|
|
|
let mut buf = vec![];
|
|
|
|
module.serialize(&mut buf).map_err(map_failure_error)?;
|
|
|
|
stdlib_modules.push((module.self_id(), buf));
|
|
|
|
}
|
2019-07-23 21:34:17 -07:00
|
|
|
|
|
|
|
txn_executor
|
2019-10-29 10:39:10 -07:00
|
|
|
.make_write_set(stdlib_modules, Ok(()))
|
|
|
|
.map_err(map_err_vm_status)?
|
2019-07-23 21:34:17 -07:00
|
|
|
.write_set()
|
|
|
|
.clone()
|
|
|
|
.into_mut()
|
|
|
|
}
|
|
|
|
.freeze()
|
2019-07-30 23:43:12 -07:00
|
|
|
.map_err(map_failure_error)?;
|
2019-07-23 21:34:17 -07:00
|
|
|
|
2019-10-15 18:30:45 -07:00
|
|
|
Ok(Self::Genesis(write_set))
|
2019-07-23 21:34:17 -07:00
|
|
|
}
|
|
|
|
}
|