From 3af9e169a47ee22438369f4ebe110fd114a57ecc Mon Sep 17 00:00:00 2001 From: yejiayu Date: Wed, 25 Dec 2019 19:27:47 +0800 Subject: [PATCH 1/9] feat(build-in-services): Add asset service. --- Cargo.lock | 19 ++- Cargo.toml | 1 + build-in-services/asset/Cargo.toml | 23 +++ build-in-services/asset/src/lib.rs | 147 ++++++++++++++++++ build-in-services/asset/src/tests/mod.rs | 187 +++++++++++++++++++++++ build-in-services/asset/src/types.rs | 81 ++++++++++ framework/src/binding/mod.rs | 6 +- framework/src/tests/mod.rs | 4 +- protocol/Cargo.toml | 4 +- protocol/src/fixed_codec/primitive.rs | 18 +++ protocol/src/lib.rs | 1 + protocol/src/traits/binding.rs | 11 ++ protocol/src/traits/mod.rs | 4 +- protocol/src/types/genesis.rs | 2 +- protocol/src/types/primitive.rs | 5 +- 15 files changed, 500 insertions(+), 13 deletions(-) create mode 100644 build-in-services/asset/Cargo.toml create mode 100644 build-in-services/asset/src/lib.rs create mode 100644 build-in-services/asset/src/tests/mod.rs create mode 100644 build-in-services/asset/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index bbfefc6f8..b3a741a88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,6 +62,23 @@ name = "arrayref" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "asset" +version = "0.1.0" +dependencies = [ + "async-trait 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "binding-macro 0.1.0", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cita_trie 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "framework 0.1.0", + "protocol 0.1.0", + "rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "async-datagram" version = "3.0.0" @@ -2214,6 +2231,7 @@ version = "0.1.0" dependencies = [ "async-trait 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cita_trie 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "creep 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2231,7 +2249,6 @@ dependencies = [ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 0fa69a35c..ef1371fcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ members = [ "binding-macro", "framework", + "build-in-services/asset", "protocol", ] diff --git a/build-in-services/asset/Cargo.toml b/build-in-services/asset/Cargo.toml new file mode 100644 index 000000000..ec1b0c0fa --- /dev/null +++ b/build-in-services/asset/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "asset" +version = "0.1.0" +authors = ["Muta Dev "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +framework = { path = "../../framework" } +binding-macro = { path = "../../binding-macro" } +protocol = { path = "../../protocol" } + +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +rlp = "0.4" +bytes = "0.4" +derive_more = "0.15" +byteorder = "1.3" + +[dev-dependencies] +cita_trie = "2.0" +async-trait = "0.1" diff --git a/build-in-services/asset/src/lib.rs b/build-in-services/asset/src/lib.rs new file mode 100644 index 000000000..e2b8be037 --- /dev/null +++ b/build-in-services/asset/src/lib.rs @@ -0,0 +1,147 @@ +#[cfg(test)] +mod tests; +mod types; + +use bytes::Bytes; +use derive_more::{Display, From}; + +use binding_macro::{cycles, init, read, service, write}; +use protocol::traits::{RequestContext, ReturnEmpty, ServiceSDK, StoreMap, RETURN_EMPTY}; +use protocol::types::Hash; +use protocol::{ProtocolError, ProtocolErrorKind, ProtocolResult}; + +use crate::types::{ + Asset, CreateAssetPayload, GetAssetPayload, GetBalancePayload, GetBalanceResponse, + TransferPayload, +}; + +pub struct AssetService { + sdk: SDK, + assets: Box>, +} + +#[service] +impl AssetService { + #[init] + fn init(mut sdk: SDK) -> ProtocolResult { + let assets: Box> = sdk.alloc_or_recover_map("assrts")?; + + Ok(Self { assets, sdk }) + } + + #[cycles(100_00)] + #[read] + fn get_asset( + &self, + _ctx: Context, + payload: GetAssetPayload, + ) -> ProtocolResult { + let asset = self.assets.get(&payload.id)?; + Ok(asset) + } + + #[cycles(100_00)] + #[read] + fn get_balance( + &self, + ctx: Context, + payload: GetBalancePayload, + ) -> ProtocolResult { + let balance = self + .sdk + .get_account_value(&ctx.get_caller(), &payload.asset_id)? + .unwrap_or(0); + Ok(GetBalanceResponse { + asset_id: payload.asset_id, + balance, + }) + } + + #[cycles(210_00)] + #[write] + fn create_asset( + &mut self, + ctx: Context, + payload: CreateAssetPayload, + ) -> ProtocolResult { + let caller = ctx.get_caller(); + let payload_str = + serde_json::to_string(&payload).map_err(|e| ServiceError::JsonParse(e))?; + + let id = Hash::digest(Bytes::from(payload_str + &caller.as_hex())); + + if self.assets.contains(&id)? { + return Err(ServiceError::Exists { id }.into()); + } + let asset = Asset { + id: id.clone(), + name: payload.name, + symbol: payload.symbol, + supply: payload.supply, + owner: caller.clone(), + }; + self.assets.insert(id.clone(), asset.clone())?; + + self.sdk + .set_account_value(&caller, id.clone(), payload.supply)?; + + Ok(asset) + } + + #[cycles(210_00)] + #[write] + fn transfer( + &mut self, + ctx: Context, + payload: TransferPayload, + ) -> ProtocolResult { + let caller = ctx.get_caller(); + let asset_id = payload.asset_id.clone(); + let value = payload.value; + let to = payload.to.clone(); + + if !self.assets.contains(&asset_id)? { + return Err(ServiceError::NotFoundAsset { id: asset_id }.into()); + } + + let caller_balance: u64 = self.sdk.get_account_value(&caller, &asset_id)?.unwrap_or(0); + if caller_balance < value { + return Err(ServiceError::LackOfBalance { + expect: value, + real: caller_balance, + } + .into()); + } + + let to_balance = self.sdk.get_account_value(&to, &asset_id)?.unwrap_or(0); + self.sdk + .set_account_value(&to, asset_id.clone(), to_balance + value)?; + self.sdk + .set_account_value(&caller, asset_id.clone(), caller_balance - value)?; + + Ok(RETURN_EMPTY) + } +} + +#[derive(Debug, Display, From)] +pub enum ServiceError { + #[display(fmt = "Parsing payload to json failed {:?}", _0)] + JsonParse(serde_json::Error), + + #[display(fmt = "Asset {:?} already exists", id)] + Exists { id: Hash }, + + #[display(fmt = "Not found asset, id {:?}", id)] + NotFoundAsset { id: Hash }, + + #[display(fmt = "Not found asset, expect {:?} real {:?}", expect, real)] + LackOfBalance { expect: u64, real: u64 }, +} + +impl std::error::Error for ServiceError {} + +impl From for ProtocolError { + fn from(err: ServiceError) -> ProtocolError { + ProtocolError::new(ProtocolErrorKind::Service, Box::new(err)) + } +} diff --git a/build-in-services/asset/src/tests/mod.rs b/build-in-services/asset/src/tests/mod.rs new file mode 100644 index 000000000..8a9354dc1 --- /dev/null +++ b/build-in-services/asset/src/tests/mod.rs @@ -0,0 +1,187 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::sync::Arc; + +use async_trait::async_trait; +use cita_trie::MemoryDB; + +use framework::binding::sdk::{DefalutServiceSDK, DefaultChainQuerier}; +use framework::binding::state::{GeneralServiceState, MPTTrie}; +use framework::{ContextParams, DefaultRequestContext}; +use protocol::traits::Storage; +use protocol::types::{Address, Epoch, Hash, Proof, Receipt, SignedTransaction}; +use protocol::ProtocolResult; + +use crate::types::{CreateAssetPayload, GetAssetPayload, GetBalancePayload, TransferPayload}; +use crate::AssetService; + +#[test] +fn get_asset() {} + +#[test] +fn test_create_asset() { + let cycles_limit = 1024 * 1024 * 1024; // 1073741824 + let caller = Address::from_hex("0x755cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); + let context = mock_context(cycles_limit, caller); + + let mut service = new_asset_service(context.clone()); + + let supply = 1024 * 1024; + // test create_asset + let asset = service + .create_asset(context.clone(), CreateAssetPayload { + name: "test".to_owned(), + symbol: "test".to_owned(), + supply, + }) + .unwrap(); + + let new_asset = service + .get_asset(context.clone(), GetAssetPayload { + id: asset.id.clone(), + }) + .unwrap(); + assert_eq!(asset, new_asset); + + let balance_res = service + .get_balance(context.clone(), GetBalancePayload { + asset_id: asset.id.clone(), + }) + .unwrap(); + assert_eq!(balance_res.balance, supply); + assert_eq!(balance_res.asset_id, asset.id); +} + +#[test] +fn test_transfer() { + let cycles_limit = 1024 * 1024 * 1024; // 1073741824 + let caller = Address::from_hex("0x755cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); + let context = mock_context(cycles_limit, caller.clone()); + + let mut service = new_asset_service(context.clone()); + + let supply = 1024 * 1024; + // test create_asset + let asset = service + .create_asset(context.clone(), CreateAssetPayload { + name: "test".to_owned(), + symbol: "test".to_owned(), + supply, + }) + .unwrap(); + + let to_address = Address::from_hex("0x666cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); + service + .transfer(context.clone(), TransferPayload { + asset_id: asset.id.clone(), + to: to_address.clone(), + value: 1024, + }) + .unwrap(); + + let balance_res = service + .get_balance(context, GetBalancePayload { + asset_id: asset.id.clone(), + }) + .unwrap(); + assert_eq!(balance_res.balance, supply - 1024); + + let context = mock_context(cycles_limit, to_address); + let balance_res = service + .get_balance(context, GetBalancePayload { + asset_id: asset.id.clone(), + }) + .unwrap(); + assert_eq!(balance_res.balance, 1024); +} + +fn new_asset_service( + context: DefaultRequestContext, +) -> AssetService< + DefalutServiceSDK< + GeneralServiceState, + DefaultChainQuerier, + DefaultRequestContext, + >, +> { + let chain_db = DefaultChainQuerier::new(Arc::new(MockStorage {})); + let trie = MPTTrie::new(Arc::new(MemoryDB::new(false))); + let state = GeneralServiceState::new(trie); + + let sdk = DefalutServiceSDK::new( + Rc::new(RefCell::new(state)), + Rc::new(chain_db), + context.clone(), + ); + + AssetService::init(sdk).unwrap() +} + +fn mock_context(cycles_limit: u64, caller: Address) -> DefaultRequestContext { + let params = ContextParams { + cycles_limit, + cycles_price: 1, + cycles_used: Rc::new(RefCell::new(0)), + caller, + epoch_id: 1, + service_name: "service_name".to_owned(), + service_method: "service_method".to_owned(), + service_payload: "service_payload".to_owned(), + events: Rc::new(RefCell::new(vec![])), + }; + + DefaultRequestContext::new(params) +} + +struct MockStorage; + +#[async_trait] +impl Storage for MockStorage { + async fn insert_transactions(&self, _: Vec) -> ProtocolResult<()> { + unimplemented!() + } + + async fn insert_epoch(&self, _: Epoch) -> ProtocolResult<()> { + unimplemented!() + } + + async fn insert_receipts(&self, _: Vec) -> ProtocolResult<()> { + unimplemented!() + } + + async fn update_latest_proof(&self, _: Proof) -> ProtocolResult<()> { + unimplemented!() + } + + async fn get_transaction_by_hash(&self, _: Hash) -> ProtocolResult { + unimplemented!() + } + + async fn get_transactions(&self, _: Vec) -> ProtocolResult> { + unimplemented!() + } + + async fn get_latest_epoch(&self) -> ProtocolResult { + unimplemented!() + } + + async fn get_epoch_by_epoch_id(&self, _: u64) -> ProtocolResult { + unimplemented!() + } + + async fn get_epoch_by_hash(&self, _: Hash) -> ProtocolResult { + unimplemented!() + } + + async fn get_receipt(&self, _: Hash) -> ProtocolResult { + unimplemented!() + } + + async fn get_receipts(&self, _: Vec) -> ProtocolResult> { + unimplemented!() + } + + async fn get_latest_proof(&self) -> ProtocolResult { + unimplemented!() + } +} diff --git a/build-in-services/asset/src/types.rs b/build-in-services/asset/src/types.rs new file mode 100644 index 000000000..e11c32a4a --- /dev/null +++ b/build-in-services/asset/src/types.rs @@ -0,0 +1,81 @@ +use serde::{Deserialize, Serialize}; + +use bytes::Bytes; + +use protocol::fixed_codec::{FixedCodec, FixedCodecError}; +use protocol::types::{Address, Hash}; +use protocol::ProtocolResult; + +/// Payload +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct CreateAssetPayload { + pub name: String, + pub symbol: String, + pub supply: u64, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct GetAssetPayload { + pub id: Hash, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct TransferPayload { + pub asset_id: Hash, + pub to: Address, + pub value: u64, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct GetBalancePayload { + pub asset_id: Hash, +} + +/// Response +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct GetBalanceResponse { + pub asset_id: Hash, + pub balance: u64, +} + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +pub struct Asset { + pub id: Hash, + pub name: String, + pub symbol: String, + pub supply: u64, + pub owner: Address, +} + +impl rlp::Decodable for Asset { + fn decode(rlp: &rlp::Rlp) -> Result { + Ok(Self { + id: rlp.at(0)?.as_val()?, + name: rlp.at(1)?.as_val()?, + symbol: rlp.at(2)?.as_val()?, + supply: rlp.at(3)?.as_val()?, + owner: rlp.at(4)?.as_val()?, + }) + } +} + +impl rlp::Encodable for Asset { + fn rlp_append(&self, s: &mut rlp::RlpStream) { + s.begin_list(5) + .append(&self.id) + .append(&self.name) + .append(&self.symbol) + .append(&self.supply) + .append(&self.owner); + } +} + +impl FixedCodec for Asset { + fn encode_fixed(&self) -> ProtocolResult { + Ok(Bytes::from(rlp::encode(self))) + } + + fn decode_fixed(bytes: Bytes) -> ProtocolResult { + Ok(rlp::decode(bytes.as_ref()).map_err(FixedCodecError::from)?) + } +} diff --git a/framework/src/binding/mod.rs b/framework/src/binding/mod.rs index 7b59cb70e..695a30143 100644 --- a/framework/src/binding/mod.rs +++ b/framework/src/binding/mod.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod tests; -mod sdk; -mod state; -mod store; +pub mod sdk; +pub mod state; +pub mod store; diff --git a/framework/src/tests/mod.rs b/framework/src/tests/mod.rs index b0dd25d00..4648b262d 100644 --- a/framework/src/tests/mod.rs +++ b/framework/src/tests/mod.rs @@ -8,7 +8,7 @@ use crate::{ContextParams, DefaultRequestContext}; #[test] fn test_request_context() { - let parrams = ContextParams { + let params = ContextParams { cycles_limit: 100, cycles_price: 8, cycles_used: Rc::new(RefCell::new(10)), @@ -19,7 +19,7 @@ fn test_request_context() { service_payload: "service_payload".to_owned(), events: Rc::new(RefCell::new(vec![])), }; - let mut ctx = DefaultRequestContext::new(parrams); + let mut ctx = DefaultRequestContext::new(params); ctx.sub_cycles(8).unwrap(); assert_eq!(ctx.get_cycles_used(), 18); diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index ee973e8b6..b5f24e1a1 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -19,12 +19,12 @@ prost = "0.5" hasher = { version = "0.1", features = ['hash-keccak'] } creep = "0.1" bincode = "1.1" -serde = "1.0" -serde_derive = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rlp = "0.4" cita_trie = "2.0" json = "0.12" +byteorder = "1.3" [dev-dependencies] num-traits = "0.2" diff --git a/protocol/src/fixed_codec/primitive.rs b/protocol/src/fixed_codec/primitive.rs index 8cfa2fc30..212d6d13e 100644 --- a/protocol/src/fixed_codec/primitive.rs +++ b/protocol/src/fixed_codec/primitive.rs @@ -1,3 +1,6 @@ +use std::mem; + +use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; use bytes::Bytes; use crate::fixed_codec::{FixedCodec, FixedCodecError}; @@ -17,6 +20,21 @@ impl FixedCodec for Bytes { } } +impl FixedCodec for u64 { + fn encode_fixed(&self) -> ProtocolResult { + let mut bs = [0u8; mem::size_of::()]; + bs.as_mut() + .write_u64::(*self) + .expect("write u64 should not fail"); + + Ok(Bytes::from(bs.as_ref())) + } + + fn decode_fixed(bytes: Bytes) -> ProtocolResult { + Ok(LittleEndian::read_u64(bytes.as_ref())) + } +} + // AssetID, MerkleRoot are alias of Hash type impl rlp::Encodable for Hash { fn rlp_append(&self, s: &mut rlp::RlpStream) { diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index d02afcc2f..87d557222 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -20,6 +20,7 @@ pub enum ProtocolErrorKind { Storage, Runtime, Binding, + Service, // codec Codec, diff --git a/protocol/src/traits/binding.rs b/protocol/src/traits/binding.rs index 105ac3508..bb6d0af94 100644 --- a/protocol/src/traits/binding.rs +++ b/protocol/src/traits/binding.rs @@ -1,7 +1,16 @@ +use serde::{Deserialize, Serialize}; + use crate::fixed_codec::FixedCodec; use crate::types::{Address, Epoch, Hash, MerkleRoot, Receipt, SignedTransaction}; use crate::ProtocolResult; +#[derive(Deserialize, Serialize, Clone)] +pub struct ReturnEmpty { + pub message: Option<()>, +} + +pub const RETURN_EMPTY: ReturnEmpty = ReturnEmpty { message: None }; + // `ServiceState` provides access to` world state` and `account` for` service`. // The bottom layer is an MPT tree. // @@ -72,6 +81,8 @@ pub trait RequestContext: Clone { fn get_payload(&self) -> &str; + // fn get_timestamp(&self) -> u64; + // Trigger an `event`, which can be any string // NOTE: The string is recommended as json string fn emit_event(&mut self, message: String) -> ProtocolResult<()>; diff --git a/protocol/src/traits/mod.rs b/protocol/src/traits/mod.rs index 24ddee341..945d49e96 100644 --- a/protocol/src/traits/mod.rs +++ b/protocol/src/traits/mod.rs @@ -8,8 +8,8 @@ mod storage; pub use api::APIAdapter; pub use binding::{ - AdmissionControl, ChainQuerier, RequestContext, Service, ServiceSDK, ServiceState, StoreArray, - StoreBool, StoreMap, StoreString, StoreUint64, + AdmissionControl, ChainQuerier, RequestContext, ReturnEmpty, Service, ServiceSDK, ServiceState, + StoreArray, StoreBool, StoreMap, StoreString, StoreUint64, RETURN_EMPTY, }; pub use consensus::{Consensus, ConsensusAdapter, CurrentConsensusStatus, MessageTarget, NodeInfo}; pub use executor::{Executor, ExecutorAdapter, ExecutorParams, ExecutorResp}; diff --git a/protocol/src/types/genesis.rs b/protocol/src/types/genesis.rs index ab0096910..231dfcd72 100644 --- a/protocol/src/types/genesis.rs +++ b/protocol/src/types/genesis.rs @@ -1,4 +1,4 @@ -use serde_derive::Deserialize; +use serde::Deserialize; #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct Genesis { diff --git a/protocol/src/types/primitive.rs b/protocol/src/types/primitive.rs index efd74e785..802528b66 100644 --- a/protocol/src/types/primitive.rs +++ b/protocol/src/types/primitive.rs @@ -4,6 +4,7 @@ use bytes::Bytes; use hasher::{Hasher, HasherKeccak}; use lazy_static::lazy_static; use num_bigint::BigUint; +use serde::{Deserialize, Serialize}; use crate::types::TypesError; use crate::ProtocolResult; @@ -18,7 +19,7 @@ pub const GENESIS_EPOCH_ID: u64 = 0; /// Hash length const HASH_LEN: usize = 32; -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize)] pub struct Hash([u8; HASH_LEN]); /// Balance pub type Balance = BigUint; @@ -88,7 +89,7 @@ impl fmt::Debug for Hash { /// Address length. const ADDRESS_LEN: usize = 20; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct Address([u8; ADDRESS_LEN]); impl Address { From c93d2adb76928453e292b3a94e14d3d4c142a745 Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 02:05:17 +0800 Subject: [PATCH 2/9] feat(framework): Service executor. --- Cargo.lock | 65 ++-- binding-macro/Cargo.toml | 8 +- binding-macro/src/lib.rs | 4 +- binding-macro/src/{servive.rs => service.rs} | 14 +- build-in-services/asset/Cargo.toml | 2 +- build-in-services/asset/src/lib.rs | 4 +- build-in-services/asset/src/tests/mod.rs | 3 - devtools/chain/genesis.yaml | 7 + framework/Cargo.toml | 3 + framework/src/binding/sdk/mod.rs | 6 - framework/src/binding/tests/sdk.rs | 5 +- framework/src/context.rs | 14 +- framework/src/executor/mod.rs | 312 +++++++++++++++++- .../src/executor/tests/genesis_services.yaml | 4 + framework/src/executor/tests/mod.rs | 161 +++++++++ framework/src/lib.rs | 22 +- framework/src/tests/mod.rs | 7 +- protocol/Cargo.toml | 2 +- protocol/src/fixed_codec/mod.rs | 1 + protocol/src/fixed_codec/primitive.rs | 10 + protocol/src/traits/binding.rs | 27 +- protocol/src/traits/executor.rs | 30 +- protocol/src/traits/mod.rs | 7 +- protocol/src/types/genesis.rs | 8 + protocol/src/types/mod.rs | 2 +- protocol/src/types/primitive.rs | 89 ++++- 26 files changed, 700 insertions(+), 117 deletions(-) rename binding-macro/src/{servive.rs => service.rs} (92%) create mode 100644 devtools/chain/genesis.yaml create mode 100644 framework/src/executor/tests/genesis_services.yaml create mode 100644 framework/src/executor/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index b3a741a88..c9548dc9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -188,6 +188,7 @@ name = "binding-macro" version = "0.1.0" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "framework 0.1.0", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "protocol 0.1.0", @@ -815,11 +816,11 @@ dependencies = [ [[package]] name = "ethbloom" -version = "0.6.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -883,15 +884,14 @@ dependencies = [ [[package]] name = "fixed-hash" -version = "0.3.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -943,6 +943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "framework" version = "0.1.0" dependencies = [ + "asset 0.1.0", "async-trait 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -950,12 +951,14 @@ dependencies = [ "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "json 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "protocol 0.1.0", "rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1592,6 +1595,11 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lock_api" version = "0.2.0" @@ -2236,7 +2244,7 @@ dependencies = [ "cita_trie 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "creep 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethbloom 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2329,18 +2337,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.6.5" @@ -2860,6 +2856,17 @@ dependencies = [ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_yaml" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha-1" version = "0.8.1" @@ -2943,7 +2950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "static_assertions" -version = "0.2.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3849,6 +3856,14 @@ dependencies = [ "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" @@ -3922,14 +3937,14 @@ dependencies = [ "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum ethbloom 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6294da962646baa738414e8e718d1a1f0360a51d92de89ccbf91870418f5360" -"checksum ethbloom 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3932e82d64d347a045208924002930dc105a138995ccdc1479d0f05f0359f17c" +"checksum ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cfe1c169414b709cf28aa30c74060bdb830a03a8ba473314d079ac79d80a5f" "checksum ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e742184dc63a01c8ea0637369f8faa27c40f537949908a237f95c05e68d2c96" "checksum ethereum-types-serialize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1873d77b32bc1891a79dad925f2acbc318ee942b38b9110f9dbc5fbeffcea350" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7afe6ce860afb14422711595a7b26ada9ed7de2f43c0b2ab79d09ee196287273" -"checksum fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a683d1234507e4f3bf2736eeddf0de1dc65996dc0164d57eba0a74bcf29489" +"checksum fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" "checksum flatbuffers 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc1af59fd8248b59beb048d614a869ce211315c195f5412334e47f5b7e22726" "checksum flatbuffers-verifier 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6aa84480528a2ba6a8007690655a5d7d083037d98bdf4b7246baf1b336bb44c5" "checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" @@ -4006,6 +4021,7 @@ dependencies = [ "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" "checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" "checksum librocksdb-sys 6.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b93b02499a16b46dfa35536a54b54ca14cc27275dd766aba4f4e267c97572994" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -4078,7 +4094,6 @@ dependencies = [ "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand04 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "58595cc8bb12add45412667f9b422d5a9842d61d36e8607bc7c84ff738bf9263" @@ -4133,6 +4148,7 @@ dependencies = [ "checksum serde_qs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b232c387059b62b17eb0487bf23de3ddf21b648ad2206fadc6ff3af9e2f3c07" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" @@ -4144,7 +4160,7 @@ dependencies = [ "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" "checksum static_merkle_tree 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "773abf52222c716fcf9ea6dc1e16c7c1e5d72c0aafaf278a70750666bf9ca041" "checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" @@ -4236,3 +4252,4 @@ dependencies = [ "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" "checksum xmltree 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8eaee9d17062850f1e6163b509947969242990ee59a35801af437abe041e70" +"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/binding-macro/Cargo.toml b/binding-macro/Cargo.toml index a0a8dead8..c730ccaa1 100644 --- a/binding-macro/Cargo.toml +++ b/binding-macro/Cargo.toml @@ -11,15 +11,15 @@ proc-macro = true doctest = false [dependencies] -framework = { path = "../framework" } +protocol = { path = "../protocol" } syn = { version = "1.0", features = ["full"] } proc-macro2 = "1.0" quote = "1.0" +derive_more = "0.15" +serde_json = "1.0" [dev-dependencies] -protocol = { path = "../protocol" } - -serde_json = "1.0" +framework = { path = "../framework" } bytes = "0.4" serde = { version = "1.0", features = ["derive"] } diff --git a/binding-macro/src/lib.rs b/binding-macro/src/lib.rs index 874dc7842..710a712dd 100644 --- a/binding-macro/src/lib.rs +++ b/binding-macro/src/lib.rs @@ -3,13 +3,13 @@ extern crate proc_macro; mod common; mod cycles; mod read_write; -mod servive; +mod service; use proc_macro::TokenStream; use crate::cycles::gen_cycles_code; use crate::read_write::verify_read_or_write; -use crate::servive::gen_service_code; +use crate::service::gen_service_code; #[rustfmt::skip] /// `#[read]` marks a service method as readable. diff --git a/binding-macro/src/servive.rs b/binding-macro/src/service.rs similarity index 92% rename from binding-macro/src/servive.rs rename to binding-macro/src/service.rs index 7b4a91d9e..8dc1cdf34 100644 --- a/binding-macro/src/servive.rs +++ b/binding-macro/src/service.rs @@ -81,30 +81,32 @@ pub fn gen_service_code(_: TokenStream, item: TokenStream) -> TokenStream { } fn read_(&self, ctx: Context) -> protocol::ProtocolResult { + let service = ctx.get_service_name(); let method = ctx.get_service_method(); match method { #(#list_read_name => { let payload: #list_read_payload = serde_json::from_str(ctx.get_payload()) - .map_err(|e| framework::ServiceError::JsonParse(e))?; + .map_err(|e| protocol::traits::BindingMacroError::JsonParse(e))?; let res = self.#list_read_ident(ctx, payload)?; - serde_json::to_string(&res).map_err(|e| framework::ServiceError::JsonParse(e).into()) + serde_json::to_string(&res).map_err(|e| protocol::traits::BindingMacroError::JsonParse(e).into()) },)* - _ => Err(framework::ServiceError::NotFoundMethod(method.to_owned()).into()) + _ => Err(protocol::traits::BindingMacroError::NotFoundMethod{ service: service.to_owned(), method: method.to_owned() }.into()) } } fn write_(&mut self, ctx: Context) -> protocol::ProtocolResult { + let service = ctx.get_service_name(); let method = ctx.get_service_method(); match method { #(#list_write_name => { let payload: #list_write_payload = serde_json::from_str(ctx.get_payload()) - .map_err(|e| framework::ServiceError::JsonParse(e))?; + .map_err(|e| protocol::traits::BindingMacroError::JsonParse(e))?; let res = self.#list_write_ident(ctx, payload)?; - serde_json::to_string(&res).map_err(|e| framework::ServiceError::JsonParse(e).into()) + serde_json::to_string(&res).map_err(|e| protocol::traits::BindingMacroError::JsonParse(e).into()) },)* - _ => Err(framework::ServiceError::NotFoundMethod(method.to_owned()).into()) + _ => Err(protocol::traits::BindingMacroError::NotFoundMethod{ service: service.to_owned(), method: method.to_owned() }.into()) } } } diff --git a/build-in-services/asset/Cargo.toml b/build-in-services/asset/Cargo.toml index ec1b0c0fa..4053d0eb7 100644 --- a/build-in-services/asset/Cargo.toml +++ b/build-in-services/asset/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -framework = { path = "../../framework" } binding-macro = { path = "../../binding-macro" } protocol = { path = "../../protocol" } @@ -21,3 +20,4 @@ byteorder = "1.3" [dev-dependencies] cita_trie = "2.0" async-trait = "0.1" +framework = { path = "../../framework" } diff --git a/build-in-services/asset/src/lib.rs b/build-in-services/asset/src/lib.rs index e2b8be037..969604af7 100644 --- a/build-in-services/asset/src/lib.rs +++ b/build-in-services/asset/src/lib.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod tests; -mod types; +pub mod types; use bytes::Bytes; use derive_more::{Display, From}; @@ -33,7 +33,7 @@ impl AssetService { #[read] fn get_asset( &self, - _ctx: Context, + ctx: Context, payload: GetAssetPayload, ) -> ProtocolResult { let asset = self.assets.get(&payload.id)?; diff --git a/build-in-services/asset/src/tests/mod.rs b/build-in-services/asset/src/tests/mod.rs index 8a9354dc1..23be5c7c7 100644 --- a/build-in-services/asset/src/tests/mod.rs +++ b/build-in-services/asset/src/tests/mod.rs @@ -15,9 +15,6 @@ use protocol::ProtocolResult; use crate::types::{CreateAssetPayload, GetAssetPayload, GetBalancePayload, TransferPayload}; use crate::AssetService; -#[test] -fn get_asset() {} - #[test] fn test_create_asset() { let cycles_limit = 1024 * 1024 * 1024; // 1073741824 diff --git a/devtools/chain/genesis.yaml b/devtools/chain/genesis.yaml new file mode 100644 index 000000000..8f770cb17 --- /dev/null +++ b/devtools/chain/genesis.yaml @@ -0,0 +1,7 @@ +timestamp: 0 +prevhash: 44915be5b6c20b0678cf05fcddbbaa832e25d7e6ac538784cd5c24de00d47472 +services: + - caller: f8389d774afdad8755ef8e629e5a154fddc6325a # id f56924db538e77bb5951eb5ff0d02b88983c49c45eea30e8ae3e7234b311436c + service: asset + method: create_asset + payload: '{ "name": "MutaToken", "symbol": "MT", "supply": 320000011 }' diff --git a/framework/Cargo.toml b/framework/Cargo.toml index 15e4242ed..af9014917 100644 --- a/framework/Cargo.toml +++ b/framework/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] protocol = { path = "../protocol" } +asset = { path = "../build-in-services/asset"} hasher = { version = "0.1", features = ['hash-keccak'] } cita_trie = "2.0" @@ -20,6 +21,8 @@ rlp = "0.4" futures = "0.3" json = "0.12" serde_json = "1.0" +hex = "0.4" [dev-dependencies] async-trait = "0.1" +serde_yaml = "0.8" diff --git a/framework/src/binding/sdk/mod.rs b/framework/src/binding/sdk/mod.rs index 11ba93d5b..bbc1def24 100644 --- a/framework/src/binding/sdk/mod.rs +++ b/framework/src/binding/sdk/mod.rs @@ -36,8 +36,6 @@ impl DefalutServiceSDK ServiceSDK for DefalutServiceSDK { - type ContextItem = R; - // Alloc or recover a `Map` by` var_name` fn alloc_or_recover_map( &mut self, @@ -139,10 +137,6 @@ impl ServiceSDK self.chain_querier.get_receipt_by_hash(tx_hash) } - fn get_request_context(&self) -> ProtocolResult { - Ok(self.request_context.clone()) - } - // Call other read-only methods of `service` and return the results // synchronously NOTE: You can use recursive calls, but the maximum call // stack is 1024 diff --git a/framework/src/binding/tests/sdk.rs b/framework/src/binding/tests/sdk.rs index fc6d05016..3e102afdb 100644 --- a/framework/src/binding/tests/sdk.rs +++ b/framework/src/binding/tests/sdk.rs @@ -98,10 +98,6 @@ fn test_service_sdk() { let epoch_data = sdk.get_epoch_by_epoch_id(Some(1)).unwrap().unwrap(); assert_eq!(mock_epoch(1), epoch_data); - - // test get request context - let ctx_data = sdk.get_request_context().unwrap(); - assert_eq!(mock_request_context(), ctx_data); } struct MockStorage; @@ -301,6 +297,7 @@ pub fn mock_request_context() -> DefaultRequestContext { cycles_used: Rc::new(RefCell::new(10)), caller: Address::from_hash(Hash::from_empty()).unwrap(), epoch_id: 1, + timestamp: 0, service_name: "service_name".to_owned(), service_method: "service_method".to_owned(), service_payload: "service_payload".to_owned(), diff --git a/framework/src/context.rs b/framework/src/context.rs index 9f53ec306..c1ec3be1c 100644 --- a/framework/src/context.rs +++ b/framework/src/context.rs @@ -17,6 +17,7 @@ pub struct ContextParams { pub service_name: String, pub service_method: String, pub service_payload: String, + pub timestamp: u64, pub events: Rc>>, } @@ -30,6 +31,7 @@ pub struct DefaultRequestContext { service_name: String, service_method: String, service_payload: String, + timestamp: u64, events: Rc>>, } @@ -44,6 +46,7 @@ impl DefaultRequestContext { service_name: params.service_name, service_method: params.service_method, service_payload: params.service_payload, + timestamp: params.timestamp, events: params.events, } } @@ -63,9 +66,14 @@ impl DefaultRequestContext { service_name, service_method, service_payload, + timestamp: context.get_timestamp(), events: Rc::clone(&context.events), } } + + pub fn get_events(&self) -> Vec { + self.events.borrow().clone() + } } impl RequestContext for DefaultRequestContext { @@ -110,7 +118,11 @@ impl RequestContext for DefaultRequestContext { &self.service_payload } - fn emit_event(&mut self, message: String) -> ProtocolResult<()> { + fn get_timestamp(&self) -> u64 { + self.timestamp + } + + fn emit_event(&self, message: String) -> ProtocolResult<()> { self.events.borrow_mut().push(Event { service: self.service_name.clone(), data: message, diff --git a/framework/src/executor/mod.rs b/framework/src/executor/mod.rs index fb017c534..6a71f06a3 100644 --- a/framework/src/executor/mod.rs +++ b/framework/src/executor/mod.rs @@ -1,29 +1,319 @@ -use protocol::traits::{Executor, ExecutorAdapter, ExecutorParams, ExecutorResp}; -use protocol::types::{Address, SignedTransaction, TransactionRequest}; -use protocol::ProtocolResult; +#[cfg(test)] +mod tests; -use crate::DefaultRequestContext; +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; +use std::sync::Arc; -pub struct ServiceExecutor { - adapter: Adapter, +use cita_trie::DB as TrieDB; +use derive_more::{Display, From}; + +use asset::AssetService; +use bytes::Bytes; +use protocol::traits::{ + ExecResp, Executor, ExecutorParams, ExecutorResp, RequestContext, Service, ServiceState, + Storage, +}; +use protocol::types::{ + Address, Bloom, BloomInput, GenesisService, Hash, MerkleRoot, Receipt, ReceiptResponse, + SignedTransaction, TransactionRequest, +}; +use protocol::{ProtocolError, ProtocolErrorKind, ProtocolResult}; + +use crate::binding::sdk::{DefalutServiceSDK, DefaultChainQuerier}; +use crate::binding::state::{GeneralServiceState, MPTTrie}; +use crate::{ContextParams, DefaultRequestContext}; + +pub struct ServiceExecutor { + querier: Rc>, + states: HashMap>>>, + root_state: GeneralServiceState, } -impl Executor for ServiceExecutor { +impl ServiceExecutor { + pub fn create_genesis( + genesis_services: Vec, + trie_db: Arc, + storage: Arc, + ) -> ProtocolResult { + let querier = Rc::new(DefaultChainQuerier::new(Arc::clone(&storage))); + + let mut states = HashMap::new(); + for service_alloc in genesis_services.iter() { + let trie = MPTTrie::new(Arc::clone(&trie_db)); + + states.insert( + service_alloc.service.to_owned(), + Rc::new(RefCell::new(GeneralServiceState::new(trie))), + ); + } + + for service_alloc in genesis_services.into_iter() { + let ctx_params = ContextParams { + cycles_limit: std::u64::MAX, + cycles_price: 1, + cycles_used: Rc::new(RefCell::new(0)), + caller: Address::from_hex(&service_alloc.caller)?, + epoch_id: 0, + timestamp: 0, + service_name: service_alloc.service.to_owned(), + service_method: service_alloc.method.to_owned(), + service_payload: service_alloc.payload.to_owned(), + events: Rc::new(RefCell::new(vec![])), + }; + + let context = DefaultRequestContext::new(ctx_params); + let state = + states + .get(context.get_service_name()) + .ok_or(ExecutorError::NotFoundService { + service: context.get_service_name().to_owned(), + })?; + let sdk = + DefalutServiceSDK::new(Rc::clone(state), Rc::clone(&querier), context.clone()); + + match context.get_service_name() { + "asset" => { + let mut service = AssetService::init_(sdk)?; + service.write_(context.clone())?; + } + _ => unreachable!(), + }; + + state.borrow_mut().stash()?; + } + + let trie = MPTTrie::new(Arc::clone(&trie_db)); + let mut root_state = GeneralServiceState::new(trie); + for (name, state) in states.iter() { + let root = state.borrow_mut().commit()?; + root_state.insert(name.to_owned(), root)?; + } + root_state.stash()?; + root_state.commit() + } + + pub fn with_root(root: MerkleRoot, trie_db: Arc, storage: Arc) -> ProtocolResult { + let trie = MPTTrie::from(root.clone(), Arc::clone(&trie_db))?; + let root_state = GeneralServiceState::new(trie); + + let asset_root = + root_state + .get(&"asset".to_owned())? + .ok_or(ExecutorError::NotFoundService { + service: "asset".to_owned(), + })?; + let trie = MPTTrie::from(asset_root, Arc::clone(&trie_db))?; + let asset_state = GeneralServiceState::new(trie); + + let mut states = HashMap::new(); + states.insert("asset".to_owned(), Rc::new(RefCell::new(asset_state))); + + Ok(Self { + querier: Rc::new(DefaultChainQuerier::new(storage)), + states, + root_state, + }) + } + + fn commit(&mut self) -> ProtocolResult { + for (name, state) in self.states.iter() { + let root = state.borrow_mut().commit()?; + self.root_state.insert(name.to_owned(), root)?; + } + self.root_state.stash()?; + self.root_state.commit() + } + + fn stash(&mut self) -> ProtocolResult<()> { + for state in self.states.values() { + state.borrow_mut().stash()?; + } + + Ok(()) + } + + fn revert_cache(&mut self) -> ProtocolResult<()> { + for state in self.states.values() { + state.borrow_mut().revert_cache()?; + } + + Ok(()) + } + + fn get_sdk( + &self, + context: DefaultRequestContext, + service: &str, + ) -> ProtocolResult< + DefalutServiceSDK, DefaultChainQuerier, DefaultRequestContext>, + > { + let state = self + .states + .get(service) + .ok_or(ExecutorError::NotFoundService { + service: service.to_owned(), + })?; + + Ok(DefalutServiceSDK::new( + Rc::clone(&state), + Rc::clone(&self.querier), + context, + )) + } + + fn get_context( + &self, + params: &ExecutorParams, + caller: &Address, + cycles_price: u64, + request: &TransactionRequest, + ) -> ProtocolResult { + let ctx_params = ContextParams { + cycles_limit: params.cycels_limit, + cycles_price, + cycles_used: Rc::new(RefCell::new(0)), + caller: caller.clone(), + epoch_id: params.epoch_id, + timestamp: params.timestamp, + service_name: request.service_name.to_owned(), + service_method: request.method.to_owned(), + service_payload: request.payload.to_owned(), + events: Rc::new(RefCell::new(vec![])), + }; + + Ok(DefaultRequestContext::new(ctx_params)) + } + + fn exec_service( + &self, + context: DefaultRequestContext, + readonly: bool, + ) -> ProtocolResult { + let sdk = self.get_sdk(context.clone(), context.get_service_name())?; + + let mut service = match context.get_service_name() { + "asset" => AssetService::init_(sdk)?, + _ => { + return Err(ExecutorError::NotFoundService { + service: context.get_service_name().to_owned(), + } + .into()) + } + }; + + let result = if readonly { + service.read_(context.clone()) + } else { + service.write_(context.clone()) + }; + + let (ret, is_error) = match result { + Ok(ret) => (ret, false), + Err(e) => (e.to_string(), true), + }; + + Ok(ExecResp { ret, is_error }) + } + + fn logs_bloom(&self, receipts: &[Receipt]) -> Bloom { + let mut bloom = Bloom::default(); + for receipt in receipts { + for event in receipt.events.iter() { + let bytes = Bytes::from((event.service.clone() + &event.data).as_bytes()); + let hash = Hash::digest(bytes).as_bytes(); + + let input = BloomInput::Raw(hash.as_ref()); + bloom.accrue(input) + } + } + + bloom + } +} + +impl Executor for ServiceExecutor { fn exec( &mut self, params: &ExecutorParams, txs: &[SignedTransaction], ) -> ProtocolResult { - unimplemented!() + let mut receipts = txs + .iter() + .map(|stx| { + let caller = Address::from_pubkey_bytes(stx.pubkey.clone())?; + let context = + self.get_context(params, &caller, stx.raw.cycles_price, &stx.raw.request)?; + + let exec_resp = self.exec_service(context.clone(), false)?; + + if exec_resp.is_error { + self.stash()?; + } else { + self.revert_cache()?; + }; + + Ok(Receipt { + state_root: MerkleRoot::from_empty(), + epoch_id: context.get_current_epoch_id(), + tx_hash: stx.tx_hash.clone(), + cycles_used: context.get_cycles_used(), + events: context.get_events(), + response: ReceiptResponse { + service_name: context.get_service_name().to_owned(), + method: context.get_service_method().to_owned(), + ret: exec_resp.ret, + is_error: exec_resp.is_error, + }, + }) + }) + .collect::, ProtocolError>>()?; + + let state_root = self.commit()?; + let mut all_cycles_used = 0; + + for receipt in receipts.iter_mut() { + receipt.state_root = state_root.clone(); + all_cycles_used += receipt.cycles_used; + } + let logs_bloom = self.logs_bloom(&receipts); + + Ok(ExecutorResp { + receipts, + all_cycles_used, + state_root, + logs_bloom, + }) } fn read( &self, params: &ExecutorParams, caller: &Address, + cycles_price: u64, request: &TransactionRequest, - ) -> ProtocolResult { - // DefaultRequestContext::new(cycles_limit: u64, cycles_price: u64, cycles_used: u64, caller: Address, epoch_id: u64, service_name: String, service_method: String, service_payload: String) - unimplemented!() + ) -> ProtocolResult { + let context = self.get_context(params, caller, cycles_price, request)?; + self.exec_service(context, true) + } +} + +#[derive(Debug, Display, From)] +pub enum ExecutorError { + #[display(fmt = "service {:?} was not found", service)] + NotFoundService { service: String }, + + #[display(fmt = "service {:?} method {:?} was not found", service, method)] + NotFoundMethod { service: String, method: String }, + + #[display(fmt = "Parsing payload to json failed {:?}", _0)] + JsonParse(serde_json::Error), +} +impl std::error::Error for ExecutorError {} + +impl From for ProtocolError { + fn from(err: ExecutorError) -> ProtocolError { + ProtocolError::new(ProtocolErrorKind::Executor, Box::new(err)) } } diff --git a/framework/src/executor/tests/genesis_services.yaml b/framework/src/executor/tests/genesis_services.yaml new file mode 100644 index 000000000..0567eb8ba --- /dev/null +++ b/framework/src/executor/tests/genesis_services.yaml @@ -0,0 +1,4 @@ +- caller: f8389d774afdad8755ef8e629e5a154fddc6325a # id f56924db538e77bb5951eb5ff0d02b88983c49c45eea30e8ae3e7234b311436c + service: asset + method: create_asset + payload: '{ "name": "MutaToken", "symbol": "MT", "supply": 320000011 }' diff --git a/framework/src/executor/tests/mod.rs b/framework/src/executor/tests/mod.rs new file mode 100644 index 000000000..ebb2badc2 --- /dev/null +++ b/framework/src/executor/tests/mod.rs @@ -0,0 +1,161 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use bytes::Bytes; +use cita_trie::MemoryDB; + +use asset::types::{Asset, GetBalanceResponse}; +use protocol::traits::{Executor, ExecutorParams, Storage}; +use protocol::types::{ + Address, Epoch, GenesisService, Hash, Proof, RawTransaction, Receipt, SignedTransaction, + TransactionRequest, +}; +use protocol::ProtocolResult; + +use crate::executor::ServiceExecutor; + +#[test] +fn test_create_genesis() { + let yaml = include_str!("./genesis_services.yaml"); + let genesis_services: Vec = serde_yaml::from_str(yaml).unwrap(); + let db = Arc::new(MemoryDB::new(false)); + + let root = ServiceExecutor::create_genesis( + genesis_services, + Arc::clone(&db), + Arc::new(MockStorage {}), + ) + .unwrap(); + + let executor = + ServiceExecutor::with_root(root.clone(), Arc::clone(&db), Arc::new(MockStorage {})) + .unwrap(); + let params = ExecutorParams { + state_root: root.clone(), + epoch_id: 1, + timestamp: 0, + cycels_limit: std::u64::MAX, + }; + let caller = Address::from_hex("f8389d774afdad8755ef8e629e5a154fddc6325a").unwrap(); + let request = TransactionRequest { + service_name: "asset".to_owned(), + method: "get_balance".to_owned(), + payload: + r#"{"asset_id": "f56924db538e77bb5951eb5ff0d02b88983c49c45eea30e8ae3e7234b311436c"}"# + .to_owned(), + }; + let res = executor.read(¶ms, &caller, 1, &request).unwrap(); + let resp: GetBalanceResponse = serde_json::from_str(&res.ret).unwrap(); + + assert_eq!(resp.balance, 320000011); +} + +#[test] +fn test_exec() { + let yaml = include_str!("./genesis_services.yaml"); + let genesis_services: Vec = serde_yaml::from_str(yaml).unwrap(); + let db = Arc::new(MemoryDB::new(false)); + + let root = ServiceExecutor::create_genesis( + genesis_services, + Arc::clone(&db), + Arc::new(MockStorage {}), + ) + .unwrap(); + + let mut executor = + ServiceExecutor::with_root(root.clone(), Arc::clone(&db), Arc::new(MockStorage {})) + .unwrap(); + + let params = ExecutorParams { + state_root: root.clone(), + epoch_id: 1, + timestamp: 0, + cycels_limit: std::u64::MAX, + }; + + let raw = RawTransaction { + chain_id: Hash::from_empty(), + nonce: Hash::from_empty(), + timeout: 0, + cycles_price: 1, + cycles_limit: std::u64::MAX, + request: TransactionRequest { + service_name: "asset".to_owned(), + method: "create_asset".to_owned(), + payload: r#"{ "name": "MutaToken2", "symbol": "MT2", "supply": 320000011 }"# + .to_owned(), + }, + }; + let stx = SignedTransaction { + raw, + tx_hash: Hash::from_empty(), + pubkey: Bytes::from( + hex::decode("031288a6788678c25952eba8693b2f278f66e2187004b64ac09416d07f83f96d5b") + .unwrap(), + ), + signature: Bytes::from("".as_bytes()), + }; + let txs = vec![stx]; + let executor_resp = executor.exec(¶ms, &txs).unwrap(); + let receipt = &executor_resp.receipts[0]; + + assert_eq!(receipt.response.is_error, false); + let asset: Asset = serde_json::from_str(&receipt.response.ret).unwrap(); + assert_eq!(asset.name, "MutaToken2"); + assert_eq!(asset.symbol, "MT2"); + assert_eq!(asset.supply, 320000011); +} + +struct MockStorage; + +#[async_trait] +impl Storage for MockStorage { + async fn insert_transactions(&self, _: Vec) -> ProtocolResult<()> { + unimplemented!() + } + + async fn insert_epoch(&self, _: Epoch) -> ProtocolResult<()> { + unimplemented!() + } + + async fn insert_receipts(&self, _: Vec) -> ProtocolResult<()> { + unimplemented!() + } + + async fn update_latest_proof(&self, _: Proof) -> ProtocolResult<()> { + unimplemented!() + } + + async fn get_transaction_by_hash(&self, _: Hash) -> ProtocolResult { + unimplemented!() + } + + async fn get_transactions(&self, _: Vec) -> ProtocolResult> { + unimplemented!() + } + + async fn get_latest_epoch(&self) -> ProtocolResult { + unimplemented!() + } + + async fn get_epoch_by_epoch_id(&self, _: u64) -> ProtocolResult { + unimplemented!() + } + + async fn get_epoch_by_hash(&self, _: Hash) -> ProtocolResult { + unimplemented!() + } + + async fn get_receipt(&self, _: Hash) -> ProtocolResult { + unimplemented!() + } + + async fn get_receipts(&self, _: Vec) -> ProtocolResult> { + unimplemented!() + } + + async fn get_latest_proof(&self) -> ProtocolResult { + unimplemented!() + } +} diff --git a/framework/src/lib.rs b/framework/src/lib.rs index 53fb6ae1c..d6e0e1c03 100644 --- a/framework/src/lib.rs +++ b/framework/src/lib.rs @@ -4,25 +4,7 @@ pub mod binding; pub mod executor; mod context; +#[cfg(test)] +mod tests; pub use context::{ContextError, ContextParams, DefaultRequestContext}; - -use derive_more::{Display, From}; - -use protocol::{ProtocolError, ProtocolErrorKind}; - -#[derive(Debug, Display, From)] -pub enum ServiceError { - #[display(fmt = "method {:?} was not found", _0)] - NotFoundMethod(String), - - #[display(fmt = "Parsing payload to json failed {:?}", _0)] - JsonParse(serde_json::Error), -} -impl std::error::Error for ServiceError {} - -impl From for ProtocolError { - fn from(err: ServiceError) -> ProtocolError { - ProtocolError::new(ProtocolErrorKind::Binding, Box::new(err)) - } -} diff --git a/framework/src/tests/mod.rs b/framework/src/tests/mod.rs index 4648b262d..a3b75ab7d 100644 --- a/framework/src/tests/mod.rs +++ b/framework/src/tests/mod.rs @@ -14,6 +14,7 @@ fn test_request_context() { cycles_used: Rc::new(RefCell::new(10)), caller: Address::from_hash(Hash::from_empty()).unwrap(), epoch_id: 1, + timestamp: 0, service_name: "service_name".to_owned(), service_method: "service_method".to_owned(), service_payload: "service_payload".to_owned(), @@ -26,8 +27,12 @@ fn test_request_context() { assert_eq!(ctx.get_cycles_limit(), 100); assert_eq!(ctx.get_cycles_price(), 8); - assert_eq!(ctx.get_caller(), mock_address()); + assert_eq!( + ctx.get_caller(), + Address::from_hash(Hash::from_empty()).unwrap() + ); assert_eq!(ctx.get_current_epoch_id(), 1); + assert_eq!(ctx.get_timestamp(), 0); assert_eq!(ctx.get_service_name(), "service_name"); assert_eq!(ctx.get_service_method(), "service_method"); assert_eq!(ctx.get_payload(), "service_payload"); diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index b5f24e1a1..1a855ebba 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -12,7 +12,7 @@ derive_more = "0.15" async-trait = "0.1" lazy_static = "1.4" num-bigint = "0.2" -ethbloom = "0.6" +ethbloom = "0.8" bytes = "0.4" hex = "0.3" prost = "0.5" diff --git a/protocol/src/fixed_codec/mod.rs b/protocol/src/fixed_codec/mod.rs index 3e8c49dd7..a771480d0 100644 --- a/protocol/src/fixed_codec/mod.rs +++ b/protocol/src/fixed_codec/mod.rs @@ -25,6 +25,7 @@ pub trait FixedCodec: Sized { #[derive(Debug, Display, From)] pub enum FixedCodecError { Decoder(rlp::DecoderError), + StringUTF8(std::string::FromUtf8Error), } impl Error for FixedCodecError {} diff --git a/protocol/src/fixed_codec/primitive.rs b/protocol/src/fixed_codec/primitive.rs index 212d6d13e..2b000dfa4 100644 --- a/protocol/src/fixed_codec/primitive.rs +++ b/protocol/src/fixed_codec/primitive.rs @@ -10,6 +10,16 @@ use crate::{impl_default_fixed_codec_for, ProtocolResult}; // Impl ProtocolFixedCodec trait for types impl_default_fixed_codec_for!(primitive, [Hash, Fee, Address, Account]); +impl FixedCodec for String { + fn encode_fixed(&self) -> ProtocolResult { + Ok(Bytes::from(self.as_bytes())) + } + + fn decode_fixed(bytes: Bytes) -> ProtocolResult { + String::from_utf8(bytes.to_vec()).map_err(|e| FixedCodecError::StringUTF8(e).into()) + } +} + impl FixedCodec for Bytes { fn encode_fixed(&self) -> ProtocolResult { Ok(self.clone()) diff --git a/protocol/src/traits/binding.rs b/protocol/src/traits/binding.rs index bb6d0af94..9cb348396 100644 --- a/protocol/src/traits/binding.rs +++ b/protocol/src/traits/binding.rs @@ -1,8 +1,25 @@ +use derive_more::{Display, From}; use serde::{Deserialize, Serialize}; use crate::fixed_codec::FixedCodec; use crate::types::{Address, Epoch, Hash, MerkleRoot, Receipt, SignedTransaction}; -use crate::ProtocolResult; +use crate::{ProtocolError, ProtocolErrorKind, ProtocolResult}; + +#[derive(Debug, Display, From)] +pub enum BindingMacroError { + #[display(fmt = "service {:?} method {:?} was not found", service, method)] + NotFoundMethod { service: String, method: String }, + + #[display(fmt = "Parsing payload to json failed {:?}", _0)] + JsonParse(serde_json::Error), +} +impl std::error::Error for BindingMacroError {} + +impl From for ProtocolError { + fn from(err: BindingMacroError) -> ProtocolError { + ProtocolError::new(ProtocolErrorKind::Binding, Box::new(err)) + } +} #[derive(Deserialize, Serialize, Clone)] pub struct ReturnEmpty { @@ -81,11 +98,11 @@ pub trait RequestContext: Clone { fn get_payload(&self) -> &str; - // fn get_timestamp(&self) -> u64; + fn get_timestamp(&self) -> u64; // Trigger an `event`, which can be any string // NOTE: The string is recommended as json string - fn emit_event(&mut self, message: String) -> ProtocolResult<()>; + fn emit_event(&self, message: String) -> ProtocolResult<()>; } // Admission control will be called before entering service @@ -143,8 +160,6 @@ pub trait Service { // - ChainDB // - ServiceState pub trait ServiceSDK { - type ContextItem: RequestContext; - // Alloc or recover a `Map` by` var_name` fn alloc_or_recover_map( &mut self, @@ -205,8 +220,6 @@ pub trait ServiceSDK { // if not found on the chain, return None fn get_receipt_by_hash(&self, tx_hash: &Hash) -> ProtocolResult>; - fn get_request_context(&self) -> ProtocolResult; - // Call other read-only methods of `service` and return the results // synchronously NOTE: You can use recursive calls, but the maximum call // stack is 1024 diff --git a/protocol/src/traits/executor.rs b/protocol/src/traits/executor.rs index 9705fa69b..4c22a0b13 100644 --- a/protocol/src/traits/executor.rs +++ b/protocol/src/traits/executor.rs @@ -1,4 +1,3 @@ -use crate::traits::{Service, ServiceSDK}; use crate::types::{Address, Bloom, MerkleRoot, Receipt, SignedTransaction, TransactionRequest}; use crate::ProtocolResult; @@ -12,9 +11,16 @@ pub struct ExecutorResp { #[derive(Debug, Clone)] pub struct ExecutorParams { - state_root: MerkleRoot, - epoch_id: u64, - cycels_limit: u64, + pub state_root: MerkleRoot, + pub epoch_id: u64, + pub timestamp: u64, + pub cycels_limit: u64, +} + +#[derive(Debug, Clone)] +pub struct ExecResp { + pub ret: String, + pub is_error: bool, } pub trait Executor { @@ -28,19 +34,7 @@ pub trait Executor { &self, params: &ExecutorParams, caller: &Address, + cycles_price: u64, request: &TransactionRequest, - ) -> ProtocolResult; -} - -pub trait ExecutorAdapter { - fn get_service_inst>( - &self, - service_name: &str, - ) -> ProtocolResult; - - fn revert_state(&mut self) -> ProtocolResult<()>; - - fn stash_state(&mut self) -> ProtocolResult<()>; - - fn commit_state(&mut self) -> ProtocolResult; + ) -> ProtocolResult; } diff --git a/protocol/src/traits/mod.rs b/protocol/src/traits/mod.rs index 945d49e96..47f47fc7a 100644 --- a/protocol/src/traits/mod.rs +++ b/protocol/src/traits/mod.rs @@ -8,11 +8,12 @@ mod storage; pub use api::APIAdapter; pub use binding::{ - AdmissionControl, ChainQuerier, RequestContext, ReturnEmpty, Service, ServiceSDK, ServiceState, - StoreArray, StoreBool, StoreMap, StoreString, StoreUint64, RETURN_EMPTY, + AdmissionControl, BindingMacroError, ChainQuerier, RequestContext, ReturnEmpty, Service, + ServiceSDK, ServiceState, StoreArray, StoreBool, StoreMap, StoreString, StoreUint64, + RETURN_EMPTY, }; pub use consensus::{Consensus, ConsensusAdapter, CurrentConsensusStatus, MessageTarget, NodeInfo}; -pub use executor::{Executor, ExecutorAdapter, ExecutorParams, ExecutorResp}; +pub use executor::{ExecResp, Executor, ExecutorParams, ExecutorResp}; pub use mempool::{MemPool, MemPoolAdapter, MixedTxHashes}; pub use network::{Gossip, MessageCodec, MessageHandler, Priority, Rpc}; pub use storage::{Storage, StorageAdapter, StorageBatchModify, StorageCategory, StorageSchema}; diff --git a/protocol/src/types/genesis.rs b/protocol/src/types/genesis.rs index 231dfcd72..524428205 100644 --- a/protocol/src/types/genesis.rs +++ b/protocol/src/types/genesis.rs @@ -28,6 +28,14 @@ pub struct GenesisSystemToken { pub supply: u64, } +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +pub struct GenesisService { + pub caller: String, + pub service: String, + pub method: String, + pub payload: String, +} + #[cfg(test)] mod tests { use super::Genesis; diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index a5ea0364f..f0cf6cc69 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -12,7 +12,7 @@ use crate::{ProtocolError, ProtocolErrorKind}; pub use epoch::{Epoch, EpochHeader, EpochId, Pill, Proof, Validator}; pub use ethbloom::{Bloom, BloomRef, Input as BloomInput}; -pub use genesis::{Genesis, GenesisStateAlloc, GenesisStateAsset}; +pub use genesis::{Genesis, GenesisService, GenesisStateAlloc, GenesisStateAsset}; pub use primitive::{ Account, Address, Balance, Fee, Hash, JsonString, MerkleRoot, GENESIS_EPOCH_ID, }; diff --git a/protocol/src/types/primitive.rs b/protocol/src/types/primitive.rs index 802528b66..f41bff1fa 100644 --- a/protocol/src/types/primitive.rs +++ b/protocol/src/types/primitive.rs @@ -4,6 +4,7 @@ use bytes::Bytes; use hasher::{Hasher, HasherKeccak}; use lazy_static::lazy_static; use num_bigint::BigUint; +use serde::de; use serde::{Deserialize, Serialize}; use crate::types::TypesError; @@ -19,7 +20,7 @@ pub const GENESIS_EPOCH_ID: u64 = 0; /// Hash length const HASH_LEN: usize = 32; -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Hash([u8; HASH_LEN]); /// Balance pub type Balance = BigUint; @@ -28,6 +29,48 @@ pub type MerkleRoot = Hash; /// Json string pub type JsonString = String; +impl Serialize for Hash { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + serializer.serialize_str(&self.as_hex()) + } +} + +struct HashVisitor; + +impl<'de> de::Visitor<'de> for HashVisitor { + type Value = Hash; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Expect a hex string") + } + + fn visit_string(self, v: String) -> Result + where + E: de::Error, + { + Hash::from_hex(&v).map_err(|e| de::Error::custom(e.to_string())) + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Hash::from_hex(&v).map_err(|e| de::Error::custom(e.to_string())) + } +} + +impl<'de> Deserialize<'de> for Hash { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_string(HashVisitor) + } +} + impl Hash { /// Enter an array of bytes to get a 32-bit hash. /// Note: sha3 is used for the time being and may be replaced with other @@ -89,9 +132,51 @@ impl fmt::Debug for Hash { /// Address length. const ADDRESS_LEN: usize = 20; -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Address([u8; ADDRESS_LEN]); +impl Serialize for Address { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + serializer.serialize_str(&self.as_hex()) + } +} + +struct AddressVisitor; + +impl<'de> de::Visitor<'de> for AddressVisitor { + type Value = Address; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Expect a hex string") + } + + fn visit_string(self, v: String) -> Result + where + E: de::Error, + { + Address::from_hex(&v).map_err(|e| de::Error::custom(e.to_string())) + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Address::from_hex(&v).map_err(|e| de::Error::custom(e.to_string())) + } +} + +impl<'de> Deserialize<'de> for Address { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_string(AddressVisitor) + } +} + impl Address { pub fn from_pubkey_bytes(bytes: Bytes) -> ProtocolResult { let hash = Hash::digest(bytes); From da0e6fbb1c9c2d628e9d92b83eafec4816d0f384 Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 02:45:18 +0800 Subject: [PATCH 3/9] exec hook --- framework/src/binding/sdk/mod.rs | 16 ++++------- framework/src/binding/tests/sdk.rs | 3 +- framework/src/executor/mod.rs | 44 ++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/framework/src/binding/sdk/mod.rs b/framework/src/binding/sdk/mod.rs index bbc1def24..e22db129e 100644 --- a/framework/src/binding/sdk/mod.rs +++ b/framework/src/binding/sdk/mod.rs @@ -17,25 +17,21 @@ use crate::binding::store::{ DefaultStoreArray, DefaultStoreBool, DefaultStoreMap, DefaultStoreString, DefaultStoreUint64, }; -pub struct DefalutServiceSDK { - state: Rc>, - chain_querier: Rc, - request_context: R, +pub struct DefalutServiceSDK { + state: Rc>, + chain_querier: Rc, } -impl DefalutServiceSDK { - pub fn new(state: Rc>, chain_querier: Rc, request_context: R) -> Self { +impl DefalutServiceSDK { + pub fn new(state: Rc>, chain_querier: Rc) -> Self { Self { state, chain_querier, - request_context, } } } -impl ServiceSDK - for DefalutServiceSDK -{ +impl ServiceSDK for DefalutServiceSDK { // Alloc or recover a `Map` by` var_name` fn alloc_or_recover_map( &mut self, diff --git a/framework/src/binding/tests/sdk.rs b/framework/src/binding/tests/sdk.rs index 3e102afdb..599b19cc0 100644 --- a/framework/src/binding/tests/sdk.rs +++ b/framework/src/binding/tests/sdk.rs @@ -26,9 +26,8 @@ fn test_service_sdk() { let arcs = Arc::new(MockStorage {}); let cq = DefaultChainQuerier::new(Arc::clone(&arcs)); - let ctx = mock_request_context(); - let mut sdk = DefalutServiceSDK::new(Rc::clone(&rs), Rc::new(cq), ctx); + let mut sdk = DefalutServiceSDK::new(Rc::clone(&rs), Rc::new(cq)); // test sdk store bool let mut sdk_bool = sdk.alloc_or_recover_bool("test_bool").unwrap(); diff --git a/framework/src/executor/mod.rs b/framework/src/executor/mod.rs index 6a71f06a3..3bb99fa66 100644 --- a/framework/src/executor/mod.rs +++ b/framework/src/executor/mod.rs @@ -25,6 +25,11 @@ use crate::binding::sdk::{DefalutServiceSDK, DefaultChainQuerier}; use crate::binding::state::{GeneralServiceState, MPTTrie}; use crate::{ContextParams, DefaultRequestContext}; +enum HookType { + Before, + After, +} + pub struct ServiceExecutor { querier: Rc>, states: HashMap>>>, @@ -70,8 +75,7 @@ impl ServiceExecutor { .ok_or(ExecutorError::NotFoundService { service: context.get_service_name().to_owned(), })?; - let sdk = - DefalutServiceSDK::new(Rc::clone(state), Rc::clone(&querier), context.clone()); + let sdk = DefalutServiceSDK::new(Rc::clone(state), Rc::clone(&querier)); match context.get_service_name() { "asset" => { @@ -142,13 +146,34 @@ impl ServiceExecutor { Ok(()) } + fn hook(&mut self, hook: HookType) -> ProtocolResult<()> { + for (name, state) in self.states.iter() { + let sdk = self.get_sdk(name)?; + + let mut service = match name.as_ref() { + "asset" => AssetService::init_(sdk)?, + _ => { + return Err(ExecutorError::NotFoundService { + service: name.to_owned(), + } + .into()) + } + }; + + match hook { + HookType::Before => service.hook_before_()?, + HookType::After => service.hook_after_()?, + }; + + state.borrow_mut().stash()?; + } + Ok(()) + } + fn get_sdk( &self, - context: DefaultRequestContext, service: &str, - ) -> ProtocolResult< - DefalutServiceSDK, DefaultChainQuerier, DefaultRequestContext>, - > { + ) -> ProtocolResult, DefaultChainQuerier>> { let state = self .states .get(service) @@ -159,7 +184,6 @@ impl ServiceExecutor { Ok(DefalutServiceSDK::new( Rc::clone(&state), Rc::clone(&self.querier), - context, )) } @@ -191,7 +215,7 @@ impl ServiceExecutor { context: DefaultRequestContext, readonly: bool, ) -> ProtocolResult { - let sdk = self.get_sdk(context.clone(), context.get_service_name())?; + let sdk = self.get_sdk(context.get_service_name())?; let mut service = match context.get_service_name() { "asset" => AssetService::init_(sdk)?, @@ -239,6 +263,8 @@ impl Executor for ServiceExecutor { params: &ExecutorParams, txs: &[SignedTransaction], ) -> ProtocolResult { + self.hook(HookType::Before)?; + let mut receipts = txs .iter() .map(|stx| { @@ -270,6 +296,8 @@ impl Executor for ServiceExecutor { }) .collect::, ProtocolError>>()?; + self.hook(HookType::After)?; + let state_root = self.commit()?; let mut all_cycles_used = 0; From afcc2b66ec4676104fe358b54d69efeb7334d22b Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 02:49:00 +0800 Subject: [PATCH 4/9] fix stash --- framework/src/executor/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/executor/mod.rs b/framework/src/executor/mod.rs index 3bb99fa66..1fb39900e 100644 --- a/framework/src/executor/mod.rs +++ b/framework/src/executor/mod.rs @@ -275,9 +275,9 @@ impl Executor for ServiceExecutor { let exec_resp = self.exec_service(context.clone(), false)?; if exec_resp.is_error { - self.stash()?; - } else { self.revert_cache()?; + } else { + self.stash()?; }; Ok(Receipt { From b891080f0ec5715fcacba72f91be50be2928d615 Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 02:56:36 +0800 Subject: [PATCH 5/9] fix typo --- build-in-services/asset/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-in-services/asset/src/lib.rs b/build-in-services/asset/src/lib.rs index 969604af7..fa88253ee 100644 --- a/build-in-services/asset/src/lib.rs +++ b/build-in-services/asset/src/lib.rs @@ -24,7 +24,7 @@ pub struct AssetService { impl AssetService { #[init] fn init(mut sdk: SDK) -> ProtocolResult { - let assets: Box> = sdk.alloc_or_recover_map("assrts")?; + let assets: Box> = sdk.alloc_or_recover_map("assets")?; Ok(Self { assets, sdk }) } From 3ba50ceddcd8590335449a2c8f768f17152f12e2 Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 13:29:23 +0800 Subject: [PATCH 6/9] fix typo --- Cargo.toml | 2 +- {build-in-services => built-in-services}/asset/Cargo.toml | 0 {build-in-services => built-in-services}/asset/src/lib.rs | 0 {build-in-services => built-in-services}/asset/src/tests/mod.rs | 0 {build-in-services => built-in-services}/asset/src/types.rs | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename {build-in-services => built-in-services}/asset/Cargo.toml (100%) rename {build-in-services => built-in-services}/asset/src/lib.rs (100%) rename {build-in-services => built-in-services}/asset/src/tests/mod.rs (100%) rename {build-in-services => built-in-services}/asset/src/types.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index ef1371fcc..09646258e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ members = [ "binding-macro", "framework", - "build-in-services/asset", + "built-in-services/asset", "protocol", ] diff --git a/build-in-services/asset/Cargo.toml b/built-in-services/asset/Cargo.toml similarity index 100% rename from build-in-services/asset/Cargo.toml rename to built-in-services/asset/Cargo.toml diff --git a/build-in-services/asset/src/lib.rs b/built-in-services/asset/src/lib.rs similarity index 100% rename from build-in-services/asset/src/lib.rs rename to built-in-services/asset/src/lib.rs diff --git a/build-in-services/asset/src/tests/mod.rs b/built-in-services/asset/src/tests/mod.rs similarity index 100% rename from build-in-services/asset/src/tests/mod.rs rename to built-in-services/asset/src/tests/mod.rs diff --git a/build-in-services/asset/src/types.rs b/built-in-services/asset/src/types.rs similarity index 100% rename from build-in-services/asset/src/types.rs rename to built-in-services/asset/src/types.rs From 668ec780fa82cf1788c979a026d7591fc2822a17 Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 13:40:11 +0800 Subject: [PATCH 7/9] fix overflow --- built-in-services/asset/src/lib.rs | 31 +++++++++++++++++++++++------- framework/Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/built-in-services/asset/src/lib.rs b/built-in-services/asset/src/lib.rs index fa88253ee..659e8e94c 100644 --- a/built-in-services/asset/src/lib.rs +++ b/built-in-services/asset/src/lib.rs @@ -114,10 +114,18 @@ impl AssetService { } let to_balance = self.sdk.get_account_value(&to, &asset_id)?.unwrap_or(0); - self.sdk - .set_account_value(&to, asset_id.clone(), to_balance + value)?; - self.sdk - .set_account_value(&caller, asset_id.clone(), caller_balance - value)?; + let (v, overflow) = to_balance.overflowing_add(value); + if overflow { + return Err(ServiceError::U64Overflow.into()); + } + + self.sdk.set_account_value(&to, asset_id.clone(), v)?; + + let (v, overflow) = caller_balance.overflowing_sub(value); + if overflow { + return Err(ServiceError::U64Overflow.into()); + } + self.sdk.set_account_value(&caller, asset_id.clone(), v)?; Ok(RETURN_EMPTY) } @@ -129,13 +137,22 @@ pub enum ServiceError { JsonParse(serde_json::Error), #[display(fmt = "Asset {:?} already exists", id)] - Exists { id: Hash }, + Exists { + id: Hash, + }, #[display(fmt = "Not found asset, id {:?}", id)] - NotFoundAsset { id: Hash }, + NotFoundAsset { + id: Hash, + }, #[display(fmt = "Not found asset, expect {:?} real {:?}", expect, real)] - LackOfBalance { expect: u64, real: u64 }, + LackOfBalance { + expect: u64, + real: u64, + }, + + U64Overflow, } impl std::error::Error for ServiceError {} diff --git a/framework/Cargo.toml b/framework/Cargo.toml index af9014917..826d44c1e 100644 --- a/framework/Cargo.toml +++ b/framework/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] protocol = { path = "../protocol" } -asset = { path = "../build-in-services/asset"} +asset = { path = "../built-in-services/asset"} hasher = { version = "0.1", features = ['hash-keccak'] } cita_trie = "2.0" From 929206ff700f35357e7f812f4fe2d4ff2f2f28b4 Mon Sep 17 00:00:00 2001 From: yejiayu Date: Thu, 26 Dec 2019 13:42:58 +0800 Subject: [PATCH 8/9] fix typo --- built-in-services/asset/src/tests/mod.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/built-in-services/asset/src/tests/mod.rs b/built-in-services/asset/src/tests/mod.rs index 23be5c7c7..4a25002f0 100644 --- a/built-in-services/asset/src/tests/mod.rs +++ b/built-in-services/asset/src/tests/mod.rs @@ -21,7 +21,7 @@ fn test_create_asset() { let caller = Address::from_hex("0x755cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); let context = mock_context(cycles_limit, caller); - let mut service = new_asset_service(context.clone()); + let mut service = new_asset_service(); let supply = 1024 * 1024; // test create_asset @@ -55,7 +55,7 @@ fn test_transfer() { let caller = Address::from_hex("0x755cdba6ae4f479f7164792b318b2a06c759833b").unwrap(); let context = mock_context(cycles_limit, caller.clone()); - let mut service = new_asset_service(context.clone()); + let mut service = new_asset_service(); let supply = 1024 * 1024; // test create_asset @@ -93,23 +93,13 @@ fn test_transfer() { } fn new_asset_service( - context: DefaultRequestContext, -) -> AssetService< - DefalutServiceSDK< - GeneralServiceState, - DefaultChainQuerier, - DefaultRequestContext, - >, -> { +) -> AssetService, DefaultChainQuerier>> +{ let chain_db = DefaultChainQuerier::new(Arc::new(MockStorage {})); let trie = MPTTrie::new(Arc::new(MemoryDB::new(false))); let state = GeneralServiceState::new(trie); - let sdk = DefalutServiceSDK::new( - Rc::new(RefCell::new(state)), - Rc::new(chain_db), - context.clone(), - ); + let sdk = DefalutServiceSDK::new(Rc::new(RefCell::new(state)), Rc::new(chain_db)); AssetService::init(sdk).unwrap() } @@ -121,6 +111,7 @@ fn mock_context(cycles_limit: u64, caller: Address) -> DefaultRequestContext { cycles_used: Rc::new(RefCell::new(0)), caller, epoch_id: 1, + timestamp: 0, service_name: "service_name".to_owned(), service_method: "service_method".to_owned(), service_payload: "service_payload".to_owned(), From 02133c169fe90303170e386c764991fa8b3f99d4 Mon Sep 17 00:00:00 2001 From: Jiayu Ye Date: Thu, 26 Dec 2019 16:35:04 +0800 Subject: [PATCH 9/9] Update protocol/Cargo.toml Co-Authored-By: Eason Gao --- protocol/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index 1a855ebba..cac75d0af 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -18,7 +18,7 @@ hex = "0.3" prost = "0.5" hasher = { version = "0.1", features = ['hash-keccak'] } creep = "0.1" -bincode = "1.1" +bincode = "1.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rlp = "0.4"