#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::vec::Vec;
use ink_env::{emit_event, topics::state::HasRemainingTopics, Environment, Topics};
use ink_lang::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 predefined_accounts {
use ink_env;
pub const ACCOUNT_PALLET: [u8; 32] = *b"sys::pellet\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
pub fn is_pallet(account_id: &ink_env::AccountId) -> bool {
account_id.as_ref() as &[u8] == &ACCOUNT_PALLET
}
}
const PINK_EVENT_TOPIC: &[u8] = b"phala.pink.event";
pub type EcdhPublicKey = [u8; 32];
pub type Hash = [u8; 32];
#[derive(Encode, Decode, Debug)]
pub struct Message {
pub payload: Vec<u8>,
pub topic: Vec<u8>,
}
#[derive(Encode, Decode, Debug)]
pub struct OspMessage {
pub message: Message,
pub remote_pubkey: Option<EcdhPublicKey>,
}
#[derive(Encode, Decode, Debug)]
pub enum PinkEvent {
Message(Message),
OspMessage(OspMessage),
OnBlockEndSelector(u32),
StartSidevm {
code_hash: Hash,
auto_restart: bool,
},
SidevmMessage(Vec<u8>),
CacheOp(CacheOp),
StopSidevm,
}
impl PinkEvent {
pub fn allowed_in_query(&self) -> bool {
matches!(
self,
PinkEvent::StartSidevm { .. }
| PinkEvent::SidevmMessage(_)
| PinkEvent::CacheOp(_)
| PinkEvent::StopSidevm
)
}
}
#[derive(Encode, Decode, Debug)]
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::OnBlockEndSelector(0));
let topic: &[u8] = topics[0].as_ref();
Hash::try_from(topic).expect("Should not failed")
}
}
pub fn push_message(payload: Vec<u8>, topic: Vec<u8>) {
emit_event::<PinkEnvironment, _>(PinkEvent::Message(Message { payload, topic }))
}
pub fn push_osp_message(payload: Vec<u8>, topic: Vec<u8>, remote_pubkey: Option<EcdhPublicKey>) {
emit_event::<PinkEnvironment, _>(PinkEvent::OspMessage(OspMessage {
message: Message { payload, topic },
remote_pubkey,
}))
}
pub fn set_on_block_end_selector(selector: u32) {
emit_event::<PinkEnvironment, _>(PinkEvent::OnBlockEndSelector(selector))
}
pub fn start_sidevm(code_hash: Hash, auto_restart: bool) {
emit_event::<PinkEnvironment, _>(PinkEvent::StartSidevm {
code_hash,
auto_restart,
})
}
pub fn force_stop_sidevm() {
emit_event::<PinkEnvironment, _>(PinkEvent::StopSidevm)
}
pub fn push_sidevm_message(message: Vec<u8>) {
emit_event::<PinkEnvironment, _>(PinkEvent::SidevmMessage(message))
}
#[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());
}
}