-
Notifications
You must be signed in to change notification settings - Fork 151
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: mq egress & discover ink instantiated contracts #538
Changes from 15 commits
17b1df6
6d3cc1b
f82cd58
8eca489
9a7e540
cd1c260
a8a4202
e38ed21
c4ab0f9
96344b3
684a2b5
235ab92
786438f
a56a51d
dcd0b34
6657610
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,7 +124,7 @@ impl contracts::NativeContract for Geolocation { | |
); | ||
}; | ||
|
||
Ok(()) | ||
Ok(Default::default()) | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,11 @@ fn account_id_from_hex(s: &str) -> Result<AccountId> { | |
|
||
pub use support::*; | ||
mod support { | ||
use phala_crypto::ecdh::EcdhPublicKey; | ||
use phala_mq::traits::MessageChannel; | ||
use ::pink::runtime::ExecSideEffects; | ||
use runtime::BlockNumber; | ||
|
||
use super::pink::group::GroupKeeper; | ||
use super::*; | ||
use crate::types::BlockInfo; | ||
|
@@ -42,13 +47,14 @@ mod support { | |
|
||
pub struct NativeContext<'a> { | ||
pub block: &'a BlockInfo<'a>, | ||
mq: &'a SignedMessageChannel, | ||
#[allow(unused)] // TODO.kevin: remove this. | ||
secret_mq: SecretMessageChannel<'a, SignedMessageChannel>, | ||
pub mq: &'a SignedMessageChannel, | ||
pub secret_mq: SecretMessageChannel<'a, SignedMessageChannel>, | ||
pub contract_groups: &'a mut GroupKeeper, | ||
} | ||
|
||
pub struct QueryContext<'a> { | ||
pub block_number: BlockNumber, | ||
pub now_ms: u64, | ||
pub contract_groups: &'a mut GroupKeeper, | ||
} | ||
|
||
|
@@ -66,7 +72,16 @@ mod support { | |
req: OpaqueQuery, | ||
context: &mut QueryContext, | ||
) -> Result<OpaqueReply, OpaqueError>; | ||
fn process_messages(&mut self, env: &mut ExecuteEnv); | ||
fn group_id(&self) -> Option<phala_mq::ContractGroupId>; | ||
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>); | ||
fn push_osp_message( | ||
&self, | ||
payload: Vec<u8>, | ||
topic: Vec<u8>, | ||
remote_pubkey: Option<&EcdhPublicKey>, | ||
); | ||
} | ||
|
||
pub trait NativeContract { | ||
|
@@ -75,13 +90,16 @@ mod support { | |
type QResp: Encode + Debug; | ||
|
||
fn id(&self) -> ContractId; | ||
fn group_id(&self) -> Option<phala_mq::ContractGroupId> { | ||
None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to assign the native contract to a special group id to simplify the logic elsewhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. But if we treat the native contract the same as pink, I think there will be more tricky things to be handle, such as state handling. It will be more error-prone. |
||
} | ||
fn handle_command( | ||
&mut self, | ||
_origin: MessageOrigin, | ||
_cmd: Self::Cmd, | ||
_context: &mut NativeContext, | ||
) -> TransactionResult { | ||
Ok(()) | ||
Ok(Default::default()) | ||
} | ||
fn handle_query( | ||
&mut self, | ||
|
@@ -148,45 +166,71 @@ mod support { | |
self.contract.id() | ||
} | ||
|
||
fn group_id(&self) -> Option<phala_mq::ContractGroupId> { | ||
self.contract.group_id() | ||
} | ||
|
||
fn handle_query( | ||
&mut self, | ||
origin: Option<&runtime::AccountId>, | ||
req: OpaqueQuery, | ||
context: &mut QueryContext, | ||
) -> Result<OpaqueReply, OpaqueError> { | ||
debug!(target: "contract", "Contract {:?} handling query", self.id()); | ||
let response = self | ||
.contract | ||
.handle_query(origin, deopaque_query(req)?, context); | ||
Ok(response.encode()) | ||
} | ||
|
||
fn process_messages(&mut self, env: &mut ExecuteEnv) { | ||
fn process_next_message(&mut self, env: &mut ExecuteEnv) -> Option<TransactionResult> { | ||
let secret_mq = SecretMessageChannel::new(&self.ecdh_key, &self.send_mq); | ||
let mut context = NativeContext { | ||
block: env.block, | ||
mq: &self.send_mq, | ||
secret_mq, | ||
contract_groups: &mut env.contract_groups, | ||
}; | ||
loop { | ||
let ok = phala_mq::select! { | ||
next_cmd = self.cmd_rcv_mq => match next_cmd { | ||
Ok((_, cmd, origin)) => { | ||
let status = self.contract.handle_command(origin, cmd, &mut context); | ||
if let Err(err) = status { | ||
log::error!("Contract {:?} handle command error: {:?}", self.id(), err); | ||
} | ||
} | ||
Err(e) => { | ||
error!("Read command failed [{}]: {:?}", self.id(), e); | ||
} | ||
}, | ||
}; | ||
if ok.is_none() { | ||
break; | ||
} | ||
|
||
phala_mq::select! { | ||
next_cmd = self.cmd_rcv_mq => match next_cmd { | ||
Ok((_, cmd, origin)) => { | ||
info!(target: "contract", "Contract {:?} handling command", self.id()); | ||
self.contract.handle_command(origin, cmd, &mut context) | ||
} | ||
Err(e) => { | ||
Err(TransactionError::ChannelError) | ||
} | ||
}, | ||
} | ||
self.contract.on_block_end(&mut context) | ||
} | ||
|
||
fn on_block_end(&mut self, env: &mut ExecuteEnv) -> TransactionResult { | ||
let secret_mq = SecretMessageChannel::new(&self.ecdh_key, &self.send_mq); | ||
let mut context = NativeContext { | ||
block: env.block, | ||
mq: &self.send_mq, | ||
secret_mq, | ||
contract_groups: &mut env.contract_groups, | ||
}; | ||
self.contract.on_block_end(&mut context); | ||
Ok(Default::default()) | ||
} | ||
|
||
fn push_message(&self, payload: Vec<u8>, topic: Vec<u8>) { | ||
self.send_mq.push_data(payload, topic) | ||
} | ||
|
||
fn push_osp_message( | ||
&self, | ||
payload: Vec<u8>, | ||
topic: Vec<u8>, | ||
remote_pubkey: Option<&EcdhPublicKey>, | ||
) { | ||
let secret_mq = SecretMessageChannel::new(&self.ecdh_key, &self.send_mq); | ||
secret_mq | ||
.bind_remote_key(remote_pubkey) | ||
.push_data(payload, topic) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When does
groupd_id
return None?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
native contracts return None