#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))]
extern crate alloc;
use alloc::vec::Vec;
use ink::env::{emit_event, topics::state::HasRemainingTopics, Environment, Topics};
use ink::EnvAccess;
use scale::{Decode, Encode};
pub use pink_extension_macro::contract;
pub mod chain_extension;
pub use chain_extension::pink_extension_instance as ext;
pub mod logger;
pub mod system;
#[cfg(all(not(feature = "std"), feature = "dlmalloc"))]
mod allocator_dlmalloc;
pub use logger::ResultExt;
const PINK_EVENT_TOPIC: &[u8] = b"phala.pink.event";
pub type EcdhPublicKey = [u8; 32];
pub type Hash = [u8; 32];
pub type EcdsaPublicKey = [u8; 33];
pub type EcdsaSignature = [u8; 65];
pub type AccountId = <PinkEnvironment as Environment>::AccountId;
pub type Balance = <PinkEnvironment as Environment>::Balance;
pub type BlockNumber = <PinkEnvironment as Environment>::BlockNumber;
pub trait ConvertTo<To> {
fn convert_to(&self) -> To;
}
impl<F, T> ConvertTo<T> for F
where
F: AsRef<[u8; 32]>,
T: From<[u8; 32]>,
{
fn convert_to(&self) -> T {
(*self.as_ref()).into()
}
}
#[derive(Encode, Decode, Debug)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub struct Message {
pub payload: Vec<u8>,
pub topic: Vec<u8>,
}
#[derive(Encode, Decode, Debug)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub struct OspMessage {
pub message: Message,
pub remote_pubkey: Option<EcdhPublicKey>,
}
#[derive(Encode, Decode, Debug, Clone)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum HookPoint {
OnBlockEnd,
}
#[derive(Encode, Decode, Debug, Clone)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum PinkEvent {
#[codec(index = 2)]
SetHook {
hook: HookPoint,
contract: AccountId,
selector: u32,
gas_limit: u64,
},
#[codec(index = 3)]
DeploySidevmTo {
contract: AccountId,
code_hash: Hash,
},
#[codec(index = 4)]
SidevmMessage(Vec<u8>),
#[codec(index = 5)]
CacheOp(CacheOp),
#[codec(index = 6)]
StopSidevm,
#[codec(index = 7)]
ForceStopSidevm {
contract: AccountId,
},
#[codec(index = 8)]
SetLogHandler(AccountId),
#[codec(index = 9)]
SetContractWeight { contract: AccountId, weight: u32 },
#[codec(index = 10)]
UpgradeRuntimeTo { version: (u32, u32) },
}
impl PinkEvent {
pub fn allowed_in_query(&self) -> bool {
match self {
PinkEvent::SetHook { .. } => false,
PinkEvent::DeploySidevmTo { .. } => true,
PinkEvent::SidevmMessage(_) => true,
PinkEvent::CacheOp(_) => true,
PinkEvent::StopSidevm => true,
PinkEvent::ForceStopSidevm { .. } => true,
PinkEvent::SetLogHandler(_) => false,
PinkEvent::SetContractWeight { .. } => false,
PinkEvent::UpgradeRuntimeTo { .. } => false,
}
}
pub fn name(&self) -> &'static str {
match self {
PinkEvent::SetHook { .. } => "SetHook",
PinkEvent::DeploySidevmTo { .. } => "DeploySidevmTo",
PinkEvent::SidevmMessage(_) => "SidevmMessage",
PinkEvent::CacheOp(_) => "CacheOp",
PinkEvent::StopSidevm => "StopSidevm",
PinkEvent::ForceStopSidevm { .. } => "ForceStopSidevm",
PinkEvent::SetLogHandler(_) => "SetLogHandler",
PinkEvent::SetContractWeight { .. } => "SetContractWeight",
PinkEvent::UpgradeRuntimeTo { .. } => "UpgradeRuntimeTo",
}
}
}
#[derive(Encode, Decode, Debug, Clone)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum CacheOp {
Set { key: Vec<u8>, value: Vec<u8> },
SetExpiration { key: Vec<u8>, expiration: u64 },
Remove { key: Vec<u8> },
}
impl Topics for PinkEvent {
type RemainingTopics = [HasRemainingTopics; 1];
fn topics<E, B>(
&self,
builder: ink::env::topics::TopicsBuilder<ink::env::topics::state::Uninit, E, B>,
) -> <B as ink::env::topics::TopicsBuilderBackend<E>>::Output
where
E: Environment,
B: ink::env::topics::TopicsBuilderBackend<E>,
{
builder
.build::<Self>()
.push_topic(&PINK_EVENT_TOPIC)
.finish()
}
}
#[cfg(feature = "runtime_utils")]
impl PinkEvent {
pub fn event_topic() -> Hash {
use std::convert::TryFrom;
let topics = topic::topics_for(Self::StopSidevm);
let topic: &[u8] = topics[0].as_ref();
Hash::try_from(topic).expect("Should not failed")
}
}
pub fn set_hook(hook: HookPoint, contract: AccountId, selector: u32, gas_limit: u64) {
emit_event::<PinkEnvironment, _>(PinkEvent::SetHook {
hook,
contract,
selector,
gas_limit,
})
}
pub fn start_sidevm(code_hash: Hash) -> Result<(), system::DriverError> {
let driver =
crate::system::SidevmOperationRef::instance().ok_or(system::Error::DriverNotFound)?;
driver.deploy(code_hash)
}
pub fn deploy_sidevm_to(contract: AccountId, code_hash: Hash) {
emit_event::<PinkEnvironment, _>(PinkEvent::DeploySidevmTo {
contract,
code_hash,
});
}
pub fn stop_sidevm_at(contract: AccountId) {
emit_event::<PinkEnvironment, _>(PinkEvent::ForceStopSidevm { contract });
}
pub fn force_stop_sidevm() {
emit_event::<PinkEnvironment, _>(PinkEvent::StopSidevm)
}
pub fn push_sidevm_message(message: Vec<u8>) {
emit_event::<PinkEnvironment, _>(PinkEvent::SidevmMessage(message))
}
pub fn set_log_handler(contract: AccountId) {
emit_event::<PinkEnvironment, _>(PinkEvent::SetLogHandler(contract))
}
pub fn set_contract_weight(contract: AccountId, weight: u32) {
emit_event::<PinkEnvironment, _>(PinkEvent::SetContractWeight { contract, weight });
}
pub fn upgrade_runtime(version: (u32, u32)) {
emit_event::<PinkEnvironment, _>(PinkEvent::UpgradeRuntimeTo { version });
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum PinkEnvironment {}
impl Environment for PinkEnvironment {
const MAX_EVENT_TOPICS: usize = <ink::env::DefaultEnvironment as Environment>::MAX_EVENT_TOPICS;
type AccountId = <ink::env::DefaultEnvironment as Environment>::AccountId;
type Balance = <ink::env::DefaultEnvironment as Environment>::Balance;
type Hash = <ink::env::DefaultEnvironment as Environment>::Hash;
type BlockNumber = <ink::env::DefaultEnvironment as Environment>::BlockNumber;
type Timestamp = <ink::env::DefaultEnvironment as Environment>::Timestamp;
type ChainExtension = chain_extension::PinkExt;
}
pub fn env() -> EnvAccess<'static, PinkEnvironment> {
Default::default()
}
#[cfg(feature = "runtime_utils")]
mod topic;
#[cfg(test)]
mod tests {
#[test]
fn test_event_topics() {
insta::assert_debug_snapshot!(super::PinkEvent::event_topic());
}
}