From 2bfd6f93966f7d8a86522ad9897cc45332bc8ee7 Mon Sep 17 00:00:00 2001 From: wanghui Date: Tue, 28 Jun 2022 18:15:10 +0800 Subject: [PATCH] [rpc] add raw field into BlockView to support get raw block --- cmd/starcoin/src/chain/get_block_cmd.rs | 19 ++++++- rpc/api/src/chain/mod.rs | 3 ++ rpc/api/src/types.rs | 32 ++++++++++- rpc/generated_rpc_schema/chain.json | 71 +++++++++++++++++++++++++ rpc/server/src/module/chain_rpc.rs | 12 +++-- rpc/server/src/module/pubsub.rs | 1 + 6 files changed, 131 insertions(+), 7 deletions(-) diff --git a/cmd/starcoin/src/chain/get_block_cmd.rs b/cmd/starcoin/src/chain/get_block_cmd.rs index d2c2f6d1fd..3e6a6e1e11 100644 --- a/cmd/starcoin/src/chain/get_block_cmd.rs +++ b/cmd/starcoin/src/chain/get_block_cmd.rs @@ -23,6 +23,9 @@ pub enum HashOrNumber { pub struct GetBlockOpt { #[clap(name = "hash-or-number")] hash_or_number: HashOrNumber, + + #[clap(name = "contains-raw-block")] + raw: bool, } impl FromStr for HashOrNumber { @@ -52,10 +55,22 @@ impl CommandAction for GetBlockCommand { let opt = ctx.opt(); let block = match opt.hash_or_number { HashOrNumber::Hash(hash) => client - .chain_get_block_by_hash(hash, Some(GetBlockOption { decode: true }))? + .chain_get_block_by_hash( + hash, + Some(GetBlockOption { + decode: true, + raw: opt.raw, + }), + )? .ok_or_else(|| anyhow::format_err!("block of hash {} not found", hash))?, HashOrNumber::Number(number) => client - .chain_get_block_by_number(number, Some(GetBlockOption { decode: true }))? + .chain_get_block_by_number( + number, + Some(GetBlockOption { + decode: true, + raw: opt.raw, + }), + )? .ok_or_else(|| anyhow::format_err!("block of height {} not found", number))?, }; Ok(block) diff --git a/rpc/api/src/chain/mod.rs b/rpc/api/src/chain/mod.rs index 293969c776..7ec60573d2 100644 --- a/rpc/api/src/chain/mod.rs +++ b/rpc/api/src/chain/mod.rs @@ -123,6 +123,9 @@ pub struct GetTransactionOption { pub struct GetBlockOption { #[serde(default)] pub decode: bool, + + #[serde(default)] + pub raw: bool, } #[derive(Copy, Clone, Default, Serialize, Deserialize, JsonSchema)] diff --git a/rpc/api/src/types.rs b/rpc/api/src/types.rs index bd0f763363..01e85c5ded 100644 --- a/rpc/api/src/types.rs +++ b/rpc/api/src/types.rs @@ -744,15 +744,42 @@ impl From> for BlockTransactionsView { } } +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct RawBlockView { + /// Raw block header that encoded in hex format. + pub header: String, + + /// Raw block body that encoded in hex format. + pub body: String, +} + +impl TryFrom<&Block> for RawBlockView { + type Error = anyhow::Error; + + fn try_from(value: &Block) -> Result { + let header = hex::encode(bcs_ext::to_bytes(value.header())?); + let body = hex::encode(bcs_ext::to_bytes(&value.body)?); + Ok(Self { header, body }) + } +} + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] pub struct BlockView { pub header: BlockHeaderView, pub body: BlockTransactionsView, pub uncles: Vec, + + /// Raw block data that can be verified by block_hash and body_hash. + pub raw: Option, } impl BlockView { - pub fn try_from_block(block: Block, thin: bool) -> Result { + pub fn try_from_block(block: Block, thin: bool, raw: bool) -> Result { + let raw_block: Option = if raw { + Some(RawBlockView::try_from(&block)?) + } else { + None + }; let (header, body) = block.into_inner(); let BlockBody { transactions, @@ -771,6 +798,7 @@ impl BlockView { .map(|h| h.into()) .collect(), body: txns_view, + raw: raw_block, }) } } @@ -779,7 +807,7 @@ impl TryFrom for BlockView { type Error = anyhow::Error; fn try_from(block: Block) -> Result { - Self::try_from_block(block, false) + Self::try_from_block(block, false, false) } } diff --git a/rpc/generated_rpc_schema/chain.json b/rpc/generated_rpc_schema/chain.json index 3a8ba542f8..a2a83f3b6f 100644 --- a/rpc/generated_rpc_schema/chain.json +++ b/rpc/generated_rpc_schema/chain.json @@ -265,6 +265,10 @@ "decode": { "default": false, "type": "boolean" + }, + "raw": { + "default": false, + "type": "boolean" } } } @@ -664,6 +668,27 @@ } } }, + "raw": { + "description": "Raw block data that can be verified by block_hash and body_hash.", + "type": [ + "object", + "null" + ], + "required": [ + "body", + "header" + ], + "properties": { + "body": { + "description": "Raw block body that encoded in hex format.", + "type": "string" + }, + "header": { + "description": "Raw block header that encoded in hex format.", + "type": "string" + } + } + }, "uncles": { "type": "array", "items": { @@ -791,6 +816,10 @@ "decode": { "default": false, "type": "boolean" + }, + "raw": { + "default": false, + "type": "boolean" } } } @@ -1190,6 +1219,27 @@ } } }, + "raw": { + "description": "Raw block data that can be verified by block_hash and body_hash.", + "type": [ + "object", + "null" + ], + "required": [ + "body", + "header" + ], + "properties": { + "body": { + "description": "Raw block body that encoded in hex format.", + "type": "string" + }, + "header": { + "description": "Raw block header that encoded in hex format.", + "type": "string" + } + } + }, "uncles": { "type": "array", "items": { @@ -1711,6 +1761,27 @@ } } }, + "raw": { + "description": "Raw block data that can be verified by block_hash and body_hash.", + "type": [ + "object", + "null" + ], + "required": [ + "body", + "header" + ], + "properties": { + "body": { + "description": "Raw block body that encoded in hex format.", + "type": "string" + }, + "header": { + "description": "Raw block header that encoded in hex format.", + "type": "string" + } + } + }, "uncles": { "type": "array", "items": { diff --git a/rpc/server/src/module/chain_rpc.rs b/rpc/server/src/module/chain_rpc.rs index 5aa3224f48..ceb6578e9a 100644 --- a/rpc/server/src/module/chain_rpc.rs +++ b/rpc/server/src/module/chain_rpc.rs @@ -83,10 +83,13 @@ where ) -> FutureResult> { let service = self.service.clone(); let decode = option.unwrap_or_default().decode; + let raw = option.unwrap_or_default().raw; let storage = self.storage.clone(); let fut = async move { let result = service.get_block_by_hash(hash).await?; - let mut block: Option = result.map(|b| b.try_into()).transpose()?; + let mut block: Option = result + .map(|b| BlockView::try_from_block(b, false, raw)) + .transpose()?; if decode { let state = ChainStateDB::new( storage, @@ -110,11 +113,14 @@ where ) -> FutureResult> { let service = self.service.clone(); let decode = option.unwrap_or_default().decode; + let raw = option.unwrap_or_default().raw; let storage = self.storage.clone(); let fut = async move { let result = service.main_block_by_number(number).await?; - let mut block: Option = result.map(|b| b.try_into()).transpose()?; + let mut block: Option = result + .map(|b| BlockView::try_from_block(b, false, raw)) + .transpose()?; if decode { let state = ChainStateDB::new( storage, @@ -153,7 +159,7 @@ where block .into_iter() - .map(|blk| BlockView::try_from_block(blk, true)) + .map(|blk| BlockView::try_from_block(blk, true, false)) .collect::, _>>() } .map_err(map_err); diff --git a/rpc/server/src/module/pubsub.rs b/rpc/server/src/module/pubsub.rs index b242cba42c..ba3a110e9b 100644 --- a/rpc/server/src/module/pubsub.rs +++ b/rpc/server/src/module/pubsub.rs @@ -499,6 +499,7 @@ impl EventHandler> for NewHeadHandler { header: block.header.into(), body: block.body.into(), uncles: vec![], + raw: None, })))] } }