Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

pink: Use customized ink address as contract id #610

Merged
merged 7 commits into from
Dec 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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