From 8f098857254b13532bca873e845741ca4090de6e Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 15:06:20 +0400 Subject: [PATCH 01/12] Allow blocks to be serialized to json for RPC --- Cargo.lock | 3 + chainstate/src/rpc.rs | 12 +++- common/src/address/pubkeyhash.rs | 2 +- common/src/chain/block/block_body/mod.rs | 2 +- common/src/chain/block/block_header.rs | 2 +- common/src/chain/block/block_reward.rs | 2 +- common/src/chain/block/block_v1.rs | 2 +- common/src/chain/block/consensus_data.rs | 6 +- common/src/chain/block/mod.rs | 2 +- common/src/chain/block/signed_block_header.rs | 8 ++- common/src/chain/tokens/mod.rs | 6 +- common/src/chain/tokens/nft.rs | 6 +- common/src/chain/transaction/account_nonce.rs | 2 +- .../src/chain/transaction/account_outpoint.rs | 4 +- common/src/chain/transaction/input.rs | 2 +- common/src/chain/transaction/mod.rs | 2 +- common/src/chain/transaction/output/mod.rs | 4 +- .../chain/transaction/output/output_value.rs | 2 +- .../src/chain/transaction/output/stakelock.rs | 2 +- .../src/chain/transaction/output/timelock.rs | 2 +- .../transaction/signature/inputsig/mod.rs | 2 +- .../signature/inputsig/standard_signature.rs | 2 +- .../signature/sighash/sighashtype.rs | 2 +- .../chain/transaction/signed_transaction.rs | 2 +- .../src/chain/transaction/transaction_v1.rs | 2 +- common/src/chain/transaction/utxo_outpoint.rs | 4 +- common/src/primitives/compact.rs | 2 +- common/src/primitives/per_thousand.rs | 2 +- common/src/primitives/version_tag.rs | 6 ++ crypto/Cargo.toml | 2 + crypto/src/key/mod.rs | 6 ++ crypto/src/key/signature/mod.rs | 7 ++- crypto/src/vrf/mod.rs | 6 ++ crypto/src/vrf/primitives.rs | 2 +- crypto/src/vrf/schnorrkel/data.rs | 6 ++ serialization/Cargo.toml | 1 + serialization/src/extras/non_empty_vec.rs | 2 +- serialization/src/hex_encoded.rs | 8 ++- serialization/src/json_encoded.rs | 62 +++++++++++++++++++ serialization/src/lib.rs | 1 + 40 files changed, 158 insertions(+), 42 deletions(-) create mode 100644 serialization/src/json_encoded.rs diff --git a/Cargo.lock b/Cargo.lock index e7dae286f5..6c475da631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1510,6 +1510,8 @@ dependencies = [ "rstest", "schnorrkel", "secp256k1", + "serde", + "serde_json", "serialization", "sha-1 0.10.1", "sha2 0.10.7", @@ -5624,6 +5626,7 @@ version = "0.1.1" dependencies = [ "hex", "serde", + "serde_json", "serialization-core", "serialization-tagged", "thiserror", diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index d43f3801db..27570f5b74 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -26,7 +26,7 @@ use common::{ primitives::{Amount, BlockHeight, Id}, }; use rpc::Result as RpcResult; -use serialization::hex_encoded::HexEncoded; +use serialization::{hex_encoded::HexEncoded, json_encoded::JsonEncoded}; #[rpc::rpc(server, client, namespace = "chainstate")] trait ChainstateRpc { @@ -42,6 +42,10 @@ trait ChainstateRpc { #[method(name = "get_block")] async fn get_block(&self, id: Id) -> RpcResult>>; + /// Returns a hex-encoded serialized block with the given id. + #[method(name = "get_block_json")] + async fn get_block_json(&self, id: Id) -> RpcResult>; + /// Returns a hex-encoded serialized blocks from the mainchain starting from a given block height. #[method(name = "get_mainchain_blocks")] async fn get_mainchain_blocks( @@ -117,6 +121,12 @@ impl ChainstateRpcServer for super::ChainstateHandle { Ok(block.map(HexEncoded::new)) } + async fn get_block_json(&self, id: Id) -> RpcResult> { + let block: Option = + rpc::handle_result(self.call(move |this| this.get_block(id)).await)?; + Ok(block.map(JsonEncoded::new).map(|blk| blk.to_string())) + } + async fn get_mainchain_blocks( &self, from: BlockHeight, diff --git a/common/src/address/pubkeyhash.rs b/common/src/address/pubkeyhash.rs index 5cce126076..4d4bfb2a67 100644 --- a/common/src/address/pubkeyhash.rs +++ b/common/src/address/pubkeyhash.rs @@ -31,7 +31,7 @@ pub enum PublicKeyHashError { const HASH_SIZE: usize = 20; fixed_hash::construct_fixed_hash! { - #[derive(Encode, Decode)] + #[derive(Encode, Decode, serde::Serialize)] pub struct PublicKeyHash(HASH_SIZE); } diff --git a/common/src/chain/block/block_body/mod.rs b/common/src/chain/block/block_body/mod.rs index 9a21c59225..4ad98b5ebc 100644 --- a/common/src/chain/block/block_body/mod.rs +++ b/common/src/chain/block/block_body/mod.rs @@ -36,7 +36,7 @@ pub enum BlockMerkleTreeError { } #[must_use] -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub struct BlockBody { pub(super) reward: BlockReward, pub(super) transactions: Vec, diff --git a/common/src/chain/block/block_header.rs b/common/src/chain/block/block_header.rs index f0fc32b2b9..6423efa874 100644 --- a/common/src/chain/block/block_header.rs +++ b/common/src/chain/block/block_header.rs @@ -22,7 +22,7 @@ use crate::primitives::id::{Id, Idable, H256}; use crate::primitives::{id, VersionTag}; #[must_use] -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serialization::Tagged)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serialization::Tagged, serde::Serialize)] pub struct BlockHeader { pub(super) version: VersionTag<1>, pub(super) prev_block_id: Id, diff --git a/common/src/chain/block/block_reward.rs b/common/src/chain/block/block_reward.rs index 0dbc0d7e04..ee1939bd67 100644 --- a/common/src/chain/block/block_reward.rs +++ b/common/src/chain/block/block_reward.rs @@ -24,7 +24,7 @@ use crate::{ }; /// Represents a block reward. -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub struct BlockReward { reward_outputs: Vec, } diff --git a/common/src/chain/block/block_v1.rs b/common/src/chain/block/block_v1.rs index 18b0535644..a1ccee2aa4 100644 --- a/common/src/chain/block/block_v1.rs +++ b/common/src/chain/block/block_v1.rs @@ -28,7 +28,7 @@ use super::{ }; #[must_use] -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serialization::Tagged)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serialization::Tagged, serde::Serialize)] pub struct BlockV1 { pub(super) header: SignedBlockHeader, pub(super) body: BlockBody, diff --git a/common/src/chain/block/consensus_data.rs b/common/src/chain/block/consensus_data.rs index 40b496233f..b12e47526f 100644 --- a/common/src/chain/block/consensus_data.rs +++ b/common/src/chain/block/consensus_data.rs @@ -24,7 +24,7 @@ use serialization::{Decode, Encode}; use super::timestamp::BlockTimestamp; -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub enum ConsensusData { #[codec(index = 0)] None, @@ -59,7 +59,7 @@ impl ConsensusData { } /// Data required to validate a block according to the PoS consensus rules. -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub struct PoSData { /// Inputs for block reward kernel_inputs: Vec, @@ -117,7 +117,7 @@ impl PoSData { } } -#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Encode, Decode, serde::Serialize)] pub struct PoWData { bits: Compact, nonce: u128, diff --git a/common/src/chain/block/mod.rs b/common/src/chain/block/mod.rs index 6b427abefd..539c76a694 100644 --- a/common/src/chain/block/mod.rs +++ b/common/src/chain/block/mod.rs @@ -60,7 +60,7 @@ pub enum BlockCreationError { WitnessMerkleTreeMismatch(H256, H256), } -#[derive(Debug, Clone, PartialEq, Eq, DirectEncode, DirectDecode, TypeName)] +#[derive(Debug, Clone, PartialEq, Eq, DirectEncode, DirectDecode, TypeName, serde::Serialize)] #[must_use] pub enum Block { V1(BlockV1), diff --git a/common/src/chain/block/signed_block_header.rs b/common/src/chain/block/signed_block_header.rs index ced98b1e82..c48e1da730 100644 --- a/common/src/chain/block/signed_block_header.rs +++ b/common/src/chain/block/signed_block_header.rs @@ -27,7 +27,7 @@ pub enum SignedHeaderError { AttemptedMutatingSignedHeader, } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeName)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeName, serde::Serialize)] pub struct BlockHeaderSignatureData { signature: Signature, } @@ -43,7 +43,7 @@ impl BlockHeaderSignatureData { } #[must_use] -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeName)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeName, serde::Serialize)] pub enum BlockHeaderSignature { #[codec(index = 0)] None, @@ -51,7 +51,9 @@ pub enum BlockHeaderSignature { HeaderSignature(BlockHeaderSignatureData), } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeName, serialization::Tagged)] +#[derive( + Debug, Clone, PartialEq, Eq, Encode, Decode, TypeName, serialization::Tagged, serde::Serialize, +)] pub struct SignedBlockHeader { block_header: BlockHeader, signature_data: BlockHeaderSignature, diff --git a/common/src/chain/tokens/mod.rs b/common/src/chain/tokens/mod.rs index a457dd337d..47aaa49e19 100644 --- a/common/src/chain/tokens/mod.rs +++ b/common/src/chain/tokens/mod.rs @@ -91,13 +91,13 @@ impl TokenAuxiliaryData { } } -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, serde::Serialize)] pub struct TokenTransfer { pub token_id: TokenId, pub amount: Amount, } -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, serde::Serialize)] pub struct TokenIssuance { pub token_ticker: Vec, pub amount_to_issue: Amount, @@ -105,7 +105,7 @@ pub struct TokenIssuance { pub metadata_uri: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub enum TokenData { /// TokenTransfer data to another user. If it is a token, then the token data must also be transferred to the recipient. #[codec(index = 1)] diff --git a/common/src/chain/tokens/nft.rs b/common/src/chain/tokens/nft.rs index cf016b3fe0..6ab348f6c9 100644 --- a/common/src/chain/tokens/nft.rs +++ b/common/src/chain/tokens/nft.rs @@ -16,14 +16,14 @@ use crypto::key::PublicKey; use serialization::{extras::non_empty_vec::DataOrNoVec, Decode, Encode}; -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub struct NftIssuance { pub metadata: Metadata, // TODO: Implement after additional research payout, royalty and refund. // Payout might be Multisig contract with amount enforcement. } -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, serde::Serialize)] pub struct TokenCreator { pub public_key: PublicKey, } @@ -34,7 +34,7 @@ impl From for TokenCreator { } } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub struct Metadata { pub creator: Option, pub name: Vec, diff --git a/common/src/chain/transaction/account_nonce.rs b/common/src/chain/transaction/account_nonce.rs index e1da687f4c..54bf682c36 100644 --- a/common/src/chain/transaction/account_nonce.rs +++ b/common/src/chain/transaction/account_nonce.rs @@ -18,7 +18,7 @@ use serialization::{Decode, Encode}; /// An incremental value that represents sequential number of spending from an account. /// It's equivalent to the nonce in Ethereum and helps preserving order of transactions and /// avoid transaction replay. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Encode, Decode)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Encode, Decode, serde::Serialize)] pub struct AccountNonce(#[codec(compact)] u64); impl AccountNonce { diff --git a/common/src/chain/transaction/account_outpoint.rs b/common/src/chain/transaction/account_outpoint.rs index 17b19fa5f7..a88652863f 100644 --- a/common/src/chain/transaction/account_outpoint.rs +++ b/common/src/chain/transaction/account_outpoint.rs @@ -37,14 +37,14 @@ impl From for AccountType { /// The type represents the amount to withdraw from a particular account. /// Otherwise it's unclear how much should be deducted from an account balance. /// It also helps solving 2 additional problems: calculating fees and providing ability to sign input balance with the witness. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Encode, Decode)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Encode, Decode, serde::Serialize)] pub enum AccountSpending { #[codec(index = 0)] Delegation(DelegationId, Amount), } /// Type of OutPoint that represents spending from an account -#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Encode, Decode, serde::Serialize)] pub struct AccountOutPoint { nonce: AccountNonce, account: AccountSpending, diff --git a/common/src/chain/transaction/input.rs b/common/src/chain/transaction/input.rs index 0c794fa724..2c04d07243 100644 --- a/common/src/chain/transaction/input.rs +++ b/common/src/chain/transaction/input.rs @@ -19,7 +19,7 @@ use crate::chain::AccountNonce; use super::{AccountOutPoint, AccountSpending, OutPointSourceId, UtxoOutPoint}; -#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Encode, Decode, serde::Serialize)] pub enum TxInput { Utxo(UtxoOutPoint), Account(AccountOutPoint), diff --git a/common/src/chain/transaction/mod.rs b/common/src/chain/transaction/mod.rs index de473ba670..47c85d1320 100644 --- a/common/src/chain/transaction/mod.rs +++ b/common/src/chain/transaction/mod.rs @@ -54,7 +54,7 @@ pub enum TransactionSize { SmartContractTransaction(usize), } -#[derive(Debug, Clone, PartialEq, Eq, DirectEncode, DirectDecode, TypeName)] +#[derive(Debug, Clone, PartialEq, Eq, DirectEncode, DirectDecode, TypeName, serde::Serialize)] pub enum Transaction { V1(TransactionV1), } diff --git a/common/src/chain/transaction/output/mod.rs b/common/src/chain/transaction/output/mod.rs index 2740c7c548..05e171cb15 100644 --- a/common/src/chain/transaction/output/mod.rs +++ b/common/src/chain/transaction/output/mod.rs @@ -28,7 +28,7 @@ pub mod output_value; pub mod stakelock; pub mod timelock; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, serde::Serialize)] pub enum Destination { #[codec(index = 0)] AnyoneCanSpend, // zero verification; used primarily for testing. Never use this for real money @@ -62,7 +62,7 @@ impl Addressable for Destination { } } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub enum TxOutput { #[codec(index = 0)] Transfer(OutputValue, Destination), diff --git a/common/src/chain/transaction/output/output_value.rs b/common/src/chain/transaction/output/output_value.rs index 314925bc88..5169009fce 100644 --- a/common/src/chain/transaction/output/output_value.rs +++ b/common/src/chain/transaction/output/output_value.rs @@ -20,7 +20,7 @@ use crate::{ primitives::Amount, }; -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, serde::Serialize)] pub enum OutputValue { Coin(Amount), Token(Box), diff --git a/common/src/chain/transaction/output/stakelock.rs b/common/src/chain/transaction/output/stakelock.rs index 55bda2b2df..1ef46c2bd5 100644 --- a/common/src/chain/transaction/output/stakelock.rs +++ b/common/src/chain/transaction/output/stakelock.rs @@ -20,7 +20,7 @@ use crate::primitives::{per_thousand::PerThousand, Amount}; use super::Destination; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, serde::Serialize)] pub struct StakePoolData { value: Amount, staker: Destination, diff --git a/common/src/chain/transaction/output/timelock.rs b/common/src/chain/transaction/output/timelock.rs index 69a2760891..c55c76730a 100644 --- a/common/src/chain/transaction/output/timelock.rs +++ b/common/src/chain/transaction/output/timelock.rs @@ -17,7 +17,7 @@ use serialization::{Decode, Encode}; use crate::{chain::block::timestamp::BlockTimestamp, primitives::BlockHeight}; -#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Encode, Decode, serde::Serialize)] pub enum OutputTimeLock { #[codec(index = 0)] UntilHeight(BlockHeight), diff --git a/common/src/chain/transaction/signature/inputsig/mod.rs b/common/src/chain/transaction/signature/inputsig/mod.rs index 43e8e344b0..100bbb3c45 100644 --- a/common/src/chain/transaction/signature/inputsig/mod.rs +++ b/common/src/chain/transaction/signature/inputsig/mod.rs @@ -22,7 +22,7 @@ use serialization::{Decode, Encode}; use standard_signature::StandardInputSignature; -#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize)] pub enum InputWitness { #[codec(index = 0)] NoSignature(Option>), diff --git a/common/src/chain/transaction/signature/inputsig/standard_signature.rs b/common/src/chain/transaction/signature/inputsig/standard_signature.rs index 79435de1a7..a3e56f14ec 100644 --- a/common/src/chain/transaction/signature/inputsig/standard_signature.rs +++ b/common/src/chain/transaction/signature/inputsig/standard_signature.rs @@ -43,7 +43,7 @@ use super::{ }, }; -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize)] pub struct StandardInputSignature { sighash_type: SigHashType, raw_signature: Vec, diff --git a/common/src/chain/transaction/signature/sighash/sighashtype.rs b/common/src/chain/transaction/signature/sighash/sighashtype.rs index a36f0bdae0..d78fd277f3 100644 --- a/common/src/chain/transaction/signature/sighash/sighashtype.rs +++ b/common/src/chain/transaction/signature/sighash/sighashtype.rs @@ -20,7 +20,7 @@ use super::TransactionSigError; /// Specifies which parts of the transaction a signature commits to. /// /// The values of the flags are the same as in Bitcoin. -#[derive(Eq, PartialEq, Clone, Copy, Encode, Debug, Ord, PartialOrd)] +#[derive(Eq, PartialEq, Clone, Copy, Encode, Debug, Ord, PartialOrd, serde::Serialize)] pub struct SigHashType(u8); impl SigHashType { diff --git a/common/src/chain/transaction/signed_transaction.rs b/common/src/chain/transaction/signed_transaction.rs index a85f17e254..6c9f03746d 100644 --- a/common/src/chain/transaction/signed_transaction.rs +++ b/common/src/chain/transaction/signed_transaction.rs @@ -21,7 +21,7 @@ use crate::{ use serialization::{Decode, Encode}; use utils::ensure; -#[derive(Debug, Clone, PartialEq, Eq, Encode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, serde::Serialize)] pub struct SignedTransaction { transaction: Transaction, signatures: Vec, diff --git a/common/src/chain/transaction/transaction_v1.rs b/common/src/chain/transaction/transaction_v1.rs index ffc2a7a298..b68055d6e6 100644 --- a/common/src/chain/transaction/transaction_v1.rs +++ b/common/src/chain/transaction/transaction_v1.rs @@ -22,7 +22,7 @@ use serialization::{Decode, Encode, Tagged}; use super::Transaction; -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Tagged)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Tagged, serde::Serialize)] pub struct TransactionV1 { version: VersionTag<1>, #[codec(compact)] diff --git a/common/src/chain/transaction/utxo_outpoint.rs b/common/src/chain/transaction/utxo_outpoint.rs index dba5a17bae..46a4cc374d 100644 --- a/common/src/chain/transaction/utxo_outpoint.rs +++ b/common/src/chain/transaction/utxo_outpoint.rs @@ -17,7 +17,7 @@ use crate::chain::{transaction::Transaction, Block, GenBlock, Genesis}; use crate::primitives::Id; use serialization::{Decode, Encode}; -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Ord, PartialOrd, serde::Serialize)] pub enum OutPointSourceId { #[codec(index = 0)] Transaction(Id), @@ -58,7 +58,7 @@ impl OutPointSourceId { } } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Ord, PartialOrd, serde::Serialize)] pub struct UtxoOutPoint { id: OutPointSourceId, index: u32, diff --git a/common/src/primitives/compact.rs b/common/src/primitives/compact.rs index 84d02f1cb2..fa70431839 100644 --- a/common/src/primitives/compact.rs +++ b/common/src/primitives/compact.rs @@ -17,7 +17,7 @@ use crate::uint::Uint256; use serialization::{Decode, Encode}; use std::ops::Shl; -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Encode, Decode)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Encode, Decode, serde::Serialize)] pub struct Compact(pub u32); impl std::fmt::Debug for Compact { diff --git a/common/src/primitives/per_thousand.rs b/common/src/primitives/per_thousand.rs index 3ef74e2d17..37e9b06383 100644 --- a/common/src/primitives/per_thousand.rs +++ b/common/src/primitives/per_thousand.rs @@ -18,7 +18,7 @@ use serialization::{Decode, Encode, Error, Input}; use super::Amount; -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Debug)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Debug, serde::Serialize)] pub struct PerThousand(u16); impl PerThousand { diff --git a/common/src/primitives/version_tag.rs b/common/src/primitives/version_tag.rs index fe8b9b5b2a..0d532df502 100644 --- a/common/src/primitives/version_tag.rs +++ b/common/src/primitives/version_tag.rs @@ -25,6 +25,12 @@ impl Default for VersionTag { } } +impl serde::Serialize for VersionTag { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_u8(V) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index c68bf9c00b..1739df8ded 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -28,6 +28,8 @@ parity-scale-codec.workspace = true rand.workspace = true ripemd.workspace = true schnorrkel.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true sha-1.workspace = true sha2.workspace = true sha3.workspace = true diff --git a/crypto/src/key/mod.rs b/crypto/src/key/mod.rs index 04e5863365..bca38e790b 100644 --- a/crypto/src/key/mod.rs +++ b/crypto/src/key/mod.rs @@ -56,6 +56,12 @@ pub struct PublicKey { pub_key: PublicKeyHolder, } +impl serde::Serialize for PublicKey { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_bytes(&self.encode()) + } +} + impl PrivateKey { pub fn new_from_entropy(key_kind: KeyKind) -> (PrivateKey, PublicKey) { Self::new_from_rng(&mut make_true_rng(), key_kind) diff --git a/crypto/src/key/signature/mod.rs b/crypto/src/key/signature/mod.rs index eaa4e715c7..b759ba9b8b 100644 --- a/crypto/src/key/signature/mod.rs +++ b/crypto/src/key/signature/mod.rs @@ -24,12 +24,17 @@ pub enum SignatureKind { Secp256k1Schnorr = 0, } -// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum Signature { Secp256k1Schnorr(secp256k1::schnorr::Signature), } +impl serde::Serialize for Signature { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_bytes(&self.encode()) + } +} + impl Encode for Signature { fn encode(&self) -> Vec { let mut buf = BufWriter::new(Vec::new()); diff --git a/crypto/src/vrf/mod.rs b/crypto/src/vrf/mod.rs index ba57d20290..9353a7c411 100644 --- a/crypto/src/vrf/mod.rs +++ b/crypto/src/vrf/mod.rs @@ -70,6 +70,12 @@ pub struct VRFPublicKey { pub_key: VRFPublicKeyHolder, } +impl serde::Serialize for VRFPublicKey { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_bytes(&self.encode()) + } +} + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Decode, Encode)] pub(crate) enum VRFPublicKeyHolder { #[codec(index = 0)] diff --git a/crypto/src/vrf/primitives.rs b/crypto/src/vrf/primitives.rs index 124ee68d1a..1dcf59304e 100644 --- a/crypto/src/vrf/primitives.rs +++ b/crypto/src/vrf/primitives.rs @@ -18,7 +18,7 @@ use serialization::{Decode, Encode}; use super::schnorrkel::data::SchnorrkelVRFReturn; #[must_use] -#[derive(Clone, Debug, Eq, PartialEq, Encode, Decode)] +#[derive(Clone, Debug, Eq, PartialEq, Encode, Decode, serde::Serialize)] pub enum VRFReturn { Schnorrkel(SchnorrkelVRFReturn), } diff --git a/crypto/src/vrf/schnorrkel/data.rs b/crypto/src/vrf/schnorrkel/data.rs index 77b47affcd..a27fcda4f3 100644 --- a/crypto/src/vrf/schnorrkel/data.rs +++ b/crypto/src/vrf/schnorrkel/data.rs @@ -39,6 +39,12 @@ pub struct SchnorrkelVRFReturn { proof: VRFProof, } +impl serde::Serialize for SchnorrkelVRFReturn { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_bytes(&self.encode()) + } +} + impl Encode for SchnorrkelVRFReturn { fn size_hint(&self) -> usize { SCHNORKEL_RETURN_SIZE diff --git a/serialization/Cargo.toml b/serialization/Cargo.toml index 8bd9417180..780837e71d 100644 --- a/serialization/Cargo.toml +++ b/serialization/Cargo.toml @@ -11,4 +11,5 @@ serialization-tagged = { path = 'tagged' } hex.workspace = true serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true thiserror.workspace = true diff --git a/serialization/src/extras/non_empty_vec.rs b/serialization/src/extras/non_empty_vec.rs index 4620fa1c13..7ecf83a650 100644 --- a/serialization/src/extras/non_empty_vec.rs +++ b/serialization/src/extras/non_empty_vec.rs @@ -21,7 +21,7 @@ use serialization_core::{Decode, Encode}; /// - If the Vec has data, it encodes to just the Vec, the Option is omitted /// - If the Vec has no data, it encodes to None /// - Some(vec![]) and None are equivalent when encoded, but when decoded result in None -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] pub struct DataOrNoVec(Option>); impl AsRef>> for DataOrNoVec { diff --git a/serialization/src/hex_encoded.rs b/serialization/src/hex_encoded.rs index ec19bfd0cd..ef3b389dff 100644 --- a/serialization/src/hex_encoded.rs +++ b/serialization/src/hex_encoded.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::str::FromStr; +use std::{fmt::Display, str::FromStr}; use crate::hex::{HexDecode, HexEncode, HexError}; @@ -65,3 +65,9 @@ impl FromStr for HexEncoded { ::hex_decode_all(s).map(Self) } } + +impl Display for HexEncoded { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.0.hex_encode()) + } +} diff --git a/serialization/src/json_encoded.rs b/serialization/src/json_encoded.rs new file mode 100644 index 0000000000..2e745b0944 --- /dev/null +++ b/serialization/src/json_encoded.rs @@ -0,0 +1,62 @@ +// Copyright (c) 2023 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::fmt::Display; + +/// Wrapper that serializes objects as json encoded string for `serde` +#[derive(Debug, Clone)] +pub struct JsonEncoded(T); + +impl JsonEncoded { + pub fn new(value: T) -> Self { + Self(value) + } + + pub fn take(self) -> T { + self.0 + } +} + +impl AsRef for JsonEncoded { + fn as_ref(&self) -> &T { + &self.0 + } +} + +impl From for JsonEncoded { + fn from(value: T) -> Self { + Self(value) + } +} + +impl serde::Serialize for JsonEncoded { + fn serialize(&self, serializer: S) -> Result { + self.0.serialize(serializer) + } +} + +impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for JsonEncoded { + fn deserialize>(deserializer: D) -> Result { + T::deserialize(deserializer).map(Self) + } +} + +impl Display for JsonEncoded { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str( + &serde_json::to_string(&self.0).unwrap_or("".to_string()), + ) + } +} diff --git a/serialization/src/lib.rs b/serialization/src/lib.rs index 9d37024f29..8956440e8f 100644 --- a/serialization/src/lib.rs +++ b/serialization/src/lib.rs @@ -19,6 +19,7 @@ pub mod encoded; pub mod extras; pub mod hex; pub mod hex_encoded; +pub mod json_encoded; // Re-export all the constituent parts pub use serialization_core::*; From 93d2150891d8933a0095d7980ded2c54316fe082 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 15:12:25 +0400 Subject: [PATCH 02/12] Add custom from_str implementation for JsonEncoded --- serialization/src/json_encoded.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/serialization/src/json_encoded.rs b/serialization/src/json_encoded.rs index 2e745b0944..3a347090de 100644 --- a/serialization/src/json_encoded.rs +++ b/serialization/src/json_encoded.rs @@ -29,6 +29,13 @@ impl JsonEncoded { } } +impl<'de, T: serde::Deserialize<'de>> JsonEncoded { + // We cannot use FromStr because of the lifetime limitation + pub fn from_str(s: &'de str) -> Result { + serde_json::from_str(s) + } +} + impl AsRef for JsonEncoded { fn as_ref(&self) -> &T { &self.0 From 005e5d3885bc68334b3e65243e05f4e9e49f09f1 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 15:13:54 +0400 Subject: [PATCH 03/12] Minor comment fix --- chainstate/src/rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index 27570f5b74..317f7a4cc5 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -42,7 +42,7 @@ trait ChainstateRpc { #[method(name = "get_block")] async fn get_block(&self, id: Id) -> RpcResult>>; - /// Returns a hex-encoded serialized block with the given id. + /// Returns a json-encoded serialized block with the given id. #[method(name = "get_block_json")] async fn get_block_json(&self, id: Id) -> RpcResult>; From 09eeae0917f52986db18cc67e245827373aa6f54 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 16:54:37 +0400 Subject: [PATCH 04/12] Add get_transaction function and related functions --- chainstate/src/detail/chainstateref/mod.rs | 37 ++++++++++++++++++- chainstate/src/detail/query.rs | 14 ++++++- .../src/interface/chainstate_interface.rs | 7 +++- .../interface/chainstate_interface_impl.rs | 23 +++++++++++- .../chainstate_interface_impl_delegation.rs | 13 ++++++- chainstate/src/rpc.rs | 19 +++++++++- chainstate/storage/src/internal/mod.rs | 4 +- chainstate/storage/src/internal/store_tx.rs | 6 +-- chainstate/storage/src/internal/test.rs | 10 +++-- chainstate/storage/src/lib.rs | 6 ++- chainstate/storage/src/mock/mock_impl.rs | 9 +++-- .../src/tests/chainstate_storage_tests.rs | 18 ++++++++- chainstate/types/src/error.rs | 2 + mocks/src/chainstate.rs | 9 ++++- serialization/src/json_encoded.rs | 2 +- 15 files changed, 151 insertions(+), 28 deletions(-) diff --git a/chainstate/src/detail/chainstateref/mod.rs b/chainstate/src/detail/chainstateref/mod.rs index fc14515814..6000de4b72 100644 --- a/chainstate/src/detail/chainstateref/mod.rs +++ b/chainstate/src/detail/chainstateref/mod.rs @@ -34,7 +34,7 @@ use common::{ tokens::TokenAuxiliaryData, tokens::{get_tokens_issuance_count, TokenId}, AccountNonce, AccountType, Block, ChainConfig, GenBlock, GenBlockId, OutPointSourceId, - Transaction, TxOutput, UtxoOutPoint, + SignedTransaction, Transaction, TxMainChainIndex, TxOutput, UtxoOutPoint, }, primitives::{id::WithId, BlockDistance, BlockHeight, Id, Idable}, time_getter::TimeGetter, @@ -162,6 +162,14 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat self.time_getter.get_time() } + pub fn get_is_transaction_index_enabled(&self) -> Result { + Ok(self + .db_tx + .get_is_mainchain_tx_index_enabled() + .map_err(PropertyQueryError::from)? + .expect("Must be set on node initialization")) + } + pub fn get_best_block_id(&self) -> Result, PropertyQueryError> { self.db_tx .get_best_block_id() @@ -188,11 +196,36 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat pub fn get_mainchain_tx_index( &self, tx_id: &OutPointSourceId, - ) -> Result, PropertyQueryError> { + ) -> Result, PropertyQueryError> { log::trace!("Loading transaction index of id: {:?}", tx_id); self.db_tx.get_mainchain_tx_index(tx_id).map_err(PropertyQueryError::from) } + pub fn get_transaction_in_block( + &self, + id: Id, + ) -> Result, PropertyQueryError> { + log::trace!("Loading whether tx index is enabled: {}", id); + let is_tx_index_enabled = self.get_is_transaction_index_enabled()?; + if !is_tx_index_enabled { + return Err(PropertyQueryError::TransactionIndexDisabled); + } + log::trace!("Loading transaction index with id: {}", id); + let tx_index = self.db_tx.get_mainchain_tx_index(&OutPointSourceId::Transaction(id))?; + let tx_index = match tx_index { + Some(tx_index) => tx_index, + None => return Ok(None), + }; + log::trace!("Loading transaction with id: {}", id); + let position = match tx_index.position() { + common::chain::SpendablePosition::Transaction(pos) => pos, + common::chain::SpendablePosition::BlockReward(_) => { + panic!("In get_transaction(), a tx id led to a block reward") + } + }; + Ok(self.db_tx.get_mainchain_tx_by_position(position)?) + } + pub fn get_block_id_by_height( &self, height: &BlockHeight, diff --git a/chainstate/src/detail/query.rs b/chainstate/src/detail/query.rs index b8a276c083..f0137528be 100644 --- a/chainstate/src/detail/query.rs +++ b/chainstate/src/detail/query.rs @@ -22,7 +22,8 @@ use common::{ RPCFungibleTokenInfo, RPCNonFungibleTokenInfo, RPCTokenInfo, TokenAuxiliaryData, TokenData, TokenId, }, - Block, GenBlock, OutPointSourceId, Transaction, TxMainChainIndex, TxOutput, + Block, GenBlock, OutPointSourceId, SignedTransaction, Transaction, TxMainChainIndex, + TxOutput, }, primitives::{BlockDistance, BlockHeight, Id, Idable}, }; @@ -145,6 +146,17 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat } } + pub fn is_transaction_index_enabled(&self) -> Result { + self.chainstate_ref.get_is_transaction_index_enabled() + } + + pub fn get_transaction_in_block( + &self, + id: Id, + ) -> Result, PropertyQueryError> { + self.chainstate_ref.get_transaction_in_block(id) + } + pub fn get_locator(&self) -> Result { let best_block_index = self .chainstate_ref diff --git a/chainstate/src/interface/chainstate_interface.rs b/chainstate/src/interface/chainstate_interface.rs index 44c80ea8e4..fe73d67403 100644 --- a/chainstate/src/interface/chainstate_interface.rs +++ b/chainstate/src/interface/chainstate_interface.rs @@ -22,7 +22,7 @@ use crate::{ChainInfo, ChainstateConfig, ChainstateError, ChainstateEvent}; use chainstate_types::{BlockIndex, EpochData, GenBlockIndex, Locator}; use common::chain::block::signed_block_header::SignedBlockHeader; -use common::chain::{AccountNonce, AccountType}; +use common::chain::{AccountNonce, AccountType, SignedTransaction}; use common::{ chain::{ block::{timestamp::BlockTimestamp, Block, BlockReward, GenBlock}, @@ -115,6 +115,11 @@ pub trait ChainstateInterface: Send { &self, starting_block: &Id, ) -> Result; + fn is_transaction_index_enabled(&self) -> Result; + fn get_transaction( + &self, + tx_id: &Id, + ) -> Result, ChainstateError>; fn is_already_an_orphan(&self, block_id: &Id) -> bool; fn orphans_count(&self) -> usize; fn get_ancestor( diff --git a/chainstate/src/interface/chainstate_interface_impl.rs b/chainstate/src/interface/chainstate_interface_impl.rs index 1058f0f5c9..e7c384e1b9 100644 --- a/chainstate/src/interface/chainstate_interface_impl.rs +++ b/chainstate/src/interface/chainstate_interface_impl.rs @@ -32,8 +32,8 @@ use common::{ block::{signed_block_header::SignedBlockHeader, Block, BlockReward, GenBlock}, config::ChainConfig, tokens::{RPCTokenInfo, TokenAuxiliaryData, TokenId}, - AccountNonce, AccountType, DelegationId, OutPointSourceId, PoolId, Transaction, TxInput, - TxMainChainIndex, TxOutput, UtxoOutPoint, + AccountNonce, AccountType, DelegationId, OutPointSourceId, PoolId, SignedTransaction, + Transaction, TxInput, TxMainChainIndex, TxOutput, UtxoOutPoint, }, primitives::{id::WithId, Amount, BlockHeight, Id}, }; @@ -579,6 +579,25 @@ impl ChainstateInterfa .get_account_nonce_count(account) .map_err(ChainstateError::FailedToReadProperty) } + + fn is_transaction_index_enabled(&self) -> Result { + self.chainstate + .query() + .map_err(ChainstateError::from)? + .is_transaction_index_enabled() + .map_err(ChainstateError::FailedToReadProperty) + } + + fn get_transaction( + &self, + tx_id: &Id, + ) -> Result, ChainstateError> { + self.chainstate + .query() + .map_err(ChainstateError::from)? + .get_transaction_in_block(*tx_id) + .map_err(ChainstateError::from) + } } // TODO: remove this function. The value of an output cannot be generalized and exposed from ChainstateInterface in such way diff --git a/chainstate/src/interface/chainstate_interface_impl_delegation.rs b/chainstate/src/interface/chainstate_interface_impl_delegation.rs index a98244fd31..b3d0dae517 100644 --- a/chainstate/src/interface/chainstate_interface_impl_delegation.rs +++ b/chainstate/src/interface/chainstate_interface_impl_delegation.rs @@ -25,7 +25,7 @@ use common::chain::{ block::{signed_block_header::SignedBlockHeader, timestamp::BlockTimestamp, BlockReward}, config::ChainConfig, tokens::TokenAuxiliaryData, - AccountNonce, AccountType, OutPointSourceId, TxMainChainIndex, + AccountNonce, AccountType, OutPointSourceId, SignedTransaction, TxMainChainIndex, }; use common::chain::{Transaction, UtxoOutPoint}; use common::{ @@ -342,6 +342,17 @@ where ) -> Result, ChainstateError> { self.deref().get_account_nonce_count(account) } + + fn is_transaction_index_enabled(&self) -> Result { + self.deref().is_transaction_index_enabled() + } + + fn get_transaction( + &self, + tx_id: &Id, + ) -> Result, ChainstateError> { + self.deref().get_transaction(tx_id) + } } #[cfg(test)] diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index 317f7a4cc5..1e7c381cb0 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -21,7 +21,7 @@ use crate::{Block, BlockSource, ChainInfo, GenBlock}; use common::{ chain::{ tokens::{RPCTokenInfo, TokenId}, - PoolId, + PoolId, SignedTransaction, Transaction, }, primitives::{Amount, BlockHeight, Id}, }; @@ -46,6 +46,14 @@ trait ChainstateRpc { #[method(name = "get_block_json")] async fn get_block_json(&self, id: Id) -> RpcResult>; + /// returns a hex-encoded transaction, assuming it's in the mainchain. + /// Note: The transaction index must be enabled in the node. + #[method(name = "get_transaction")] + async fn get_transaction( + &self, + id: Id, + ) -> RpcResult>>; + /// Returns a hex-encoded serialized blocks from the mainchain starting from a given block height. #[method(name = "get_mainchain_blocks")] async fn get_mainchain_blocks( @@ -127,6 +135,15 @@ impl ChainstateRpcServer for super::ChainstateHandle { Ok(block.map(JsonEncoded::new).map(|blk| blk.to_string())) } + async fn get_transaction( + &self, + id: Id, + ) -> RpcResult>> { + let tx: Option = + rpc::handle_result(self.call(move |this| this.get_transaction(&id)).await)?; + Ok(tx.map(HexEncoded::new)) + } + async fn get_mainchain_blocks( &self, from: BlockHeight, diff --git a/chainstate/storage/src/internal/mod.rs b/chainstate/storage/src/internal/mod.rs index b28f7ccb9a..c261fcdbf0 100644 --- a/chainstate/storage/src/internal/mod.rs +++ b/chainstate/storage/src/internal/mod.rs @@ -23,7 +23,7 @@ use common::{ tokens::{TokenAuxiliaryData, TokenId}, transaction::{Transaction, TxMainChainIndex, TxMainChainPosition}, AccountNonce, AccountType, Block, ChainConfig, DelegationId, GenBlock, OutPointSourceId, - PoolId, UtxoOutPoint, + PoolId, SignedTransaction, UtxoOutPoint, }, primitives::{Amount, BlockHeight, Id}, }; @@ -245,7 +245,7 @@ impl BlockchainStorageRead for Store { fn get_mainchain_tx_by_position( &self, tx_index: &TxMainChainPosition, - ) -> crate::Result>; + ) -> crate::Result>; fn get_block_id_by_height( &self, diff --git a/chainstate/storage/src/internal/store_tx.rs b/chainstate/storage/src/internal/store_tx.rs index 6d46d15e3c..284f1dba03 100644 --- a/chainstate/storage/src/internal/store_tx.rs +++ b/chainstate/storage/src/internal/store_tx.rs @@ -22,7 +22,7 @@ use common::{ tokens::{TokenAuxiliaryData, TokenId}, transaction::{Transaction, TxMainChainIndex, TxMainChainPosition}, AccountNonce, AccountType, Block, DelegationId, GenBlock, OutPointSourceId, PoolId, - UtxoOutPoint, + SignedTransaction, UtxoOutPoint, }, primitives::{Amount, BlockHeight, Id, Idable, H256}, }; @@ -143,7 +143,7 @@ macro_rules! impl_read_ops { fn get_mainchain_tx_by_position( &self, tx_index: &TxMainChainPosition, - ) -> crate::Result> { + ) -> crate::Result> { let block_id = tx_index.block_id(); match self.0.get::().get(block_id) { Err(e) => Err(e.into()), @@ -153,7 +153,7 @@ macro_rules! impl_read_ops { let begin = tx_index.byte_offset_in_block() as usize; let encoded_tx = block.get(begin..).expect("Transaction outside of block range"); - let tx = Transaction::decode(&mut &*encoded_tx) + let tx = SignedTransaction::decode(&mut &*encoded_tx) .expect("Invalid tx encoding in DB"); Ok(Some(tx)) } diff --git a/chainstate/storage/src/internal/test.rs b/chainstate/storage/src/internal/test.rs index 87c283d87e..d043e7e054 100644 --- a/chainstate/storage/src/internal/test.rs +++ b/chainstate/storage/src/internal/test.rs @@ -52,8 +52,10 @@ fn test_storage_manipulation() { // Prepare some test data let tx0 = Transaction::new(0xaabbccdd, vec![], vec![]).unwrap(); let tx1 = Transaction::new(0xbbccddee, vec![], vec![]).unwrap(); + let signed_tx0 = SignedTransaction::new(tx0.clone(), vec![]).expect("invalid witness count"); + let signed_tx1 = SignedTransaction::new(tx1.clone(), vec![]).expect("invalid witness count"); let block0 = Block::new( - vec![SignedTransaction::new(tx0.clone(), vec![]).expect("invalid witness count")], + vec![signed_tx0.clone()], Id::new(H256::default()), BlockTimestamp::from_int_seconds(12), ConsensusData::None, @@ -61,7 +63,7 @@ fn test_storage_manipulation() { ) .unwrap(); let block1 = Block::new( - vec![SignedTransaction::new(tx1.clone(), vec![]).expect("invalid witness count")], + vec![signed_tx1], Id::new(block0.get_id().get()), BlockTimestamp::from_int_seconds(34), ConsensusData::None, @@ -114,7 +116,7 @@ fn test_storage_manipulation() { let pos_tx0 = TxMainChainPosition::new(block0.get_id(), offset_tx0 as u32); assert_eq!( &store.get_mainchain_tx_by_position(&pos_tx0).unwrap().unwrap(), - &tx0 + &signed_tx0 ); // Test setting and retrieving best chain id @@ -144,7 +146,7 @@ fn test_storage_manipulation() { ); if let Ok(Some(index)) = store.get_mainchain_tx_index(&out_id_tx0) { if let SpendablePosition::Transaction(ref p) = index.position() { - assert_eq!(store.get_mainchain_tx_by_position(p), Ok(Some(tx0))); + assert_eq!(store.get_mainchain_tx_by_position(p), Ok(Some(signed_tx0))); } else { unreachable!(); }; diff --git a/chainstate/storage/src/lib.rs b/chainstate/storage/src/lib.rs index 1ffa025794..f4eaae4ef7 100644 --- a/chainstate/storage/src/lib.rs +++ b/chainstate/storage/src/lib.rs @@ -31,7 +31,9 @@ use common::chain::block::BlockReward; use common::chain::config::EpochIndex; use common::chain::tokens::{TokenAuxiliaryData, TokenId}; use common::chain::transaction::{Transaction, TxMainChainIndex, TxMainChainPosition}; -use common::chain::{AccountNonce, AccountType, Block, GenBlock, OutPointSourceId}; +use common::chain::{ + AccountNonce, AccountType, Block, GenBlock, OutPointSourceId, SignedTransaction, +}; use common::primitives::{BlockHeight, Id}; use pos_accounting::{ AccountingBlockUndo, DeltaMergeUndo, PoSAccountingDeltaData, PoSAccountingStorageRead, @@ -93,7 +95,7 @@ pub trait BlockchainStorageRead: fn get_mainchain_tx_by_position( &self, tx_index: &TxMainChainPosition, - ) -> crate::Result>; + ) -> crate::Result>; /// Get mainchain block by its height fn get_block_id_by_height(&self, height: &BlockHeight) -> crate::Result>>; diff --git a/chainstate/storage/src/mock/mock_impl.rs b/chainstate/storage/src/mock/mock_impl.rs index 48a73f222b..735e31ebc9 100644 --- a/chainstate/storage/src/mock/mock_impl.rs +++ b/chainstate/storage/src/mock/mock_impl.rs @@ -25,7 +25,8 @@ use common::{ block::BlockReward, config::EpochIndex, transaction::{OutPointSourceId, Transaction, TxMainChainIndex, TxMainChainPosition}, - AccountNonce, AccountType, Block, DelegationId, GenBlock, PoolId, UtxoOutPoint, + AccountNonce, AccountType, Block, DelegationId, GenBlock, PoolId, SignedTransaction, + UtxoOutPoint, }, primitives::{Amount, BlockHeight, Id}, }; @@ -64,7 +65,7 @@ mockall::mock! { fn get_mainchain_tx_by_position( &self, tx_index: &TxMainChainPosition, - ) -> crate::Result>; + ) -> crate::Result>; fn get_block_id_by_height( &self, @@ -320,7 +321,7 @@ mockall::mock! { fn get_mainchain_tx_by_position( &self, tx_index: &TxMainChainPosition, - ) -> crate::Result>; + ) -> crate::Result>; fn get_block_id_by_height( &self, @@ -435,7 +436,7 @@ mockall::mock! { fn get_mainchain_tx_by_position( &self, tx_index: &TxMainChainPosition, - ) -> crate::Result>; + ) -> crate::Result>; fn get_block_id_by_height( &self, diff --git a/chainstate/test-suite/src/tests/chainstate_storage_tests.rs b/chainstate/test-suite/src/tests/chainstate_storage_tests.rs index 723b09b04c..2a0ba4d397 100644 --- a/chainstate/test-suite/src/tests/chainstate_storage_tests.rs +++ b/chainstate/test-suite/src/tests/chainstate_storage_tests.rs @@ -87,7 +87,12 @@ fn store_coin(#[case] seed: Seed) { SpendablePosition::BlockReward(_) => unreachable!(), }; assert_eq!( - db_tx.get_mainchain_tx_by_position(tx_pos).expect("ok").expect("some").get_id(), + db_tx + .get_mainchain_tx_by_position(tx_pos) + .expect("ok") + .expect("some") + .transaction() + .get_id(), tx_id ); } @@ -178,7 +183,12 @@ fn store_token(#[case] seed: Seed) { SpendablePosition::BlockReward(_) => unreachable!(), }; assert_eq!( - db_tx.get_mainchain_tx_by_position(tx_pos).expect("ok").expect("some").get_id(), + db_tx + .get_mainchain_tx_by_position(tx_pos) + .expect("ok") + .expect("some") + .transaction() + .get_id(), tx_id ); } @@ -306,6 +316,7 @@ fn reorg_store_coin(#[case] seed: Seed) { .get_mainchain_tx_by_position(tx_2_pos) .expect("ok") .expect("some") + .transaction() .get_id(), tx_2_id ); @@ -323,6 +334,7 @@ fn reorg_store_coin(#[case] seed: Seed) { .get_mainchain_tx_by_position(tx_3_pos) .expect("ok") .expect("some") + .transaction() .get_id(), tx_3_id ); @@ -503,6 +515,7 @@ fn reorg_store_token(#[case] seed: Seed) { .get_mainchain_tx_by_position(tx_2_pos) .expect("ok") .expect("some") + .transaction() .get_id(), tx_2_id ); @@ -520,6 +533,7 @@ fn reorg_store_token(#[case] seed: Seed) { .get_mainchain_tx_by_position(tx_3_pos) .expect("ok") .expect("some") + .transaction() .get_id(), tx_3_id ); diff --git a/chainstate/types/src/error.rs b/chainstate/types/src/error.rs index c420aedf51..e0a73175c4 100644 --- a/chainstate/types/src/error.rs +++ b/chainstate/types/src/error.rs @@ -60,6 +60,8 @@ pub enum PropertyQueryError { PoolBalanceReadError(PoolId), #[error("Invalid starting block height: {0}")] InvalidStartingBlockHeightForMainchainBlocks(BlockHeight), + #[error("Transaction index must be enabled to retrieve transactions by id")] + TransactionIndexDisabled, } #[derive(Error, Debug, PartialEq, Eq, Clone)] diff --git a/mocks/src/chainstate.rs b/mocks/src/chainstate.rs index b74a83f753..1d557e840a 100644 --- a/mocks/src/chainstate.rs +++ b/mocks/src/chainstate.rs @@ -26,8 +26,8 @@ use common::{ GenBlock, }, tokens::{RPCTokenInfo, TokenAuxiliaryData, TokenId}, - AccountNonce, AccountType, ChainConfig, DelegationId, OutPointSourceId, PoolId, TxInput, - TxMainChainIndex, UtxoOutPoint, + AccountNonce, AccountType, ChainConfig, DelegationId, OutPointSourceId, PoolId, + SignedTransaction, Transaction, TxInput, TxMainChainIndex, UtxoOutPoint, }, primitives::{Amount, BlockHeight, Id}, }; @@ -166,6 +166,11 @@ mockall::mock! { &self, account: AccountType, ) -> Result, ChainstateError>; + fn is_transaction_index_enabled(&self) -> Result; + fn get_transaction( + &self, + tx_id: &Id, + ) -> Result, ChainstateError>; } } diff --git a/serialization/src/json_encoded.rs b/serialization/src/json_encoded.rs index 3a347090de..8ae4fe7521 100644 --- a/serialization/src/json_encoded.rs +++ b/serialization/src/json_encoded.rs @@ -31,7 +31,7 @@ impl JsonEncoded { impl<'de, T: serde::Deserialize<'de>> JsonEncoded { // We cannot use FromStr because of the lifetime limitation - pub fn from_str(s: &'de str) -> Result { + pub fn from_string(s: &'de str) -> Result { serde_json::from_str(s) } } From 373763a5f6d6d1c17d8ad702a2f10430270f7ae5 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 16:58:13 +0400 Subject: [PATCH 05/12] Add get_transaction_json to retrieve main chain transaction in json encoding --- chainstate/src/rpc.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/chainstate/src/rpc.rs b/chainstate/src/rpc.rs index 1e7c381cb0..e718465835 100644 --- a/chainstate/src/rpc.rs +++ b/chainstate/src/rpc.rs @@ -54,6 +54,11 @@ trait ChainstateRpc { id: Id, ) -> RpcResult>>; + /// returns a json-encoded transaction, assuming it's in the mainchain. + /// Note: The transaction index must be enabled in the node. + #[method(name = "get_transaction_json")] + async fn get_transaction_json(&self, id: Id) -> RpcResult>; + /// Returns a hex-encoded serialized blocks from the mainchain starting from a given block height. #[method(name = "get_mainchain_blocks")] async fn get_mainchain_blocks( @@ -144,6 +149,12 @@ impl ChainstateRpcServer for super::ChainstateHandle { Ok(tx.map(HexEncoded::new)) } + async fn get_transaction_json(&self, id: Id) -> RpcResult> { + let tx: Option = + rpc::handle_result(self.call(move |this| this.get_transaction(&id)).await)?; + Ok(tx.map(JsonEncoded::new).map(|tx| tx.to_string())) + } + async fn get_mainchain_blocks( &self, from: BlockHeight, From c6caae863ca18decf7efc59d07bf11af8c437688 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 17:22:55 +0400 Subject: [PATCH 06/12] Encode as hex for json when manually done for keys and similar --- crypto/src/key/mod.rs | 3 ++- crypto/src/key/signature/mod.rs | 4 ++-- crypto/src/vrf/mod.rs | 4 ++-- crypto/src/vrf/schnorrkel/data.rs | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crypto/src/key/mod.rs b/crypto/src/key/mod.rs index bca38e790b..4cbac17ac1 100644 --- a/crypto/src/key/mod.rs +++ b/crypto/src/key/mod.rs @@ -19,6 +19,7 @@ mod key_holder; pub mod secp256k1; pub mod signature; +use serialization::hex::HexEncode; use serialization::{Decode, Encode}; use crate::key::secp256k1::{Secp256k1PrivateKey, Secp256k1PublicKey}; @@ -58,7 +59,7 @@ pub struct PublicKey { impl serde::Serialize for PublicKey { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_bytes(&self.encode()) + serializer.serialize_str(&self.hex_encode()) } } diff --git a/crypto/src/key/signature/mod.rs b/crypto/src/key/signature/mod.rs index b759ba9b8b..547f49ed2a 100644 --- a/crypto/src/key/signature/mod.rs +++ b/crypto/src/key/signature/mod.rs @@ -17,7 +17,7 @@ use secp256k1; use std::io::BufWriter; use num_derive::FromPrimitive; -use serialization::{Decode, DecodeAll, Encode}; +use serialization::{hex::HexEncode, Decode, DecodeAll, Encode}; #[derive(FromPrimitive)] pub enum SignatureKind { @@ -31,7 +31,7 @@ pub enum Signature { impl serde::Serialize for Signature { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_bytes(&self.encode()) + serializer.serialize_str(&self.hex_encode()) } } diff --git a/crypto/src/vrf/mod.rs b/crypto/src/vrf/mod.rs index 9353a7c411..41f3d2f17b 100644 --- a/crypto/src/vrf/mod.rs +++ b/crypto/src/vrf/mod.rs @@ -15,7 +15,7 @@ use hmac::{Hmac, Mac}; use merlin::Transcript; -use serialization::{Decode, Encode}; +use serialization::{hex::HexEncode, Decode, Encode}; use sha2::Sha512; use crate::{ @@ -72,7 +72,7 @@ pub struct VRFPublicKey { impl serde::Serialize for VRFPublicKey { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_bytes(&self.encode()) + serializer.serialize_str(&self.hex_encode()) } } diff --git a/crypto/src/vrf/schnorrkel/data.rs b/crypto/src/vrf/schnorrkel/data.rs index a27fcda4f3..0ee1e8ae94 100644 --- a/crypto/src/vrf/schnorrkel/data.rs +++ b/crypto/src/vrf/schnorrkel/data.rs @@ -19,7 +19,7 @@ use schnorrkel::{ vrf::{VRFInOut, VRFPreOut, VRFProof}, PublicKey, }; -use serialization::{Decode, Encode}; +use serialization::{hex::HexEncode, Decode, Encode}; use crate::vrf::{VRFError, VRFPublicKey}; @@ -41,7 +41,7 @@ pub struct SchnorrkelVRFReturn { impl serde::Serialize for SchnorrkelVRFReturn { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_bytes(&self.encode()) + serializer.serialize_str(&self.hex_encode()) } } From 0fe4e2061b1bdefa2f4df5d4ec2e234379959818 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 17:42:42 +0400 Subject: [PATCH 07/12] Serialize destination as hex --- common/src/address/pubkeyhash.rs | 2 +- common/src/chain/transaction/output/mod.rs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/common/src/address/pubkeyhash.rs b/common/src/address/pubkeyhash.rs index 4d4bfb2a67..5cce126076 100644 --- a/common/src/address/pubkeyhash.rs +++ b/common/src/address/pubkeyhash.rs @@ -31,7 +31,7 @@ pub enum PublicKeyHashError { const HASH_SIZE: usize = 20; fixed_hash::construct_fixed_hash! { - #[derive(Encode, Decode, serde::Serialize)] + #[derive(Encode, Decode)] pub struct PublicKeyHash(HASH_SIZE); } diff --git a/common/src/chain/transaction/output/mod.rs b/common/src/chain/transaction/output/mod.rs index 05e171cb15..075c31dcd3 100644 --- a/common/src/chain/transaction/output/mod.rs +++ b/common/src/chain/transaction/output/mod.rs @@ -19,7 +19,7 @@ use crate::{ primitives::{Amount, Id}, }; use script::Script; -use serialization::{Decode, DecodeAll, Encode}; +use serialization::{hex::HexEncode, Decode, DecodeAll, Encode}; use self::{stakelock::StakePoolData, timelock::OutputTimeLock}; @@ -28,7 +28,7 @@ pub mod output_value; pub mod stakelock; pub mod timelock; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, serde::Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] pub enum Destination { #[codec(index = 0)] AnyoneCanSpend, // zero verification; used primarily for testing. Never use this for real money @@ -42,6 +42,12 @@ pub enum Destination { ClassicMultisig(PublicKeyHash), } +impl serde::Serialize for Destination { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&format!("0x{}", self.hex_encode())) + } +} + impl Addressable for Destination { type Error = AddressError; From a65884374187d0995c6772265b225bf6c610a9ca Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Wed, 9 Aug 2023 17:50:14 +0400 Subject: [PATCH 08/12] Use hex_encode() for json encoding of InputWitness --- common/src/chain/transaction/signature/inputsig/mod.rs | 10 ++++++++-- .../signature/inputsig/standard_signature.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/common/src/chain/transaction/signature/inputsig/mod.rs b/common/src/chain/transaction/signature/inputsig/mod.rs index 100bbb3c45..30fd818774 100644 --- a/common/src/chain/transaction/signature/inputsig/mod.rs +++ b/common/src/chain/transaction/signature/inputsig/mod.rs @@ -18,14 +18,20 @@ pub mod authorize_pubkeyhash_spend; pub mod classical_multisig; pub mod standard_signature; -use serialization::{Decode, Encode}; +use serialization::{hex::HexEncode, Decode, Encode}; use standard_signature::StandardInputSignature; -#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize)] +#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd)] pub enum InputWitness { #[codec(index = 0)] NoSignature(Option>), #[codec(index = 1)] Standard(StandardInputSignature), } + +impl serde::Serialize for InputWitness { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.hex_encode()) + } +} diff --git a/common/src/chain/transaction/signature/inputsig/standard_signature.rs b/common/src/chain/transaction/signature/inputsig/standard_signature.rs index a3e56f14ec..79435de1a7 100644 --- a/common/src/chain/transaction/signature/inputsig/standard_signature.rs +++ b/common/src/chain/transaction/signature/inputsig/standard_signature.rs @@ -43,7 +43,7 @@ use super::{ }, }; -#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize)] +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct StandardInputSignature { sighash_type: SigHashType, raw_signature: Vec, From d333c7802f67631548e759e15b8aa2bd83e7eb2b Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Thu, 10 Aug 2023 02:23:51 +0400 Subject: [PATCH 09/12] Use HexEncoded for json hex --- common/src/chain/transaction/signature/inputsig/mod.rs | 4 ++-- crypto/src/key/mod.rs | 4 ++-- crypto/src/key/signature/mod.rs | 4 ++-- crypto/src/vrf/mod.rs | 4 ++-- crypto/src/vrf/schnorrkel/data.rs | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/common/src/chain/transaction/signature/inputsig/mod.rs b/common/src/chain/transaction/signature/inputsig/mod.rs index 30fd818774..86343043ac 100644 --- a/common/src/chain/transaction/signature/inputsig/mod.rs +++ b/common/src/chain/transaction/signature/inputsig/mod.rs @@ -18,7 +18,7 @@ pub mod authorize_pubkeyhash_spend; pub mod classical_multisig; pub mod standard_signature; -use serialization::{hex::HexEncode, Decode, Encode}; +use serialization::{hex_encoded::HexEncoded, Decode, Encode}; use standard_signature::StandardInputSignature; @@ -32,6 +32,6 @@ pub enum InputWitness { impl serde::Serialize for InputWitness { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.hex_encode()) + HexEncoded::new(self).serialize(serializer) } } diff --git a/crypto/src/key/mod.rs b/crypto/src/key/mod.rs index 4cbac17ac1..506a7a3c42 100644 --- a/crypto/src/key/mod.rs +++ b/crypto/src/key/mod.rs @@ -19,7 +19,7 @@ mod key_holder; pub mod secp256k1; pub mod signature; -use serialization::hex::HexEncode; +use serialization::hex_encoded::HexEncoded; use serialization::{Decode, Encode}; use crate::key::secp256k1::{Secp256k1PrivateKey, Secp256k1PublicKey}; @@ -59,7 +59,7 @@ pub struct PublicKey { impl serde::Serialize for PublicKey { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.hex_encode()) + HexEncoded::new(self).serialize(serializer) } } diff --git a/crypto/src/key/signature/mod.rs b/crypto/src/key/signature/mod.rs index 547f49ed2a..7157acfa0b 100644 --- a/crypto/src/key/signature/mod.rs +++ b/crypto/src/key/signature/mod.rs @@ -17,7 +17,7 @@ use secp256k1; use std::io::BufWriter; use num_derive::FromPrimitive; -use serialization::{hex::HexEncode, Decode, DecodeAll, Encode}; +use serialization::{hex_encoded::HexEncoded, Decode, DecodeAll, Encode}; #[derive(FromPrimitive)] pub enum SignatureKind { @@ -31,7 +31,7 @@ pub enum Signature { impl serde::Serialize for Signature { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.hex_encode()) + HexEncoded::new(self).serialize(serializer) } } diff --git a/crypto/src/vrf/mod.rs b/crypto/src/vrf/mod.rs index 41f3d2f17b..dcb39a11da 100644 --- a/crypto/src/vrf/mod.rs +++ b/crypto/src/vrf/mod.rs @@ -15,7 +15,7 @@ use hmac::{Hmac, Mac}; use merlin::Transcript; -use serialization::{hex::HexEncode, Decode, Encode}; +use serialization::{hex_encoded::HexEncoded, Decode, Encode}; use sha2::Sha512; use crate::{ @@ -72,7 +72,7 @@ pub struct VRFPublicKey { impl serde::Serialize for VRFPublicKey { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.hex_encode()) + HexEncoded::new(self).serialize(serializer) } } diff --git a/crypto/src/vrf/schnorrkel/data.rs b/crypto/src/vrf/schnorrkel/data.rs index 0ee1e8ae94..e9ea28868b 100644 --- a/crypto/src/vrf/schnorrkel/data.rs +++ b/crypto/src/vrf/schnorrkel/data.rs @@ -19,7 +19,7 @@ use schnorrkel::{ vrf::{VRFInOut, VRFPreOut, VRFProof}, PublicKey, }; -use serialization::{hex::HexEncode, Decode, Encode}; +use serialization::{hex_encoded::HexEncoded, Decode, Encode}; use crate::vrf::{VRFError, VRFPublicKey}; @@ -41,7 +41,7 @@ pub struct SchnorrkelVRFReturn { impl serde::Serialize for SchnorrkelVRFReturn { fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.hex_encode()) + HexEncoded::new(self).serialize(serializer) } } From 8de7dd5b58ca14cbcf117ca7f7977630a84e1a10 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Thu, 10 Aug 2023 02:25:07 +0400 Subject: [PATCH 10/12] Remove serde_json from crypto --- Cargo.lock | 1 - crypto/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c475da631..d5c99cee86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1511,7 +1511,6 @@ dependencies = [ "schnorrkel", "secp256k1", "serde", - "serde_json", "serialization", "sha-1 0.10.1", "sha2 0.10.7", diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index 1739df8ded..e05144e05e 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -29,7 +29,6 @@ rand.workspace = true ripemd.workspace = true schnorrkel.workspace = true serde = { workspace = true, features = ["derive"] } -serde_json.workspace = true sha-1.workspace = true sha2.workspace = true sha3.workspace = true From 74643f5c0c9dae2b9463170876a8607000188e7e Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Thu, 10 Aug 2023 02:33:16 +0400 Subject: [PATCH 11/12] Add FromStr impl for JsonEncoded --- serialization/src/json_encoded.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/serialization/src/json_encoded.rs b/serialization/src/json_encoded.rs index 8ae4fe7521..0a20a30086 100644 --- a/serialization/src/json_encoded.rs +++ b/serialization/src/json_encoded.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt::Display; +use std::{fmt::Display, str::FromStr}; /// Wrapper that serializes objects as json encoded string for `serde` #[derive(Debug, Clone)] @@ -54,6 +54,14 @@ impl serde::Serialize for JsonEncoded { } } +impl serde::Deserialize<'de>> FromStr for JsonEncoded { + type Err = serde_json::Error; + + fn from_str(s: &str) -> Result { + serde_json::from_str(s).map(Self) + } +} + impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for JsonEncoded { fn deserialize>(deserializer: D) -> Result { T::deserialize(deserializer).map(Self) From 8443f2581924005053881c57e55e43c731da68c5 Mon Sep 17 00:00:00 2001 From: Samer Afach Date: Thu, 10 Aug 2023 13:26:39 +0400 Subject: [PATCH 12/12] Minor function rename in JsonEncoded --- serialization/src/json_encoded.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serialization/src/json_encoded.rs b/serialization/src/json_encoded.rs index 0a20a30086..02b2434eb8 100644 --- a/serialization/src/json_encoded.rs +++ b/serialization/src/json_encoded.rs @@ -31,7 +31,7 @@ impl JsonEncoded { impl<'de, T: serde::Deserialize<'de>> JsonEncoded { // We cannot use FromStr because of the lifetime limitation - pub fn from_string(s: &'de str) -> Result { + pub fn from_string_slice(s: &'de str) -> Result { serde_json::from_str(s) } }