Skip to content

Commit

Permalink
Merge pull request #64 from dfinance/executor-moves
Browse files Browse the repository at this point in the history
move some executor-only code to executor.rs
  • Loading branch information
mkurnikov authored May 22, 2020
2 parents 4c98cd9 + 5fe717c commit f808de0
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 242 deletions.
121 changes: 113 additions & 8 deletions crates/dialects/lang/src/dfina/executor.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,125 @@
use std::collections::BTreeMap;

use anyhow::{Context, Result};
use dfin_language_e2e_tests::data_store::FakeDataStore;
use dfin_libra_types::access_path::AccessPath;
use dfin_libra_types::{
transaction::{parse_as_transaction_argument, TransactionArgument},
vm_error::StatusCode,
vm_error::{StatusCode, VMStatus},
write_set::{WriteOp, WriteSet},
};
use dfin_move_core_types::account_address::AccountAddress;
use dfin_move_core_types::gas_schedule::{GasAlgebra, GasUnits};
use dfin_move_lang::{compiled_unit::CompiledUnit, errors::Error, shared::Address, to_bytecode};
use dfin_move_vm_runtime::MoveVM;
use dfin_move_vm_state::execution_context::SystemExecutionContext;
use dfin_move_vm_types::loaded_data::types::FatStructType;
use dfin_move_vm_types::{
gas_schedule::zero_cost_schedule, transaction_metadata::TransactionMetadata,
};
use dfin_move_vm_types::{values::GlobalValue, values::Value};
use dfin_vm::errors::{vm_error, Location, VMResult};
use dfin_vm::file_format::CompiledScript;
use dfin_vm::CompiledModule;

use shared::results::ResourceChange;
use shared::errors::ExecCompilerError;
use shared::results::{ExecResult, ExecutionError, ResourceChange};
use utils::FilePath;

use crate::dfina::resources::{ResourceStructType, ResourceWriteOp};
use crate::dfina::vm_status_into_exec_status;
use crate::dfina::{check_defs, into_exec_compiler_error, parse_files, PreBytecodeProgram};

type ResourcesBTreeMap = BTreeMap<AccessPath, Option<(FatStructType, GlobalValue)>>;

fn vm_status_into_exec_status(vm_status: VMStatus) -> ExecutionError {
ExecutionError {
status: format!("{:?}", vm_status.major_status),
sub_status: vm_status.sub_status,
message: vm_status.message,
}
}

pub fn generate_bytecode(
program: PreBytecodeProgram,
) -> Result<(CompiledScript, Vec<CompiledModule>), Vec<Error>> {
let mut units = to_bytecode::translate::program(program)?;
let script = match units.remove(units.len() - 1) {
CompiledUnit::Script { script, .. } => script,
CompiledUnit::Module { .. } => unreachable!(),
};
let modules = units
.into_iter()
.map(|unit| match unit {
CompiledUnit::Module { module, .. } => module,
CompiledUnit::Script { .. } => unreachable!(),
})
.collect();
Ok((script, modules))
}

pub fn check_and_generate_bytecode(
fname: FilePath,
text: &str,
deps: &[(FilePath, String)],
sender: AccountAddress,
) -> Result<(CompiledScript, Vec<CompiledModule>), ExecCompilerError> {
let (mut script_defs, modules_defs, project_offsets_map) =
parse_files((fname, text.to_owned()), deps, format!("0x{}", sender))?;
script_defs.extend(modules_defs);

let sender = Address::new(sender.into());
let program = check_defs(script_defs, vec![], sender)
.map_err(|errors| into_exec_compiler_error(errors, project_offsets_map.clone()))?;
generate_bytecode(program)
.map_err(|errors| into_exec_compiler_error(errors, project_offsets_map))
}

pub fn serialize_script(script: CompiledScript) -> Result<Vec<u8>> {
let mut serialized = vec![];
script.serialize(&mut serialized)?;
Ok(serialized)
}

pub fn prepare_fake_network_state(
modules: Vec<CompiledModule>,
genesis_write_set: WriteSet,
) -> FakeDataStore {
let mut network_state = FakeDataStore::default();
for module in modules {
network_state.add_module(&module.self_id(), &module);
}
network_state.add_write_set(&genesis_write_set);
network_state
}

fn get_transaction_metadata(sender_address: AccountAddress) -> TransactionMetadata {
let mut metadata = TransactionMetadata::default();
metadata.sender = sender_address;
metadata
}

pub fn execute_script(
sender_address: AccountAddress,
data_store: &FakeDataStore,
script: Vec<u8>,
args: Vec<Value>,
) -> ExecResult<ResourcesBTreeMap> {
let mut exec_context = SystemExecutionContext::new(data_store, GasUnits::new(1_000_000));
let zero_cost_table = zero_cost_schedule();
let txn_metadata = get_transaction_metadata(sender_address);

let vm = MoveVM::new();
vm.execute_script(
script,
&zero_cost_table,
&mut exec_context,
&txn_metadata,
vec![],
args,
)
.map_err(vm_status_into_exec_status)?;
Ok(exec_context.data_map())
}

fn convert_set_value(struct_type: FatStructType, val: GlobalValue) -> VMResult<ResourceChange> {
// into_owned_struct will check if all references are properly released at the end of a transaction
Expand Down Expand Up @@ -54,13 +160,12 @@ pub fn compile_and_run(
let (fname, script_text) = script;

let (compiled_script, compiled_modules) =
crate::dfina::check_and_generate_bytecode(fname, &script_text, deps, sender)?;
check_and_generate_bytecode(fname, &script_text, deps, sender)?;

let network_state =
crate::dfina::prepare_fake_network_state(compiled_modules, genesis_write_set);
let network_state = prepare_fake_network_state(compiled_modules, genesis_write_set);

let serialized_script =
crate::dfina::serialize_script(compiled_script).context("Script serialization error")?;
serialize_script(compiled_script).context("Script serialization error")?;

let mut script_args = Vec::with_capacity(args.len());
for passed_arg in args {
Expand All @@ -69,7 +174,7 @@ pub fn compile_and_run(
script_args.push(script_arg);
}
let changed_resources =
crate::dfina::execute_script(sender, &network_state, serialized_script, script_args)?;
execute_script(sender, &network_state, serialized_script, script_args)?;

let mut changes = vec![];
for (_, global_val) in changed_resources {
Expand Down
116 changes: 3 additions & 113 deletions crates/dialects/lang/src/dfina/mod.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,23 @@
use std::collections::BTreeMap;
use std::path::PathBuf;

use anyhow::Result;
use codespan::ByteIndex;
use dfin_language_e2e_tests::data_store::FakeDataStore;
use dfin_libra_types::{
access_path::AccessPath, account_address::AccountAddress, vm_error::VMStatus,
write_set::WriteSet,
};
use dfin_move_core_types::gas_schedule::{GasAlgebra, GasUnits};
use dfin_libra_types::account_address::AccountAddress;
use dfin_move_ir_types::location::Loc;
use dfin_move_lang::{
cfgir,
compiled_unit::CompiledUnit,
errors::{Error, FilesSourceText},
parser,
parser::ast::Definition,
parser::syntax,
shared::Address,
strip_comments_and_verify, to_bytecode,
strip_comments_and_verify,
};
use dfin_move_vm_runtime::MoveVM;
use dfin_move_vm_state::execution_context::SystemExecutionContext;
use dfin_move_vm_types::{
gas_schedule::zero_cost_schedule,
loaded_data::types::FatStructType,
transaction_metadata::TransactionMetadata,
values::{GlobalValue, Value},
};
use dfin_vm::file_format::CompiledScript;
use dfin_vm::CompiledModule;

use shared::bech32;
use shared::errors::{
CompilerError, CompilerErrorPart, ExecCompilerError, Location, OffsetsMap, ProjectOffsetsMap,
};
use shared::results::{ExecResult, ExecutionError};
use std::path::PathBuf;
use utils::FilePath;

pub mod executor;
Expand Down Expand Up @@ -190,80 +172,6 @@ pub fn parse_files(
Ok((script_defs, dep_defs, project_offsets_map))
}

pub fn check_and_generate_bytecode(
fname: FilePath,
text: &str,
deps: &[(FilePath, String)],
sender: AccountAddress,
) -> Result<(CompiledScript, Vec<CompiledModule>), ExecCompilerError> {
let (mut script_defs, modules_defs, project_offsets_map) =
parse_files((fname, text.to_owned()), deps, format!("0x{}", sender))?;
script_defs.extend(modules_defs);

let sender = Address::new(sender.into());
let program = check_defs(script_defs, vec![], sender)
.map_err(|errors| into_exec_compiler_error(errors, project_offsets_map.clone()))?;
generate_bytecode(program)
.map_err(|errors| into_exec_compiler_error(errors, project_offsets_map))
}

pub fn serialize_script(script: CompiledScript) -> Result<Vec<u8>> {
let mut serialized = vec![];
script.serialize(&mut serialized)?;
Ok(serialized)
}

pub fn prepare_fake_network_state(
modules: Vec<CompiledModule>,
genesis_write_set: WriteSet,
) -> FakeDataStore {
let mut network_state = FakeDataStore::default();
for module in modules {
network_state.add_module(&module.self_id(), &module);
}
network_state.add_write_set(&genesis_write_set);
network_state
}

fn get_transaction_metadata(sender_address: AccountAddress) -> TransactionMetadata {
let mut metadata = TransactionMetadata::default();
metadata.sender = sender_address;
metadata
}

type ChangedMoveResources = BTreeMap<AccessPath, Option<(FatStructType, GlobalValue)>>;

fn vm_status_into_exec_status(vm_status: VMStatus) -> ExecutionError {
ExecutionError {
status: format!("{:?}", vm_status.major_status),
sub_status: vm_status.sub_status,
message: vm_status.message,
}
}

pub fn execute_script(
sender_address: AccountAddress,
data_store: &FakeDataStore,
script: Vec<u8>,
args: Vec<Value>,
) -> ExecResult<ChangedMoveResources> {
let mut exec_context = SystemExecutionContext::new(data_store, GasUnits::new(1_000_000));
let zero_cost_table = zero_cost_schedule();
let txn_metadata = get_transaction_metadata(sender_address);

let vm = MoveVM::new();
vm.execute_script(
script,
&zero_cost_table,
&mut exec_context,
&txn_metadata,
vec![],
args,
)
.map_err(vm_status_into_exec_status)?;
Ok(exec_context.data_map())
}

type PreBytecodeProgram = cfgir::ast::Program;

pub fn check_defs(
Expand All @@ -278,24 +186,6 @@ pub fn check_defs(
dfin_move_lang::check_program(Ok(ast_program), Some(sender))
}

pub fn generate_bytecode(
program: PreBytecodeProgram,
) -> Result<(CompiledScript, Vec<CompiledModule>), Vec<Error>> {
let mut units = to_bytecode::translate::program(program)?;
let script = match units.remove(units.len() - 1) {
CompiledUnit::Script { script, .. } => script,
CompiledUnit::Module { .. } => unreachable!(),
};
let modules = units
.into_iter()
.map(|unit| match unit {
CompiledUnit::Module { module, .. } => module,
CompiledUnit::Script { .. } => unreachable!(),
})
.collect();
Ok((script, modules))
}

pub fn parse_account_address(s: &str) -> Result<AccountAddress> {
AccountAddress::from_hex_literal(s)
}
Expand Down
Loading

0 comments on commit f808de0

Please sign in to comment.