Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fastx adapter] making move execution work end-to-end #88

Merged
merged 1 commit into from
Dec 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions fastpay_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2018"

[dependencies]
anyhow = "1.0"
bcs = "0.1.2"
failure = "0.1.8"
futures = "0.3.5"
rand = "0.7.3"
Expand All @@ -19,4 +20,6 @@ fastx-types = { path = "../fastx_types" }

move-binary-format = { git = "https://github.com/diem/diem", rev="346301f33b3489bb4e486ae6c0aa5e030223b492" }
move-core-types = { git = "https://github.com/diem/diem", rev="346301f33b3489bb4e486ae6c0aa5e030223b492" }
move-vm-runtime = { git = "https://github.com/diem/diem", rev="346301f33b3489bb4e486ae6c0aa5e030223b492" }


62 changes: 48 additions & 14 deletions fastpay_core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ use move_core_types::{
language_storage::{ModuleId, StructTag},
resolver::{ModuleResolver, ResourceResolver},
};
use std::{collections::BTreeMap, convert::TryInto, sync::Arc, sync::Mutex};
use move_vm_runtime::native_functions::NativeFunctionTable;
use std::{
collections::{BTreeMap, HashSet},
convert::TryInto,
sync::Arc,
sync::Mutex,
};

#[cfg(test)]
#[path = "unit_tests/authority_tests.rs"]
Expand Down Expand Up @@ -68,6 +74,9 @@ pub struct AuthorityState {
/// An index mapping object IDs to the Transaction Digest that created them.
/// This is used by synchronization logic to sync authorities.
parent_sync: BTreeMap<(ObjectID, SequenceNumber), TransactionDigest>,

/// Move native functions that are available to invoke
native_functions: NativeFunctionTable,
}

/// Interface provided by each (shard of an) authority.
Expand Down Expand Up @@ -107,6 +116,11 @@ impl Authority for AuthorityState {
!input_objects.is_empty(),
FastPayError::InsufficientObjectNumber
);
// Ensure that there are no duplicate inputs
let mut used = HashSet::new();
if !input_objects.iter().all(|o| used.insert(o)) {
return Err(FastPayError::DuplicateObjectRefInput);
}

for object_ref in input_objects {
let (object_id, sequence_number) = object_ref;
Expand Down Expand Up @@ -234,19 +248,38 @@ impl Authority for AuthorityState {
temporary_store.write_object(output_object);
}
OrderKind::Call(c) => {
let sender = c.sender.to_address_hack();
// unwraps here are safe because we built `inputs`
// TODO(https://github.com/MystenLabs/fastnft/issues/45): charge for gas
adapter::execute(
let mut gas_object = inputs.pop().unwrap();
let module = inputs.pop().unwrap();
huitseeker marked this conversation as resolved.
Show resolved Hide resolved
// Fake the gas payment
gas_object.next_sequence_number = gas_object.next_sequence_number.increment()?;
temporary_store.write_object(gas_object);
match adapter::execute(
&mut temporary_store,
&c.module,
self.native_functions.clone(),
module,
&c.function,
sender,
c.object_arguments.clone(),
c.pure_arguments.clone(),
c.type_arguments.clone(),
c.type_arguments,
inputs,
c.pure_arguments,
Some(c.gas_budget),
)
.map_err(|_| FastPayError::MoveExecutionFailure)?;
tx_ctx,
) {
Ok(()) => {
// TODO(https://github.com/MystenLabs/fastnft/issues/63): AccountInfoResponse should return all object ID outputs.
// but for now it only returns one, so use this hack
object_id = if temporary_store.written.len() > 1 {
temporary_store.written[1].0
} else {
c.gas_payment.0
}
}
Err(_e) => {
// TODO(https://github.com/MystenLabs/fastnft/issues/63): return this error to the client
object_id = c.gas_payment.0;
}
}
}
OrderKind::Publish(m) => {
// Fake the gas payment
Expand All @@ -259,13 +292,12 @@ impl Authority for AuthorityState {
let sender = m.sender.to_address_hack();
match adapter::publish(&mut temporary_store, m.modules, &sender, &mut tx_ctx) {
Ok(outputs) => {
// TODO: AccountInfoResponse should return all object ID outputs.
// TODO(https://github.com/MystenLabs/fastnft/issues/63): AccountInfoResponse should return all object ID outputs.
// but for now it only returns one, so use this hack
object_id = outputs[0].0;
}
Err(_e) => {
println!("failure during publishing: {:?}", _e);
// TODO: return this error to the client
// TODO(https://github.com/MystenLabs/fastnft/issues/63): return this error to the client
object_id = m.gas_payment.0;
}
}
Expand Down Expand Up @@ -340,6 +372,7 @@ impl AuthorityState {
number_of_shards: 1,
certificates: BTreeMap::new(),
parent_sync: BTreeMap::new(),
native_functions: NativeFunctionTable::new(),
}
}

Expand All @@ -360,6 +393,7 @@ impl AuthorityState {
number_of_shards,
certificates: BTreeMap::new(),
parent_sync: BTreeMap::new(),
native_functions: NativeFunctionTable::new(),
}
}

Expand All @@ -377,7 +411,7 @@ impl AuthorityState {
Self::get_shard(self.number_of_shards, object_id)
}

fn object_state(&self, object_id: &ObjectID) -> Result<Object, FastPayError> {
pub fn object_state(&self, object_id: &ObjectID) -> Result<Object, FastPayError> {
self.objects
.lock()
.unwrap()
Expand Down
29 changes: 0 additions & 29 deletions fastpay_core/src/genesis.rs

This file was deleted.

1 change: 0 additions & 1 deletion fastpay_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ pub mod authority;
pub mod client;
pub mod downloader;
pub mod fastpay_smart_contract;
pub mod genesis;
61 changes: 40 additions & 21 deletions fastpay_core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
// SPDX-License-Identifier: Apache-2.0

use super::*;
use crate::genesis;
use bcs;
use fastx_adapter::genesis;
#[cfg(test)]
use fastx_types::base_types::dbg_addr;
use move_binary_format::{
file_format::{self, AddressIdentifierIndex, IdentifierIndex, ModuleHandle},
CompiledModule,
};
use move_core_types::ident_str;
#[cfg(test)]
use move_core_types::language_storage::ModuleId;

#[test]
fn test_handle_transfer_order_bad_signature() {
Expand Down Expand Up @@ -188,7 +187,8 @@ fn test_publish_dependent_module_ok() {
let gas_payment_object = Object::with_id_owner_for_testing(gas_payment_object_id, sender);
let gas_payment_object_ref = gas_payment_object.to_object_reference();
// create a genesis state that contains the gas object and genesis modules
let mut genesis_module_objects = genesis::create_genesis_module_objects().unwrap();
let genesis = genesis::GENESIS.lock().unwrap();
let mut genesis_module_objects = genesis.objects.clone();
let genesis_module = match &genesis_module_objects[0].data {
Data::Module(m) => CompiledModule::deserialize(m).unwrap(),
_ => unreachable!(),
Expand Down Expand Up @@ -241,39 +241,58 @@ fn test_publish_module_no_dependencies_ok() {
}

#[test]
fn test_handle_move_order_bad() {
fn test_handle_move_order() {
let (sender, sender_key) = get_key_pair();
// create a dummy gas payment object. ok for now because we don't check gas
let gas_payment_object_id = ObjectID::random();
let gas_payment_object = Object::with_id_owner_for_testing(gas_payment_object_id, sender);
let gas_payment_object_ref = gas_payment_object.to_object_reference();
// create a dummy module. execution will fail when we try to read it
let dummy_module_object_id = ObjectID::random();
let dummy_module_object = Object::with_id_owner_for_testing(dummy_module_object_id, sender);
// find the function Object::create and call it to create a new object
let genesis = genesis::GENESIS.lock().unwrap();
let mut genesis_module_objects = genesis.objects.clone();
let module_object_ref = genesis_module_objects
.iter()
.find_map(|o| match o.data.as_module() {
Some(m) => {
if m.self_id().name() == ident_str!("ObjectBasics") {
Some((*m.self_id().address(), SequenceNumber::new()))
} else {
None
}
}
None => None,
})
.unwrap();

let mut authority_state =
init_state_with_objects(vec![gas_payment_object, dummy_module_object]);
genesis_module_objects.push(gas_payment_object);
let mut authority_state = init_state_with_objects(genesis_module_objects);
authority_state.native_functions = genesis.native_functions.clone();

let module_id = ModuleId::new(dummy_module_object_id, ident_str!("Module").to_owned());
let function = ident_str!("function_name").to_owned();
let function = ident_str!("create").to_owned();
let order = Order::new_move_call(
sender,
module_id,
module_object_ref,
function,
Vec::new(),
gas_payment_object_ref,
Vec::new(),
Vec::new(),
vec![
16u64.to_le_bytes().to_vec(),
bcs::to_bytes(&sender.to_address_hack().to_vec()).unwrap(),
],
1000,
&sender_key,
);

// Submit the confirmation. *Now* execution actually happens, and it should fail when we try to look up our dummy module.
// we unfortunately don't get a very descriptive error message, but we can at least see that something went wrong inside the VM
match send_and_confirm_order(&mut authority_state, order) {
Err(FastPayError::MoveExecutionFailure) => (),
r => panic!("Unexpected result {:?}", r),
}
let res = send_and_confirm_order(&mut authority_state, order).unwrap();
let created_object_id = res.object_id;
// check that order actually created an object with the expected ID, owner, sequence number
let created_obj = authority_state.object_state(&created_object_id).unwrap();
assert_eq!(
created_obj.owner.to_address_hack(),
sender.to_address_hack()
);
assert_eq!(created_obj.id(), created_object_id);
assert_eq!(created_obj.next_sequence_number, SequenceNumber::new());
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions fastx_programmability/adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ edition = "2018"
[dependencies]
anyhow = "1.0.38"
bcs = "0.1.2"
once_cell = "1.9.0"
structopt = "0.3.21"

move-binary-format = { git = "https://github.com/diem/diem", rev="346301f33b3489bb4e486ae6c0aa5e030223b492" }
Expand All @@ -25,6 +26,7 @@ fastx-types = { path = "../../fastx_types" }

[dev-dependencies]
datatest-stable = "0.1.1"
move-package = { git = "https://github.com/diem/diem", rev="346301f33b3489bb4e486ae6c0aa5e030223b492" }

[[bin]]
name = "fastx"
Expand Down
Loading