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

doc: Improve docs #2

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
82 changes: 8 additions & 74 deletions ckb-ssri-std/README.md
Original file line number Diff line number Diff line change
@@ -1,98 +1,32 @@
# ckb-ssri-std

>
> [[EN/CN] Script-Sourced Rich Information - 来源于 Script 的富信息](https://talk.nervos.org/t/en-cn-script-sourced-rich-information-script/8256): General introduction to SSRI.
>
> [`ssri-test`](https://github.com/Hanssen0/ssri-test): First prototype of SSRI-Compliant contract.
> [CCC App - SSRI](https://ccc-git-udtssridemo-aaaaaaaalive24.vercel.app/?_vercel_share=zQkvWcsB2U9HRbpRFtF9w3xQT9msZDWb): Interactive demo of interacting with SSRI-Compliant scripts.
>
> [`ssri-server`](https://github.com/ckb-devrel/ssri-server): Server for calling SSRI methods.
> [`pausable-udt`](https://github.com/ckb-devrel/pausable-udt): A real production level contract (instead of a pseudo-project) that exemplifies the usage of SSRI.
>
> [`ssri-server`](https://github.com/ckb-devrel/ssri-server): Server for calling SSRI methods.

## Quick Note on SSRI

- SSRI stands for `Script Sourced Rich Information`; it is a protocol for strong bindings of relevant information and conventions to the Script itself on CKB. For more information, please read [[EN/CN] Script-Sourced Rich Information - 来源于 Script 的富信息](https://talk.nervos.org/t/en-cn-script-sourced-rich-information-script/8256)>.
- Such bindings would take place in a progressive pattern:
- In the current coding paradigms for all contracts in production, testing, or active development, (or specifically, in Stage 1), the CKB smart contract being SSRI-Compliant would help us:
1. In the typical scenario of validating transactions, by specifically using Rust Traits, we recognize the purpose (or more specifically, the `Intent` of running the script) (e.g., `minting UDT`, `transferring`) and build relevant validation logics within the scope of the corresponding method.
2. On the level of reading and organizing contract code, by selectively implementing methods of public module traits (e.g. `UDT`, `UDTExtended`, `UDTPausable`) in combinations, generic users and devs would be able to quickly understand and organize functionalities of contracts as well as the relevant adaptations / integrations in dApps , especially in use cases involving multiple distinct contracts (and very likely from different projects) within same transactions.
- For writing CKB Scripts (or "Smart Contracts"), by selectively implementing methods of public module traits (e.g. `UDT`, `UDTExtended`, `UDTPausable`) in combinations, devs would be able to quickly design and organize functionalities that either validate transactions or provide rich information as well as assembling transactions off-chain.
- For dApps or other infrastructures that interact with CKB Scripts, you no longer need to retrieve and parse data or assemble transactions by yourself repetitively as they are all provided by SSRI.

### Goals of `ckb-ssri-std`

- Easier and intuitive implementations and built-in integration support (e.g. `CCC` and `ckb_ssri_cli`) of SSRI public traits.
- Easier and intuitive implementations and built-in integration support of SSRI public traits which would receive first party support such as [`@ccc-ckb/udt`](https://docs.ckbccc.com/modules/_ckb_ccc_udt.html).
- Easier and intuitive definitions of customized SSRI traits.
- [ ] TODO: Unified entry function;
- Scrip-Sourced code sharing for on-chain verification, off-chain query/integration, and off-chain transaction generations/completions.
- Unified entry function;

## Usage

1. [ ] TODO: SSRI-Compliant Smart Contract Code would have an identifier Type that also implements TypeID mechanism. Please use [`ckb-cinnabar`](https://github.com/ashuralyk/ckb-cinnabar?tab=readme-ov-file#deployment-module) for easier deployment and migration.
2. SSRI-Compliant Smart Contract would use the unified entry function to run the script and call the exposed methods by specifying the path at `argv[0]` and the arguments at `argv[1..]`.
- The default namespace is `SSRI` which consists of:
- `SSRI.version() -> u8`
- `SSRI.get_methods(offset: u64, limit: u64) -> Vec<Bytes8>`
- `SSRI.has_methods(methods: Vec<Bytes8>) -> Vec<bool>`
- [ ] TODO: By using the `#[ssri_module]` macro and `#[ssri_method]` attribute, methods can be automatically exposed in the namespace defined by trait name.
3. By implementing traits from `ckb_ssri_std::public_module_traits` in the SSRI-Compliant Smart Contract, infrastructures would be able to provide richer information off-chain as well for all kinds of purposes based on the SSRI protocol.

## Example Contract
## Usage: Example Contract

[`pausable-udt`](https://github.com/ckb-devrel/pausable-udt) is a real production level contract (instead of a pseudo-project) that exemplifies the usage of SSRI.

## [ ] TODO: Defining a SSRI Module with `proc-macros` and Implement SSRI Traits

### #[ssri_module]

- version: implement a method to get the version of the SSRI module.

### #[ssri_method]

- By default, all of the following flags are set to false or empty;
- 'level={ExecutionEnvironmentLevel}': This method can only be run when the execution environment level is above or equal to the specified level;
- 'transaction=true': Will return a transaction object of molecule `struct` that can be sent to directly to RPC. If transaction is set to true, the required level is automatically set to Chain;
- 'internal=true': This method is not exposed through SSRI, but it's a dependency for other methods;

## Defining a SSRI Public Module Trait

## Deployment and Migration

- Deploy and upgrade with [ckb-cinnabar](https://github.com/ashuralyk/ckb-cinnabar?tab=readme-ov-file#deployment-module) for easier deployment and migration with Type ID.

```shell
ckb-cinnabar deploy --contract-name pausable-udt --tag transaction.v241112 --payer-address ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqtxe0gs9yvwrsc40znvdc6sg4fehd2mttsngg4t4 --type-id


ckb-cinnabar migrate --contract-name pausable-udt --from-tag v241030.1 --to-tag v241030.2
```

## Interacting with SSRI-Compliant Contracts

With SSRI-server and SSRI-VM, users, devs, and admins would have the ability to obtain Script-Source Rich Information directly from the script by calling SSRI methods via SSRI-server (which can be both run locally and for public usage).

The returned information can be just data for display, or a transaction object that can be sent to a CKB RPC, without the need of extra implementations on either dApps or backend applications.

```sh
echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "run_script",
"params": ["<TxHash of the target Cell>", <Index>, [<Bytes of methods path>, <...argv>]]
}'
```

### `ckb_ssri_cli`

## Testing

Due to the limitations of `ckb_testtools`, it is recommended to test the same SSRI-Compliant Contract on two level:

- On-chain Verification: Test with `ckb_testtools`
- Off-chain Query/Integration, Transaction Generations/Completions: Test with `ckb_ssri_cli` against the latest deployment.

## Key Concepts

### Execution Environment Levels

- Code: If only the code hash is provided, the execution environment level is Code;
- Script: If the code hash and args are both provided, the execution environment level is Script;
- Cell: If the CellInput / Outpoint is provided, the execution environment level is Cell;
- Transaction: If the Transaction Hash is provided, the execution environment level is Transaction; This is also the level of execution environment for regular CKB-VM when submitting transaction;
70 changes: 6 additions & 64 deletions ckb-ssri-std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
//!
//! ## Overview
//!
//! The SSRI (Standard Smart Contract Runtime Interface) std provides a standardized way to develop
//! smart contracts that are compliant with the SSRI protocol. This enables better interoperability
//! and a more consistent development experience across the CKB ecosystem.
//! - SSRI stands for `Script Sourced Rich Information`; it is a protocol for strong bindings of relevant information and conventions to the Script itself on CKB. For more information, please read [[EN/CN] Script-Sourced Rich Information - 来源于 Script 的富信息](https://talk.nervos.org/t/en-cn-script-sourced-rich-information-script/8256)>.
//! - For writing CKB Scripts (or "Smart Contracts"), by selectively implementing methods of public module traits (e.g. `UDT`, `UDTExtended`, `UDTPausable`) in combinations, devs would be able to quickly design and organize functionalities that either validate transactions or provide rich information as well as assembling transactions off-chain.
//! - For dApps or other infrastructures that interact with CKB Scripts, you no longer need to retrieve and parse data or assemble transactions by yourself repetitively as they are all provided by SSRI.

//!
//! ## Features
//!
//! - **Public Traits**: Pre-defined interfaces that receive first-class support within the ecosystem
//! - **Utility Functions**: Helper functions for SSRI-VM syscalls and data handling
//! - **Procedural Macros**: Simplify contract development with automatic SSRI method generation
//! - **No Standard Library**: Designed for the constrained smart contract environment
//!
//! ## Usage
//!
Expand All @@ -25,20 +25,7 @@
//! ```
//!
//! ## Example
//!
//! ```rust,no_run
//! use ckb_ssri_std::prelude::*;
//! use ckb_ssri_std::public_module_traits::udt::UDT;
//!
//! // Implement a basic UDT (User-Defined Token)
//! #[derive(Default)]
//! struct MyToken;
//!
//! impl UDT for MyToken {
//! type Error = ();
//! // ... implement required methods
//! }
//! ```
//! [`pausable-udt`](https://github.com/ckb-devrel/pausable-udt) is a real production level contract (instead of a pseudo-project) that exemplifies the usage of SSRI.

pub mod public_module_traits;
pub mod prelude;
Expand All @@ -50,55 +37,10 @@ pub use macros::*;

extern crate alloc;

// macro_rules! ssri_entry {
// ( $( $module:path ),* $(,)? ) => {
// pub fn unified_dispatch(namespace_and_function: &str, args: Vec<&str>) -> Result<String, crate::error::DispatchError> {
// $(
// let argv = ckb_std::env::argv();
// if argv.is_empty() {
// return fallback::fallback().map(|_| ());
// }

// if vm_version() != u64::MAX {
// return Err(Error::InvalidVmVersion);
// }

// set_content(&res)?;
// if $module::EXPOSED_FUNCTIONS.contains(&namespace_and_function) {
// return $module::dispatch_function(namespace_and_function, args);
// }
// )*
// Err(crate::error::DispatchError::FunctionNotFound)
// }

// pub fn get_methods() -> Vec<&'static str> {
// let mut methods = Vec::new();
// $(
// methods.extend_from_slice($module::EXPOSED_FUNCTIONS);
// )*
// methods
// }
// };
// }

#[repr(i8)]
#[derive(Debug)]
/// Represents possible errors that can occur during SSRI method execution
///
/// This enum provides a standardized set of errors that can occur when executing
/// SSRI methods. These errors help identify issues with method discovery,
/// argument validation, implementation status, and environment compatibility.
///
/// # Examples
///
/// ```rust
/// use ckb_ssri_std::SSRIError;
///
/// fn example_handler() -> Result<(), SSRIError> {
/// // Method implementation missing
/// Err(SSRIError::SSRIMethodsNotImplemented)
/// }
/// ```
/// Should be derivable to `Error` for the actual script to use.
pub enum SSRIError {
/// The requested SSRI method was not found in the contract
SSRIMethodsNotFound,
Expand Down
21 changes: 1 addition & 20 deletions ckb-ssri-std/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,7 @@
//! Re-exports of procedural macros from ckb-ssri-std-proc-macro
//!
//! This module provides convenient access to all procedural macros defined in the
//! `ckb-ssri-std-proc-macro` crate. These macros are essential for implementing
//! SSRI-compliant smart contracts.
//! `ckb-ssri-std-proc-macro` crate.
//!
//! # Available Macros
//!
//! - `ssri_module`: Marks a module as an SSRI-compliant module
//! - `ssri_method`: Marks a function as an exposed SSRI method
//!
//! # Example
//!
//! ```ignore
//! use ckb_ssri_std::macros::*;
//!
//! #[ssri_module]
//! mod my_contract {
//! #[ssri_method]
//! fn my_method() -> Result<(), Error> {
//! // Implementation
//! }
//! }
//! ```

pub use ckb_ssri_std_proc_macro::*;
10 changes: 6 additions & 4 deletions ckb-ssri-std/src/public_module_traits/udt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use ckb_std::ckb_types::{
extern crate alloc;

use alloc::vec::Vec;
use alloc::string::String;
use serde::{Deserialize, Serialize};
use serde_molecule::dynvec_serde;

/// User-Defined Token (UDT) trait for implementing custom tokens on CKB
///
Expand All @@ -15,8 +17,9 @@ use serde::{Deserialize, Serialize};
/// # Implementation Notes
///
/// - All amounts are represented as u128 in convention
/// - Methods that modify state return a Transaction that must be committed
/// - Methods that modify state return a Transaction object for further processing in CCC.
/// - Verification methods are separate from state-changing methods
/// - All methods are optional to implement: you return SSRIError::SSRIMethodsNotImplemented if you don't implement a method.
///
/// # Example
///
Expand All @@ -28,9 +31,9 @@ use serde::{Deserialize, Serialize};
/// impl UDT for MyToken {
/// type Error = ();
///
/// fn balance() -> Result<u128, Self::Error> {
/// fn decimals() -> Result<u8, Self::Error> {
/// // Implementation
/// Ok(0)
/// Ok(6u8)
/// }
/// // ... implement other required methods
/// }
Expand Down Expand Up @@ -62,7 +65,6 @@ pub enum UDTError {
}

pub trait UDTPausable: UDT {
/* NOTE: Pausing/Unpause without lock hashes should take effect on the global level */
fn pause(
tx: Option<Transaction>,
lock_hashes: &Vec<[u8; 32]>,
Expand Down
Loading