diff --git a/README.md b/README.md index fd2943e..749497f 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,10 @@ Submits a new transaction and broadcast it to network peers curl http://localhost:9000/ -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "send_transaction", "params": [{"cell_deps":[{"dep_type":"dep_group","out_point":{"index":"0x0","tx_hash":"0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37"}}],"header_deps":[],"inputs":[{"previous_output":{"index":"0x7","tx_hash":"0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f"},"since":"0x0"}],"outputs":[{"capacity":"0x470de4df820000","lock":{"args":"0xff5094c2c5f476fc38510018609a3fd921dd28ad","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null},{"capacity":"0xb61134e5a35e800","lock":{"args":"0x64257f00b6b63e987609fa9be2d0c86d351020fb","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null}],"outputs_data":["0x","0x"],"version":"0x0","witnesses":["0x5500000010000000550000005500000041000000af34b54bebf8c5971da6a880f2df5a186c3f8d0b5c9a1fe1a90c95b8a4fb89ef3bab1ccec13797dcb3fee80400f953227dd7741227e08032e3598e16ccdaa49c00"]}], "id": 1}' ``` +### `estimate_cycles` + +This RPC method is the same as CKB's, please refer to [CKB JSON-RPC Protocols](https://github.com/nervosnetwork/ckb/tree/develop/rpc#method-estimate_cycles). + ### `get_tip_header` Returns the header with the highest block number in the canonical chain diff --git a/src/service.rs b/src/service.rs index 4913b82..f67015e 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,7 +1,8 @@ use ckb_chain_spec::consensus::Consensus; use ckb_jsonrpc_types::{ - BlockNumber, BlockView, Capacity, CellOutput, Cycle, HeaderView, JsonBytes, NodeAddress, - OutPoint, RemoteNodeProtocol, Script, Transaction, TransactionView, Uint32, Uint64, + BlockNumber, BlockView, Capacity, CellOutput, Cycle, EstimateCycles, HeaderView, JsonBytes, + NodeAddress, OutPoint, RemoteNodeProtocol, Script, Transaction, TransactionView, Uint32, + Uint64, }; use ckb_network::{extract_peer_id, NetworkController}; use ckb_systemtime::unix_time_as_millis; @@ -90,6 +91,9 @@ pub trait ChainRpc { #[rpc(name = "fetch_header")] fn fetch_header(&self, block_hash: H256) -> Result>; + + #[rpc(name = "estimate_cycles")] + fn estimate_cycles(&self, tx: Transaction) -> Result; } #[rpc(server)] @@ -386,6 +390,7 @@ pub struct TransactionRpcImpl { pub struct ChainRpcImpl { pub(crate) swc: StorageWithChainData, + pub(crate) consensus: Arc, } pub struct NetRpcImpl { @@ -1293,6 +1298,16 @@ impl ChainRpc for ChainRpcImpl { timestamp: now.into(), }) } + + fn estimate_cycles(&self, tx: Transaction) -> Result { + let tx: packed::Transaction = tx.into(); + let tx = tx.into_view(); + let cycles = verify_tx(tx.clone(), &self.swc, Arc::clone(&self.consensus)) + .map_err(|e| Error::invalid_params(format!("invalid transaction: {:?}", e)))?; + Ok(EstimateCycles { + cycles: cycles.into(), + }) + } } pub(crate) struct Service { @@ -1316,12 +1331,13 @@ impl Service { ) -> Server { let mut io_handler = IoHandler::new(); let swc = StorageWithChainData::new(storage, Arc::clone(&peers), Arc::clone(&pending_txs)); + let consensus = Arc::new(consensus); let block_filter_rpc_impl = BlockFilterRpcImpl { swc: swc.clone() }; - let chain_rpc_impl = ChainRpcImpl { swc: swc.clone() }; - let transaction_rpc_impl = TransactionRpcImpl { - swc, - consensus: Arc::new(consensus), + let chain_rpc_impl = ChainRpcImpl { + swc: swc.clone(), + consensus: Arc::clone(&consensus), }; + let transaction_rpc_impl = TransactionRpcImpl { swc, consensus }; let net_rpc_impl = NetRpcImpl { network_controller, peers, diff --git a/src/tests/service.rs b/src/tests/service.rs index 56f86d1..d46b7e7 100644 --- a/src/tests/service.rs +++ b/src/tests/service.rs @@ -777,7 +777,10 @@ fn rpc() { let swc = StorageWithChainData::new(storage.clone(), Arc::clone(&peers), Default::default()); - let rpc = ChainRpcImpl { swc }; + let rpc = ChainRpcImpl { + swc, + consensus: Arc::new(Consensus::default()), + }; let header = rpc .get_header(pre_block.header().hash().unpack()) .unwrap()