Skip to content

feat(rpc): add IPC call #4861

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

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open

feat(rpc): add IPC call #4861

wants to merge 15 commits into from

Conversation

mohanson
Copy link
Contributor

@mohanson mohanson commented Mar 27, 2025

What is changed and how it works?

What's Changed:

Added an ipc_call method in jsonrpc. The method is described in detail in rpc/src/module/ipc.rs's comments.

/// Call the ipc method in the script.
///
/// ## Params
///
/// * script_locator:
///     - out_point - Reference to the cell by transaction hash and output index.
///     - type_id_args - Reference to the cell by type id type script args.
/// * req:
///     - version - IPC protocol version. Default is 0.
///     - method_id - IPC protocol method id. Default is 0.
///     - payload_format - The format of payload.
///     - payload - Payload.
/// * env: The transaction environment that the ipc script depends on. The script specified by script_group_type + script_hash will be executed, but the script binary will be replaced by the ipc script.
///     - tx - The transaction.
///     - script_group_type - Script group type.
///     - script_hash - Script hash.
///
/// ## Returns
///
/// * version - IPC protocol version. Default is 0.
/// * error_code - IPC error code.
/// * payload_format - The format of payload.
/// * payload - Payload.
///
/// ## Examples
///
/// Request
///
/// ```json
/// {
///     "id": 2,
///     "jsonrpc": "2.0",
///     "method": "ipc_call",
///     "params": [
///         {
///             "out_point": {
///                 "tx_hash": "0x4e75e1d4dddc0efe5e028168f627e3af436f1002b61038d695b24aa8441ffaf5",
///                 "index": "0x0"
///             }
///         },
///         {
///             "version": "0x0",
///             "method_id": "0x0",
///             "payload_format": "json",
///             "payload": {
///                 "SyscallLoadScript": {}
///             }
///         },
///         {
///             "tx": {
///                 "version": "0x0",
///                 "cell_deps": [
///                     {
///                         "out_point": {
///                             "tx_hash": "0xe7db03de9c534cb63d951f5378d5a4fbf43a2ebf5e48cb626562d188a3697772",
///                             "index": "0x0"
///                         },
///                         "dep_type": "dep_group"
///                     }
///                 ],
///                 "header_deps": [],
///                 "inputs": [
///                     {
///                         "since": "0x0",
///                         "previous_output": {
///                             "tx_hash": "0x953d1a4b95cefca9588b6d0bf7e97084bb51010ce87d1bcbe65c0ccd621781b8",
///                             "index": "0x0"
///                         }
///                     }
///                 ],
///                 "outputs": [],
///                 "outputs_data": [],
///                 "witnesses": [
///                     "0x55000000100000005500000055000000410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
///                 ]
///             },
///             "script_group_type": "lock",
///             "script_hash": "0x0b1bae4beaf456349c63c3ce67491fc75a1276d7f9eedd7ea84d6a77f9f3f5f7"
///         }
///     ]
/// }
/// ```
///
/// Response
///
/// ```json
/// {
///     "jsonrpc": "2.0",
///     "result": {
///         "error_code": "0x0",
///         "payload": {
///             "SyscallLoadScript": "0x490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8011400000075178f34549c5fe9cd1a0c57aebd01e7ddf9249e"
///         },
///         "payload_format": "json",
///         "version": "0x0"
///     }
///     "id": 2
/// }
/// 

Here are some additional points to note:

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code ci-runs-only: [ quick_checks,linters ]

Release note

Note: Add a note under the PR title in the release note.

@mohanson mohanson requested a review from a team as a code owner March 27, 2025 09:45
@mohanson mohanson requested review from doitian and removed request for a team March 27, 2025 09:45
Copy link
Collaborator

@eval-exec eval-exec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please execute make gen-rpc-doc

@eval-exec eval-exec requested a review from driftluo March 27, 2025 10:20
@eval-exec eval-exec added t:enhancement Type: Feature, refactoring. b:rpc Break RPC interface labels Mar 27, 2025
@eval-exec eval-exec added this to Kanban Mar 27, 2025
@eval-exec eval-exec moved this to 🏗 In progress in Kanban Mar 27, 2025
@mohanson
Copy link
Contributor Author

Please execute make gen-rpc-doc

Done

@eval-exec eval-exec added the m:vm label Mar 28, 2025
Comment on lines +775 to +819
payload: match fmt {
IpcPayloadFormat::Hex => Value::String(format!("0x{}", hex_string(resp.payload()))),
IpcPayloadFormat::Json => {
serde_from_str::<Value>(String::from_utf8_lossy(resp.payload()).as_ref())
.map_err(|e| RPCError::custom_with_error(RPCError::IPC, e))?
}
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should change the payload's type to String instead of serde_json::Value?

Copy link
Contributor Author

@mohanson mohanson Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the design document, Payload needs to support two formats. The first is json object, for example:

{
  "Payload": {
    "MethodName": { "Parameter": "Value" } 
  }
}

The second is Hex mode, for example

{
  "Payload": "0x0000000001111111122222..."
}

It seems that only serde_json::Value can be used to define its type.

@eval-exec eval-exec requested a review from Copilot March 31, 2025 12:47
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds IPC call functionality to the RPC module by introducing a new ckb-ipc utility crate, updating the RPC service builder to support the IPC module, and extending documentation and tests accordingly.

  • Added a new ckb-ipc module with VLQ encoding/decoding utilities, pipe communication, packet definitions, and error types.
  • Extended the RPC configuration, service builder, and documentation to support the new IPC module.
  • Updated workspace and dependency configurations to include the new ckb-ipc module.

Reviewed Changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated no comments.

Show a summary per file
File Description
util/ipc/src/vlq.rs Implements VLQ encoding/decoding functions for IPC messages
util/ipc/src/pipe.rs Adds a bidirectional pipe implementation for IPC communication
util/ipc/src/packet.rs Defines IPC packet structures and serialization methods
util/ipc/src/lib.rs Re-exports IPC components
util/ipc/src/error.rs Implements custom error types for IPC
util/app-config/src/configs/rpc.rs Introduces IPC module support in the configuration
script/src/syscalls/mod.rs Adds syscall id constants for IPC-related operations
rpc/src/tests/setup.rs Integrates IPC module enablement into the RPC test suite
rpc/src/service_builder.rs Adds enable_ipc method and related changes to include IPC RPC methods
rpc/src/module/mod.rs Exposes new IPC module and related RPC method definitions
rpc/src/module/indexer.rs Adjusts visibility of IndexerRpcImpl affecting module exposure
rpc/src/error.rs Adds error codes for IPC-related errors
rpc/README.md Updates documentation with IPC module details and examples
(Other files) Workspace and dependency updates to include the new ckb-ipc module
Comments suppressed due to low confidence (3)

util/ipc/src/pipe.rs:84

  • [nitpick] Consider using a more descriptive error message for the missing receiver channel, e.g., 'Receiver channel not available', to aid debugging.
.rx.as_ref().ok_or_else(|| Error::new(ErrorKind::Other, "channel is not found"))?

util/ipc/src/pipe.rs:110

  • [nitpick] Consider revising the error message to clearly indicate that the sender channel is missing, for example, 'Sender channel not available'.
.tx.as_mut().ok_or_else(|| Error::new(ErrorKind::Other, "channel is not found"))?

rpc/src/module/indexer.rs:887

  • The visibility of IndexerRpcImpl was changed from 'pub(crate)' to 'pub'. Please ensure this change is intentional to avoid exposing internal implementation details.
pub struct IndexerRpcImpl {

@mohanson mohanson force-pushed the ipc branch 2 times, most recently from 1c29cba to 39962ad Compare April 17, 2025 11:36
@gpBlockchain
Copy link
Collaborator

LGTM

zhangsoledad
zhangsoledad previously approved these changes Apr 24, 2025
);
let builder = builder.enable_debug();
let builder = builder.enable_alert(alert_verifier, alert_notifier, network_controller);
let indexer_rpc_impl = builder.indexer_rpc_impl.clone();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any specific reason to don't use chain call style here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I need to clone a copy of indexer_rpc_impl, which cannot be achieved using chain call.

.map(|e| e.into_bytes())?)
}
None => Err(RPCError::custom(
RPCError::IPCIndexerIsDisabled,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems from the code, if IPC module is not enabled, ipc_script_data_by_type_id_args will never be called here.
it's not necessary to add a RPCError::IPCIndexerIsDisabled code for it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never mind, it's not IPC module here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if IPC module is enabled, it will require Index module required, could we just validate this rule when parsed config file.
otherwise user can only figure out this rule when error happened.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the script_locator parameter of ipc_call is type_id_args, it will depend on indexer;
When it is out_point, it will not depend on indexer.

So it can only be checked at runtime.

debug_assert_eq!(scheduler.consumed_cycles(), 0);
let tic = std::time::SystemTime::now();
loop {
let last_cycles = limit_cycles as u64 - scheduler.consumed_cycles();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a risk of overflow here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are better off using the saturating_sub method

break;
}
let toc = tic.elapsed().map(|e| e.as_secs()).unwrap_or(u64::MAX);
if toc >= limit_time as u64 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if timeout, whether we should report an error for endpoint?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
b:rpc Break RPC interface m:vm t:enhancement Type: Feature, refactoring.
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

5 participants