Skip to content

Commit f3717d4

Browse files
committed
fix: txid in minedblock events should be hex serialized for json, not as number[]
1 parent 853a7bc commit f3717d4

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

src/chainstate/stacks/miner.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use clarity_vm::clarity::{ClarityConnection, ClarityInstance};
4040
use core::mempool::*;
4141
use core::*;
4242
use net::Error as net_error;
43+
use serde::Deserialize;
4344
use util::get_epoch_time_ms;
4445
use util::hash::MerkleTree;
4546
use util::hash::Sha512Trunc256Sum;
@@ -159,6 +160,7 @@ pub struct TransactionSkipped {
159160
/// Represents an event for a successful transaction. This transaction should be added to the block.
160161
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
161162
pub struct TransactionSuccessEvent {
163+
#[serde(deserialize_with = "hex_deserialize", serialize_with = "hex_serialize")]
162164
pub txid: Txid,
163165
pub fee: u64,
164166
pub execution_cost: ExecutionCost,
@@ -168,17 +170,29 @@ pub struct TransactionSuccessEvent {
168170
/// Represents an event for a failed transaction. Something went wrong when processing this transaction.
169171
#[derive(Debug, Clone, Serialize, Deserialize)]
170172
pub struct TransactionErrorEvent {
173+
#[serde(deserialize_with = "hex_deserialize", serialize_with = "hex_serialize")]
171174
pub txid: Txid,
172175
pub error: String,
173176
}
174177

175178
/// Represents an event for a transaction that was skipped, but might succeed later.
176179
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
177180
pub struct TransactionSkippedEvent {
181+
#[serde(deserialize_with = "hex_deserialize", serialize_with = "hex_serialize")]
178182
pub txid: Txid,
179183
pub error: String,
180184
}
181185

186+
fn hex_serialize<S: serde::Serializer>(txid: &Txid, s: S) -> Result<S::Ok, S::Error> {
187+
let inst = txid.to_hex();
188+
s.serialize_str(inst.as_str())
189+
}
190+
191+
fn hex_deserialize<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Txid, D::Error> {
192+
let inst_str = String::deserialize(d)?;
193+
Txid::from_hex(&inst_str).map_err(serde::de::Error::custom)
194+
}
195+
182196
/// `TransactionResult` represents the outcome of transaction processing.
183197
/// We use this enum to involve the compiler in forcing us to always clearly
184198
/// indicate the outcome of a transaction.

testnet/stacks-node/src/tests/neon_integrations.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,35 @@ pub mod test_observer {
165165

166166
async fn handle_mined_block(block: serde_json::Value) -> Result<impl warp::Reply, Infallible> {
167167
let mut mined_blocks = MINED_BLOCKS.lock().unwrap();
168+
// assert that the mined transaction events have string-y txids
169+
block
170+
.as_object()
171+
.expect("Expected JSON object for mined block event")
172+
.get("tx_events")
173+
.expect("Expected tx_events key in mined block event")
174+
.as_array()
175+
.expect("Expected tx_events key to be an array in mined block event")
176+
.iter()
177+
.for_each(|txevent| {
178+
let txevent_obj = txevent.as_object().expect("TransactionEvent should be object");
179+
let inner_obj = if let Some(inner_obj) = txevent_obj.get("Success") {
180+
inner_obj
181+
} else if let Some(inner_obj) = txevent_obj.get("ProcessingError") {
182+
inner_obj
183+
} else if let Some(inner_obj) = txevent_obj.get("Skipped") {
184+
inner_obj
185+
} else {
186+
panic!("TransactionEvent object should have one of Success, ProcessingError, or Skipped")
187+
};
188+
inner_obj
189+
.as_object()
190+
.expect("TransactionEvent should be an object")
191+
.get("txid")
192+
.expect("Should have txid key")
193+
.as_str()
194+
.expect("Expected txid to be a string");
195+
});
196+
168197
mined_blocks.push(serde_json::from_value(block).unwrap());
169198
Ok(warp::http::StatusCode::OK)
170199
}

0 commit comments

Comments
 (0)