diff --git a/src/chainstate/burn/db/sortdb.rs b/src/chainstate/burn/db/sortdb.rs index 10a36d67f..c6ae61ddb 100644 --- a/src/chainstate/burn/db/sortdb.rs +++ b/src/chainstate/burn/db/sortdb.rs @@ -9602,7 +9602,10 @@ pub mod tests { delegate_to: StacksAddress::new(7, Hash160([7u8; 20])), reward_addr: Some(( 123, - PoxAddress::Standard(StacksAddress::new(8, Hash160([8u8; 20])), None), + PoxAddress::Standard( + StacksAddress::new(8, Hash160([8u8; 20])), + Some(AddressHashMode::SerializeP2PKH), + ), )), delegated_ustx: 789, until_burn_height: Some(1000), diff --git a/src/chainstate/burn/operations/mod.rs b/src/chainstate/burn/operations/mod.rs index 76dca0199..430b254a0 100644 --- a/src/chainstate/burn/operations/mod.rs +++ b/src/chainstate/burn/operations/mod.rs @@ -182,59 +182,33 @@ impl From for Error { #[derive(Debug, PartialEq, Clone, Eq, Serialize, Deserialize)] pub struct TransferStxOp { - #[serde( - deserialize_with = "stacks_common::codec::serde::stacks_addr_deserialize", - serialize_with = "stacks_common::codec::serde::stacks_addr_serialize" - )] pub sender: StacksAddress, - #[serde( - deserialize_with = "stacks_common::codec::serde::stacks_addr_deserialize", - serialize_with = "stacks_common::codec::serde::stacks_addr_serialize" - )] pub recipient: StacksAddress, pub transfered_ustx: u128, - #[serde( - deserialize_with = "stacks_common::codec::serde::memo_deserialize", - serialize_with = "stacks_common::codec::serde::memo_serialize" - )] pub memo: Vec, // common to all transactions - pub txid: Txid, // transaction ID - pub vtxindex: u32, // index in the block where this tx occurs - pub block_height: u64, // block height at which this tx occurs - #[serde( - deserialize_with = "stacks_common::codec::serde::burn_hh_deserialize", - serialize_with = "stacks_common::codec::serde::burn_hh_serialize" - )] + pub txid: Txid, // transaction ID + pub vtxindex: u32, // index in the block where this tx occurs + pub block_height: u64, // block height at which this tx occurs pub burn_header_hash: BurnchainHeaderHash, // hash of the burn chain block header } #[derive(Debug, PartialEq, Clone, Eq, Serialize, Deserialize)] pub struct StackStxOp { - #[serde( - deserialize_with = "stacks_common::codec::serde::stacks_addr_deserialize", - serialize_with = "stacks_common::codec::serde::stacks_addr_serialize" - )] pub sender: StacksAddress, /// the PoX reward address. /// NOTE: the address in .pox will be tagged as either p2pkh or p2sh; it's impossible to tell /// if it's a segwit-p2sh since that looks identical to a p2sh address. - #[serde(serialize_with = "crate::chainstate::stacks::address::pox_addr_b58_serialize")] - #[serde(deserialize_with = "crate::chainstate::stacks::address::pox_addr_b58_deser")] pub reward_addr: PoxAddress, /// how many ustx this transaction locks pub stacked_ustx: u128, pub num_cycles: u8, // common to all transactions - pub txid: Txid, // transaction ID - pub vtxindex: u32, // index in the block where this tx occurs - pub block_height: u64, // block height at which this tx occurs - #[serde( - deserialize_with = "stacks_common::codec::serde::burn_hh_deserialize", - serialize_with = "stacks_common::codec::serde::burn_hh_serialize" - )] + pub txid: Txid, // transaction ID + pub vtxindex: u32, // index in the block where this tx occurs + pub block_height: u64, // block height at which this tx occurs pub burn_header_hash: BurnchainHeaderHash, // hash of the burn chain block header } @@ -242,45 +216,25 @@ pub struct StackStxOp { pub struct PreStxOp { /// the output address /// (must be a legacy Bitcoin address) - #[serde( - deserialize_with = "stacks_common::codec::serde::stacks_addr_deserialize", - serialize_with = "stacks_common::codec::serde::stacks_addr_serialize" - )] pub output: StacksAddress, // common to all transactions - pub txid: Txid, // transaction ID - pub vtxindex: u32, // index in the block where this tx occurs - pub block_height: u64, // block height at which this tx occurs - #[serde( - deserialize_with = "stacks_common::codec::serde::burn_hh_deserialize", - serialize_with = "stacks_common::codec::serde::burn_hh_serialize" - )] + pub txid: Txid, // transaction ID + pub vtxindex: u32, // index in the block where this tx occurs + pub block_height: u64, // block height at which this tx occurs pub burn_header_hash: BurnchainHeaderHash, // hash of the burn chain block header } #[derive(Debug, PartialEq, Clone, Eq, Serialize, Deserialize)] pub struct LeaderBlockCommitOp { - #[serde( - deserialize_with = "stacks_common::codec::serde::block_hh_deserialize", - serialize_with = "stacks_common::codec::serde::block_hh_serialize" - )] pub block_header_hash: BlockHeaderHash, // hash of Stacks block header (sha512/256) - #[serde( - deserialize_with = "stacks_common::codec::serde::vrf_seed_deserialize", - serialize_with = "stacks_common::codec::serde::vrf_seed_serialize" - )] - pub new_seed: VRFSeed, // new seed for this block + pub new_seed: VRFSeed, // new seed for this block pub parent_block_ptr: u32, // block height of the block that contains the parent block hash pub parent_vtxindex: u16, // offset in the parent block where the parent block hash can be found pub key_block_ptr: u32, // pointer to the block that contains the leader key registration pub key_vtxindex: u16, // offset in the block where the leader key can be found - #[serde( - deserialize_with = "stacks_common::codec::serde::memo_deserialize", - serialize_with = "stacks_common::codec::serde::memo_serialize" - )] - pub memo: Vec, // extra unused byte + pub memo: Vec, // extra unused byte /// how many burn tokens (e.g. satoshis) were committed to produce this block pub burn_fee: u64, @@ -295,45 +249,27 @@ pub struct LeaderBlockCommitOp { pub apparent_sender: BurnchainSigner, /// PoX/Burn outputs - #[serde(serialize_with = "crate::chainstate::stacks::address::pox_addr_vec_b58_serialize")] - #[serde(deserialize_with = "crate::chainstate::stacks::address::pox_addr_vec_b58_deser")] pub commit_outs: Vec, // PoX sunset burn pub sunset_burn: u64, // common to all transactions - pub txid: Txid, // transaction ID - pub vtxindex: u32, // index in the block where this tx occurs - pub block_height: u64, // block height at which this tx occurs - #[serde( - deserialize_with = "stacks_common::codec::serde::burn_hh_deserialize", - serialize_with = "stacks_common::codec::serde::burn_hh_serialize" - )] + pub txid: Txid, // transaction ID + pub vtxindex: u32, // index in the block where this tx occurs + pub block_height: u64, // block height at which this tx occurs pub burn_header_hash: BurnchainHeaderHash, // hash of the burn chain block header } #[derive(Debug, PartialEq, Clone, Eq, Serialize, Deserialize)] pub struct LeaderKeyRegisterOp { - #[serde( - deserialize_with = "stacks_common::codec::serde::consensus_hash_deserialize", - serialize_with = "stacks_common::codec::serde::consensus_hash_serialize" - )] pub consensus_hash: ConsensusHash, // consensus hash at time of issuance - pub public_key: VRFPublicKey, // EdDSA public key - #[serde( - deserialize_with = "stacks_common::codec::serde::memo_deserialize", - serialize_with = "stacks_common::codec::serde::memo_serialize" - )] - pub memo: Vec, // extra bytes in the op-return + pub public_key: VRFPublicKey, // EdDSA public key + pub memo: Vec, // extra bytes in the op-return // common to all transactions - pub txid: Txid, // transaction ID - pub vtxindex: u32, // index in the block where this tx occurs - pub block_height: u64, // block height at which this tx occurs - #[serde( - deserialize_with = "stacks_common::codec::serde::burn_hh_deserialize", - serialize_with = "stacks_common::codec::serde::burn_hh_serialize" - )] + pub txid: Txid, // transaction ID + pub vtxindex: u32, // index in the block where this tx occurs + pub block_height: u64, // block height at which this tx occurs pub burn_header_hash: BurnchainHeaderHash, // hash of burn chain block } @@ -357,36 +293,20 @@ pub struct UserBurnSupportOp { #[derive(Debug, PartialEq, Clone, Eq, Serialize, Deserialize)] pub struct DelegateStxOp { - #[serde( - deserialize_with = "stacks_common::codec::serde::stacks_addr_deserialize", - serialize_with = "stacks_common::codec::serde::stacks_addr_serialize" - )] pub sender: StacksAddress, - #[serde( - deserialize_with = "stacks_common::codec::serde::stacks_addr_deserialize", - serialize_with = "stacks_common::codec::serde::stacks_addr_serialize" - )] pub delegate_to: StacksAddress, /// a tuple representing the output index of the reward address in the BTC transaction, // and the actual PoX reward address. /// NOTE: the address in .pox-2 will be tagged as either p2pkh or p2sh; it's impossible to tell /// if it's a segwit-p2sh since that looks identical to a p2sh address. - #[serde( - deserialize_with = "reward_addr_deserialize", - serialize_with = "reward_addr_serialize" - )] pub reward_addr: Option<(u32, PoxAddress)>, pub delegated_ustx: u128, pub until_burn_height: Option, // common to all transactions - pub txid: Txid, // transaction ID - pub vtxindex: u32, // index in the block where this tx occurs - pub block_height: u64, // block height at which this tx occurs - #[serde( - deserialize_with = "stacks_common::codec::serde::burn_hh_deserialize", - serialize_with = "stacks_common::codec::serde::burn_hh_serialize" - )] + pub txid: Txid, // transaction ID + pub vtxindex: u32, // index in the block where this tx occurs + pub block_height: u64, // block height at which this tx occurs pub burn_header_hash: BurnchainHeaderHash, // hash of the burn chain block header } @@ -401,6 +321,21 @@ pub enum BlockstackOperationType { DelegateStx(DelegateStxOp), } +// serialization helpers for blockstack_op_to_json function +pub fn memo_serialize(memo: &Vec) -> String { + let hex_inst = to_hex(memo); + format!("0x{}", hex_inst) +} + +pub fn stacks_addr_serialize(addr: &StacksAddress) -> serde_json::Value { + let addr_str = addr.to_string(); + json!({ + "address": addr_str, + "address_hash_bytes": format!("0x{}", addr.bytes), + "address_version": addr.version + }) +} + impl BlockstackOperationType { pub fn opcode(&self) -> Opcodes { match *self { @@ -497,6 +432,78 @@ impl BlockstackOperationType { BlockstackOperationType::DelegateStx(ref mut data) => data.burn_header_hash = hash, }; } + + pub fn pre_stx_to_json(op: &PreStxOp) -> serde_json::Value { + json!({ + "PreStx": { + "block_height": op.block_height, + "burn_header_hash": &op.burn_header_hash.to_hex(), + "output": stacks_addr_serialize(&op.output), + "txid": op.txid, + "vtxindex": op.vtxindex, + } + }) + } + + pub fn stack_stx_to_json(op: &StackStxOp) -> serde_json::Value { + json!({ + "StackStx": { + "block_height": op.block_height, + "burn_header_hash": &op.burn_header_hash.to_hex(), + "num_cycles": op.num_cycles, + "reward_addr": op.reward_addr.clone().to_b58(), + "sender": stacks_addr_serialize(&op.sender), + "stacked_ustx": op.stacked_ustx, + "txid": op.txid, + "vtxindex": op.vtxindex, + } + }) + } + + pub fn transfer_stx_to_json(op: &TransferStxOp) -> serde_json::Value { + json!({ + "TransferStx": { + "block_height": op.block_height, + "burn_header_hash": &op.burn_header_hash.to_hex(), + "memo": memo_serialize(&op.memo), + "recipient": stacks_addr_serialize(&op.recipient), + "sender": stacks_addr_serialize(&op.sender), + "transfered_ustx": op.transfered_ustx, + "txid": op.txid, + "vtxindex": op.vtxindex, + } + }) + } + + pub fn delegate_stx_to_json(op: &DelegateStxOp) -> serde_json::Value { + json!({ + "DelegateStx": { + "block_height": op.block_height, + "burn_header_hash": &op.burn_header_hash.to_hex(), + "delegate_to": stacks_addr_serialize(&op.delegate_to), + "delegated_ustx": op.delegated_ustx, + "sender": stacks_addr_serialize(&op.sender), + "reward_addr": &op.reward_addr.as_ref().map(|(index, addr)| (index, addr.clone().to_b58())), + "txid": op.txid, + "until_burn_height": op.until_burn_height, + "vtxindex": op.vtxindex, + } + + }) + } + + pub fn blockstack_op_to_json(&self) -> serde_json::Value { + match self { + BlockstackOperationType::PreStx(op) => Self::pre_stx_to_json(op), + BlockstackOperationType::StackStx(op) => Self::stack_stx_to_json(op), + BlockstackOperationType::TransferStx(op) => Self::transfer_stx_to_json(op), + BlockstackOperationType::DelegateStx(op) => Self::delegate_stx_to_json(op), + // json serialization for the remaining op types is not implemented for now. This function + // is currently only used to json-ify burnchain ops executed as Stacks transactions (so, + // stack_stx, transfer_stx, and delegate_stx). + _ => json!(null), + } + } } impl fmt::Display for BlockstackOperationType { @@ -530,52 +537,18 @@ pub fn parse_u16_from_be(bytes: &[u8]) -> Option { bytes.try_into().ok().map(u16::from_be_bytes) } -// these serialization functions should be moved to stacks_common/src/codec/serde.rs -// once PoxAddress is moved to stacks_common. -fn reward_addr_serialize( - addr: &Option<(u32, PoxAddress)>, - s: S, -) -> Result { - match addr { - None => s.serialize_none(), - Some((index, pox_addr)) => { - let str_addr = pox_addr.clone().to_b58(); - s.serialize_some(&(index, str_addr)) - } - } -} - -fn reward_addr_deserialize<'de, D: serde::Deserializer<'de>>( - d: D, -) -> Result, D::Error> { - let reward_addr: Option<(u32, String)> = Option::deserialize(d)?; - match reward_addr { - None => Ok(None), - Some((input, pox_add_str)) => { - let pox_addr = PoxAddress::from_b58(&pox_add_str).ok_or_else(|| { - serde::de::Error::custom("Failed to decode PoxAddress from string") - })?; - Ok(Some((input, pox_addr))) - } - } -} - mod test { - use crate::burnchains::{BurnchainSigner, Txid}; + use crate::burnchains::Txid; use crate::chainstate::burn::operations::{ - DelegateStxOp, LeaderBlockCommitOp, LeaderKeyRegisterOp, PreStxOp, StackStxOp, - TransferStxOp, UserBurnSupportOp, + BlockstackOperationType, DelegateStxOp, PreStxOp, StackStxOp, TransferStxOp, }; use crate::chainstate::stacks::address::PoxAddress; - use serde::{Deserialize, Serialize}; - use serde_json::Serializer; - use stacks_common::address::{AddressHashMode, C32_ADDRESS_VERSION_MAINNET_SINGLESIG}; + use stacks_common::address::C32_ADDRESS_VERSION_MAINNET_SINGLESIG; use stacks_common::types::chainstate::{ BlockHeaderHash, BurnchainHeaderHash, ConsensusHash, StacksAddress, VRFSeed, }; use stacks_common::types::Address; use stacks_common::util::hash::Hash160; - use stacks_common::util::vrf::{VRFPrivateKey, VRFPublicKey}; #[test] fn test_serialization_transfer_stx_op() { @@ -593,30 +566,29 @@ mod test { block_height: 10, burn_header_hash: BurnchainHeaderHash([0x10; 32]), }; - let serialized_json = serde_json::json!(&op); + let serialized_json = BlockstackOperationType::transfer_stx_to_json(&op); let constructed_json = json!({ - "block_height": 10, - "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "memo": "0x000102030405", - "recipient": { - "address": "SP24ZBZ8ZE6F48JE9G3F3HRTG9FK7E2H6K2QZ3Q1K", - "address_hash_bytes": "0x89f5fd1f719e4449c980de38e3504be6770a2698", - "address_version": 22, - }, - "sender": { - "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", - "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", - "address_version": 26, - }, - "transfered_ustx": 10, - "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", - "vtxindex": 10, + "TransferStx": { + "block_height": 10, + "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", + "memo": "0x000102030405", + "recipient": { + "address": "SP24ZBZ8ZE6F48JE9G3F3HRTG9FK7E2H6K2QZ3Q1K", + "address_hash_bytes": "0x89f5fd1f719e4449c980de38e3504be6770a2698", + "address_version": 22, + }, + "sender": { + "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", + "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", + "address_version": 26, + }, + "transfered_ustx": 10, + "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "vtxindex": 10, + } }); - assert_json_eq!(serialized_json.clone(), constructed_json); - - let deserialized = TransferStxOp::deserialize(serialized_json).unwrap(); - assert_eq!(op, deserialized); + assert_json_eq!(serialized_json, constructed_json); } #[test] @@ -641,26 +613,25 @@ mod test { burn_header_hash: BurnchainHeaderHash([0x10; 32]), num_cycles: 10, }; - let serialized_json = serde_json::json!(&op); + let serialized_json = BlockstackOperationType::stack_stx_to_json(&op); let constructed_json = json!({ - "block_height": 10, - "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "num_cycles": 10, - "reward_addr": "16Jswqk47s9PUcyCc88MMVwzgvHPvtEpf", - "sender": { - "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", - "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", - "address_version": 26, - }, - "stacked_ustx": 10, - "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", - "vtxindex": 10, + "StackStx": { + "block_height": 10, + "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", + "num_cycles": 10, + "reward_addr": "16Jswqk47s9PUcyCc88MMVwzgvHPvtEpf", + "sender": { + "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", + "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", + "address_version": 26, + }, + "stacked_ustx": 10, + "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "vtxindex": 10, + } }); - assert_json_eq!(serialized_json.clone(), constructed_json); - - let deserialized = StackStxOp::deserialize(serialized_json).unwrap(); - assert_eq!(op, deserialized); + assert_json_eq!(serialized_json, constructed_json); } #[test] @@ -675,108 +646,22 @@ mod test { block_height: 10, burn_header_hash: BurnchainHeaderHash([0x10; 32]), }; - let serialized_json = serde_json::json!(&op); + let serialized_json = BlockstackOperationType::pre_stx_to_json(&op); let constructed_json = json!({ - "block_height": 10, - "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "output": { - "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", - "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", - "address_version": 26, - }, - "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", - "vtxindex": 10, + "PreStx": { + "block_height": 10, + "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", + "output": { + "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", + "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", + "address_version": 26, + }, + "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "vtxindex": 10, + } }); - assert_json_eq!(serialized_json.clone(), constructed_json); - - let deserialized = PreStxOp::deserialize(serialized_json).unwrap(); - assert_eq!(op, deserialized); - } - - #[test] - fn test_serialization_leader_block_commit_op() { - let pox_addr = PoxAddress::Standard( - StacksAddress { - version: C32_ADDRESS_VERSION_MAINNET_SINGLESIG, - bytes: Hash160([0x01; 20]), - }, - None, - ); - - let op = LeaderBlockCommitOp { - block_header_hash: BlockHeaderHash([0x10; 32]), - new_seed: VRFSeed([0x10; 32]), - parent_block_ptr: 10, - parent_vtxindex: 10, - key_block_ptr: 10, - key_vtxindex: 10, - memo: vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05], - input: (Txid([10u8; 32]), 10), - burn_parent_modulus: 10, - apparent_sender: BurnchainSigner("signer".to_string()), - commit_outs: vec![pox_addr.clone(), pox_addr], - sunset_burn: 10, - burn_fee: 10, - txid: Txid([10u8; 32]), - vtxindex: 10, - block_height: 10, - burn_header_hash: BurnchainHeaderHash([0x10; 32]), - }; - let serialized_json = serde_json::json!(&op); - let constructed_json = json!({ - "apparent_sender": "signer", - "block_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "block_height": 10, - "burn_fee": 10, - "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "burn_parent_modulus": 10, - "commit_outs": ["16Jswqk47s9PUcyCc88MMVwzgvHPvtEpf", "16Jswqk47s9PUcyCc88MMVwzgvHPvtEpf"], - "input": ("0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", 10), - "key_block_ptr": 10, - "key_vtxindex": 10, - "memo": "0x000102030405", - "new_seed": "1010101010101010101010101010101010101010101010101010101010101010", - "parent_block_ptr": 10, - "parent_vtxindex": 10, - "sunset_burn": 10, - "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", - "vtxindex": 10, - }); - - assert_json_eq!(serialized_json.clone(), constructed_json); - - let deserialized = LeaderBlockCommitOp::deserialize(serialized_json).unwrap(); - assert_eq!(op, deserialized); - } - - #[test] - fn test_serialization_leader_key_register_op() { - let public_key = VRFPublicKey::from_bytes(&[0x10; 32]).unwrap(); - let op = LeaderKeyRegisterOp { - consensus_hash: ConsensusHash([0x10; 20]), - public_key, - memo: vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05], - txid: Txid([10u8; 32]), - vtxindex: 10, - block_height: 10, - burn_header_hash: BurnchainHeaderHash([0x10; 32]), - }; - let serialized_json = serde_json::json!(&op); - let constructed_json = json!({ - "block_height": 10, - "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "consensus_hash": "1010101010101010101010101010101010101010", - "memo": "0x000102030405", - "public_key": "1010101010101010101010101010101010101010101010101010101010101010", - "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", - "vtxindex": 10, - }); - - assert_json_eq!(serialized_json.clone(), constructed_json); - - let deserialized = LeaderKeyRegisterOp::deserialize(serialized_json).unwrap(); - assert_eq!(op, deserialized); + assert_json_eq!(serialized_json, constructed_json); } #[test] @@ -803,30 +688,29 @@ mod test { block_height: 10, burn_header_hash: BurnchainHeaderHash([0x10; 32]), }; - let serialized_json = serde_json::json!(&op); + let serialized_json = BlockstackOperationType::delegate_stx_to_json(&op); let constructed_json = json!({ - "block_height": 10, - "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", - "delegate_to": { - "address": "SP24ZBZ8ZE6F48JE9G3F3HRTG9FK7E2H6K2QZ3Q1K", - "address_hash_bytes": "0x89f5fd1f719e4449c980de38e3504be6770a2698", - "address_version": 22, - }, - "delegated_ustx": 10, - "sender": { - "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", - "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", - "address_version": 26, - }, - "reward_addr": [10, "16Jswqk47s9PUcyCc88MMVwzgvHPvtEpf"], - "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", - "until_burn_height": null, - "vtxindex": 10, + "DelegateStx": { + "block_height": 10, + "burn_header_hash": "1010101010101010101010101010101010101010101010101010101010101010", + "delegate_to": { + "address": "SP24ZBZ8ZE6F48JE9G3F3HRTG9FK7E2H6K2QZ3Q1K", + "address_hash_bytes": "0x89f5fd1f719e4449c980de38e3504be6770a2698", + "address_version": 22, + }, + "delegated_ustx": 10, + "sender": { + "address": "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2", + "address_hash_bytes": "0xaf3f91f38aa21ade7e9f95efdbc4201eeb4cf0f8", + "address_version": 26, + }, + "reward_addr": [10, "16Jswqk47s9PUcyCc88MMVwzgvHPvtEpf"], + "txid": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "until_burn_height": null, + "vtxindex": 10, + } }); - assert_json_eq!(serialized_json.clone(), constructed_json); - - let deserialized = DelegateStxOp::deserialize(serialized_json).unwrap(); - assert_eq!(op, deserialized); + assert_json_eq!(serialized_json, constructed_json); } } diff --git a/stacks-common/src/codec/mod.rs b/stacks-common/src/codec/mod.rs index d1c2f2feb..b0eca1e25 100644 --- a/stacks-common/src/codec/mod.rs +++ b/stacks-common/src/codec/mod.rs @@ -8,7 +8,6 @@ use crate::util::secp256k1::MESSAGE_SIGNATURE_ENCODED_SIZE; #[macro_use] pub mod macros; -pub mod serde; #[derive(Debug)] pub enum Error { diff --git a/stacks-common/src/codec/serde.rs b/stacks-common/src/codec/serde.rs deleted file mode 100644 index 237a84394..000000000 --- a/stacks-common/src/codec/serde.rs +++ /dev/null @@ -1,121 +0,0 @@ -use crate::types::chainstate::{ - BlockHeaderHash, BurnchainHeaderHash, ConsensusHash, StacksAddress, VRFSeed, -}; -use crate::util::hash::{hex_bytes, to_hex, Hash160}; -use serde::{Deserialize, Serialize}; - -/// This file contains functions used for custom serde serializations and deserializations. - -pub fn burn_hh_serialize( - bhh: &BurnchainHeaderHash, - s: S, -) -> Result { - let inst = bhh.to_hex(); - s.serialize_str(inst.as_str()) -} - -pub fn burn_hh_deserialize<'de, D: serde::Deserializer<'de>>( - d: D, -) -> Result { - let inst_str = String::deserialize(d)?; - BurnchainHeaderHash::from_hex(&inst_str).map_err(serde::de::Error::custom) -} - -pub fn block_hh_serialize( - bhh: &BlockHeaderHash, - s: S, -) -> Result { - let inst = bhh.to_hex(); - s.serialize_str(inst.as_str()) -} - -pub fn block_hh_deserialize<'de, D: serde::Deserializer<'de>>( - d: D, -) -> Result { - let inst_str = String::deserialize(d)?; - BlockHeaderHash::from_hex(&inst_str).map_err(serde::de::Error::custom) -} - -pub fn vrf_seed_serialize(seed: &VRFSeed, s: S) -> Result { - let inst = seed.to_hex(); - s.serialize_str(inst.as_str()) -} - -pub fn vrf_seed_deserialize<'de, D: serde::Deserializer<'de>>(d: D) -> Result { - let inst_str = String::deserialize(d)?; - VRFSeed::from_hex(&inst_str).map_err(serde::de::Error::custom) -} - -pub fn consensus_hash_serialize( - ch: &ConsensusHash, - s: S, -) -> Result { - let inst = ch.to_hex(); - s.serialize_str(inst.as_str()) -} - -pub fn consensus_hash_deserialize<'de, D: serde::Deserializer<'de>>( - d: D, -) -> Result { - let inst_str = String::deserialize(d)?; - ConsensusHash::from_hex(&inst_str).map_err(serde::de::Error::custom) -} - -pub fn memo_serialize(memo: &Vec, s: S) -> Result { - let hex_inst = to_hex(memo); - let byte_str = format!("0x{}", hex_inst); - s.serialize_str(byte_str.as_str()) -} - -pub fn memo_deserialize<'de, D: serde::Deserializer<'de>>(d: D) -> Result, D::Error> { - let bytes_str = String::deserialize(d)?; - let hex_inst = &bytes_str[2..]; - - hex_bytes(&hex_inst).map_err(serde::de::Error::custom) -} - -#[derive(Serialize, Deserialize)] -struct StacksAddrJsonDisplay { - address: String, - #[serde( - deserialize_with = "hash_160_deserialize", - serialize_with = "hash_160_serialize" - )] - address_hash_bytes: Hash160, - address_version: u8, -} - -fn hash_160_serialize(hash: &Hash160, s: S) -> Result { - let hex_inst = to_hex(&hash.0); - let byte_str = format!("0x{}", hex_inst); - s.serialize_str(byte_str.as_str()) -} - -fn hash_160_deserialize<'de, D: serde::Deserializer<'de>>(d: D) -> Result { - let bytes_str = String::deserialize(d)?; - let hex_inst = &bytes_str[2..]; - Hash160::from_hex(&hex_inst).map_err(serde::de::Error::custom) -} - -pub fn stacks_addr_serialize( - addr: &StacksAddress, - s: S, -) -> Result { - let addr_str = addr.to_string(); - let addr_display = StacksAddrJsonDisplay { - address: addr_str, - address_hash_bytes: addr.bytes, - address_version: addr.version, - }; - addr_display.serialize(s) -} - -pub fn stacks_addr_deserialize<'de, D: serde::Deserializer<'de>>( - d: D, -) -> Result { - let addr_display = StacksAddrJsonDisplay::deserialize(d)?; - Ok(StacksAddress { - version: addr_display.address_version, - bytes: addr_display.address_hash_bytes, - }) -} diff --git a/testnet/stacks-node/src/event_dispatcher.rs b/testnet/stacks-node/src/event_dispatcher.rs index 9550e3df4..42220b043 100644 --- a/testnet/stacks-node/src/event_dispatcher.rs +++ b/testnet/stacks-node/src/event_dispatcher.rs @@ -30,6 +30,7 @@ use stacks::vm::events::{FTEventType, NFTEventType, STXEventType}; use stacks::vm::types::{AssetIdentifier, QualifiedContractIdentifier, Value}; use super::config::{EventKeyType, EventObserverConfig}; +use stacks::chainstate::burn::operations::BlockstackOperationType; use stacks::chainstate::burn::ConsensusHash; use stacks::chainstate::stacks::db::unconfirmed::ProcessedUnconfirmedState; use stacks::chainstate::stacks::miner::TransactionEvent; @@ -216,9 +217,11 @@ impl EventObserver { }; let (txid, raw_tx, burnchain_op_json) = match tx { - TransactionOrigin::Burn(op) => { - (op.txid().to_string(), "00".to_string(), json!(op.clone())) - } + TransactionOrigin::Burn(op) => ( + op.txid().to_string(), + "00".to_string(), + BlockstackOperationType::blockstack_op_to_json(&op), + ), TransactionOrigin::Stacks(ref tx) => { let txid = tx.txid().to_string(); let bytes = tx.serialize_to_vec(); @@ -251,7 +254,8 @@ impl EventObserver { receipt: &StacksTransactionReceipt, tx_index: u32, ) -> serde_json::Value { - let receipt_payload_info = EventObserver::generate_payload_info_for_receipt(receipt); + let receipt_payloa + d_info = EventObserver::generate_payload_info_for_receipt(receipt); json!({ "txid": format!("0x{}", &receipt_payload_info.txid),