From a06704dc42bfdef226cf033aca34fbe8ccc40c1f Mon Sep 17 00:00:00 2001 From: "Dm. Yakushev" Date: Tue, 12 May 2020 11:13:04 +0300 Subject: [PATCH] Native functions. --- Cargo.lock | 12 ++++ client/libra-dev/include/data.h | 4 +- client/libra-dev/src/event.rs | 2 +- .../move-core/types/src/account_address.rs | 2 +- language/move-lang/src/expansion/translate.rs | 3 - language/move-lang/src/parser/mod.rs | 2 +- language/move-lang/src/shared/mod.rs | 2 +- language/move-vm/natives/Cargo.toml | 3 + language/move-vm/natives/src/lib.rs | 2 + language/move-vm/natives/src/mod.rs | 0 language/move-vm/natives/src/oracle.rs | 68 ++++++++++++------- language/move-vm/runtime/src/data_cache.rs | 6 +- .../move-vm/runtime/src/native_functions.rs | 16 +++-- .../move-vm/state/src/execution_context.rs | 0 language/move-vm/types/Cargo.toml | 2 + language/move-vm/types/src/chain_state.rs | 0 language/move-vm/types/src/data_store.rs | 2 + .../move-vm/types/src/interpreter_context.rs | 0 .../move-vm/types/src/natives/function.rs | 5 +- .../tools/vm-genesis/src/genesis_context.rs | 4 ++ types/src/account_config/constants/account.rs | 4 +- types/src/vm_error.rs | 2 +- 22 files changed, 98 insertions(+), 43 deletions(-) create mode 100644 language/move-vm/natives/src/mod.rs create mode 100644 language/move-vm/state/src/execution_context.rs create mode 100644 language/move-vm/types/src/chain_state.rs create mode 100644 language/move-vm/types/src/interpreter_context.rs diff --git a/Cargo.lock b/Cargo.lock index 8860eddaa0b8..617a597a778c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3470,6 +3470,7 @@ name = "move-vm-natives" version = "0.1.0" dependencies = [ "bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "libra-crypto 0.1.0", "libra-types 0.1.0", "libra-workspace-hack 0.1.0", @@ -3478,6 +3479,7 @@ dependencies = [ "move-vm-types 0.1.0", "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", ] @@ -3509,6 +3511,7 @@ version = "0.1.0" dependencies = [ "libra-canonical-serialization 0.1.0", "libra-crypto 0.1.0", + "libra-state-view 0.1.0", "libra-types 0.1.0", "libra-workspace-hack 0.1.0", "mirai-annotations 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6164,6 +6167,14 @@ dependencies = [ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "twox-hash" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typed-arena" version = "2.0.1" @@ -7139,6 +7150,7 @@ dependencies = [ "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +"checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" "checksum typed-arena 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" "checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" "checksum ucd-trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" diff --git a/client/libra-dev/include/data.h b/client/libra-dev/include/data.h index 6ccbc92659dd..2a82342b8934 100644 --- a/client/libra-dev/include/data.h +++ b/client/libra-dev/include/data.h @@ -13,8 +13,8 @@ extern "C" { #define LIBRA_PUBKEY_SIZE 32 #define LIBRA_PRIVKEY_SIZE 32 #define LIBRA_SIGNATURE_SIZE 64 -#define LIBRA_ADDRESS_SIZE 16 -#define LIBRA_EVENT_KEY_SIZE 24 +#define LIBRA_ADDRESS_SIZE 20 +#define LIBRA_EVENT_KEY_SIZE 28 enum LibraStatus { Ok = 0, diff --git a/client/libra-dev/src/event.rs b/client/libra-dev/src/event.rs index 6afc9819d3ae..034030cc548d 100644 --- a/client/libra-dev/src/event.rs +++ b/client/libra-dev/src/event.rs @@ -192,7 +192,7 @@ fn test_libra_LibraEvent_from() { let sent_event_handle = EventHandle::new(EventKey::new_from_address(&sender_address, 0), 0); let sequence_number = sent_event_handle.count(); let event_key = sent_event_handle.key(); - let module = "LibraAccount"; + let module = "Account"; let name = "SentPaymentEvent"; let type_tag = Struct(StructTag { diff --git a/language/move-core/types/src/account_address.rs b/language/move-core/types/src/account_address.rs index 24674c6f8b14..682f15bda233 100644 --- a/language/move-core/types/src/account_address.rs +++ b/language/move-core/types/src/account_address.rs @@ -26,7 +26,7 @@ impl AccountAddress { } /// The number of bytes in an address. - pub const LENGTH: usize = 16; + pub const LENGTH: usize = 20; pub const DEFAULT: Self = Self([0u8; AccountAddress::LENGTH]); diff --git a/language/move-lang/src/expansion/translate.rs b/language/move-lang/src/expansion/translate.rs index 265c36cb2e2f..b6786ff92d18 100644 --- a/language/move-lang/src/expansion/translate.rs +++ b/language/move-lang/src/expansion/translate.rs @@ -276,9 +276,6 @@ fn module_(context: &mut Context, mdef: P::ModuleDefinition) -> (ModuleIdent, E: }; let current_module = ModuleIdent(sp(name_loc, mident_)); let old_is_source_module = context.is_source_module; - context.is_source_module = - context.is_source_module && !fake_natives::is_fake_native(¤t_module); - let mut new_scope = AliasMap::new(); module_self_aliases(&mut new_scope, ¤t_module); let members = members diff --git a/language/move-lang/src/parser/mod.rs b/language/move-lang/src/parser/mod.rs index db90007dbfe1..9d7e67e836c5 100644 --- a/language/move-lang/src/parser/mod.rs +++ b/language/move-lang/src/parser/mod.rs @@ -1,6 +1,6 @@ // Copyright (c) The Libra Core Contributors // SPDX-License-Identifier: Apache-2.0 +pub mod ast; pub mod lexer; pub mod syntax; -pub mod ast; diff --git a/language/move-lang/src/shared/mod.rs b/language/move-lang/src/shared/mod.rs index f5fefe74fed5..4152b387b7e4 100644 --- a/language/move-lang/src/shared/mod.rs +++ b/language/move-lang/src/shared/mod.rs @@ -19,7 +19,7 @@ pub mod unique_map; // Address //************************************************************************************************** -pub const ADDRESS_LENGTH: usize = 16; +pub const ADDRESS_LENGTH: usize = 20; #[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Default, Clone, Copy)] pub struct Address([u8; ADDRESS_LENGTH]); diff --git a/language/move-vm/natives/Cargo.toml b/language/move-vm/natives/Cargo.toml index f480418130d4..6ddb474fe520 100644 --- a/language/move-vm/natives/Cargo.toml +++ b/language/move-vm/natives/Cargo.toml @@ -23,6 +23,9 @@ libra-workspace-hack = { path = "../../../common/workspace-hack", version = "0.1 move-core-types = { path = "../../move-core/types", version = "0.1.0" } move-vm-types = { path = "../types", version = "0.1.0" } vm = { path = "../../vm", version = "0.1.0" } +twox-hash = "1.5.0" + +byteorder = "1.3.4" [features] default = [] diff --git a/language/move-vm/natives/src/lib.rs b/language/move-vm/natives/src/lib.rs index fa6408664e7a..45e3744fd0c0 100644 --- a/language/move-vm/natives/src/lib.rs +++ b/language/move-vm/natives/src/lib.rs @@ -6,9 +6,11 @@ extern crate move_vm_types; pub mod account; pub mod debug; +pub mod dfinance; pub mod event; pub mod hash; pub mod lcs; +pub mod oracle; pub mod signature; pub mod signer; pub mod vector; diff --git a/language/move-vm/natives/src/mod.rs b/language/move-vm/natives/src/mod.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/language/move-vm/natives/src/oracle.rs b/language/move-vm/natives/src/oracle.rs index 29f26787c5f4..defe97b45e1b 100644 --- a/language/move-vm/natives/src/oracle.rs +++ b/language/move-vm/natives/src/oracle.rs @@ -1,37 +1,51 @@ -use move_vm_types::natives::function::{NativeContext, NativeResult}; -use move_vm_types::loaded_data::runtime_types::Type; -use move_vm_types::values::Value; -use libra_types::access_path::AccessPath; -use libra_types::account_address::AccountAddress; -use libra_types::vm_error::{VMStatus, StatusCode}; -use libra_crypto::hash::{DefaultHasher, CryptoHasher}; -use std::collections::VecDeque; -use vm::errors::VMResult; -use byteorder::{LittleEndian, ByteOrder}; -use move_core_types::{ - gas_schedule::{GasUnits, GasAlgebra}, +use byteorder::{ByteOrder, LittleEndian}; +use libra_crypto::hash::DefaultHasher; +use libra_types::{ + access_path::AccessPath, + account_address::AccountAddress, + vm_error::{StatusCode, VMStatus}, +}; +use move_core_types::gas_schedule::{GasAlgebra, GasUnits}; +use move_vm_types::{ + loaded_data::{runtime_types::Type, types::FatType}, + natives::function::{NativeContext, NativeResult}, + values::Value, }; -use std::io::Write; +use std::{collections::VecDeque, hash::Hasher}; +use twox_hash::XxHash64; +use vm::errors::VMResult; const COST: u64 = 929; const PRICE_ORACLE_TAG: u8 = 255; pub fn native_oracle_get_price( context: &impl NativeContext, - _ty_args: Vec, - mut arguments: VecDeque, + ty_args: Vec, + _arguments: VecDeque, ) -> VMResult { - if arguments.len() != 1 { + let ty_args = context.convert_to_fat_types(ty_args)?; + + if ty_args.len() != 2 { let msg = format!( - "wrong number of arguments for get_price expected 1 found {}", - arguments.len() + "wrong number of type parameters for get_price expected 2 found {}", + ty_args.len() ); return Err(status(StatusCode::UNREACHABLE, &msg)); } - let ticker = pop_arg!(arguments, u64); - let price = - make_path(ticker) + let price = type_parameter_name(&ty_args[0]) + .and_then(|ticker_part| { + type_parameter_name(&ty_args[1]) + .and_then(|ticker_part_2| { + Ok(format!("{}{}", ticker_part, ticker_part_2).to_lowercase()) + }) + .and_then(|ticker| { + let mut hash = XxHash64::default(); + Hasher::write(&mut hash, ticker.as_bytes()); + Ok(Hasher::finish(&hash)) + }) + }) + .and_then(|ticker| make_path(ticker)) .and_then(|path| { let value = context.raw_load(&path).map_err(|err| { status( @@ -58,17 +72,23 @@ pub fn native_oracle_get_price( }) } +fn type_parameter_name(ty_arg: &FatType) -> Result { + match ty_arg { + FatType::Struct(t) => Ok(t.name.as_str().to_owned()), + _ => Err(status(StatusCode::TYPE_MISMATCH, "Expected a struct")), + } +} + fn status(code: StatusCode, msg: &str) -> VMStatus { VMStatus::new(code).with_message(msg.to_owned()) } pub fn make_path(ticker_pair: u64) -> Result { - let mut hasher = DefaultHasher::default(); + let mut hasher = DefaultHasher::new(&[]); let mut buf = [0; 8]; LittleEndian::write_u64(&mut buf, ticker_pair); - hasher.write(&buf).map_err(|_| VMStatus::new(StatusCode::BAD_U64))?; + hasher.update(&buf); let mut hash = hasher.finish().to_vec(); hash.insert(0, PRICE_ORACLE_TAG); Ok(AccessPath::new(AccountAddress::DEFAULT, hash)) } - diff --git a/language/move-vm/runtime/src/data_cache.rs b/language/move-vm/runtime/src/data_cache.rs index e85498618490..308a2902833d 100644 --- a/language/move-vm/runtime/src/data_cache.rs +++ b/language/move-vm/runtime/src/data_cache.rs @@ -48,7 +48,7 @@ pub struct TransactionDataCache<'txn> { data_map: BTreeMap>, module_map: BTreeMap>, event_data: Vec, - data_cache: &'txn dyn RemoteCache, + pub data_cache: &'txn dyn RemoteCache, } impl<'txn> TransactionDataCache<'txn> { @@ -197,6 +197,10 @@ impl<'a> DataStore for TransactionDataCache<'a> { } } + fn raw_load(&self, path: &AccessPath) -> VMResult>> { + self.data_cache.get(&path) + } + fn publish_module(&mut self, m: ModuleId, bytes: Vec) -> VMResult<()> { self.module_map.insert(m, bytes); Ok(()) diff --git a/language/move-vm/runtime/src/native_functions.rs b/language/move-vm/runtime/src/native_functions.rs index 64b962f2e9c7..ef79c11d7ba4 100644 --- a/language/move-vm/runtime/src/native_functions.rs +++ b/language/move-vm/runtime/src/native_functions.rs @@ -7,7 +7,7 @@ use libra_types::{ contract_event::ContractEvent, }; use move_core_types::{gas_schedule::CostTable, identifier::IdentStr, language_storage::ModuleId}; -use move_vm_natives::{account, debug, event, hash, lcs, signature, signer, vector}; +use move_vm_natives::{account, debug, event, hash, lcs, oracle, signature, signer, vector, dfinance}; use move_vm_types::{ data_store::DataStore, gas_schedule::CostStrategy, @@ -46,6 +46,8 @@ pub(crate) enum NativeFunction { SignerBorrowAddress, CreateSigner, DestroySigner, + OraclePrice, + DfinanceSaveInfo, } impl NativeFunction { @@ -75,11 +77,13 @@ impl NativeFunction { (&CORE_CODE_ADDRESS, "Vector", "destroy_empty") => VectorDestroyEmpty, (&CORE_CODE_ADDRESS, "Vector", "swap") => VectorSwap, (&CORE_CODE_ADDRESS, "Event", "write_to_event_store") => AccountWriteEvent, - (&CORE_CODE_ADDRESS, "LibraAccount", "create_signer") => CreateSigner, - (&CORE_CODE_ADDRESS, "LibraAccount", "destroy_signer") => DestroySigner, + (&CORE_CODE_ADDRESS, "Account", "create_signer") => CreateSigner, + (&CORE_CODE_ADDRESS, "Account", "destroy_signer") => DestroySigner, (&CORE_CODE_ADDRESS, "Debug", "print") => DebugPrint, (&CORE_CODE_ADDRESS, "Debug", "print_stack_trace") => DebugPrintStackTrace, (&CORE_CODE_ADDRESS, "Signer", "borrow_address") => SignerBorrowAddress, + (&CORE_CODE_ADDRESS, "Oracle", "get_price") => OraclePrice, + (&CORE_CODE_ADDRESS, "Dfinance", "register_token_info") => DfinanceSaveInfo, _ => return None, }) } @@ -115,6 +119,8 @@ impl NativeFunction { Self::SignerBorrowAddress => signer::native_borrow_address(ctx, t, v), Self::CreateSigner => account::native_create_signer(ctx, t, v), Self::DestroySigner => account::native_destroy_signer(ctx, t, v), + Self::OraclePrice => oracle::native_oracle_get_price(ctx, t, v), + Self::DfinanceSaveInfo => dfinance::native_register_token_info(ctx, t, v), } } } @@ -171,7 +177,9 @@ impl<'a> NativeContext for FunctionContext<'a> { resource_to_save, ) } - + fn raw_load(&self, path: &AccessPath) -> VMResult>> { + self.data_store.raw_load(path) + } fn save_event(&mut self, event: ContractEvent) -> VMResult<()> { Ok(self.data_store.emit_event(event)) } diff --git a/language/move-vm/state/src/execution_context.rs b/language/move-vm/state/src/execution_context.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/language/move-vm/types/Cargo.toml b/language/move-vm/types/Cargo.toml index 023ece2b7d5e..cfc27a3e4cb5 100644 --- a/language/move-vm/types/Cargo.toml +++ b/language/move-vm/types/Cargo.toml @@ -23,6 +23,8 @@ libra-workspace-hack = { path = "../../../common/workspace-hack", version = "0.1 move-core-types = { path = "../../move-core/types", version = "0.1.0" } vm = { path = "../../vm", version = "0.1.0" } +libra-state-view = { path = "../../../storage/state-view", version = "0.1.0"} + [dev-dependencies] proptest = "0.10.0" diff --git a/language/move-vm/types/src/chain_state.rs b/language/move-vm/types/src/chain_state.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/language/move-vm/types/src/data_store.rs b/language/move-vm/types/src/data_store.rs index c1e927aca34d..acd6a0eb3d5c 100644 --- a/language/move-vm/types/src/data_store.rs +++ b/language/move-vm/types/src/data_store.rs @@ -41,6 +41,8 @@ pub trait DataStore { /// Get the serialized format of a `CompiledModule` given a `ModuleId`. fn load_module(&self, module: &ModuleId) -> VMResult>; + fn raw_load(&self, path: &AccessPath) -> VMResult>>; + /// Publish a module. fn publish_module(&mut self, module_id: ModuleId, module: Vec) -> VMResult<()>; diff --git a/language/move-vm/types/src/interpreter_context.rs b/language/move-vm/types/src/interpreter_context.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/language/move-vm/types/src/natives/function.rs b/language/move-vm/types/src/natives/function.rs index 23a9c48c7add..48b9d50a5ee0 100644 --- a/language/move-vm/types/src/natives/function.rs +++ b/language/move-vm/types/src/natives/function.rs @@ -22,9 +22,8 @@ use crate::{ values::{Struct, Value}, }; use libra_types::{ - account_address::AccountAddress, contract_event::ContractEvent, + access_path::AccessPath, account_address::AccountAddress, contract_event::ContractEvent, vm_error::VMStatus, - access_path::AccessPath }; use move_core_types::{ gas_schedule::{AbstractMemorySize, CostTable, GasAlgebra, GasCarrier, GasUnits}, @@ -58,6 +57,8 @@ pub trait NativeContext { fn save_event(&mut self, event: ContractEvent) -> VMResult<()>; /// Converts types to fet types. fn convert_to_fat_types(&self, types: Vec) -> VMResult>; + /// Load from state view. + fn raw_load(&self, path: &AccessPath) -> VMResult>>; /// Whether a type is a resource or not. fn is_resource(&self, ty: &Type) -> VMResult; } diff --git a/language/tools/vm-genesis/src/genesis_context.rs b/language/tools/vm-genesis/src/genesis_context.rs index bf43c65ec42b..6dbfa8a67f37 100644 --- a/language/tools/vm-genesis/src/genesis_context.rs +++ b/language/tools/vm-genesis/src/genesis_context.rs @@ -234,4 +234,8 @@ impl<'txn> DataStore for GenesisDataCache<'txn> { fn emit_event(&mut self, event: ContractEvent) { self.data_store.emit_event(event) } + + fn raw_load(&self, path: &AccessPath) -> VMResult>> { + self.data_store.raw_load(path) + } } diff --git a/types/src/account_config/constants/account.rs b/types/src/account_config/constants/account.rs index 46d4a1b27c87..1ee22d3447de 100644 --- a/types/src/account_config/constants/account.rs +++ b/types/src/account_config/constants/account.rs @@ -8,11 +8,11 @@ use move_core_types::{ }; use once_cell::sync::Lazy; -pub const ACCOUNT_MODULE_NAME: &str = "LibraAccount"; +pub const ACCOUNT_MODULE_NAME: &str = "Account"; // Account static ACCOUNT_MODULE_IDENTIFIER: Lazy = - Lazy::new(|| Identifier::new("LibraAccount").unwrap()); + Lazy::new(|| Identifier::new("Account").unwrap()); /// The ModuleId for the Account module. pub static ACCOUNT_MODULE: Lazy = diff --git a/types/src/vm_error.rs b/types/src/vm_error.rs index c55be56972aa..6d41d72feb99 100644 --- a/types/src/vm_error.rs +++ b/types/src/vm_error.rs @@ -4,13 +4,13 @@ #![allow(clippy::unit_arg)] use anyhow::Result; +use enum_iterator::IntoEnumIterator; #[cfg(any(test, feature = "fuzzing"))] use proptest::prelude::*; #[cfg(any(test, feature = "fuzzing"))] use proptest_derive::Arbitrary; use serde::{de, ser, Deserialize, Serialize}; use std::{convert::TryFrom, fmt}; -use enum_iterator::IntoEnumIterator; /// The minimum status code for validation statuses pub static VALIDATION_STATUS_MIN_CODE: u64 = 0;