diff --git a/Cargo.lock b/Cargo.lock index 113982dfd7..a1fcf6e758 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8344,7 +8344,10 @@ dependencies = [ "libc", "log", "once_cell", + "phala-crypto", "pink-capi", + "pink-extension-runtime", + "serde", "sp-weights", ] diff --git a/crates/phactory/api/proto b/crates/phactory/api/proto index a9478506fd..d5679bc43f 160000 --- a/crates/phactory/api/proto +++ b/crates/phactory/api/proto @@ -1 +1 @@ -Subproject commit a9478506fdea7ca3f1e9a6f4d52430c8fdfd8e89 +Subproject commit d5679bc43f65b8a0cbcabc2ba25733c56fab43f3 diff --git a/crates/phactory/src/contracts/pink.rs b/crates/phactory/src/contracts/pink.rs index 173173b139..af42beb7e5 100644 --- a/crates/phactory/src/contracts/pink.rs +++ b/crates/phactory/src/contracts/pink.rs @@ -1,17 +1,30 @@ use std::time::Duration; -use crate::contracts; -use crate::system::{TransactionError, TransactionResult}; -use anyhow::{anyhow, Result}; +use crate::{ + contracts::{self, QueryContext, TransactionContext}, + system::{TransactionError, TransactionResult}, +}; +use anyhow::{anyhow, Context, Result}; use parity_scale_codec::{Decode, Encode}; +use phala_crypto::sr25519::{Persistence, Sr25519SecretKey, KDF}; use phala_mq::{ContractClusterId, ContractId, MessageOrigin}; -use phala_types::contract::ConvertTo; -use pink::constants::WEIGHT_REF_TIME_PER_SECOND; -use pink::types::{Address, EventCallbacks, TransactionArguments}; -use runtime::{AccountId, BlockNumber, Hash}; +use phala_serde_more as more; +use phala_types::contract::{messaging::ResourceType, ConvertTo}; +use serde::{Deserialize, Serialize}; use sidevm::service::{Command as SidevmCommand, CommandSender, SystemMessage}; +use sp_core::sr25519; +use sp_runtime::{AccountId32, DispatchError}; +use std::collections::{BTreeMap, BTreeSet}; + +use ::pink::{ + constants::WEIGHT_REF_TIME_PER_SECOND, + types::{ + AccountId, Address, Balance, BlockNumber, EventCallbacks, ExecSideEffects, Hash, + TransactionArguments, Weight, + }, +}; -pub use phala_types::contract::InkCommand as Command; +pub use phala_types::contract::InkCommand; #[derive(Debug, Encode, Decode)] pub enum Query { @@ -49,264 +62,374 @@ pub enum QueryError { Timeout, } -#[derive(Encode, Decode, Clone)] -pub struct Pink { - pub(crate) address: Address, - cluster_id: ContractClusterId, +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct ClusterConfig { + pub log_handler: Option, + // Version used to control the contract API availability. + pub system_version: (u16, u16), + // todo!: fill it according to chain config + pub runtime_version: (u32, u32), } -impl Pink { - pub fn instantiate( - cluster_id: ContractClusterId, - code_hash: Hash, - input_data: Vec, - salt: Vec, - in_query: bool, - tx_args: TransactionArguments, - ) -> Result<(Self, ExecSideEffects)> { - let origin = tx_args.origin.clone(); - let (address, effects) = pink::instantiate(code_hash, input_data, salt, in_query, tx_args) - .map_err( - |err| anyhow!("Instantiate contract failed: {:?} origin={:?}", err, origin,), - )?; - Ok(( - Self { - cluster_id, - address, - }, - effects, - )) +#[derive(Serialize, Deserialize, Clone)] +pub struct Cluster { + pub id: ContractClusterId, + pub config: ClusterConfig, + pub storage: pink::storage::ClusterStorage, +} + +impl Cluster { + pub fn new(id: &ContractClusterId, cluster_key: &sr25519::Pair) -> Self { + let mut cluster = Cluster { + storage: Default::default(), + config: Default::default(), + id: *id, + }; + let seed_key = cluster_key + .derive_sr25519_pair(&[b"ink key derivation seed"]) + .expect("Derive key seed should always success!"); + cluster.storage.set_id(id.as_ref()); + cluster.storage.set_key(cluster_key.dump_secret_key()); + cluster.storage.set_key_seed(seed_key.dump_secret_key()); + cluster + } + + pub fn key(&self) -> &sr25519::Pair { + // self.storage.get_key() + todo!() } - pub fn from_address(address: AccountId, cluster_id: ContractClusterId) -> Self { - let instance = pink::Contract::from_address(address); - Self { - instance, - cluster_id, + pub fn system_contract(&self) -> Option { + self.storage.system_contract() + } + + pub fn set_system_contract(&mut self, contract: AccountId32) { + self.storage.set_system_contract(contract); + } + + pub fn upload_resource( + &mut self, + origin: &AccountId, + resource_type: ResourceType, + resource_data: Vec, + ) -> Result> { + match resource_type { + ResourceType::InkCode => self.storage.upload_code(origin, resource_data, true), + ResourceType::SidevmCode => self.storage.upload_sidevm_code(origin, resource_data), + ResourceType::IndeterministicInkCode => { + self.storage.upload_code(origin, resource_data, false) + } } } - pub fn id(&self) -> ContractId { - self.instance.address.convert_to() + pub fn get_resource(&self, resource_type: ResourceType, hash: &Hash) -> Option> { + match resource_type { + ResourceType::InkCode => None, + ResourceType::SidevmCode => self.storage.get_sidevm_code(hash), + ResourceType::IndeterministicInkCode => None, + } } - pub fn address(&self) -> AccountId { - self.instance.address.clone() + pub fn setup( + &mut self, + gas_price: Balance, + deposit_per_item: Balance, + deposit_per_byte: Balance, + treasury_account: &::pink::types::AccountId, + ) { + self.storage.setup( + gas_price, + deposit_per_item, + deposit_per_byte, + treasury_account, + ); } - pub fn set_on_block_end_selector(&mut self, selector: u32, gas_limit: u64) { - self.instance.set_on_block_end_selector(selector, gas_limit) + pub fn deposit(&mut self, who: &::pink::types::AccountId, amount: Balance) { + self.storage.deposit(who, amount) + } + + pub fn set_system_contract_code(&mut self, code_hash: Hash) -> Result<(), DispatchError> { + // self.storage.set_system_contract_code(code_hash)?; + // self.sync_system_contract_version() + // .expect("Failed to sync the system contract version. Please upgrade pRuntime!"); + // Ok(()) + todo!() + } + + pub fn sync_system_contract_version(&mut self) -> Result<()> { + let Some(system_address) = self.system_contract() else { + anyhow::bail!("No system contract"); + }; + // System::version + let selector = 0x87c98a8d_u32.to_be_bytes().to_vec(); + let args = TransactionArguments { + origin: system_address, + now: 1, + block_number: 1, + transfer: 0, + gas_limit: Weight::MAX, + gas_free: true, + storage_deposit_limit: None, + }; + todo!() + // let (result, _) = self.bare_call(&system_address, selector, true, args); + // let output = result + // .result + // .map_err(|err| anyhow::anyhow!("Failed to get the system contract version: {err:?}"))?; + // self.config.system_version = Result::<_, ()>::decode(&mut &output.data[..]) + // .context("Failed to decode the system contract version")? + // .or(Err(anyhow::anyhow!( + // "Failed to get the system contract version" + // )))?; + // const SUPPORTED_API_VERSION: u16 = 0; + // if self.config.system_version.0 > SUPPORTED_API_VERSION { + // anyhow::bail!("The pink-system version is not supported, please upgrade the pRuntime"); + // } + // Ok(()) + } + + // pub fn bare_call( + // &self, + // contract_id: &ContractId, + // input_data: Vec, + // in_query: bool, + // tx_args: TransactionArguments, + // ) -> (ContractExecResult, ExecSideEffects) { + // todo!() + // } + + pub fn instantiate( + &self, + code_hash: Hash, + input_data: Vec, + salt: Vec, + in_query: bool, + tx_args: TransactionArguments, + ) -> Result<(ContractId, ExecSideEffects)> { + todo!() } -} -impl Pink { pub(crate) async fn handle_query( &self, + contract_id: &ContractId, origin: Option<&AccountId>, req: Query, - context: &mut contracts::QueryContext, - side_effects: &mut ExecSideEffects, - ) -> Result { - match req { - Query::InkMessage { - payload: input_data, - deposit, - transfer, - } => { - let _guard = context - .query_scheduler - .acquire(self.id(), context.weight) - .await - .or(Err(QueryError::ServiceUnavailable))?; - - let origin = origin.cloned().ok_or(QueryError::BadOrigin)?; - let storage = &mut context.storage; - if deposit > 0 { - storage.deposit(&origin, deposit); - } - let args = TransactionArguments { - origin, - now: context.now_ms, - block_number: context.block_number, - storage, - transfer, - gas_limit: WEIGHT_REF_TIME_PER_SECOND * 10, - gas_free: true, - storage_deposit_limit: None, - }; - let (ink_result, effects) = self.instance.bare_call(input_data, true, args); - if let Some(log_handler) = &context.log_handler { - if !ink_result.debug_message.is_empty() { - ContractEventCallback::new(log_handler.clone(), context.block_number) - .emit_log( - &self.address(), - true, - log::Level::Debug as usize as _, - String::from_utf8_lossy(&ink_result.debug_message).into_owned(), - ); - } - } - if ink_result.result.is_err() { - log::error!("Pink [{:?}] query exec error: {:?}", self.id(), ink_result); - if !ink_result.debug_message.is_empty() { - let message = String::from_utf8_lossy(&ink_result.debug_message); - log::error!("Pink [{:?}] buffer: {:?}", self.id(), message); - } - } else { - *side_effects = effects.into_query_only_effects(); - } - Ok(Response::Payload(ink_result.encode())) - } - Query::SidevmQuery(payload) => { - let handle = context - .sidevm_handle - .as_ref() - .ok_or(QueryError::SidevmNotFound)?; - let cmd_sender = match handle { - contracts::SidevmHandle::Stopped(_) => return Err(QueryError::SidevmNotFound), - contracts::SidevmHandle::Running(sender) => sender, - }; - let origin = origin.cloned().map(Into::into); - - let (reply_tx, rx) = tokio::sync::oneshot::channel(); - - const SIDEVM_QUERY_TIMEOUT: Duration = Duration::from_secs(60 * 5); - - tokio::time::timeout(SIDEVM_QUERY_TIMEOUT, async move { - cmd_sender - .send(SidevmCommand::PushQuery { - origin, - payload, - reply_tx, - }) - .await - .or(Err(QueryError::ServiceUnavailable))?; - rx.await - .or(Err(QueryError::NoResponse)) - .map(Response::Payload) - }) - .await - .or(Err(QueryError::Timeout))? - } - Query::InkInstantiate { - code_hash, - salt, - instantiate_data, - deposit, - transfer, - } => { - let _guard = context - .query_scheduler - .acquire(self.id(), context.weight) - .await - .or(Err(QueryError::ServiceUnavailable))?; - - let origin = origin.cloned().ok_or(QueryError::BadOrigin)?; - let storage = &mut context.storage; - if deposit > 0 { - storage.deposit(&origin, deposit); - } - let args = TransactionArguments { - origin, - now: context.now_ms, - block_number: context.block_number, - storage, - transfer, - gas_limit: WEIGHT_REF_TIME_PER_SECOND * 10, - gas_free: true, - storage_deposit_limit: None, - }; - let (ink_result, _effects) = - ::pink::Contract::instantiate(code_hash, instantiate_data, salt, true, args); - if ink_result.result.is_err() { - log::error!( - "Pink [{:?}] est instantiate error: {:?}", - self.id(), - ink_result - ); - } - Ok(Response::Payload(ink_result.encode())) - } - } + context: &mut QueryContext, + ) -> Result<(Response, ExecSideEffects), QueryError> { + todo!() + // match req { + // Query::InkMessage { + // payload: input_data, + // deposit, + // transfer, + // } => { + // let _guard = context + // .query_scheduler + // .acquire(self.id(), context.weight) + // .await + // .or(Err(QueryError::ServiceUnavailable))?; + + // let origin = origin.cloned().ok_or(QueryError::BadOrigin)?; + // let storage = &mut context.storage; + // if deposit > 0 { + // storage.deposit(&origin, deposit); + // } + // let args = TransactionArguments { + // origin, + // now: context.now_ms, + // block_number: context.block_number, + // storage, + // transfer, + // gas_limit: WEIGHT_REF_TIME_PER_SECOND * 10, + // gas_free: true, + // storage_deposit_limit: None, + // }; + // let (ink_result, effects) = self.instance.bare_call(input_data, true, args); + // if let Some(log_handler) = &context.log_handler { + // if !ink_result.debug_message.is_empty() { + // ContractEventCallback::new(log_handler.clone(), context.block_number) + // .emit_log( + // &self.address(), + // true, + // log::Level::Debug as usize as _, + // String::from_utf8_lossy(&ink_result.debug_message).into_owned(), + // ); + // } + // } + // if ink_result.result.is_err() { + // log::error!("Pink [{:?}] query exec error: {:?}", self.id(), ink_result); + // if !ink_result.debug_message.is_empty() { + // let message = String::from_utf8_lossy(&ink_result.debug_message); + // log::error!("Pink [{:?}] buffer: {:?}", self.id(), message); + // } + // } else { + // *side_effects = effects.into_query_only_effects(); + // } + // Ok(Response::Payload(ink_result.encode())) + // } + // Query::SidevmQuery(payload) => { + // let handle = context + // .sidevm_handle + // .as_ref() + // .ok_or(QueryError::SidevmNotFound)?; + // let cmd_sender = match handle { + // contracts::SidevmHandle::Stopped(_) => { + // return Err(QueryError::SidevmNotFound) + // } + // contracts::SidevmHandle::Running(sender) => sender, + // }; + // let origin = origin.cloned().map(Into::into); + + // let (reply_tx, rx) = tokio::sync::oneshot::channel(); + + // const SIDEVM_QUERY_TIMEOUT: Duration = Duration::from_secs(60 * 5); + + // tokio::time::timeout(SIDEVM_QUERY_TIMEOUT, async move { + // cmd_sender + // .send(SidevmCommand::PushQuery { + // origin, + // payload, + // reply_tx, + // }) + // .await + // .or(Err(QueryError::ServiceUnavailable))?; + // rx.await + // .or(Err(QueryError::NoResponse)) + // .map(Response::Payload) + // }) + // .await + // .or(Err(QueryError::Timeout))? + // } + // Query::InkInstantiate { + // code_hash, + // salt, + // instantiate_data, + // deposit, + // transfer, + // } => { + // let _guard = context + // .query_scheduler + // .acquire(self.id(), context.weight) + // .await + // .or(Err(QueryError::ServiceUnavailable))?; + + // let origin = origin.cloned().ok_or(QueryError::BadOrigin)?; + // let storage = &mut context.storage; + // if deposit > 0 { + // storage.deposit(&origin, deposit); + // } + // let args = TransactionArguments { + // origin, + // now: context.now_ms, + // block_number: context.block_number, + // storage, + // transfer, + // gas_limit: WEIGHT_REF_TIME_PER_SECOND * 10, + // gas_free: true, + // storage_deposit_limit: None, + // }; + // let (ink_result, _effects) = ::pink::Contract::instantiate( + // code_hash, + // instantiate_data, + // salt, + // true, + // args, + // ); + // if ink_result.result.is_err() { + // log::error!( + // "Pink [{:?}] est instantiate error: {:?}", + // self.id(), + // ink_result + // ); + // } + // Ok(Response::Payload(ink_result.encode())) + // } + // } } pub(crate) fn handle_command( &mut self, + contract_id: ContractId, origin: MessageOrigin, - cmd: Command, + cmd: InkCommand, context: &mut contracts::TransactionContext, ) -> TransactionResult { - match cmd { - Command::InkMessage { - nonce, - message, - transfer, - gas_limit, - storage_deposit_limit, - } => { - let storage = &mut context.contract_cluster.storage; - let mut gas_free = false; - let origin: runtime::AccountId = match origin { - MessageOrigin::AccountId(origin) => origin.0.into(), - MessageOrigin::Pallet(_) => { - // The caller will be set to the system contract if it's from a pallet call - // and without charging for gas - gas_free = true; - storage - .system_contract() - .expect("BUG: system contract missing") - } - _ => return Err(TransactionError::BadOrigin), - }; - - let args = TransactionArguments { - origin: origin.clone(), - now: context.block.now_ms, - block_number: context.block.block_number, - storage, - transfer, - gas_limit, - gas_free, - storage_deposit_limit, - }; - - let (result, effects) = self.instance.bare_call(message, false, args); - - if let Some(log_handler) = &context.log_handler { - let msg = SidevmCommand::PushSystemMessage(SystemMessage::PinkMessageOutput { - origin: origin.into(), - contract: self.instance.address.clone().into(), - block_number: context.block.block_number, - nonce: nonce.into_inner(), - output: result.result.encode(), - }); - if log_handler.try_send(msg).is_err() { - error!("Pink emit message output to log handler failed"); - } - if !result.debug_message.is_empty() { - ContractEventCallback::new(log_handler.clone(), context.block.block_number) - .emit_log( - &self.instance.address, - false, - log::Level::Debug as usize as _, - String::from_utf8_lossy(&result.debug_message).into_owned(), - ); - } - } - - if let Err(err) = result.result { - log::error!("Pink [{:?}] command exec error: {:?}", self.id(), err); - if !result.debug_message.is_empty() { - let message = String::from_utf8_lossy(&result.debug_message); - log::error!("Pink [{:?}] buffer: {:?}", self.id(), message); - } - return Err(TransactionError::Other(format!( - "Call contract method failed: {err:?}" - ))); - } - Ok(effects) - } - } + todo!() + // match cmd { + // InkCommand::InkMessage { + // nonce, + // message, + // transfer, + // gas_limit, + // storage_deposit_limit, + // } => { + // let storage = &mut context.contract_cluster.storage; + // let mut gas_free = false; + // let origin: runtime::AccountId = match origin { + // MessageOrigin::AccountId(origin) => origin.0.into(), + // MessageOrigin::Pallet(_) => { + // // The caller will be set to the system contract if it's from a pallet call + // // and without charging for gas + // gas_free = true; + // storage + // .system_contract() + // .expect("BUG: system contract missing") + // } + // _ => return Err(TransactionError::BadOrigin), + // }; + + // let args = TransactionArguments { + // origin: origin.clone(), + // now: context.block.now_ms, + // block_number: context.block.block_number, + // transfer, + // gas_limit, + // gas_free, + // storage_deposit_limit, + // }; + + // let (result, effects) = self.instance.bare_call(message, false, args); + + // if let Some(log_handler) = &context.log_handler { + // let msg = + // SidevmCommand::PushSystemMessage(SystemMessage::PinkMessageOutput { + // origin: origin.into(), + // contract: self.instance.address.clone().into(), + // block_number: context.block.block_number, + // nonce: nonce.into_inner(), + // output: result.result.encode(), + // }); + // if log_handler.try_send(msg).is_err() { + // error!("Pink emit message output to log handler failed"); + // } + // if !result.debug_message.is_empty() { + // ContractEventCallback::new( + // log_handler.clone(), + // context.block.block_number, + // ) + // .emit_log( + // &self.instance.address, + // false, + // log::Level::Debug as usize as _, + // String::from_utf8_lossy(&result.debug_message).into_owned(), + // ); + // } + // } + + // if let Err(err) = result.result { + // log::error!("Pink [{:?}] command exec error: {:?}", self.id(), err); + // if !result.debug_message.is_empty() { + // let message = String::from_utf8_lossy(&result.debug_message); + // log::error!("Pink [{:?}] buffer: {:?}", self.id(), message); + // } + // return Err(TransactionError::Other(format!( + // "Call contract method failed: {err:?}" + // ))); + // } + // Ok(effects) + // } + // } } pub(crate) fn on_block_end( @@ -339,198 +462,33 @@ impl Pink { } } -pub mod cluster { - use anyhow::{Context, Result}; - use parity_scale_codec::Decode; - use phala_crypto::sr25519::{Persistence, Sr25519SecretKey, KDF}; - use phala_mq::{ContractClusterId, ContractId}; - use phala_serde_more as more; - use phala_types::contract::messaging::ResourceType; - use pink::{ - capi::types::Weight, - types::{AccountId, Balance, Hash}, - weights::Weight, - }; - use serde::{Deserialize, Serialize}; - use sp_core::sr25519; - use sp_runtime::{AccountId32, DispatchError}; - use std::collections::{BTreeMap, BTreeSet}; - - #[derive(Serialize, Deserialize, Default)] - pub struct ClusterConfig { - pub log_handler: Option, - // Version used to control the contract API availability. - pub version: (u16, u16), - } - - #[derive(Serialize, Deserialize)] - pub struct Cluster { - pub storage: pink::Storage, - contracts: BTreeSet, - #[serde(with = "more::key_bytes")] - key: sr25519::Pair, - pub id: ContractClusterId, - pub config: ClusterConfig, +pub trait ClusterContainer { + fn is_empty(&self) -> bool { + self.len() == 0 } + fn len(&self) -> usize; + fn get_cluster(&self, cluster_id: &ContractClusterId) -> Option<&Cluster>; + fn get_cluster_mut(&mut self, cluster_id: &ContractClusterId) -> Option<&mut Cluster>; + fn remove_cluster(&mut self, cluster_id: &ContractClusterId) -> Option; +} - impl Cluster { - pub fn new(id: &ContractClusterId, cluster_key: &sr25519::Pair) -> Self { - let mut cluster = Cluster { - storage: Default::default(), - contracts: Default::default(), - key: cluster_key.clone(), - config: Default::default(), - id: id.clone(), - }; - let seed_key = cluster_key - .derive_sr25519_pair(&[b"ink key derivation seed"]) - .expect("Derive key seed should always success!"); - cluster.set_id(id); - cluster.set_key_seed(seed_key.dump_secret_key()); - cluster - } - /// Add a new contract to the cluster. Returns true if the contract is new. - pub fn add_contract(&mut self, address: ContractId) -> bool { - self.contracts.insert(address) - } - - pub fn key(&self) -> &sr25519::Pair { - &self.key - } - - pub fn system_contract(&self) -> Option { - self.storage.system_contract() - } - - pub fn set_system_contract(&mut self, contract: AccountId32) { - self.storage.set_system_contract(contract); - } - - pub fn set_id(&mut self, id: &ContractClusterId) { - self.storage.set_cluster_id(id.as_bytes()); - } - - pub fn set_key_seed(&mut self, seed: Sr25519SecretKey) { - self.storage.set_key_seed(seed); - } - - pub fn upload_resource( - &mut self, - origin: &AccountId, - resource_type: ResourceType, - resource_data: Vec, - ) -> Result { - match resource_type { - ResourceType::InkCode => self.storage.upload_code(origin, resource_data, true), - ResourceType::SidevmCode => self.storage.upload_sidevm_code(origin, resource_data), - ResourceType::IndeterministicInkCode => { - self.storage.upload_code(origin, resource_data, false) - } - } - } - - pub fn get_resource(&self, resource_type: ResourceType, hash: &Hash) -> Option> { - match resource_type { - ResourceType::InkCode => None, - ResourceType::SidevmCode => self.storage.get_sidevm_code(hash), - ResourceType::IndeterministicInkCode => None, - } - } - - pub fn iter_contracts(&self) -> impl Iterator { - self.contracts.iter() - } - - pub fn setup( - &mut self, - gas_price: Balance, - deposit_per_item: Balance, - deposit_per_byte: Balance, - treasury_account: &::pink::types::AccountId, - ) { - self.storage.setup( - gas_price, - deposit_per_item, - deposit_per_byte, - treasury_account, - ); - } - - pub fn deposit(&mut self, who: &::pink::types::AccountId, amount: Balance) { - self.storage.deposit(who, amount) - } - - pub fn set_system_contract_code(&mut self, code_hash: Hash) -> Result<(), DispatchError> { - self.storage.set_system_contract_code(code_hash)?; - self.sync_system_contract_version() - .expect("Failed to sync the system contract version. Please upgrade pRuntime!"); - Ok(()) - } - - pub fn sync_system_contract_version(&mut self) -> Result<()> { - let Some(system_address) = self.system_contract() else { - anyhow::bail!("No system contract"); - }; - let system = pink::Contract::from_address(system_address.clone()); - // System::version - let selector = 0x87c98a8d_u32.to_be_bytes().to_vec(); - let args = TransactionArguments { - origin: system_address, - now: 1, - block_number: 1, - storage: &mut self.storage, - transfer: 0, - gas_limit: Weight::MAX, - gas_free: true, - storage_deposit_limit: None, - callbacks: None, - }; - let (result, _) = system.bare_call(selector, true, args); - let output = result.result.map_err(|err| { - anyhow::anyhow!("Failed to get the system contract version: {err:?}") - })?; - self.config.version = Result::<_, ()>::decode(&mut &output.data[..]) - .context("Failed to decode the system contract version")? - .or(Err(anyhow::anyhow!( - "Failed to get the system contract version" - )))?; - const SUPPORTED_API_VERSION: u16 = 0; - if self.config.version.0 > SUPPORTED_API_VERSION { - anyhow::bail!( - "The pink-system version is not supported, please upgrade the pRuntime" - ); - } - Ok(()) +impl ClusterContainer for Option { + fn len(&self) -> usize { + if self.is_some() { + 1 + } else { + 0 } } - - pub trait ClusterContainer { - fn len(&self) -> usize; - fn get_cluster(&self, cluster_id: &ContractClusterId) -> Option<&Cluster>; - fn get_cluster_mut(&mut self, cluster_id: &ContractClusterId) -> Option<&mut Cluster>; - fn remove_cluster(&mut self, cluster_id: &ContractClusterId) -> Option; + fn get_cluster(&self, cluster_id: &ContractClusterId) -> Option<&Cluster> { + self.as_ref().filter(|c| c.id == *cluster_id) } - - impl ClusterContainer for Option { - fn len(&self) -> usize { - if self.is_some() { - 1 - } else { - 0 - } - } - fn get_cluster(&self, cluster_id: &ContractClusterId) -> Option<&Cluster> { - self.as_ref().filter(|c| c.id == *cluster_id) - } - fn get_cluster_mut(&mut self, cluster_id: &ContractClusterId) -> Option<&mut Cluster> { - self.as_mut().filter(|c| c.id == *cluster_id) - } - fn remove_cluster(&mut self, cluster_id: &ContractClusterId) -> Option { - if self.get_cluster(cluster_id).is_none() { - return None; - } - self.take() - } + fn get_cluster_mut(&mut self, cluster_id: &ContractClusterId) -> Option<&mut Cluster> { + self.as_mut().filter(|c| c.id == *cluster_id) + } + fn remove_cluster(&mut self, cluster_id: &ContractClusterId) -> Option { + _ = self.get_cluster(cluster_id)?; + self.take() } } diff --git a/crates/phactory/src/contracts/support.rs b/crates/phactory/src/contracts/support.rs index 5db039cf58..56a7b44aee 100644 --- a/crates/phactory/src/contracts/support.rs +++ b/crates/phactory/src/contracts/support.rs @@ -13,7 +13,7 @@ use sidevm::{ OcallAborted, VmId, }; -use super::pink::cluster::Cluster; +use super::pink::Cluster; use crate::{ hex, secret_channel::{KeyPair, SecretMessageChannel, SecretReceiver}, @@ -35,14 +35,12 @@ pub struct TransactionContext<'a, 'b> { pub block: &'a mut BlockInfo<'b>, pub mq: &'a SignedMessageChannel, pub secret_mq: SecretMessageChannel<'a, SignedMessageChannel>, - pub contract_cluster: &'a mut Cluster, pub log_handler: Option, } pub struct QueryContext { pub block_number: BlockNumber, pub now_ms: u64, - pub storage: ClusterStorage, pub sidevm_handle: Option, pub log_handler: Option, pub query_scheduler: RequestScheduler, @@ -128,13 +126,17 @@ pub struct FatContract { sidevm_info: Option, weight: u32, code_hash: Option, - // todo!: - // hooks: Hooks + on_block_end: Option, +} + +#[derive(Serialize, Deserialize)] +struct OnBlockEnd { + selector: u32, + gas_limit: u64, } impl FatContract { pub(crate) fn new( - contract: impl Into, send_mq: SignedMessageChannel, cmd_rcv_mq: SecretReceiver, ecdh_key: KeyPair, @@ -143,7 +145,6 @@ impl FatContract { code_hash: Option, ) -> Self { FatContract { - contract: contract.into(), send_mq, cmd_rcv_mq, ecdh_key, @@ -152,6 +153,7 @@ impl FatContract { sidevm_info: None, weight: 0, code_hash, + on_block_end: None, } } @@ -163,10 +165,6 @@ impl FatContract { self.cluster_id } - pub(crate) fn snapshot_for_query(&self) -> AnyContract { - self.contract.snapshot() - } - pub(crate) fn sidevm_handle(&self) -> Option { self.sidevm_info .as_ref() @@ -182,7 +180,6 @@ impl FatContract { block: env.block, mq: &self.send_mq, secret_mq, - contract_cluster: env.contract_cluster, log_handler: env.log_handler.clone(), }; @@ -190,7 +187,11 @@ impl FatContract { next_cmd = self.cmd_rcv_mq => match next_cmd { Ok((_, cmd, origin)) => { info!("Contract {:?} handling command", self.id()); - self.contract.handle_command(origin, cmd.0, &mut context) + let Ok(command) = Decode::decode(&mut &cmd.0[..]) else { + error!("Failed to decode command input"); + return Some(Err(TransactionError::BadInput)); + }; + env.contract_cluster.handle_command(self.id(), origin, command, &mut context) } Err(_e) => { Err(TransactionError::ChannelError) @@ -205,18 +206,21 @@ impl FatContract { block: env.block, mq: &self.send_mq, secret_mq, - contract_cluster: env.contract_cluster, log_handler: env.log_handler.clone(), }; - self.contract.on_block_end(&mut context) + // self.contract.on_block_end(&mut context) + todo!() } pub(crate) fn set_on_block_end_selector(&mut self, selector: u32, gas_limit: u64) { - let AnyContract::Pink(pink) = &mut self.contract; - pink.set_on_block_end_selector(selector, gas_limit) + self.on_block_end = Some(OnBlockEnd { + selector, + gas_limit, + }); } pub(crate) fn push_message(&self, payload: Vec, topic: Vec) { + // todo! disable it in the runtime self.send_mq.push_data(payload, topic) } diff --git a/crates/phactory/src/contracts/support/keeper.rs b/crates/phactory/src/contracts/support/keeper.rs index 23a81cd368..5d21724c5b 100644 --- a/crates/phactory/src/contracts/support/keeper.rs +++ b/crates/phactory/src/contracts/support/keeper.rs @@ -1,10 +1,9 @@ -use pink::runtime::ExecSideEffects; use serde::{Deserialize, Serialize}; use sidevm::service::Spawner; use std::collections::BTreeMap; use crate::{ - contracts::{pink::Pink, FatContract, TransactionContext}, + contracts::{FatContract, TransactionContext}, system::{TransactionError, TransactionResult}, types::{deopaque_query, OpaqueError, OpaqueQuery, OpaqueReply}, }; @@ -15,79 +14,6 @@ use super::QueryContext; type ContractMap = BTreeMap; -macro_rules! define_any_native_contract { - (pub enum $name:ident { $($contract:ident ($contract_type: tt),)* }) => { - #[derive(Encode, Decode)] - pub enum $name { - $($contract($contract_type),)* - } - - impl $name { - pub(crate) fn handle_command( - &mut self, - origin: MessageOrigin, - cmd: Vec, - context: &mut TransactionContext, - ) -> TransactionResult { - match self { - $(Self::$contract(me) => { - let cmd = Decode::decode(&mut &cmd[..]).or(Err(TransactionError::BadInput))?; - me.handle_command(origin, cmd, context) - })* - } - } - - pub(crate) fn on_block_end(&mut self, context: &mut TransactionContext) -> TransactionResult { - match self { - $(Self::$contract(me) => { - me.on_block_end(context) - })* - } - } - - pub(crate) fn snapshot(&self) -> Self { - match self { - $($name::$contract(me) => { - Self::$contract(me.snapshot()) - })* - } - } - - pub(crate) async fn handle_query( - &self, - origin: Option<&runtime::AccountId>, - req: OpaqueQuery, - context: &mut QueryContext, - ) -> Result<(OpaqueReply, ExecSideEffects), OpaqueError> { - match self { - $($name::$contract(me) => { - let mut effects = ExecSideEffects::default(); - let response = me.handle_query(origin, deopaque_query(&req)?, context, &mut effects).await; - if let Err(err) = &response { - warn!("Error handling query: {:?}", err); - } - Ok((response.encode(), effects)) - })* - } - } - } - - $( - impl From<$contract_type> for $name { - fn from(c: $contract_type) -> Self { - $name::$contract(c) - } - } - )* - }; -} - -define_any_native_contract!( - pub enum AnyContract { - Pink(Pink), - } -); - #[derive(Default, Serialize, Deserialize)] pub struct ContractsKeeper { contracts: ContractMap, @@ -128,6 +54,10 @@ impl ContractsKeeper { self.contracts.remove(id) } + pub fn drain(&mut self) -> impl Iterator { + std::mem::take(&mut self.contracts).into_values() + } + pub fn iter(&self) -> impl Iterator { self.contracts.iter() } diff --git a/crates/phactory/src/prpc_service.rs b/crates/phactory/src/prpc_service.rs index c0dbff3f00..afd251040a 100644 --- a/crates/phactory/src/prpc_service.rs +++ b/crates/phactory/src/prpc_service.rs @@ -9,7 +9,7 @@ use crate::system::{System, MAX_SUPPORTED_CONSENSUS_VERSION}; use super::*; use crate::contracts::ContractClusterId; -use ::pink::runtime::ExecSideEffects; +use ::pink::types::ExecSideEffects; use parity_scale_codec::Encode; use pb::{ phactory_api_server::{PhactoryApi, PhactoryApiServer}, @@ -507,7 +507,7 @@ impl Phactory Ok(messages) } - fn apply_side_effects(&mut self, cluster_id: ContractClusterId, effects: ExecSideEffects) { + fn apply_side_effects(&mut self, effects: ExecSideEffects) { let Some(state) = self.runtime_state.as_ref() else { error!("Failed to apply side effects: chain storage missing"); return; @@ -522,7 +522,7 @@ impl Phactory fn contract_query( &mut self, request: pb::ContractQueryRequest, - effects_queue: Sender<(ContractClusterId, ExecSideEffects)>, + effects_queue: Sender, ) -> RpcResult>> { if self.args.safe_mode_level > 0 { return Err(from_display("Query is unavailable in safe mode")); @@ -580,10 +580,10 @@ impl Phactory )?; Ok(async move { - let (response, cluster_id, effects) = query_future.await?; + let (response, effects) = query_future.await?; effects_queue - .send((cluster_id, effects)) + .send(effects) .map_err(|_| from_display("Failed to apply side effects"))?; let response = contract::ContractQueryResponse { @@ -795,19 +795,22 @@ impl Phactory } pub fn get_cluster_info(&self) -> RpcResult { - let Some(System{ contract_cluster: Some(cluster), .. }) = &self.system else { + let Some(System{ contract_cluster: Some(cluster), contracts, .. }) = &self.system else { return Ok(Default::default()); }; - let ver = cluster.config.version; - let version = format!("{}.{}", ver.0, ver.1); + let ver = cluster.config.system_version; + let system_version = format!("{}.{}", ver.0, ver.1); + let ver = cluster.config.runtime_version; + let runtime_version = format!("{}.{}", ver.0, ver.1); Ok(pb::GetClusterInfoResponse { info: Some(pb::ClusterInfo { - id: hex(&cluster.id), + id: hex(cluster.id), state_root: hex(cluster.storage.root()), - contracts: cluster.iter_contracts().map(hex).collect(), - version, + contracts: contracts.keys().map(hex).collect(), + system_version, + runtime_version, }), }) } @@ -1037,11 +1040,11 @@ impl PhactoryApi for Rpc let (tx, rx) = channel(); let phactory = self.phactory.clone(); tokio::spawn(async move { - if let Ok((cluster_id, effects)) = rx.await { + if let Ok(effects) = rx.await { phactory .lock() .unwrap() - .apply_side_effects(cluster_id, effects); + .apply_side_effects(effects); } }); let query_fut = self.lock_phactory().contract_query(request, tx)?; diff --git a/crates/phactory/src/system/mod.rs b/crates/phactory/src/system/mod.rs index 2efce3fd2f..9cc719c1e2 100644 --- a/crates/phactory/src/system/mod.rs +++ b/crates/phactory/src/system/mod.rs @@ -3,13 +3,10 @@ mod master_key; use crate::{ benchmark, - contracts::{AnyContract, ContractsKeeper, ExecuteEnv, SidevmCode}, - pink::{ - cluster::{Cluster, ClusterContainer}, - ContractEventCallback, Pink, - }, + contracts::{ContractsKeeper, ExecuteEnv, SidevmCode}, + pink::{Cluster, ClusterContainer, ContractEventCallback}, secret_channel::{ecdh_serde, SecretReceiver}, - types::{BlockInfo, OpaqueError, OpaqueQuery, OpaqueReply}, + types::{deopaque_query, BlockInfo, OpaqueError, OpaqueQuery, OpaqueReply}, }; use anyhow::{anyhow, Context, Result}; use core::fmt; @@ -42,7 +39,7 @@ use phala_types::{ BatchDispatchClusterKeyEvent, ClusterOperation, ContractOperation, ResourceType, WorkerClusterReport, }, - CodeIndex, ConvertTo, + CodeIndex, ContractQueryError, ConvertTo, }, messaging::{ AeadIV, BatchRotateMasterKeyEvent, DispatchMasterKeyEvent, DispatchMasterKeyHistoryEvent, @@ -56,12 +53,12 @@ use serde::{Deserialize, Serialize}; use sidevm::service::{Command as SidevmCommand, CommandSender, Report, Spawner, SystemMessage}; use sp_core::{hashing::blake2_256, sr25519, Pair, U256}; -use pink::runtime::{HookPoint, PinkEvent}; +use pink::types::{HookPoint, PinkEvent}; use std::cell::Cell; use std::convert::TryFrom; use std::future::Future; -pub type TransactionResult = Result; +pub type TransactionResult = Result; pub(crate) const MAX_SUPPORTED_CONSENSUS_VERSION: u32 = 0; @@ -587,45 +584,38 @@ impl System { query: OpaqueQuery, query_scheduler: RequestScheduler, ) -> Result< - impl Future< - Output = Result< - (OpaqueReply, contracts::ContractClusterId, ExecSideEffects), - OpaqueError, - >, - >, + impl Future>, OpaqueError, > { - use pink::storage::Snapshot as _; - let contract = self .contracts .get_mut(contract_id) .ok_or(OpaqueError::ContractNotFound)?; let cluster_id = contract.cluster_id(); - let storage = self - .contract_clusters - .get_cluster_mut(&cluster_id) + let cluster = self + .contract_cluster + .as_mut() .expect("BUG: contract cluster should always exists") - .storage .snapshot(); let sidevm_handle = contract.sidevm_handle(); let weight = contract.weight(); - let contract = contract.snapshot_for_query(); let mut context = contracts::QueryContext { block_number: self.block_number, now_ms: self.now_ms, - storage, sidevm_handle, - log_handler: self.get_system_message_handler(&cluster_id), + log_handler: self.get_system_message_handler(), query_scheduler, weight, }; let origin = origin.cloned(); + let query = deopaque_query(&query)?; + let contract_id = *contract_id; Ok(async move { - contract - .handle_query(origin.as_ref(), query, &mut context) + cluster + .handle_query(&contract_id, origin.as_ref(), query, &mut context) .await - .map(|(reply, effects)| (reply, cluster_id, effects)) + .map(|(reply, effects)| (reply.encode(), effects)) + .map_err(|err| ContractQueryError::OtherError(format!("{err:?}"))) }) } @@ -761,7 +751,7 @@ impl System { block, &self.egress, &self.sidevm_spawner, - log_handler, + log_handler.clone(), block.storage, ); } @@ -1126,12 +1116,10 @@ impl System { None => return Ok(()), Some(cluster) => cluster, }; - info!("Destroying cluster {}", hex_fmt::HexFmt(&cluster_id)); - for contract in cluster.iter_contracts() { - if let Some(contract) = self.contracts.remove(contract) { - contract.destroy(&self.sidevm_spawner); - } + for contract in self.contracts.drain() { + contract.destroy(&self.sidevm_spawner); } + info!("Destroyed cluster {}", hex_fmt::HexFmt(&cluster_id)); } ClusterOperation::UploadResource { origin, @@ -1227,8 +1215,9 @@ impl System { gas_limit, storage_deposit_limit, } => { + let log_handler = self.get_system_message_handler(); let cluster_id = contract_info.cluster_id; - let Some(cluster) = &mut self + let Some(cluster) = self .contract_cluster .get_cluster_mut(&cluster_id) else { return Ok(()); @@ -1239,10 +1228,7 @@ impl System { match contract_info.code_index { CodeIndex::WasmCode(code_hash) => { let deployer = contract_info.deployer.clone(); - - let log_handler = self.get_system_message_handler(); - - /** + /* * todo!: set the logger callbacks: ContractEventCallback::from_log_sender( &log_handler, @@ -1253,7 +1239,6 @@ impl System { origin: deployer.clone(), now: block.now_ms, block_number: block.block_number, - storage: &mut cluster.storage, transfer, gas_limit, gas_free: false, @@ -1268,15 +1253,15 @@ impl System { ); blake2_256(&buf) }; - let result = Pink::instantiate( - cluster_id, - code_hash, - contract_info.instantiate_data, - contract_info.salt, - false, - tx_args, - ) - .with_context(|| format!("Contract deployer: {deployer:?}")); + let result = cluster + .instantiate( + code_hash, + contract_info.instantiate_data, + contract_info.salt, + false, + tx_args, + ) + .with_context(|| format!("Contract deployer: {deployer:?}")); // Send the reault to the log server if let Some(log_handler) = &log_handler { macro_rules! send_log { @@ -1309,8 +1294,6 @@ impl System { } } let (_, effects) = result?; - - let cluster = self.contract_cluster.as_mut().expect("Cluster must exist"); apply_pink_side_effects( effects, &mut self.contracts, @@ -1540,7 +1523,7 @@ impl System { system_code.len() ); // register cluster - let cluster = Cluster::new(&event.cluster, &cluster_key); + let mut cluster = Cluster::new(&event.cluster, &cluster_key); cluster.setup( gas_price, deposit_per_item, @@ -1558,23 +1541,20 @@ impl System { origin: owner.clone(), now: block.now_ms, block_number: block.block_number, - storage: &mut cluster.storage, transfer: 0, gas_limit: Weight::MAX, gas_free: true, storage_deposit_limit: None, }; - let (pink, effects) = - Pink::instantiate(event.cluster, code_hash, selector, vec![], false, args)?; - cluster.set_system_contract(pink.address()); + let (system_address, effects) = + cluster.instantiate(code_hash, selector, vec![], false, args)?; + cluster.set_system_contract(system_address.0.into()); cluster .sync_system_contract_version() .expect("Failed to sync the system contract version. Please upgrade pRuntime!"); info!( "Cluster deployed, id={:?}, system={:?}, version={:?}", - event.cluster, - pink.id(), - cluster.config.version + cluster.id, system_address, cluster.config.system_version ); apply_pink_side_effects( effects, @@ -1630,7 +1610,7 @@ impl System { cluster: self .contract_cluster .as_ref() - .map(|c| hex::encode(&c.id)) + .map(|c| hex::encode(c.id)) .unwrap_or_default(), number_of_contracts: self.contracts.len() as _, public_key: hex::encode(self.identity_key.public()), @@ -1660,10 +1640,7 @@ impl System

{ let cluster = match &mut self.contract_cluster { Some(cluster) => cluster, None => { - error!( - "Can not apply effects: cluster {:?} is not deployed", - cluster_id - ); + error!("Can not apply effects: not cluster deployed"); return; } }; @@ -1761,31 +1738,28 @@ fn apply_instantiating_events( let code_hash = cluster.storage.code_hash(&address); let result = install_contract( contracts, - id, - pink, + contract_id, code_hash, contract_key.clone(), ecdh_key.clone(), block, - cluster.id(), + cluster.id, ); if let Err(err) = result { error!("BUG: Install contract failed: {:?}", err); - error!(" address: {:?}", address); - error!(" cluster_id: {:?}", cluster.id()); + error!(" address: {:?}", contract_id); + error!(" cluster_id: {:?}", cluster.id); error!(" deployer: {:?}", deployer); continue; }; - cluster.add_contract(id); - let message = ContractRegistryEvent::PubkeyAvailable { contract: contract_id, pubkey: contract_key.public(), deployer: phala_types::messaging::AccountId(deployer.into()), }; - let sender = MessageOrigin::Cluster(cluster.id()); + let sender = MessageOrigin::Cluster(cluster.id); let cluster_mq: SignedMessageChannel = block.send_mq.channel(sender, cluster.key().clone().into()); cluster_mq.push_message(&message); @@ -1934,7 +1908,7 @@ pub(crate) fn apply_pink_events( } info!( "The system contract has been upgraded to {:?}, hash={hash:?}", - cluster.config.version + cluster.config.system_version ); } } @@ -1967,7 +1941,6 @@ fn apply_ink_side_effects( pub fn install_contract( contracts: &mut ContractsKeeper, contract_id: phala_mq::ContractId, - contract: impl Into, code_hash: Option, contract_key: sr25519::Pair, ecdh_key: EcdhKey, @@ -1986,15 +1959,8 @@ pub fn install_contract( .into(), ecdh_key.clone(), ); - let wrapped = contracts::FatContract::new( - contract, - mq, - cmd_mq, - ecdh_key, - cluster_id, - contract_id, - code_hash, - ); + let wrapped = + contracts::FatContract::new(mq, cmd_mq, ecdh_key, cluster_id, contract_id, code_hash); contracts.insert(wrapped); Ok(()) } diff --git a/crates/pink/capi/src/types.rs b/crates/pink/capi/src/types.rs index e34ae6b2fe..188b5e4f9b 100644 --- a/crates/pink/capi/src/types.rs +++ b/crates/pink/capi/src/types.rs @@ -1,4 +1,3 @@ -use pink_extension::PinkEvent; use scale::{Decode, Encode}; use sp_core::{Hasher, H256}; use sp_runtime::{traits::BlakeTwo256, AccountId32}; @@ -12,6 +11,8 @@ pub type Index = u64; pub type Address = AccountId32; pub type Weight = u64; +pub use pink_extension::{PinkEvent, HookPoint}; + #[derive(Decode, Encode)] pub enum ExecSideEffects { V0 { diff --git a/crates/pink/runner/Cargo.toml b/crates/pink/runner/Cargo.toml index a9a979614b..f88504ea86 100644 --- a/crates/pink/runner/Cargo.toml +++ b/crates/pink/runner/Cargo.toml @@ -4,9 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] +serde = { version = "1", features = ["derive"] } sp-weights = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } pink-capi = { path = "../capi" } im = "15" once_cell = "1" libc = "0.2" log = "0.4" +phala-crypto = { path = "../../phala-crypto" } +pink-extension-runtime = { path = "../pink-extension-runtime" } diff --git a/crates/pink/runner/src/lib.rs b/crates/pink/runner/src/lib.rs index 084d179533..afcf81bd32 100644 --- a/crates/pink/runner/src/lib.rs +++ b/crates/pink/runner/src/lib.rs @@ -1,15 +1,14 @@ pub use pink_capi as capi; pub use sp_weights::constants; +pub use pink_extension_runtime::local_cache; pub mod types { pub use crate::capi::types::*; - use crate::storage::ClusterStorage; - pub struct TransactionArguments<'a> { + pub struct TransactionArguments { pub origin: AccountId, pub now: u64, pub block_number: BlockNumber, - pub storage: &'a mut ClusterStorage, pub transfer: Balance, pub gas_limit: Weight, pub gas_free: bool, diff --git a/crates/pink/runner/src/storage.rs b/crates/pink/runner/src/storage.rs index 8042628179..bc7d98f9b9 100644 --- a/crates/pink/runner/src/storage.rs +++ b/crates/pink/runner/src/storage.rs @@ -1,9 +1,152 @@ use im::OrdMap; -use pink_capi::types::Hash; +use phala_crypto::sr25519::Sr25519SecretKey; +use pink_capi::types::{AccountId, Balance, Hash}; +use serde::{Deserialize, Serialize}; -#[derive(Clone)] +#[derive(Clone, Default, Serialize, Deserialize)] pub struct ClusterStorage { - runtime_version: (u32, u32), root: Hash, kv_store: OrdMap)>, } + +impl ClusterStorage { + pub fn set_cluster_id(&mut self, cluster_id: &[u8]) { + todo!() + //self.execute_mut(false, None, || { + //PalletPink::set_cluster_id(cluster_id); + //}); + } + pub fn setup( + &mut self, + gas_price: Balance, + deposit_per_item: Balance, + deposit_per_byte: Balance, + treasury_account: &AccountId, + ) { + todo!() + ////self.execute_mut(false, None, || { + ////PalletPink::set_gas_price(gas_price); + ////PalletPink::set_deposit_per_item(deposit_per_item); + ////PalletPink::set_deposit_per_byte(deposit_per_byte); + ////PalletPink::set_treasury_account(treasury_account); + ////}); + } + + pub fn deposit(&mut self, who: &AccountId, value: Balance) { + todo!() + ////self.execute_mut(false, None, || { + ////let _ = Balances::deposit_creating(who, value); + ////}); + } + + pub fn set_key_seed(&mut self, seed: Sr25519SecretKey) { + todo!() + ////self.execute_mut(false, None, || { + ////PalletPink::set_key_seed(seed); + ////}); + } + + pub fn set_id(&mut self, id: &[u8]) { + todo!() + } + + pub fn set_key(&mut self, seed: Sr25519SecretKey) { + todo!() + } + + pub fn get_key(&mut self) -> Sr25519SecretKey { + todo!() + } + + pub fn upload_code( + &mut self, + account: &AccountId, + code: Vec, + deterministic: bool, + ) -> Result> { + todo!() + ////self.execute_mut(false, None, || { + ////crate::runtime::Contracts::bare_upload_code( + ////account.clone(), + ////code, + ////None, + ////if deterministic { + ////Determinism::Deterministic + ////} else { + ////Determinism::AllowIndeterminism + ////}, + ////) + ////}) + ////.0 + ////.map(|v| v.code_hash) + } + + pub fn upload_sidevm_code( + &mut self, + account: &AccountId, + code: Vec, + ) -> Result> { + todo!() + ////self.execute_mut(false, None, || { + ////PalletPink::put_sidevm_code(account.clone(), code) + ////}) + ////.0 + } + + pub fn get_sidevm_code(&self, hash: &Hash) -> Option> { + todo!() + ////self.execute_with(true, None, || { + ////PalletPink::sidevm_codes(&hash).map(|v| v.code) + ////}) + ////.0 + } + + pub fn set_system_contract(&mut self, address: AccountId) { + todo!() + ////self.execute_mut(false, None, move || { + ////PalletPink::set_system_contract(address); + ////}); + } + + pub fn system_contract(&self) -> Option { + todo!() + ////self.execute_with(true, None, PalletPink::system_contract).0 + } + + pub fn get(&self, key: &[u8]) -> Option> { + todo!() + ////self.backend.storage(key).ok().flatten() + } + + pub fn root(&self) -> Hash { + todo!() + ////*self.backend.as_trie_backend().root() + } + + pub fn free_balance(&self, account: &AccountId) -> Balance { + todo!() + ////self.execute_with(true, None, || Balances::free_balance(account)) + ////.0 + } + + pub fn total_balance(&self, account: &AccountId) -> Balance { + todo!() + ////self.execute_with(true, None, || Balances::total_balance(account)) + ////.0 + } + + pub fn code_hash(&self, account: &AccountId) -> Option { + todo!() + ////self.execute_with(true, None, || Contracts::code_hash(account)) + ////.0 + } + + pub fn set_system_contract_code(&mut self, code_hash: Hash) -> Result<(), Vec> { + todo!() + ////let system_contract = self.system_contract().ok_or(DispatchError::CannotLookup)?; + ////self.execute_mut(false, None, || { + ////Contracts::set_code(RawOrigin::Root.into(), system_contract, code_hash) + ////}) + ////.0 + } +}