Skip to content

Commit

Permalink
Merge pull request #610 from Phala-Network/custom-ink-address
Browse files Browse the repository at this point in the history
pink: Use customized ink address as contract id
  • Loading branch information
kvinwang authored Dec 30, 2021
2 parents 998d1a9 + 7dd789d commit d0ff13b
Show file tree
Hide file tree
Showing 35 changed files with 966 additions and 491 deletions.
434 changes: 326 additions & 108 deletions Cargo.lock

Large diffs are not rendered by default.

99 changes: 52 additions & 47 deletions crates/phactory/src/contracts/pink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::contracts;
use crate::system::{TransactionError, TransactionResult};
use anyhow::{anyhow, Result};
use parity_scale_codec::{Decode, Encode};
use phala_mq::{ContractGroupId, MessageOrigin};
use phala_mq::{ContractClusterId, MessageOrigin};
use pink::runtime::ExecSideEffects;
use runtime::{AccountId, BlockNumber};

Expand Down Expand Up @@ -32,12 +32,12 @@ pub enum QueryError {
#[derive(Encode, Decode)]
pub struct Pink {
instance: pink::Contract,
group: ContractGroupId,
cluster_id: ContractClusterId,
}

impl Pink {
pub fn instantiate(
group: ContractGroupId,
cluster_id: ContractClusterId,
storage: &mut pink::Storage,
origin: AccountId,
wasm_bin: Vec<u8>,
Expand All @@ -56,15 +56,15 @@ impl Pink {
now,
)
.map_err(|err| anyhow!("Instantiate contract failed: {:?} origin={:?}", err, origin,))?;
Ok((Self { group, instance }, effects))
Ok((Self { cluster_id, instance }, effects))
}

pub fn from_address(address: AccountId, group: ContractGroupId) -> Self {
pub fn from_address(address: AccountId, cluster_id: ContractClusterId) -> Self {
let instance = pink::Contract::from_address(address);
Self { instance, group }
Self { instance, cluster_id }
}

pub fn address_to_id(address: &AccountId) -> contracts::NativeContractId {
pub fn address_to_id(address: &AccountId) -> contracts::ContractId {
let inner: &[u8; 32] = address.as_ref();
inner.into()
}
Expand All @@ -86,8 +86,8 @@ impl contracts::NativeContract for Pink {
let origin = origin.ok_or(QueryError::BadOrigin)?;
match req {
Query::InkMessage(input_data) => {
let storage = group_storage(&mut context.contract_groups, &self.group)
.expect("Pink group should always exists!");
let storage = cluster_storage(&mut context.contract_clusters, &self.cluster_id)
.expect("Pink cluster should always exists!");

let (ink_result, _effects) = self.instance.bare_call(
storage,
Expand Down Expand Up @@ -118,8 +118,8 @@ impl contracts::NativeContract for Pink {
_ => return Err(TransactionError::BadOrigin),
};

let storage = group_storage(&mut context.contract_groups, &self.group)
.expect("Pink group should always exists!");
let storage = cluster_storage(&mut context.contract_clusters, &self.cluster_id)
.expect("Pink cluster should always exists!");

let (result, effects) = self
.instance
Expand All @@ -146,8 +146,8 @@ impl contracts::NativeContract for Pink {
}

fn on_block_end(&mut self, context: &mut contracts::NativeContext) -> TransactionResult {
let storage = group_storage(&mut context.contract_groups, &self.group)
.expect("Pink group should always exists!");
let storage = cluster_storage(&mut context.contract_clusters, &self.cluster_id)
.expect("Pink cluster should always exists!");
let effects = self
.instance
.on_block_end(storage, context.block.block_number, context.block.now_ms)
Expand All @@ -160,7 +160,7 @@ impl contracts::NativeContract for Pink {
}

impl NativeContractMore for Pink {
fn id(&self) -> contracts::NativeContractId {
fn id(&self) -> phala_mq::ContractId {
Pink::address_to_id(&self.instance.address)
}

Expand All @@ -169,20 +169,20 @@ impl NativeContractMore for Pink {
}
}

fn group_storage<'a>(
groups: &'a mut group::GroupKeeper,
group_id: &ContractGroupId,
fn cluster_storage<'a>(
clusters: &'a mut cluster::ClusterKeeper,
cluster_id: &ContractClusterId,
) -> Result<&'a mut pink::Storage> {
groups
.get_group_storage_mut(group_id)
.ok_or(anyhow!("Contract group {:?} not found! qed!", group_id))
clusters
.get_cluster_storage_mut(cluster_id)
.ok_or(anyhow!("Contract cluster {:?} not found! qed!", cluster_id))
}

pub mod group {
pub mod cluster {
use super::Pink;

use anyhow::Result;
use phala_mq::{ContractGroupId, ContractId};
use phala_mq::{ContractClusterId, ContractId};
use phala_serde_more as more;
use pink::{runtime::ExecSideEffects, types::AccountId};
use runtime::BlockNumber;
Expand All @@ -191,14 +191,14 @@ pub mod group {
use std::collections::{BTreeMap, BTreeSet};

#[derive(Default, Serialize, Deserialize)]
pub struct GroupKeeper {
groups: BTreeMap<ContractGroupId, Group>,
pub struct ClusterKeeper {
clusters: BTreeMap<ContractClusterId, Cluster>,
}

impl GroupKeeper {
impl ClusterKeeper {
pub fn instantiate_contract(
&mut self,
group_id: ContractGroupId,
cluster_id: ContractClusterId,
origin: AccountId,
wasm_bin: Vec<u8>,
input_data: Vec<u8>,
Expand All @@ -207,11 +207,10 @@ pub mod group {
block_number: BlockNumber,
now: u64,
) -> Result<ExecSideEffects> {
let group = self
.get_group_or_default_mut(&group_id, contract_key);
let cluster = self.get_cluster_or_default_mut(&cluster_id, contract_key);
let (_, effects) = Pink::instantiate(
group_id,
&mut group.storage,
cluster_id,
&mut cluster.storage,
origin,
wasm_bin,
input_data,
Expand All @@ -222,49 +221,51 @@ pub mod group {
Ok(effects)
}

pub fn get_group_storage_mut(
pub fn get_cluster_storage_mut(
&mut self,
group_id: &ContractGroupId,
cluster_id: &ContractClusterId,
) -> Option<&mut pink::Storage> {
Some(&mut self.groups.get_mut(group_id)?.storage)
Some(&mut self.clusters.get_mut(cluster_id)?.storage)
}

pub fn get_group_mut(&mut self, group_id: &ContractGroupId) -> Option<&mut Group> {
self.groups.get_mut(group_id)
pub fn get_cluster_mut(&mut self, cluster_id: &ContractClusterId) -> Option<&mut Cluster> {
self.clusters.get_mut(cluster_id)
}

pub fn get_group_or_default_mut(
pub fn get_cluster_or_default_mut(
&mut self,
group_id: &ContractGroupId,
cluster_id: &ContractClusterId,
contract_key: &sr25519::Pair,
) -> &mut Group {
self.groups
.entry(group_id.clone())
.or_insert_with(|| Group {
) -> &mut Cluster {
self.clusters.entry(cluster_id.clone()).or_insert_with(|| {
let mut cluster = Cluster {
storage: Default::default(),
contracts: Default::default(),
key: contract_key.clone(),
})
};
cluster.set_id(cluster_id);
cluster
})
}

pub fn commit_changes(&mut self) -> anyhow::Result<()> {
for group in self.groups.values_mut() {
group.commit_changes()?;
for cluster in self.clusters.values_mut() {
cluster.commit_changes()?;
}
Ok(())
}
}

#[derive(Serialize, Deserialize)]
pub struct Group {
pub struct Cluster {
pub storage: pink::Storage,
contracts: BTreeSet<ContractId>,
#[serde(with = "more::key_bytes")]
key: sr25519::Pair,
}

impl Group {
/// Add a new contract to the group. Returns true if the contract is new.
impl 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)
}
Expand All @@ -277,5 +278,9 @@ pub mod group {
self.storage.commit_changes();
Ok(())
}

pub fn set_id(&mut self, id: &ContractClusterId) {
self.storage.set_cluster_id(id.as_bytes());
}
}
}
55 changes: 23 additions & 32 deletions crates/phactory/src/contracts/support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@ use phala_mq::traits::MessageChannel;
use runtime::BlockNumber;
use serde::{Deserialize, Serialize};

use super::pink::group::GroupKeeper;
use super::pink::cluster::ClusterKeeper;
use super::*;
use crate::secret_channel::SecretReceiver;
use crate::types::BlockInfo;
use phala_serde_more as more;

pub struct ExecuteEnv<'a, 'b> {
pub block: &'a mut BlockInfo<'b>,
pub contract_groups: &'a mut GroupKeeper,
pub contract_clusters: &'a mut ClusterKeeper,
}

pub struct NativeContext<'a, 'b> {
pub block: &'a mut BlockInfo<'b>,
pub mq: &'a SignedMessageChannel,
pub secret_mq: SecretMessageChannel<'a, SignedMessageChannel>,
pub contract_groups: &'a mut GroupKeeper,
pub contract_clusters: &'a mut ClusterKeeper,
pub self_id: ContractId,
}

pub struct QueryContext<'a> {
pub block_number: BlockNumber,
pub now_ms: u64,
pub contract_groups: &'a mut GroupKeeper,
pub contract_clusters: &'a mut ClusterKeeper,
}

impl NativeContext<'_, '_> {
Expand All @@ -42,7 +42,7 @@ pub trait Contract {
req: OpaqueQuery,
context: &mut QueryContext,
) -> Result<OpaqueReply, OpaqueError>;
fn group_id(&self) -> phala_mq::ContractGroupId;
fn cluster_id(&self) -> phala_mq::ContractClusterId;
fn process_next_message(&mut self, env: &mut ExecuteEnv) -> Option<TransactionResult>;
fn on_block_end(&mut self, env: &mut ExecuteEnv) -> TransactionResult;
fn push_message(&self, payload: Vec<u8>, topic: Vec<u8>);
Expand All @@ -55,23 +55,8 @@ pub trait Contract {
fn set_on_block_end_selector(&mut self, selector: u32);
}

#[derive(Encode, Decode, Clone, Debug, Copy, derive_more::From)]
pub struct NativeContractId(sp_core::H256);

impl From<&[u8; 32]> for NativeContractId {
fn from(bytes: &[u8; 32]) -> Self {
NativeContractId(bytes.into())
}
}

impl NativeContractId {
pub fn to_contract_id(&self, group_id: &phala_mq::ContractGroupId) -> phala_mq::ContractId {
sp_core::blake2_256(&(group_id, &self.0).encode()).into()
}
}

pub trait NativeContractMore {
fn id(&self) -> NativeContractId;
fn id(&self) -> phala_mq::ContractId;
fn set_on_block_end_selector(&mut self, _selector: u32) {}
}

Expand Down Expand Up @@ -106,8 +91,14 @@ pub struct NativeContractWrapper<Con> {
}

impl<Con> NativeContractWrapper<Con> {
pub fn new(inner: Con, deployer: sp_core::H256, salt: &[u8], id: u32) -> Self {
let encoded = (deployer, id, salt).encode();
pub fn new(
inner: Con,
cluster_id: &phala_mq::ContractClusterId,
deployer: sp_core::H256,
salt: &[u8],
id: u32,
) -> Self {
let encoded = (deployer, id, cluster_id, salt).encode();
let id = sp_core::blake2_256(&encoded).into();
NativeContractWrapper { inner, id }
}
Expand Down Expand Up @@ -142,8 +133,8 @@ impl<Con: NativeContract> NativeContract for NativeContractWrapper<Con> {
}

impl<Con: NativeContract> NativeContractMore for NativeContractWrapper<Con> {
fn id(&self) -> NativeContractId {
self.id.into()
fn id(&self) -> phala_mq::ContractId {
self.id
}
}

Expand All @@ -156,7 +147,7 @@ pub struct NativeCompatContract<Con: NativeContract> {
cmd_rcv_mq: SecretReceiver<Con::Cmd>,
#[serde(with = "crate::secret_channel::ecdh_serde")]
ecdh_key: KeyPair,
group_id: phala_mq::ContractGroupId,
cluster_id: phala_mq::ContractClusterId,
contract_id: phala_mq::ContractId,
}

Expand All @@ -166,15 +157,15 @@ impl<Con: NativeContract> NativeCompatContract<Con> {
send_mq: SignedMessageChannel,
cmd_rcv_mq: SecretReceiver<Con::Cmd>,
ecdh_key: KeyPair,
group_id: phala_mq::ContractGroupId,
cluster_id: phala_mq::ContractClusterId,
contract_id: phala_mq::ContractId,
) -> Self {
NativeCompatContract {
contract,
send_mq,
cmd_rcv_mq,
ecdh_key,
group_id,
cluster_id,
contract_id,
}
}
Expand All @@ -185,8 +176,8 @@ impl<Con: NativeContract + NativeContractMore> Contract for NativeCompatContract
self.contract_id
}

fn group_id(&self) -> phala_mq::ContractGroupId {
self.group_id
fn cluster_id(&self) -> phala_mq::ContractClusterId {
self.cluster_id
}

fn handle_query(
Expand All @@ -208,7 +199,7 @@ impl<Con: NativeContract + NativeContractMore> Contract for NativeCompatContract
block: env.block,
mq: &self.send_mq,
secret_mq,
contract_groups: &mut env.contract_groups,
contract_clusters: &mut env.contract_clusters,
self_id: self.id(),
};

Expand All @@ -231,7 +222,7 @@ impl<Con: NativeContract + NativeContractMore> Contract for NativeCompatContract
block: env.block,
mq: &self.send_mq,
secret_mq,
contract_groups: &mut env.contract_groups,
contract_clusters: &mut env.contract_clusters,
self_id: self.id(),
};
self.contract.on_block_end(&mut context)
Expand Down
Loading

0 comments on commit d0ff13b

Please sign in to comment.