From 2bde2d219289913bdf8729b6403d02983406058d Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 29 Jun 2023 02:14:07 +0000 Subject: [PATCH 1/9] Enrich the doc comments --- crates/pink/pink-extension/README.md | 68 ++- .../macro/src/chain_extension.rs | 4 +- crates/pink/pink-extension/macro/src/lib.rs | 55 ++- .../pink-extension/src/chain_extension.rs | 440 +++++++++++++++++- .../src/chain_extension/http_request.rs | 16 +- crates/pink/pink-extension/src/lib.rs | 140 +++++- 6 files changed, 671 insertions(+), 52 deletions(-) diff --git a/crates/pink/pink-extension/README.md b/crates/pink/pink-extension/README.md index 1b676e55c0..1f9914ef26 100644 --- a/crates/pink/pink-extension/README.md +++ b/crates/pink/pink-extension/README.md @@ -1,11 +1,65 @@ -

- Phala's ink! for writing phat contracts -

+

Phala's ink! - Writing Enhanced Smart Contracts

-pink! is based on Parity's ink! language and provide some extra functionality to interact with phala's phat contract runtime. +Pink! is a smart contract language based on Parity's `ink!`. It extends the basic functionality with additional features, tailored to interact efficiently with Phala's Phat Contract runtime. -# Getting started +## Getting Started -The orignal `ink!` contract can run under Phala's phat contract platform without any modifacation. So you can follow Parity's `ink!` [documentation](https://paritytech.github.io/ink-docs/) to get started. +Unaltered `ink!` contracts are fully compatible and executable on the Phala's Phat Contract platform. To learn how to start writing contracts with `ink!`, follow the Parity's [ink! documentation](https://paritytech.github.io/ink-docs/). -If you want to use phat contract's specific features, such as phala-mq message, HTTP requests, you can use `pink_extension` to achieve this. See [examples](https://github.com/Phala-Network/phala-blockchain/tree/master/crates/pink/examples) for more detail. +To get started with Pink!, add the following dependency to your `Cargo.toml`: + +```toml +[dependencies] +ink = { version = "4", default-features = false } +pink = { package = "pink-extension", version = "0.4", default-features = false } + +[features] +std = [ + "ink/std", + "pink/std", +] +``` + +Then, you can use the `http_get!` macro to make a GET request to a remote server: + +```rust +#[ink::message] +fn http_get_example(&self) { + let response = pink::http_get!("https://httpbin.org/get"); + assert_eq!(response.status_code, 200); +} +``` + +## Phat Contract-Specific Features + +The Pink! crate is designed to empower you, enabling you to leverage the unique features of the Phat Contract, such as making HTTP requests as demonstrated in our examples. This crate supplies the crucial types and functions needed to seamlessly interact with the Phat Contract runtime. + +There two kind of APIs to communication with the runtime: + +- Emitting Events: + These APIs are primarily used in situations where the operation could lead to side effects that need to be deterministically recorded and may be rolled back during the execution of the contract call. For additional information on Emitting Events APIs, please refer to the [PinkEvent documentation](crate::PinkEvent). + +- Chain Extension: + These APIs are predominantly used for read-only operations or operations that aren't expected to create deterministic side effects. For an in-depth understanding of Chain Extension APIs, please refer to the [PinkExt documentation](crate::chain_extension::PinkExtBackend). + +For practical implementation examples, explore our [Phat Contract examples](https://github.com/Phala-Network/phat-contract-examples) repository. + +## Using JavaScript with Phat Contract + +Phat Contract supports JavaScript through the [phat-quickjs](https://github.com/Phala-Network/phat-quickjs) contract. + +There are two ways to use JavaScript in your contract: + +- You can deploy your phat-quickjs contract instance through a standard deployment process. + +- However, for a more convenient approach, most public clusters should already have a public driver quickjs contract deployed. You can obtain the contract code_hash with `System::get_driver("JsDelegate")`. + +- For the simplest integration, consider using the [`phat_js`](https://docs.rs/phat_js/) crate. It provides an `eval` function that lets you evaluate JavaScript code snippets directly. + For example: + ```rust + #[ink::message] + fn eval_js_example(&self) { + let result = phat_js::eval("'Hello,' + 'World'", &[]); + assert_eq!(result, phat_js::Output::String("Hello,World".to_string())); + } + ``` diff --git a/crates/pink/pink-extension/macro/src/chain_extension.rs b/crates/pink/pink-extension/macro/src/chain_extension.rs index 46e2114c4e..6f882c7715 100644 --- a/crates/pink/pink-extension/macro/src/chain_extension.rs +++ b/crates/pink/pink-extension/macro/src/chain_extension.rs @@ -50,7 +50,9 @@ fn patch_chain_extension_or_err(input: TokenStream2) -> Result { for item in item_trait.items.iter_mut() { if let syn::TraitItem::Fn(item_method) = item { - item_method.attrs.clear(); + item_method + .attrs + .retain(|attr| !attr.path().is_ident("ink")); // Turn &[u8] into Cow<[u8]> for input in item_method.sig.inputs.iter_mut() { diff --git a/crates/pink/pink-extension/macro/src/lib.rs b/crates/pink/pink-extension/macro/src/lib.rs index 759c806b70..1a6427c4e1 100644 --- a/crates/pink/pink-extension/macro/src/lib.rs +++ b/crates/pink/pink-extension/macro/src/lib.rs @@ -27,7 +27,7 @@ pub fn chain_extension(_: TokenStream, input: TokenStream) -> TokenStream { output.into() } -/// Mark an ink trait as pink's system contract +/// Mark an ink trait as pink's system contract. Internal use only. #[proc_macro_attribute] pub fn system(arg: TokenStream, input: TokenStream) -> TokenStream { let config = parse_macro_input!(arg as TokenStream2); @@ -36,7 +36,58 @@ pub fn system(arg: TokenStream, input: TokenStream) -> TokenStream { module.into() } -/// Mark an ink trait as pink's driver contract +/// This procedural macro marks an ink! trait as a 'driver contract' for the Pink system. +/// +/// # What is the driver system? +/// +/// The driver system is a straightforward concept. In the Pink system, there is a registry mapping driver names +/// to driver contract addresses. The System contract provides two methods to manage this registry: +/// `System::set_driver(driver_name, contract_address)` and `System::get_driver(driver_name)`. +/// +/// # How does this macro work? +/// +/// When this attribute is used, it modifies the given trait to be utilized as a driver contract +/// within the Pink system. This is achieved by adding a new type, TraitNameRef, which implements +/// the marked trait and provides a static method `instance()` to retrieve an instance of the driver. +/// +/// # Example +/// +/// Below, the `SidevmOperation` trait is annotated with `#[pink::driver]`. This marks it +/// as a driver contract, enabling it to manage SideVM deployments. +/// +/// ```rust +/// #[pink::driver] +/// #[ink::trait_definition] +/// pub trait SidevmOperation { +/// #[ink(message)] +/// fn deploy(&self, code_hash: Hash) -> Result<(), DriverError>; +/// +/// #[ink(message)] +/// fn can_deploy(&self, contract_id: AccountId) -> bool; +/// } +/// ``` +/// +/// Once a trait has been defined as a driver using this macro, it can be set as a driver +/// by invoking the `System::set_driver(driver_name, contract_address)` method. +/// +/// # Usage +/// +/// The actual driver can then be retrieved and its methods, defined by the trait, can be used. +/// For instance, to start a SideVM, one would get the driver instance and call its `deploy` method: +/// +/// ```rust +/// pub fn start_sidevm(code_hash: Hash) -> Result<(), system::DriverError> { +/// let driver = +/// SidevmOperationRef::instance().ok_or(system::Error::DriverNotFound)?; +/// driver.deploy(code_hash) +/// } +/// ``` +/// +/// Here, `SidevmOperationRef::instance()` retrieves an instance of the driver contract for "SidevmOperation", +/// and then the `deploy` method of the driver is invoked to deploy a SideVM instance. +/// Internally, `SidevmOperationRef::instance()` retrieves the driver contract by invoking `System::get_driver("SidevmOperation")`. +/// +/// Note: The name of the driver contract instance (e.g., "SidevmOperation") is generated by the macro. #[proc_macro_attribute] pub fn driver(arg: TokenStream, input: TokenStream) -> TokenStream { let config = parse_macro_input!(arg as TokenStream2); diff --git a/crates/pink/pink-extension/src/chain_extension.rs b/crates/pink/pink-extension/src/chain_extension.rs index 4a490c9db3..b925e4e96d 100644 --- a/crates/pink/pink-extension/src/chain_extension.rs +++ b/crates/pink/pink-extension/src/chain_extension.rs @@ -104,105 +104,505 @@ pub type BatchHttpResult = Result>, H pub trait PinkExt { type ErrorCode = ErrorCode; + /// Make a HTTP request. + /// + /// # Arguments + /// + /// * `request`: A `HttpRequest` struct containing all the details for the HTTP request. + /// + /// # Returns + /// + /// * `HttpResponse` - The response from the HTTP request which contains the status code, headers, and body. + /// + /// # Example + /// + /// ``` + /// let request = HttpRequest::new("https://httpbin.org/get", "GET", Defualt::default(), Defualt::default()); + /// let response = pink::ext().http_request(request); + /// ``` + /// + /// There are also some shortcut macros for this function: + /// - [`crate::http_get!`] + /// - [`crate::http_post!`] + /// - [`crate::http_put!`] + /// + /// # Availability + /// any contract | query only #[ink(extension = 1, handle_status = false)] fn http_request(request: HttpRequest) -> HttpResponse; + /// Sign a message with a given key. + /// + /// # Arguments + /// + /// * `sigtype`: The signature type to use for signing the message. + /// * `key`: The private key used for signing the message. + /// * `message`: The message to be signed. + /// + /// # Returns + /// + /// * `Vec` - The signed message as a byte vector. + /// + /// # Example + /// + /// ``` + /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); + /// let message = b"Hello, world!"; + /// let signature = pink::ext().sign(SigType::Sr25519, &key, message); + /// let pubkey = pink::ext().get_public_key(SigType::Sr25519, &derived_key); + /// let is_valid = pink::ext().verify(SigType::Sr25519, &pubkey, message, &signature); + /// ``` + /// + /// # Availability + /// For SigType::Sr25519: + /// any contract | query only + /// + /// For Others: + /// any contract | query | transaction #[ink(extension = 2, handle_status = false)] fn sign(sigtype: SigType, key: &[u8], message: &[u8]) -> Vec; + /// Verify a signature. + /// + /// This method verifies a digital signature given the signature type, public key, message, and signature. + /// + /// # Arguments + /// + /// * `sigtype`: The type of signature to verify. + /// * `pubkey`: The public key associated with the private key that signed the message. + /// * `message`: The original message that was signed. + /// * `signature`: The digital signature to verify. + /// + /// # Returns + /// + /// * `bool` - `true` if the signature is valid, `false` otherwise. + /// + /// # Example + /// + /// ``` + /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); + /// let message = b"Hello, world!"; + /// let signature = pink::ext().sign(SigType::Sr25519, &key, message); + /// let pubkey = pink::ext().get_public_key(SigType::Sr25519, &derived_key); + /// let is_valid = pink::ext().verify(SigType::Sr25519, &pubkey, message, &signature); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 3, handle_status = false)] fn verify(sigtype: SigType, pubkey: &[u8], message: &[u8], signature: &[u8]) -> bool; + /// Derive a sr25519 key. + /// + /// This method derives a sr25519 key using the provided salt and the contract private key. + /// The derived key is deterministic so it could be used in transactions to sign messages. + /// + /// # Arguments + /// + /// * `salt`: The salt to use in the key derivation function. + /// + /// # Returns + /// + /// * `Vec` - The derived sr25519 key as a byte vector. + /// + /// # Example + /// + /// ``` + /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 4, handle_status = false)] fn derive_sr25519_key(salt: Cow<[u8]>) -> Vec; + /// Get the public key associated with a private key. + /// + /// This method takes a signature type and private key and returns the associated public key. + /// + /// # Arguments + /// + /// * `sigtype`: The type of signature to generate the public key for. + /// * `key`: The private key used to generate the public key. + /// + /// # Returns + /// + /// * `Vec` - The public key associated with the given private key as a byte vector. + /// + /// # Example + /// + /// ``` + /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); + /// let pubkey = pink::ext().get_public_key(SigType::Sr25519, &derived_key); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 5, handle_status = false)] fn get_public_key(sigtype: SigType, key: &[u8]) -> Vec; /// Set a value in the local cache. /// - /// The default expiration time is 7 days. Use `cache_set_expiration` to set a custom expiration - /// time. + /// This method sets a value in the local cache with the default expiration time of 7 days. + /// To set a custom expiration time, use `cache_set_expiration`. /// Values stored in cache can only be read in query functions. + /// Always returns `Ok(())` if it is called from a transaction context. + /// + /// # Arguments + /// + /// * `key`: The key used to identify the value in the cache. + /// * `value`: The value to be stored in the cache. + /// + /// # Returns + /// + /// * `Result<(), StorageQuotaExceeded>` - `Ok(())` or `Err(StorageQuotaExceeded)` if the storage quota is exceeded. /// - /// Alwasy returns `Ok(())` if it is called from a command context. + /// # Example + /// + /// ``` + /// let key = b"my key"; + /// let value = b"my value"; + /// let result = pink::ext().cache_set(key, value); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 6, handle_status = true)] fn cache_set(key: &[u8], value: &[u8]) -> Result<(), StorageQuotaExceeded>; /// Set the expiration time of a value in the local cache. /// - /// Arguments: - /// - `key`: The key of the value to set the expiration time for. - /// - `expire`: The expiration time from now in seconds. + /// This method sets the expiration time for a given key in the local cache. + /// + /// # Arguments + /// + /// * `key`: The key of the value to set the expiration time for. + /// * `expire`: The expiration time from now in seconds. + /// + /// # Example + /// + /// ``` + /// let key = b"my key"; + /// let expire = 60; // 1 minute + /// pink::ext().cache_set_expiration(key, expire); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 7, handle_status = false)] fn cache_set_expiration(key: &[u8], expire: u64); /// Get a value from the local cache. /// - /// Only for query functions. Always returns `None` if it is called from a command context. + /// This method retrieves a value from the local cache. It can only be used in query functions. + /// If called from a command context, it will always return `None`. + /// + /// # Arguments + /// + /// * `key`: The key used to identify the value in the cache. + /// + /// # Returns + /// + /// * `Option>` - The value from the cache as a byte vector wrapped in an Option, + /// or `None` if the value does not exist or called in transaction. + /// + /// # Example + /// + /// ``` + /// let key = b"my key"; + /// let value = pink::ext().cache_get(key); + /// ``` + /// + /// # Availability + /// any contract | query #[ink(extension = 8, handle_status = false)] fn cache_get(key: &[u8]) -> Option>; /// Remove a value from the local cache. /// - /// Returns the removed value if it existed. Always returns `None` if it is called from a - /// command context. + /// This method removes a value from the local cache and returns the removed value if it existed. + /// If called from a command context, it will always return `None`. + /// + /// # Arguments + /// + /// * `args`: The key used to identify the value in the cache. + /// + /// # Returns + /// + /// * `Option>` - The removed value as a byte vector wrapped in an Option + /// or `None` if the value did not exist or called in transaction. + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 9, handle_status = false)] fn cache_remove(args: &[u8]) -> Option>; - /// Print log message. + /// Log a message. + /// + /// This method logs a message at a given level. + /// + /// # Arguments + /// + /// * `level`: The level of the log message. + /// * `message`: The message to be logged. + /// + /// # Example + /// + /// ``` + /// let level = 1; + /// let message = "Hello, world!"; + /// pink::ext().log(level, message); + /// ``` + /// + /// # Note + /// This is the low-level method for logging. It is recommended to use shortcuts macros below instead: + /// + /// - [`crate::debug!`] + /// - [`crate::info!`] + /// - [`crate::warn!`] + /// - [`crate::error!`] + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 10, handle_status = false)] fn log(level: u8, message: &str); - /// Get random bytes, for query only + /// Get random bytes. + /// + /// This method generates a vector of random bytes of a given length. It returns random bytes + /// generated by hardware RNG. So it is not deterministic and only available in a query context. + /// + /// # Note + /// It always returns an empty vec![] when called in a transaction. + /// + /// + /// # Arguments + /// + /// * `length`: The length of the random bytes vector. + /// + /// # Returns + /// + /// * `Vec` - A vector of random bytes of the given length. + /// + /// # Example + /// + /// ``` + /// let length = 32; + /// let random_bytes = pink::ext().getrandom(length); + /// ``` + /// + /// # Availability + /// any contract | query only #[ink(extension = 11, handle_status = false)] fn getrandom(length: u8) -> Vec; /// Check if it is running in a Command context. - #[allow(clippy::wrong_self_convention)] + /// + /// # Returns + /// + /// * `bool` - `true` if it is running in a Command context, `false` if in query. + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 12, handle_status = false)] fn is_in_transaction() -> bool; + /// Sign a prehashed message with a given key. + /// + /// This method uses the given key and prehashed message to create a ECDSA signature. + /// + /// # Arguments + /// + /// * `key`: The private key used for signing the message. + /// * `message_hash`: The prehashed message to be signed. + /// + /// # Returns + /// + /// * `EcdsaSignature` - The signature of the message. + /// + /// # Example + /// + /// ``` + /// let key = [0u8; 32]; // replace with actual key + /// let message_hash = Hash::zero(); // replace with actual hash + /// let signature = pink::ext().ecdsa_sign_prehashed(&key, message_hash); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 13, handle_status = false)] fn ecdsa_sign_prehashed(key: &[u8], message_hash: Hash) -> EcdsaSignature; + /// Verify a prehashed ECDSA signature. + /// + /// This method verifies a prehashed ECDSA signature given the signature, prehashed message, and public key. + /// + /// # Arguments + /// + /// * `signature`: The ECDSA digital signature to verify. + /// * `message_hash`: The prehashed original message that was signed. + /// * `pubkey`: The public key associated with the private key that signed the message. + /// + /// # Returns + /// + /// * `bool` - `true` if the signature is valid, `false` otherwise. + /// + /// # Example + /// + /// ``` + /// let signature = EcdsaSignature::default(); // replace with actual signature + /// let message_hash = Hash::zero(); // replace with actual hash + /// let pubkey = EcdsaPublicKey::default(); // replace with actual pubkey + /// let is_valid = pink::ext().ecdsa_verify_prehashed(signature, message_hash, pubkey); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 14, handle_status = false)] fn ecdsa_verify_prehashed( signature: EcdsaSignature, message_hash: Hash, pubkey: EcdsaPublicKey, ) -> bool; - /// Get the contract id of the preinstalled pink-system + + /// Get the contract id of the preinstalled system contract. + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 15, handle_status = false)] fn system_contract_id() -> AccountId; - /// Get (total, free) balance of given contract + /// Get balance of a given contract. + /// + /// # Arguments + /// + /// * `account`: The `AccountId` of the contract. + /// + /// # Returns + /// + /// * `(Balance, Balance)` - The total and free balance of a given contract. + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 16, handle_status = false)] fn balance_of(account: AccountId) -> (Balance, Balance); - /// Get worker public key. Query only. + /// Get the worker public key. + /// + /// # Returns + /// + /// * `crate::EcdhPublicKey` - The public key of the worker. + /// + /// # Availability + /// any contract | query only #[ink(extension = 17, handle_status = false)] fn worker_pubkey() -> crate::EcdhPublicKey; - /// Get current millis since unix epoch from the OS. (Query only) + /// Get current millis since Unix epoch. + /// + /// This method returns the current time as milliseconds since the Unix epoch from the OS. + /// + /// # Returns + /// + /// * `u64` - The current time as milliseconds since the Unix epoch from the OS. + /// + /// # Note + /// Because this method uses the OS time, it is not deterministic and may be manipulated by compromised OS. + /// + /// # Example + /// + /// ``` + /// let current_millis = pink::ext().untrusted_millis_since_unix_epoch(); + /// ``` + /// + /// # Availability + /// any contract | query only #[ink(extension = 18, handle_status = false)] fn untrusted_millis_since_unix_epoch() -> u64; /// Check whether the code exists in the cluster storage. + /// + /// # Returns + /// + /// * `bool` - `true` if the code exists, `false` otherwise. + /// + /// # Example + /// + /// ``` + /// let code_hash = Hash::zero(); // replace with actual code hash + /// let exists = pink::ext().code_exists(code_hash, false); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 19, handle_status = false)] fn code_exists(code_hash: Hash, sidevm: bool) -> bool; - /// This loads the latest system contract code from chain storage to the cluster storage. + /// Import the latest system contract code from chain storage to the cluster storage. + /// + /// # Returns + /// + /// * `Option` - The code hash of the latest system contract code, or `None` if the import failed. + /// + /// # Example + /// + /// ``` + /// let payer = AccountId::default(); // replace with actual payer id + /// let code_hash = pink::ext().import_latest_system_code(payer); + /// ``` /// - /// Returns the code hash of the latest system contract code. + /// # Availability + /// system only | query | transaction #[ink(extension = 20, handle_status = false)] fn import_latest_system_code(payer: AccountId) -> Option; - /// Get the version of the current contract runtime in this cluster. + /// Get the version of the current contract runtime. + /// + /// # Returns + /// + /// * `(u32, u32)` - The version of the current contract runtime in this cluster as a tuple (major, minor). + /// + /// # Example + /// + /// ``` + /// let (major, minor) = pink::ext().runtime_version(); + /// ``` + /// + /// # Availability + /// any contract | query | transaction #[ink(extension = 21, handle_status = false)] fn runtime_version() -> (u32, u32); - /// Batch http request + /// Batch HTTP request. + /// + /// This method sends a batch of HTTP requests with a given timeout and returns the results. + /// + /// # Arguments + /// + /// * `requests`: A vector of `HttpRequest` structs containing all the details for the HTTP requests. + /// * `timeout_ms`: The timeout for the batch request in milliseconds. + /// + /// # Returns + /// + /// * `BatchHttpResult` - A vector of response to eahch HTTP requests. + /// + /// # Example + /// + /// ``` + /// let requests = vec![ + /// HttpRequest::new("https://httpbin.org/get", + /// "GET", + /// Default::default(), + /// Default::default(), + /// ), + /// HttpRequest::new("https://httpbin.org/post", + /// "POST", + /// Default::default(), + /// b"Hello, world!".to_vec(), + /// ), + /// ]; + /// let result = pink::ext().batch_http_request(requests, 5000); + /// ``` #[ink(extension = 22, handle_status = true)] fn batch_http_request(requests: Vec, timeout_ms: u64) -> BatchHttpResult; } diff --git a/crates/pink/pink-extension/src/chain_extension/http_request.rs b/crates/pink/pink-extension/src/chain_extension/http_request.rs index 24cfbe0d04..5b8d706df4 100644 --- a/crates/pink/pink-extension/src/chain_extension/http_request.rs +++ b/crates/pink/pink-extension/src/chain_extension/http_request.rs @@ -126,8 +126,8 @@ macro_rules! http_req { /// Make a simple HTTP GET request /// /// # Arguments -/// url: The URL to GET -/// headers: The headers to send with the request +/// - url: The URL to GET +/// - headers: The headers to send with the request /// /// # Examples /// @@ -156,9 +156,9 @@ macro_rules! http_get { /// Make a simple HTTP POST request /// /// # Arguments -/// url: The URL to POST -/// data: The payload to POST -/// headers: The headers to send with the request +/// - url: The URL to POST +/// - data: The payload to POST +/// - headers: The headers to send with the request /// /// # Examples /// @@ -187,9 +187,9 @@ macro_rules! http_post { /// Make a simple HTTP PUT request /// /// # Arguments -/// url: The destination URL -/// data: The payload to PUT -/// headers: The headers to send with the request +/// - url: The destination URL +/// - data: The payload to PUT +/// - headers: The headers to send with the request /// /// # Examples /// diff --git a/crates/pink/pink-extension/src/lib.rs b/crates/pink/pink-extension/src/lib.rs index 94f90e8433..33f92d0840 100644 --- a/crates/pink/pink-extension/src/lib.rs +++ b/crates/pink/pink-extension/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![doc = include_str!("../README.md")] extern crate alloc; @@ -61,9 +62,11 @@ pub struct OspMessage { pub remote_pubkey: Option, } +/// Hook points defined in the runtime. #[derive(Encode, Decode, Debug, Clone)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum HookPoint { + /// When all events in a block are processed. OnBlockEnd, } @@ -72,6 +75,11 @@ pub enum HookPoint { #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum PinkEvent { /// Set contract hook + /// + /// Please do not use this event directly, use [`set_hook()`] instead. + /// + /// # Availability + /// System contract #[codec(index = 2)] SetHook { /// The event to hook @@ -84,6 +92,11 @@ pub enum PinkEvent { gas_limit: u64, }, /// Deploy a sidevm instance to given contract instance + /// + /// Please do not use this event directly, use [`deploy_sidevm_to()`] instead. + /// + /// # Availability + /// System contract #[codec(index = 3)] DeploySidevmTo { /// The target contract address @@ -92,27 +105,60 @@ pub enum PinkEvent { code_hash: Hash, }, /// Push a message to the associated sidevm instance. + /// + /// Please do not use this event directly, use [`push_sidevm_message()`] instead. + /// + /// # Availability + /// Any contract #[codec(index = 4)] SidevmMessage(Vec), - /// CacheOperation + /// Instructions to manipulate the cache. Including set, remove and set expiration. + /// + /// # Availability + /// Any contract #[codec(index = 5)] CacheOp(CacheOp), - /// Stop the side VM instance if it is running. + /// Stop the side VM instance associated with the caller contract if it is running. + /// + /// Please do not use this event directly, use [`force_stop_sidevm()`] instead. + /// + /// # Availability + /// Any contract #[codec(index = 6)] StopSidevm, - /// Force stop the side VM instance if it is running. + /// Force stop the side VM instance associated with the given contract if it is running. + /// + /// Please do not use this event directly, use [`stop_sidevm_at()`] instead. + /// + /// # Availability + /// System contract #[codec(index = 7)] ForceStopSidevm { /// The target contract address contract: AccountId, }, /// Set the log handler contract for current cluster. + /// + /// Please do not use this event directly, use [`set_log_handler()`] instead. + /// + /// # Availability + /// System contract #[codec(index = 8)] SetLogHandler(AccountId), /// Set the weight of contract used to schedule queries and sidevm vruntime + /// + /// Please do not use this event directly, use [`set_contract_weight()`] instead. + /// + /// # Availability + /// System contract #[codec(index = 9)] SetContractWeight { contract: AccountId, weight: u32 }, /// Upgrade the runtime to given version + /// + /// Please do not use this event directly, use [`upgrade_runtime()`] instead. + /// + /// # Availability + /// System contract #[codec(index = 10)] UpgradeRuntimeTo { version: (u32, u32) }, } @@ -147,11 +193,15 @@ impl PinkEvent { } } +/// Instructions to manipulate the cache. #[derive(Encode, Decode, Debug, Clone)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum CacheOp { + /// Set a key-value pair in the cache. Set { key: Vec, value: Vec }, + /// Set the expiration of a key-value pair in the cache. SetExpiration { key: Vec, expiration: u64 }, + /// Remove a key-value pair from the cache. Remove { key: Vec }, } @@ -183,8 +233,23 @@ impl PinkEvent { } } -/// Turn on on_block_end feature and set it's selector +/// Sets a hook receiver for a given hook point. /// +/// A hook is a mechanism that allows certain actions to be triggered when a specific situation arises. +/// When the situation corresponding to the hook point occurs, the runtime will call the receiver contract +/// using the specified selector. +/// +/// # Supported Hook Points +/// - `OnBlockEnd`: The receiver contract will be invoked once all events in a Phala chain block have been processed. +/// +/// # Arguments +/// +/// * `hook`: The hook point for which the receiver is set. +/// * `contract`: The AccountId of the contract to be called when the hook is triggered. +/// * `selector`: The function selector to be used when calling the receiver contract. +/// * `gas_limit`: The maximum amount of gas that can be used when calling the receiver contract. +/// +/// Note: The cost of the execution would be charged to the contract itself. pub fn set_hook(hook: HookPoint, contract: AccountId, selector: u32, gas_limit: u64) { emit_event::(PinkEvent::SetHook { hook, @@ -194,15 +259,28 @@ pub fn set_hook(hook: HookPoint, contract: AccountId, selector: u32, gas_limit: }) } -/// Start a SideVM instance +/// Starts a SideVM instance with the provided code hash. +/// +/// The calling contract must be authorized by the `SidevmOperation` driver contract. +/// +/// If the code corresponding to the provided hash hasn't been uploaded to the cluster storage yet, +/// it will create an empty SideVM instance. This instance will wait for the code to be uploaded +/// via `prpc::UploadSidevmCode`. +/// +///# Arguments +/// +///* `code_hash`: The hash of the code to be used for starting the SideVM instance. +/// +///# Returns +/// +/// A `Result` indicating success or failure, specifically a `system::DriverError` in case of failure. 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) } -/// Deploy a SideVM instance to a given contract. -/// The caller must be the system contract. +/// Deploy a SideVM instance to a given contract. (system only) pub fn deploy_sidevm_to(contract: AccountId, code_hash: Hash) { emit_event::(PinkEvent::DeploySidevmTo { contract, @@ -210,8 +288,7 @@ pub fn deploy_sidevm_to(contract: AccountId, code_hash: Hash) { }); } -/// Stop a SideVM instance running at given contract address. -/// The caller must be the system contract. +/// Stop a SideVM instance running at given contract address. (system only) pub fn stop_sidevm_at(contract: AccountId) { emit_event::(PinkEvent::ForceStopSidevm { contract }); } @@ -224,27 +301,61 @@ pub fn force_stop_sidevm() { emit_event::(PinkEvent::StopSidevm) } -/// Push a message to the associated sidevm instance. +/// Pushes a message to the associated SideVM instance. +/// +/// Note: There is no guarantee that the message will be received by the SideVM instance. +/// The message may be dropped due to several reasons: +/// +/// - The SideVM instance is not currently running. +/// - The SideVM instance is running, but the message queue is full. This may occur when the SideVM +/// instance is busy processing other messages. +/// +///# Arguments +/// +///* `message`: The message to be pushed to the SideVM instance. pub fn push_sidevm_message(message: Vec) { emit_event::(PinkEvent::SidevmMessage(message)) } -/// Set the log handler contract of current cluster +/// Set the log handler contract of current cluster. (system only) pub fn set_log_handler(contract: AccountId) { emit_event::(PinkEvent::SetLogHandler(contract)) } -/// Set the weight of contract used to schedule queries and sidevm vruntime +/// Set the weight of contract used to schedule queries and sidevm vruntime. (system only) pub fn set_contract_weight(contract: AccountId, weight: u32) { emit_event::(PinkEvent::SetContractWeight { contract, weight }); } -/// Upgrade the runtime to given version +/// Upgrade the pink runtime to given version. (system only) +/// +/// Note: pRuntime would exit if the version is not supported. pub fn upgrade_runtime(version: (u32, u32)) { emit_event::(PinkEvent::UpgradeRuntimeTo { version }); } -/// Pink defined environment. Used this environment to access the phat contract runtime features. +/// Pink defined environment. This environment is used to access the phat contract extended runtime features. +/// +/// # Example +/// ``` +/// #[ink::contract(env = PinkEnvironment)] +/// mod my_contract { +/// use pink_extension::PinkEnvironment; +/// #[ink(storage)] +/// pub struct MyContract {} +/// impl MyContract { +/// #[ink(constructor)] +/// pub fn new() -> Self { +/// Self {} +/// } +/// #[ink(message)] +/// pub fn my_message(&self) { +/// // Access the pink environment. +/// let _pink_version = self.env().extension().runtime_version(); +/// } +/// } +/// } +/// ``` #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum PinkEnvironment {} @@ -261,6 +372,7 @@ impl Environment for PinkEnvironment { type ChainExtension = chain_extension::PinkExt; } +/// Returns the PinkEnvironment. pub fn env() -> EnvAccess<'static, PinkEnvironment> { Default::default() } From b42962562e1f03f20a388ec6d4d5a20dbc704943 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 30 Jun 2023 06:55:08 +0000 Subject: [PATCH 2/9] Add cautions for cache_set --- crates/pink/pink-extension/src/chain_extension.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/pink/pink-extension/src/chain_extension.rs b/crates/pink/pink-extension/src/chain_extension.rs index b925e4e96d..9016a23683 100644 --- a/crates/pink/pink-extension/src/chain_extension.rs +++ b/crates/pink/pink-extension/src/chain_extension.rs @@ -257,6 +257,20 @@ pub trait PinkExt { /// /// * `Result<(), StorageQuotaExceeded>` - `Ok(())` or `Err(StorageQuotaExceeded)` if the storage quota is exceeded. /// + ///

+ /// Warning: + /// The cache is not guaranteed to be persistent. It may be cleared at any time due + /// to various reasons: + /// + /// - The cached item is expired. + /// - The entire cache in pRuntime is full and a new value needs to be stored (either from the contract itself or + /// other contracts). + /// - The worker is restarted. + ///

+ /// + /// In order to use cache, the contract need to be staked via the phala on-chain API `PhatTokenomic::adjust_stake`. + /// All contracts will share the 20MB cache storage by the ratio of stake. + /// /// # Example /// /// ``` From 1c65067aca98a1143c164da1542471408ea5b185 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 3 Jul 2023 02:09:50 +0000 Subject: [PATCH 3/9] Improve doc for the System contract --- crates/pink/pink-extension/README.md | 5 +- .../pink-extension/macro/src/driver_system.rs | 39 +++++++++- .../src/chain_extension/http_request.rs | 17 +++++ crates/pink/pink-extension/src/system.rs | 76 +++++++++++-------- 4 files changed, 103 insertions(+), 34 deletions(-) diff --git a/crates/pink/pink-extension/README.md b/crates/pink/pink-extension/README.md index 1f9914ef26..39d16cc356 100644 --- a/crates/pink/pink-extension/README.md +++ b/crates/pink/pink-extension/README.md @@ -34,7 +34,7 @@ fn http_get_example(&self) { The Pink! crate is designed to empower you, enabling you to leverage the unique features of the Phat Contract, such as making HTTP requests as demonstrated in our examples. This crate supplies the crucial types and functions needed to seamlessly interact with the Phat Contract runtime. -There two kind of APIs to communication with the runtime: +There are three kind of APIs to communication with the runtime: - Emitting Events: These APIs are primarily used in situations where the operation could lead to side effects that need to be deterministically recorded and may be rolled back during the execution of the contract call. For additional information on Emitting Events APIs, please refer to the [PinkEvent documentation](crate::PinkEvent). @@ -42,6 +42,9 @@ There two kind of APIs to communication with the runtime: - Chain Extension: These APIs are predominantly used for read-only operations or operations that aren't expected to create deterministic side effects. For an in-depth understanding of Chain Extension APIs, please refer to the [PinkExt documentation](crate::chain_extension::PinkExtBackend). +- System contract: + There is a special contract called the System contract in each cluster. The system contract is instantiated when the cluster is created. Either ink contracts or external accounts can call the system contract to perform certain operations. For more information on the System contract, please refer to the [System documentation](crate::system::SystemForDoc). + For practical implementation examples, explore our [Phat Contract examples](https://github.com/Phala-Network/phat-contract-examples) repository. ## Using JavaScript with Phat Contract diff --git a/crates/pink/pink-extension/macro/src/driver_system.rs b/crates/pink/pink-extension/macro/src/driver_system.rs index 0b4f5a78f0..0388760487 100644 --- a/crates/pink/pink-extension/macro/src/driver_system.rs +++ b/crates/pink/pink-extension/macro/src/driver_system.rs @@ -1,6 +1,6 @@ use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{spanned::Spanned, FnArg, Result}; +use syn::{parse_quote, spanned::Spanned, FnArg, Result}; pub(crate) enum InterfaceType { System, @@ -25,6 +25,8 @@ fn patch_or_err( ) -> Result { use heck::{ToLowerCamelCase, ToSnakeCase}; let the_trait: syn::ItemTrait = syn::parse2(input)?; + let trait_for_doc = generate_trait_for_doc(the_trait.clone()); + let the_trait = patch_origin_system_doc(the_trait); let trait_ident = &the_trait.ident; let trait_name = the_trait.ident.to_string(); let trait_impl_mod = Ident::new( @@ -133,6 +135,9 @@ fn patch_or_err( #config #the_trait + #[cfg(doc)] + #trait_for_doc + pub use #trait_impl_mod::#impl_type; mod #trait_impl_mod { use super::*; @@ -223,6 +228,38 @@ fn patch_or_err( }) } +fn patch_origin_system_doc(mut trait_item: syn::ItemTrait) -> syn::ItemTrait { + let additonal_doc = format!( + "**The doc is messed up by the ink macro. See [`{}ForDoc`] for a clean version**\n\n", + trait_item.ident + ); + trait_item + .attrs + .insert(0, parse_quote!(#[doc = #additonal_doc])); + trait_item +} + +fn generate_trait_for_doc(mut trait_item: syn::ItemTrait) -> syn::ItemTrait { + let additonal_doc = format!( + "**This is the clean version doc of [`{}`]**\n\n", + trait_item.ident + ); + trait_item.attrs.retain(|attr| attr.path().is_ident("doc")); + trait_item + .attrs + .insert(0, parse_quote!(#[doc = #additonal_doc])); + trait_item.ident = syn::Ident::new( + &format!("{}ForDoc", trait_item.ident), + trait_item.ident.span(), + ); + for item in trait_item.items.iter_mut() { + if let syn::TraitItem::Fn(method) = item { + method.attrs.retain(|attr| !attr.path().is_ident("ink")); + } + } + trait_item +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/pink/pink-extension/src/chain_extension/http_request.rs b/crates/pink/pink-extension/src/chain_extension/http_request.rs index 5b8d706df4..a2010cd5bf 100644 --- a/crates/pink/pink-extension/src/chain_extension/http_request.rs +++ b/crates/pink/pink-extension/src/chain_extension/http_request.rs @@ -12,6 +12,23 @@ pub struct HttpRequest { pub body: Vec, } +impl HttpRequest { + /// Create a new http request. + pub fn new( + url: impl Into, + method: impl Into, + headers: Vec<(String, String)>, + body: Vec, + ) -> Self { + Self { + url: url.into(), + method: method.into(), + headers, + body, + } + } +} + #[derive(scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub struct HttpResponse { diff --git a/crates/pink/pink-extension/src/system.rs b/crates/pink/pink-extension/src/system.rs index f06b166293..d42d7924af 100644 --- a/crates/pink/pink-extension/src/system.rs +++ b/crates/pink/pink-extension/src/system.rs @@ -41,52 +41,65 @@ pub use this_crate::VersionTuple; /// The pink system contract interface. /// -/// A system contract would be instantiated whenever a cluster is created. +/// The system contract, instantiated with each cluster creation, manages access permissions to +/// the privileged chain extension functions and pink events. Some of these functions or events +/// are exclusive to the system contract. User contracts wishing to call these functions or +/// emit these events must first request the system contract, which then checks the permissions +/// to either execute or reject the request. #[pink::system] #[ink::trait_definition(namespace = "pink_system")] pub trait System { - /// The version of the system. Can be used to determine the api ability. + /// Returns the system contract version, indicating its API capabilities. + /// + /// # Example + /// ```no_run + /// use pink_extension::system::SystemRef; + /// let (major, minor, patch) = SystemRef::instance().version(); + /// ``` #[ink(message, selector = 0x87c98a8d)] fn version(&self) -> VersionTuple; - /// Grant an address the administrator role. + + /// Grants the administrator role to an address. Administrator contracts can set drivers, + /// deploy sidevm, etc. /// - /// The caller must be the owner of the cluster. + /// Must be called by the cluster owner. #[ink(message)] fn grant_admin(&mut self, contract_id: AccountId) -> Result<()>; - /// Check if an address is an administrator + /// Checks if an address is an administrator. #[ink(message)] fn is_admin(&self, contract_id: AccountId) -> bool; - /// Set a contract as a driver for `name`. + /// Marks a contract as a driver for a given name, retrievable via `get_driver` or `get_driver2`. + /// The caller must be the cluster owner or an administrator. Any valid string can be a name. + /// There are predefined names used by the Phat Contract system. /// - /// The caller must be the owner of the cluster or an administrator. + /// There are some predefined names that are used by the Phat Contract system: + /// - `PinkLogger`: The contract that with a sidevm instance that collect the logs and events + /// emitted by the ink! contracts in current cluster. + /// - `ContractDeposit`: The contract that implements the `trait ContractDeposit` which talks + /// to the pallet PhatKokenomic on Phala chain. #[ink(message)] fn set_driver(&mut self, name: String, contract_id: AccountId) -> Result<()>; - /// Get driver contract id for `name`. + /// Retrieves the driver contract id for a given name. #[ink(message)] fn get_driver(&self, name: String) -> Option; - /// Get driver contract id for `name` and the set block number. + /// Retrieves the driver contract id and the set block number for a given name. #[ink(message)] fn get_driver2(&self, name: String) -> Option<(crate::BlockNumber, AccountId)>; - /// Deploy a sidevm instance attached to a given contract. - /// - /// The caller must be an administrator. + /// Deploys a sidevm instance attached to a contract. Must be called by an administrator. #[ink(message)] fn deploy_sidevm_to(&self, contract_id: AccountId, code_hash: Hash) -> Result<()>; - /// Stop a sidevm instance attached to a given contract. - /// - /// The caller must be an administrator. + /// Stops a sidevm instance attached to a contract. Must be called by an administrator. #[ink(message)] fn stop_sidevm_at(&self, contract_id: AccountId) -> Result<()>; - /// Set block hook, such as OnBlockEnd, for given contract - /// - /// The caller must be an administrator. + /// Sets a block hook for a contract. Must be called by an administrator. + /// Note: This feature is deprecated and will be removed in the future. #[ink(message)] fn set_hook( &mut self, @@ -96,44 +109,43 @@ pub trait System { gas_limit: u64, ) -> Result<()>; - /// Set weight of the contract for query requests and sidevm scheduling. - /// - /// Higher weight would let the contract to get more resource. + /// Sets the contract weight for query requests and sidevm scheduling. + /// A higher weight allows the contract to access more resources. #[ink(message)] fn set_contract_weight(&self, contract_id: AccountId, weight: u32) -> Result<()>; - /// Return the total balance of given account + /// Returns the total balance of a given account. #[ink(message)] fn total_balance_of(&self, account: AccountId) -> Balance; - /// Return the free balance of given account + /// Returns the free balance of a given account. #[ink(message)] fn free_balance_of(&self, account: AccountId) -> Balance; - /// Upgrade the system contract to the latest version. + /// Upgrades the system contract to the latest version. #[ink(message)] fn upgrade_system_contract(&mut self) -> Result<()>; - /// Do the upgrade condition checks and state migration if necessary. - /// - /// This function is called by the system contract itself on the new version - /// of code in the upgrading process. + /// Performs upgrade condition checks and state migration if necessary. + /// Called by the system contract on the new code version during an upgrade process. #[ink(message)] fn do_upgrade(&self, from_version: VersionTuple) -> Result<()>; - /// Upgrade the contract runtime + /// Upgrades the contract runtime. #[ink(message)] fn upgrade_runtime(&mut self, version: (u32, u32)) -> Result<()>; - /// Check if the code is already uploaded to the cluster with given code hash. + /// Checks if the code with a given hash is already uploaded to the cluster. #[ink(message)] fn code_exists(&self, code_hash: Hash, code_type: CodeType) -> bool; - /// Get the current code hash of given contract. + /// Retrieves the current code hash of a given contract. #[ink(message)] fn code_hash(&self, account: AccountId) -> Option; - /// Get the history of given driver. + /// Retrieves the history of a given driver, returning a vector of + /// (block_number, contract_id) tuples where the block number is the + /// block number when the driver is set. #[ink(message)] fn driver_history(&self, name: String) -> Option>; } From 939acd8cd8592a070589202d88de5f70bdc78ac9 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 3 Jul 2023 05:08:12 +0000 Subject: [PATCH 4/9] Fix compilation errors --- Cargo.lock | 30 ++++------- crates/pink/pink-extension/README.md | 4 +- crates/pink/pink-extension/macro/src/lib.rs | 4 +- ...iver_system__tests__show_patch_result.snap | 10 +++- .../pink-extension/src/chain_extension.rs | 52 ++++++++++--------- crates/pink/pink-extension/src/logger.rs | 33 +++++++++--- 6 files changed, 78 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5571b9d3bb..d78b4c8914 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4862,7 +4862,7 @@ checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes 1.0.11", - "rustix 0.36.14", + "rustix 0.36.21", "windows-sys 0.45.0", ] @@ -5944,7 +5944,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb" dependencies = [ - "rustix 0.36.14", + "rustix 0.36.21", ] [[package]] @@ -10182,20 +10182,6 @@ dependencies = [ "windows-sys 0.42.0", ] -[[package]] -name = "rustix" -version = "0.36.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" -dependencies = [ - "bitflags 1.3.2", - "errno 0.3.1", - "io-lifetimes 1.0.11", - "libc", - "linux-raw-sys 0.1.4", - "windows-sys 0.45.0", -] - [[package]] name = "rustix" version = "0.37.21" @@ -10208,6 +10194,10 @@ dependencies = [ "libc", "linux-raw-sys 0.3.8", "windows-sys 0.48.0", + "io-lifetimes 1.0.4", + "libc", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", ] [[package]] @@ -10730,7 +10720,7 @@ dependencies = [ "libc", "log", "once_cell", - "rustix 0.36.14", + "rustix 0.36.21", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -15326,7 +15316,7 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.36.14", + "rustix 0.36.21", "serde", "sha2 0.10.2", "toml 0.5.9", @@ -15422,7 +15412,7 @@ checksum = "6e0554b84c15a27d76281d06838aed94e13a77d7bf604bbbaf548aa20eb93846" dependencies = [ "object 0.30.4", "once_cell", - "rustix 0.36.14", + "rustix 0.36.21", ] [[package]] @@ -15453,7 +15443,7 @@ dependencies = [ "memoffset 0.8.0", "paste", "rand 0.8.5", - "rustix 0.36.14", + "rustix 0.36.21", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", diff --git a/crates/pink/pink-extension/README.md b/crates/pink/pink-extension/README.md index 39d16cc356..489ab80e10 100644 --- a/crates/pink/pink-extension/README.md +++ b/crates/pink/pink-extension/README.md @@ -22,7 +22,7 @@ std = [ Then, you can use the `http_get!` macro to make a GET request to a remote server: -```rust +```ignore #[ink::message] fn http_get_example(&self) { let response = pink::http_get!("https://httpbin.org/get"); @@ -59,7 +59,7 @@ There are two ways to use JavaScript in your contract: - For the simplest integration, consider using the [`phat_js`](https://docs.rs/phat_js/) crate. It provides an `eval` function that lets you evaluate JavaScript code snippets directly. For example: - ```rust + ```ignore #[ink::message] fn eval_js_example(&self) { let result = phat_js::eval("'Hello,' + 'World'", &[]); diff --git a/crates/pink/pink-extension/macro/src/lib.rs b/crates/pink/pink-extension/macro/src/lib.rs index 1a6427c4e1..abf1bc0dbc 100644 --- a/crates/pink/pink-extension/macro/src/lib.rs +++ b/crates/pink/pink-extension/macro/src/lib.rs @@ -55,7 +55,7 @@ pub fn system(arg: TokenStream, input: TokenStream) -> TokenStream { /// Below, the `SidevmOperation` trait is annotated with `#[pink::driver]`. This marks it /// as a driver contract, enabling it to manage SideVM deployments. /// -/// ```rust +/// ```ignore /// #[pink::driver] /// #[ink::trait_definition] /// pub trait SidevmOperation { @@ -75,7 +75,7 @@ pub fn system(arg: TokenStream, input: TokenStream) -> TokenStream { /// The actual driver can then be retrieved and its methods, defined by the trait, can be used. /// For instance, to start a SideVM, one would get the driver instance and call its `deploy` method: /// -/// ```rust +/// ```ignore /// pub fn start_sidevm(code_hash: Hash) -> Result<(), system::DriverError> { /// let driver = /// SidevmOperationRef::instance().ok_or(system::Error::DriverNotFound)?; diff --git a/crates/pink/pink-extension/macro/src/snapshots/pink_extension_macro__driver_system__tests__show_patch_result.snap b/crates/pink/pink-extension/macro/src/snapshots/pink_extension_macro__driver_system__tests__show_patch_result.snap index 0ae5912bf8..1d8f135fa4 100644 --- a/crates/pink/pink-extension/macro/src/snapshots/pink_extension_macro__driver_system__tests__show_patch_result.snap +++ b/crates/pink/pink-extension/macro/src/snapshots/pink_extension_macro__driver_system__tests__show_patch_result.snap @@ -1,8 +1,9 @@ --- source: crates/pink/pink-extension/macro/src/driver_system.rs -assertion_line: 250 +assertion_line: 286 expression: "rustfmt_snippet::rustfmt_token_stream(&stream).unwrap()" --- +#[doc = "**The doc is messed up by the ink macro. See [`SystemForDoc`] for a clean version**\n\n"] #[ink::trait_definition(namespace = "pink_system")] pub trait System { #[ink(message)] @@ -12,6 +13,13 @@ pub trait System { #[ink(message)] fn deploy_sidevm_to(&self, code_hash: Hash, contract_id: AccountId) -> Result<()>; } +#[cfg(doc)] +#[doc = "**This is the clean version doc of [`System`]**\n\n"] +pub trait SystemForDoc { + fn get_driver(&self, name: String) -> Option; + fn set_driver(&self, name: String, driver: AccountId); + fn deploy_sidevm_to(&self, code_hash: Hash, contract_id: AccountId) -> Result<()>; +} pub use _pink_system_impl::SystemRef; mod _pink_system_impl { use super::*; diff --git a/crates/pink/pink-extension/src/chain_extension.rs b/crates/pink/pink-extension/src/chain_extension.rs index 9016a23683..9a7f5807fc 100644 --- a/crates/pink/pink-extension/src/chain_extension.rs +++ b/crates/pink/pink-extension/src/chain_extension.rs @@ -8,6 +8,9 @@ pub use signing::SigType; use crate::{Balance, EcdsaPublicKey, EcdsaSignature, Hash}; +#[cfg(doc)] +use crate::{http_get, http_post, http_put, debug, info, warn, error}; + mod http_request; pub mod signing; @@ -116,15 +119,15 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let request = HttpRequest::new("https://httpbin.org/get", "GET", Defualt::default(), Defualt::default()); /// let response = pink::ext().http_request(request); /// ``` /// /// There are also some shortcut macros for this function: - /// - [`crate::http_get!`] - /// - [`crate::http_post!`] - /// - [`crate::http_put!`] + /// - [`http_get!`] + /// - [`http_post!`] + /// - [`http_put!`] /// /// # Availability /// any contract | query only @@ -145,7 +148,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); /// let message = b"Hello, world!"; /// let signature = pink::ext().sign(SigType::Sr25519, &key, message); @@ -179,7 +182,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); /// let message = b"Hello, world!"; /// let signature = pink::ext().sign(SigType::Sr25519, &key, message); @@ -207,7 +210,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); /// ``` /// @@ -231,7 +234,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let derived_key = pink::ext().derive_sr25519_key(b"some salt".into()); /// let pubkey = pink::ext().get_public_key(SigType::Sr25519, &derived_key); /// ``` @@ -273,7 +276,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let key = b"my key"; /// let value = b"my value"; /// let result = pink::ext().cache_set(key, value); @@ -295,7 +298,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let key = b"my key"; /// let expire = 60; // 1 minute /// pink::ext().cache_set_expiration(key, expire); @@ -322,7 +325,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let key = b"my key"; /// let value = pink::ext().cache_get(key); /// ``` @@ -362,7 +365,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let level = 1; /// let message = "Hello, world!"; /// pink::ext().log(level, message); @@ -371,10 +374,10 @@ pub trait PinkExt { /// # Note /// This is the low-level method for logging. It is recommended to use shortcuts macros below instead: /// - /// - [`crate::debug!`] - /// - [`crate::info!`] - /// - [`crate::warn!`] - /// - [`crate::error!`] + /// - [`debug!`] + /// - [`info!`] + /// - [`warn!`] + /// - [`error!`] /// /// # Availability /// any contract | query | transaction @@ -400,7 +403,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let length = 32; /// let random_bytes = pink::ext().getrandom(length); /// ``` @@ -418,6 +421,7 @@ pub trait PinkExt { /// /// # Availability /// any contract | query | transaction + #[allow(clippy::wrong_self_convention)] #[ink(extension = 12, handle_status = false)] fn is_in_transaction() -> bool; @@ -436,7 +440,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let key = [0u8; 32]; // replace with actual key /// let message_hash = Hash::zero(); // replace with actual hash /// let signature = pink::ext().ecdsa_sign_prehashed(&key, message_hash); @@ -463,7 +467,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let signature = EcdsaSignature::default(); // replace with actual signature /// let message_hash = Hash::zero(); // replace with actual hash /// let pubkey = EcdsaPublicKey::default(); // replace with actual pubkey @@ -525,7 +529,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let current_millis = pink::ext().untrusted_millis_since_unix_epoch(); /// ``` /// @@ -542,7 +546,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let code_hash = Hash::zero(); // replace with actual code hash /// let exists = pink::ext().code_exists(code_hash, false); /// ``` @@ -560,7 +564,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let payer = AccountId::default(); // replace with actual payer id /// let code_hash = pink::ext().import_latest_system_code(payer); /// ``` @@ -578,7 +582,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let (major, minor) = pink::ext().runtime_version(); /// ``` /// @@ -602,7 +606,7 @@ pub trait PinkExt { /// /// # Example /// - /// ``` + /// ```ignore /// let requests = vec![ /// HttpRequest::new("https://httpbin.org/get", /// "GET", diff --git a/crates/pink/pink-extension/src/logger.rs b/crates/pink/pink-extension/src/logger.rs index 89f1f785fe..ed156ebc30 100644 --- a/crates/pink/pink-extension/src/logger.rs +++ b/crates/pink/pink-extension/src/logger.rs @@ -34,37 +34,58 @@ pub fn log(level: Level, args: Arguments<'_>) { Logger.log(&record); } -/// Same as log::log! +/// The `log!` macro allows you to log messages with specific logging levels in pink contract. +/// +/// It is a flexible macro that uses a provided log level (trace, debug, info, warn, error), +/// followed by a format string and an optional list of arguments to generate the final log message. #[macro_export] macro_rules! log { ($level: expr, $($arg:tt)+) => {{ $crate::logger::log($level, ::core::format_args!($($arg)+)) }} } -/// Same as log::error! +/// Same as `info!` but at Error level. #[macro_export(local_inner_macros)] macro_rules! error { ($($arg:tt)+) => {{ log!($crate::logger::Level::Error, $($arg)+) }} } -/// Same as log::warn! +/// Same as `info!` but at Warn level. #[macro_export(local_inner_macros)] macro_rules! warn { ($($arg:tt)+) => {{ log!($crate::logger::Level::Warn, $($arg)+) }} } -/// Same as log::info! +/// Macro `info!` logs messages at the Info level in pink contract. +/// +/// This macro is used to log information that would be helpful to understand the general flow +/// of the system's execution. It is similar to `log::info`, but it is specifically designed +/// to work within the pink contract environment. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ```ignore +/// use pink_extension as pink; +/// pink::info!("This is an information message."); +/// let answer = 42; +/// pink::info!("The answer is {}.", answer); +/// ``` +/// +/// The above example would log "This is an information message." and +/// "The answer is 42." at the Info level. #[macro_export(local_inner_macros)] macro_rules! info { ($($arg:tt)+) => {{ log!($crate::logger::Level::Info, $($arg)+) }} } -/// Same as log::debug! +/// Same as `info!` but at Debug level. #[macro_export(local_inner_macros)] macro_rules! debug { ($($arg:tt)+) => {{ log!($crate::logger::Level::Debug, $($arg)+) }} } -/// Same as log::trace! +/// Same as `info!` but at Trace level. #[macro_export(local_inner_macros)] macro_rules! trace { ($($arg:tt)+) => {{ log!($crate::logger::Level::Trace, $($arg)+) }} From 883fd76b2946379581946e0b19fc95154c8c1736 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 6 Jul 2023 01:36:30 +0000 Subject: [PATCH 5/9] Update Cargo.lock --- Cargo.lock | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d78b4c8914..80ae6b9cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4862,7 +4862,7 @@ checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes 1.0.11", - "rustix 0.36.21", + "rustix 0.36.15", "windows-sys 0.45.0", ] @@ -5944,7 +5944,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb" dependencies = [ - "rustix 0.36.21", + "rustix 0.36.15", ] [[package]] @@ -10184,22 +10184,32 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.21" +version = "0.36.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" +checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" dependencies = [ "bitflags 1.3.2", "errno 0.3.1", "io-lifetimes 1.0.11", "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", - "io-lifetimes 1.0.4", - "libc", "linux-raw-sys 0.1.4", "windows-sys 0.45.0", ] +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags 1.3.2", + "errno 0.3.1", + "io-lifetimes 1.0.11", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustls" version = "0.19.1" @@ -10720,7 +10730,7 @@ dependencies = [ "libc", "log", "once_cell", - "rustix 0.36.21", + "rustix 0.36.15", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -13685,7 +13695,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.21", + "rustix 0.37.23", "windows-sys 0.48.0", ] @@ -15316,7 +15326,7 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.36.21", + "rustix 0.36.15", "serde", "sha2 0.10.2", "toml 0.5.9", @@ -15412,7 +15422,7 @@ checksum = "6e0554b84c15a27d76281d06838aed94e13a77d7bf604bbbaf548aa20eb93846" dependencies = [ "object 0.30.4", "once_cell", - "rustix 0.36.21", + "rustix 0.36.15", ] [[package]] @@ -15443,7 +15453,7 @@ dependencies = [ "memoffset 0.8.0", "paste", "rand 0.8.5", - "rustix 0.36.21", + "rustix 0.36.15", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", From b5a0ee1ea6c8fa9a4f3e70d2a8685004d868ebcd Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 6 Jul 2023 01:37:22 +0000 Subject: [PATCH 6/9] "based" -> "extending" --- crates/pink/pink-extension/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pink/pink-extension/README.md b/crates/pink/pink-extension/README.md index 489ab80e10..32ac7a86d0 100644 --- a/crates/pink/pink-extension/README.md +++ b/crates/pink/pink-extension/README.md @@ -1,6 +1,6 @@

Phala's ink! - Writing Enhanced Smart Contracts

-Pink! is a smart contract language based on Parity's `ink!`. It extends the basic functionality with additional features, tailored to interact efficiently with Phala's Phat Contract runtime. +Pink! is a smart contract language extending Parity's `ink!`. It extends the basic functionality with additional features, tailored to interact efficiently with Phala's Phat Contract runtime. ## Getting Started From b58c5e2ae90471ffd53551dea512cfcd9eda229b Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 7 Jul 2023 07:44:23 +0000 Subject: [PATCH 7/9] Apply review sugguestions --- crates/phactory/src/contracts/support.rs | 4 ++-- crates/phactory/src/system/mod.rs | 2 +- .../pink-extension/src/chain_extension.rs | 20 ++++++++++++------- crates/pink/pink-extension/src/lib.rs | 2 ++ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/phactory/src/contracts/support.rs b/crates/phactory/src/contracts/support.rs index 425b046f52..e3257cf4a4 100644 --- a/crates/phactory/src/contracts/support.rs +++ b/crates/phactory/src/contracts/support.rs @@ -183,9 +183,9 @@ impl Contract { phala_mq::select! { next_cmd = self.cmd_rcv_mq => match next_cmd { Ok((_, cmd, origin)) => { - info!("Contract {:?} handling command", self.address()); + info!("Contract {:?} handling tx call", self.address()); let Ok(command) = Decode::decode(&mut &cmd.0[..]) else { - error!("Failed to decode command input"); + error!("Failed to decode tx input"); return Some(Err(TransactionError::BadInput)); }; env.contract_cluster.handle_command(self.address(), origin, command, &mut context) diff --git a/crates/phactory/src/system/mod.rs b/crates/phactory/src/system/mod.rs index 16eaee73ee..b2eddf5b60 100644 --- a/crates/phactory/src/system/mod.rs +++ b/crates/phactory/src/system/mod.rs @@ -1674,7 +1674,7 @@ pub fn handle_contract_command_result( ) { let effects = match result { Err(err) => { - error!("Run contract command failed: {:?}", err); + error!("Run contract tx call failed: {:?}", err); return; } Ok(Some(effects)) => effects, diff --git a/crates/pink/pink-extension/src/chain_extension.rs b/crates/pink/pink-extension/src/chain_extension.rs index 9a7f5807fc..5e3d203a53 100644 --- a/crates/pink/pink-extension/src/chain_extension.rs +++ b/crates/pink/pink-extension/src/chain_extension.rs @@ -200,6 +200,8 @@ pub trait PinkExt { /// This method derives a sr25519 key using the provided salt and the contract private key. /// The derived key is deterministic so it could be used in transactions to sign messages. /// + /// The derived key can also be used as a cryptographically secure entropy source. + /// /// # Arguments /// /// * `salt`: The salt to use in the key derivation function. @@ -219,7 +221,7 @@ pub trait PinkExt { #[ink(extension = 4, handle_status = false)] fn derive_sr25519_key(salt: Cow<[u8]>) -> Vec; - /// Get the public key associated with a private key. + /// Derive the public key from a private key. /// /// This method takes a signature type and private key and returns the associated public key. /// @@ -312,7 +314,7 @@ pub trait PinkExt { /// Get a value from the local cache. /// /// This method retrieves a value from the local cache. It can only be used in query functions. - /// If called from a command context, it will always return `None`. + /// If called from a transaction context, it will always return `None`. /// /// # Arguments /// @@ -338,7 +340,7 @@ pub trait PinkExt { /// Remove a value from the local cache. /// /// This method removes a value from the local cache and returns the removed value if it existed. - /// If called from a command context, it will always return `None`. + /// If called from a transaction context, it will always return `None`. /// /// # Arguments /// @@ -358,6 +360,10 @@ pub trait PinkExt { /// /// This method logs a message at a given level. /// + /// The logs would be shown in the worker log file. Additionally, if a log server + /// contract has been deployed in the cluster, the logs would be sent to the log server. + /// Users can query the logs via the log server API. + /// /// # Arguments /// /// * `level`: The level of the log message. @@ -413,11 +419,11 @@ pub trait PinkExt { #[ink(extension = 11, handle_status = false)] fn getrandom(length: u8) -> Vec; - /// Check if it is running in a Command context. + /// Check if it is running in a transaction context. /// /// # Returns /// - /// * `bool` - `true` if it is running in a Command context, `false` if in query. + /// * `bool` - `true` if it is running in a transaction context, `false` if in query. /// /// # Availability /// any contract | query | transaction @@ -490,7 +496,7 @@ pub trait PinkExt { #[ink(extension = 15, handle_status = false)] fn system_contract_id() -> AccountId; - /// Get balance of a given contract. + /// Get balance of a given address. /// /// # Arguments /// @@ -505,7 +511,7 @@ pub trait PinkExt { #[ink(extension = 16, handle_status = false)] fn balance_of(account: AccountId) -> (Balance, Balance); - /// Get the worker public key. + /// Get the public key of the worker running this query. /// /// # Returns /// diff --git a/crates/pink/pink-extension/src/lib.rs b/crates/pink/pink-extension/src/lib.rs index 33f92d0840..e4e1a978af 100644 --- a/crates/pink/pink-extension/src/lib.rs +++ b/crates/pink/pink-extension/src/lib.rs @@ -250,6 +250,8 @@ impl PinkEvent { /// * `gas_limit`: The maximum amount of gas that can be used when calling the receiver contract. /// /// Note: The cost of the execution would be charged to the contract itself. +/// +/// This api is only available for the system contract. User contracts should use `System::set_hook` instead. pub fn set_hook(hook: HookPoint, contract: AccountId, selector: u32, gas_limit: u64) { emit_event::(PinkEvent::SetHook { hook, From 73507b21ed3797708ef409358bae53c2429170a8 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Sat, 8 Jul 2023 01:14:17 +0000 Subject: [PATCH 8/9] Fix typo & chore --- crates/pink/pink-extension/src/lib.rs | 4 ++-- crates/pink/pink-extension/src/system.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/pink/pink-extension/src/lib.rs b/crates/pink/pink-extension/src/lib.rs index e4e1a978af..b08c4fcbe1 100644 --- a/crates/pink/pink-extension/src/lib.rs +++ b/crates/pink/pink-extension/src/lib.rs @@ -145,7 +145,7 @@ pub enum PinkEvent { /// System contract #[codec(index = 8)] SetLogHandler(AccountId), - /// Set the weight of contract used to schedule queries and sidevm vruntime + /// Set the weight of contract used to schedule queries and sidevm virtual runtime /// /// Please do not use this event directly, use [`set_contract_weight()`] instead. /// @@ -324,7 +324,7 @@ pub fn set_log_handler(contract: AccountId) { emit_event::(PinkEvent::SetLogHandler(contract)) } -/// Set the weight of contract used to schedule queries and sidevm vruntime. (system only) +/// Set the weight of contract used to schedule queries and sidevm virtual runtime. (system only) pub fn set_contract_weight(contract: AccountId, weight: u32) { emit_event::(PinkEvent::SetContractWeight { contract, weight }); } diff --git a/crates/pink/pink-extension/src/system.rs b/crates/pink/pink-extension/src/system.rs index d42d7924af..48775de94b 100644 --- a/crates/pink/pink-extension/src/system.rs +++ b/crates/pink/pink-extension/src/system.rs @@ -78,7 +78,7 @@ pub trait System { /// - `PinkLogger`: The contract that with a sidevm instance that collect the logs and events /// emitted by the ink! contracts in current cluster. /// - `ContractDeposit`: The contract that implements the `trait ContractDeposit` which talks - /// to the pallet PhatKokenomic on Phala chain. + /// to the pallet PhatTokenomic on Phala chain. #[ink(message)] fn set_driver(&mut self, name: String, contract_id: AccountId) -> Result<()>; From 4b8ac40fb086355974ab11ba320ed340b4e5fcd4 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 10 Jul 2023 01:37:11 +0000 Subject: [PATCH 9/9] Bump pink version to 0.4.4 --- Cargo.lock | 4 ++-- crates/pink/pink-extension/Cargo.toml | 2 +- crates/pink/pink-extension/macro/Cargo.toml | 2 +- standalone/pruntime/Cargo.lock | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80ae6b9cf1..7e4bbca77f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8665,7 +8665,7 @@ dependencies = [ [[package]] name = "pink-extension" -version = "0.4.3" +version = "0.4.4" dependencies = [ "dlmalloc", "ink", @@ -8680,7 +8680,7 @@ dependencies = [ [[package]] name = "pink-extension-macro" -version = "0.4.2" +version = "0.4.4" dependencies = [ "heck 0.4.1", "ink_ir", diff --git a/crates/pink/pink-extension/Cargo.toml b/crates/pink/pink-extension/Cargo.toml index 2cac2c3954..2473332418 100644 --- a/crates/pink/pink-extension/Cargo.toml +++ b/crates/pink/pink-extension/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pink-extension" -version = "0.4.3" +version = "0.4.4" edition = "2018" description = "Phala's ink! for writing phat contracts" license = "Apache-2.0" diff --git a/crates/pink/pink-extension/macro/Cargo.toml b/crates/pink/pink-extension/macro/Cargo.toml index 5c4feabea6..3eb0fd777b 100644 --- a/crates/pink/pink-extension/macro/Cargo.toml +++ b/crates/pink/pink-extension/macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pink-extension-macro" -version = "0.4.2" +version = "0.4.4" edition = "2018" description = "Macros for writing phat contract" license = "Apache-2.0" diff --git a/standalone/pruntime/Cargo.lock b/standalone/pruntime/Cargo.lock index fe1bcc20a8..657d1ac278 100644 --- a/standalone/pruntime/Cargo.lock +++ b/standalone/pruntime/Cargo.lock @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "pink-extension" -version = "0.4.3" +version = "0.4.4" dependencies = [ "ink", "log", @@ -4882,7 +4882,7 @@ dependencies = [ [[package]] name = "pink-extension-macro" -version = "0.4.2" +version = "0.4.4" dependencies = [ "heck 0.4.0", "ink_ir",