Skip to content

Commit e20b4bd

Browse files
author
Eason
committed
feat: add axon exclusive rpc
1 parent 950a9bb commit e20b4bd

7 files changed

Lines changed: 137 additions & 12 deletions

File tree

core/api/src/jsonrpc/impl/axon.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use std::sync::Arc;
2+
3+
use jsonrpsee::core::Error;
4+
5+
use protocol::async_trait;
6+
use protocol::traits::{APIAdapter, Context};
7+
use protocol::types::{Block, Proof};
8+
9+
use crate::jsonrpc::web3_types::BlockId;
10+
use crate::jsonrpc::{AxonRpcServer, RpcResult};
11+
12+
pub struct AxonRpcImpl<Adapter> {
13+
adapter: Arc<Adapter>,
14+
}
15+
16+
impl<Adapter: APIAdapter> AxonRpcImpl<Adapter> {
17+
pub fn new(adapter: Arc<Adapter>) -> Self {
18+
AxonRpcImpl { adapter }
19+
}
20+
}
21+
22+
#[async_trait]
23+
impl<Adapter: APIAdapter + 'static> AxonRpcServer for AxonRpcImpl<Adapter> {
24+
async fn get_block_by_id(&self, block_id: BlockId) -> RpcResult<Option<Block>> {
25+
let ret = match block_id {
26+
BlockId::Hash(hash) => self.adapter.get_block_by_hash(Context::new(), hash).await,
27+
BlockId::Num(num) => {
28+
self.adapter
29+
.get_block_by_number(Context::new(), Some(num.as_u64()))
30+
.await
31+
}
32+
_ => return Err(Error::InvalidRequestId),
33+
}
34+
.map_err(|e| Error::Custom(e.to_string()))?;
35+
36+
Ok(ret)
37+
}
38+
39+
async fn get_proof_by_id(&self, block_id: BlockId) -> RpcResult<Option<Proof>> {
40+
let ret = self
41+
.get_block_by_id(block_id)
42+
.await?
43+
.map(|b| b.header.proof);
44+
Ok(ret)
45+
}
46+
}

core/api/src/jsonrpc/impl/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
mod axon;
12
mod ckb_light_client;
23
mod filter;
34
mod node;
45
mod web3;
56

7+
pub use axon::AxonRpcImpl;
68
pub use ckb_light_client::CkbLightClientRpcImpl;
79
pub use filter::filter_module;
810
pub use node::NodeRpcImpl;

core/api/src/jsonrpc/impl/web3.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::jsonrpc::web3_types::{
2323
BlockId, RichTransactionOrHash, Web3Block, Web3CallRequest, Web3FeeHistory, Web3Filter,
2424
Web3Log, Web3Receipt, Web3Transaction,
2525
};
26-
use crate::jsonrpc::{error::RpcError, AxonWeb3RpcServer, RpcResult};
26+
use crate::jsonrpc::{error::RpcError, RpcResult, Web3RpcServer};
2727
use crate::APIError;
2828

2929
pub(crate) const MAX_LOG_NUM: usize = 10000;
@@ -90,7 +90,7 @@ impl<Adapter: APIAdapter> Web3RpcImpl<Adapter> {
9090
}
9191

9292
#[async_trait]
93-
impl<Adapter: APIAdapter + 'static> AxonWeb3RpcServer for Web3RpcImpl<Adapter> {
93+
impl<Adapter: APIAdapter + 'static> Web3RpcServer for Web3RpcImpl<Adapter> {
9494
#[metrics_rpc("eth_sendRawTransaction")]
9595
async fn send_raw_transaction(&self, tx: Hex) -> RpcResult<H256> {
9696
let utx = UnverifiedTransaction::decode(&tx.as_bytes())

core/api/src/jsonrpc/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use jsonrpsee::{core::Error, proc_macros::rpc};
1111

1212
use common_config_parser::types::Config;
1313
use protocol::traits::APIAdapter;
14-
use protocol::types::{Hash, Hex, H160, H256, U256};
14+
use protocol::types::{Block, Hash, Hex, Proof, H160, H256, U256};
1515
use protocol::ProtocolResult;
1616

1717
use crate::jsonrpc::web3_types::{
@@ -24,7 +24,7 @@ use crate::APIError;
2424
type RpcResult<T> = Result<T, Error>;
2525

2626
#[rpc(server)]
27-
pub trait AxonWeb3Rpc {
27+
pub trait Web3Rpc {
2828
/// Sends signed transaction, returning its hash.
2929
#[method(name = "eth_sendRawTransaction")]
3030
async fn send_raw_transaction(&self, tx: Hex) -> RpcResult<H256>;
@@ -140,6 +140,7 @@ pub trait AxonWeb3Rpc {
140140

141141
#[method(name = "eth_getUncleCountByBlockHash")]
142142
async fn get_uncle_count_by_block_hash(&self, hash: Hash) -> RpcResult<U256>;
143+
143144
#[method(name = "eth_getUncleCountByBlockNumber")]
144145
async fn get_uncle_count_by_block_number(&self, number: BlockId) -> RpcResult<U256>;
145146
}
@@ -201,6 +202,15 @@ pub trait AxonNodeRpc {
201202
fn pprof(&self, enable: bool) -> RpcResult<bool>;
202203
}
203204

205+
#[rpc(server)]
206+
pub trait AxonRpc {
207+
#[method(name = "axon_getBlockById")]
208+
async fn get_block_by_id(&self, block_id: BlockId) -> RpcResult<Option<Block>>;
209+
210+
#[method(name = "axon_getProofById")]
211+
async fn get_proof_by_id(&self, block_id: BlockId) -> RpcResult<Option<Proof>>;
212+
}
213+
204214
#[rpc(server)]
205215
pub trait CkbLightClientRpc {
206216
#[method(name = "ckb_getBlockHeaderByHash")]
@@ -223,10 +233,12 @@ pub async fn run_jsonrpc_server<Adapter: APIAdapter + 'static>(
223233
let mut rpc = r#impl::Web3RpcImpl::new(Arc::clone(&adapter), config.rpc.gas_cap).into_rpc();
224234
let node_rpc =
225235
r#impl::NodeRpcImpl::new(&config.rpc.client_version, config.data_path).into_rpc();
236+
let axon_rpc = r#impl::AxonRpcImpl::new(Arc::clone(&adapter)).into_rpc();
226237
let filter = r#impl::filter_module(Arc::clone(&adapter)).into_rpc();
227238
let ckb_light_client_rpc = r#impl::CkbLightClientRpcImpl::default().into_rpc();
228239

229240
rpc.merge(node_rpc).unwrap();
241+
rpc.merge(axon_rpc).unwrap();
230242
rpc.merge(filter).unwrap();
231243
rpc.merge(ckb_light_client_rpc).unwrap();
232244

core/storage/src/adapter/rocks.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ impl RocksAdapter {
3737
map_category(StorageCategory::Wal),
3838
map_category(StorageCategory::HashHeight),
3939
map_category(StorageCategory::Code),
40-
map_category(StorageCategory::CkbCrossChain),
41-
map_category(StorageCategory::IbcCrossChain),
4240
];
4341

4442
let (mut opts, cf_descriptors) = if let Some(ref file) = config.options_file {
@@ -286,8 +284,6 @@ const C_RECEIPTS: &str = "c4";
286284
const C_WALS: &str = "c5";
287285
const C_HASH_HEIGHT_MAP: &str = "c6";
288286
const C_EVM_CODE_MAP: &str = "c7";
289-
const C_CKB_CROSSCHAIN_MAP: &str = "c8";
290-
const C_IBC_CROSSCHAIN_MAP: &str = "c9";
291287

292288
fn map_category(c: StorageCategory) -> &'static str {
293289
match c {
@@ -298,8 +294,6 @@ fn map_category(c: StorageCategory) -> &'static str {
298294
StorageCategory::Wal => C_WALS,
299295
StorageCategory::HashHeight => C_HASH_HEIGHT_MAP,
300296
StorageCategory::Code => C_EVM_CODE_MAP,
301-
StorageCategory::CkbCrossChain => C_CKB_CROSSCHAIN_MAP,
302-
StorageCategory::IbcCrossChain => C_IBC_CROSSCHAIN_MAP,
303297
}
304298
}
305299

protocol/src/traits/storage.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ pub enum StorageCategory {
1010
Wal,
1111
HashHeight,
1212
Code,
13-
CkbCrossChain,
14-
IbcCrossChain,
1513
}
1614

1715
pub type StorageIterator<'a, S> = Box<

protocol/src/types/block.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@ pub struct Proposal {
2020
pub prev_state_root: MerkleRoot,
2121
pub transactions_root: MerkleRoot,
2222
pub signed_txs_hash: Hash,
23+
#[serde(serialize_with = "serde_hex::serialize_uint")]
2324
pub timestamp: u64,
25+
#[serde(serialize_with = "serde_hex::serialize_uint")]
2426
pub number: BlockNumber,
2527
pub gas_limit: U256,
28+
#[serde(serialize_with = "serde_hex::serialize_bytes")]
2629
pub extra_data: Bytes,
2730
pub mixed_hash: Option<Hash>,
2831
pub base_fee_per_gas: U256,
2932
pub proof: Proof,
33+
#[serde(serialize_with = "serde_hex::serialize_uint")]
3034
pub chain_id: u64,
35+
#[serde(serialize_with = "serde_hex::serialize_uint")]
3136
pub call_system_script_count: u32,
3237
pub tx_hashes: Vec<Hash>,
3338
}
@@ -145,16 +150,21 @@ pub struct Header {
145150
pub receipts_root: MerkleRoot,
146151
pub log_bloom: Bloom,
147152
pub difficulty: U256,
153+
#[serde(serialize_with = "serde_hex::serialize_uint")]
148154
pub timestamp: u64,
155+
#[serde(serialize_with = "serde_hex::serialize_uint")]
149156
pub number: BlockNumber,
150157
pub gas_used: U256,
151158
pub gas_limit: U256,
159+
#[serde(serialize_with = "serde_hex::serialize_bytes")]
152160
pub extra_data: Bytes,
153161
pub mixed_hash: Option<Hash>,
154162
pub nonce: H64,
155163
pub base_fee_per_gas: U256,
156164
pub proof: Proof,
165+
#[serde(serialize_with = "serde_hex::serialize_uint")]
157166
pub call_system_script_count: u32,
167+
#[serde(serialize_with = "serde_hex::serialize_uint")]
158168
pub chain_id: u64,
159169
}
160170

@@ -172,10 +182,14 @@ impl Header {
172182
RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq,
173183
)]
174184
pub struct Proof {
185+
#[serde(serialize_with = "serde_hex::serialize_uint")]
175186
pub number: u64,
187+
#[serde(serialize_with = "serde_hex::serialize_uint")]
176188
pub round: u64,
177189
pub block_hash: Hash,
190+
#[serde(serialize_with = "serde_hex::serialize_bytes")]
178191
pub signature: Bytes,
192+
#[serde(serialize_with = "serde_hex::serialize_bytes")]
179193
pub bitmap: Bytes,
180194
}
181195

@@ -185,6 +199,65 @@ pub struct RichBlock {
185199
pub txs: Vec<SignedTransaction>,
186200
}
187201

202+
mod serde_hex {
203+
use serde::Serializer;
204+
205+
use crate::types::{Bytes, Hex, U256};
206+
207+
static CHARS: &[u8] = b"0123456789abcdef";
208+
209+
pub fn serialize_bytes<S>(val: &Bytes, s: S) -> Result<S::Ok, S::Error>
210+
where
211+
S: Serializer,
212+
{
213+
s.serialize_str(&Hex::encode(val).as_string())
214+
}
215+
216+
pub fn serialize_uint<S, U>(val: &U, s: S) -> Result<S::Ok, S::Error>
217+
where
218+
S: Serializer,
219+
U: Into<U256> + Copy,
220+
{
221+
let val: U256 = (*val).into();
222+
let mut slice = [0u8; 2 + 64];
223+
let mut bytes = [0u8; 32];
224+
val.to_big_endian(&mut bytes);
225+
let non_zero = bytes.iter().take_while(|b| **b == 0).count();
226+
let bytes = &bytes[non_zero..];
227+
228+
if bytes.is_empty() {
229+
s.serialize_str("0x0")
230+
} else {
231+
s.serialize_str(to_hex_raw(&mut slice, bytes, true))
232+
}
233+
}
234+
235+
fn to_hex_raw<'a>(v: &'a mut [u8], bytes: &[u8], skip_leading_zero: bool) -> &'a str {
236+
assert!(v.len() > 1 + bytes.len() * 2);
237+
238+
v[0] = b'0';
239+
v[1] = b'x';
240+
241+
let mut idx = 2;
242+
let first_nibble = bytes[0] >> 4;
243+
if first_nibble != 0 || !skip_leading_zero {
244+
v[idx] = CHARS[first_nibble as usize];
245+
idx += 1;
246+
}
247+
v[idx] = CHARS[(bytes[0] & 0xf) as usize];
248+
idx += 1;
249+
250+
for &byte in bytes.iter().skip(1) {
251+
v[idx] = CHARS[(byte >> 4) as usize];
252+
v[idx + 1] = CHARS[(byte & 0xf) as usize];
253+
idx += 2;
254+
}
255+
256+
// SAFETY: all characters come either from CHARS or "0x", therefore valid UTF8
257+
unsafe { std::str::from_utf8_unchecked(&v[0..idx]) }
258+
}
259+
}
260+
188261
#[cfg(test)]
189262
mod tests {
190263
use crate::types::{

0 commit comments

Comments
 (0)