Skip to content

Commit 5224137

Browse files
committed
refactor: use Txid taking into account bitcoin endiness, #6250
1 parent 4114e6e commit 5224137

File tree

4 files changed

+43
-35
lines changed

4 files changed

+43
-35
lines changed

stacks-node/src/burnchains/rpc/bitcoin_rpc_client/mod.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,21 @@ impl<'de> Deserialize<'de> for GenerateToAddressResponse {
283283
}
284284
}
285285

286+
/// Response mainly used as deserialization wrapper for [`Txid`]
287+
struct TxidWrapperResponse(pub Txid);
288+
289+
/// Deserializes a JSON string (hex-encoded, big-endian) into [`Txid`] and wrap it into [`TxidWrapperResponse`]
290+
impl<'de> Deserialize<'de> for TxidWrapperResponse {
291+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
292+
where
293+
D: Deserializer<'de>,
294+
{
295+
let hex_str: String = Deserialize::deserialize(deserializer)?;
296+
let txid = Txid::from_bitcoin_hex(&hex_str).map_err(serde::de::Error::custom)?;
297+
Ok(TxidWrapperResponse(txid))
298+
}
299+
}
300+
286301
/// Client for interacting with a Bitcoin RPC service.
287302
#[derive(Debug)]
288303
pub struct BitcoinRpcClient {
@@ -526,19 +541,21 @@ impl BitcoinRpcClient {
526541
/// hex-encoded transaction, and other metadata for a transaction tracked by the wallet.
527542
///
528543
/// # Arguments
529-
/// * `txid` - The transaction ID (as [`Txid`]) to query.
544+
/// * `txid` - The transaction ID (as [`Txid`]) to query,
545+
/// which is intended to be created with [`Txid::from_bitcoin_hex`],
546+
/// or an analogous process.
530547
///
531548
/// # Returns
532549
/// A [`GetTransactionResponse`] containing detailed metadata for the specified transaction.
533550
///
534551
/// # Availability
535552
/// - **Since**: Bitcoin Core **v0.10.0**.
536553
pub fn get_transaction(&self, txid: &Txid) -> BitcoinRpcClientResult<GetTransactionResponse> {
537-
Ok(self.wallet_ep.send(
538-
&self.client_id,
539-
"gettransaction",
540-
vec![txid.to_string().into()],
541-
)?)
554+
let btc_txid = txid.to_bitcoin_hex();
555+
556+
Ok(self
557+
.wallet_ep
558+
.send(&self.client_id, "gettransaction", vec![btc_txid.into()])?)
542559
}
543560

544561
/// Broadcasts a raw transaction to the Bitcoin network.
@@ -557,7 +574,7 @@ impl BitcoinRpcClient {
557574
/// - If `None`, defaults to `0`, meaning burning is not allowed.
558575
///
559576
/// # Returns
560-
/// A [`Txid`] as a transaction ID.
577+
/// A [`Txid`] as a transaction ID (storing internally bytes in **little-endian** order)
561578
///
562579
/// # Availability
563580
/// - **Since**: Bitcoin Core **v0.7.0**.
@@ -572,11 +589,12 @@ impl BitcoinRpcClient {
572589
let max_fee_rate = max_fee_rate.unwrap_or(0.10);
573590
let max_burn_amount = max_burn_amount.unwrap_or(0);
574591

575-
Ok(self.global_ep.send(
592+
let response = self.global_ep.send::<TxidWrapperResponse>(
576593
&self.client_id,
577594
"sendrawtransaction",
578595
vec![tx_hex.into(), max_fee_rate.into(), max_burn_amount.into()],
579-
)?)
596+
)?;
597+
Ok(response.0)
580598
}
581599

582600
/// Returns information about a descriptor, including its checksum.

stacks-node/src/burnchains/rpc/bitcoin_rpc_client/test_utils.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ use stacks::types::Address;
2525
use stacks_common::deps_common::bitcoin::blockdata::transaction::Transaction;
2626
use stacks_common::deps_common::bitcoin::network::serialize::deserialize_hex;
2727

28-
use crate::burnchains::rpc::bitcoin_rpc_client::{BitcoinRpcClient, BitcoinRpcClientResult};
28+
use crate::burnchains::rpc::bitcoin_rpc_client::{
29+
BitcoinRpcClient, BitcoinRpcClientResult, TxidWrapperResponse,
30+
};
2931

3032
/// Represents the response returned by the `getblockchaininfo` RPC call.
3133
///
@@ -138,21 +140,6 @@ impl<'de> Deserialize<'de> for GetNewAddressResponse {
138140
}
139141
}
140142

141-
/// Response for `sendtoaddress` rpc, mainly used as deserialization wrapper for `Txid`
142-
struct SendToAddressResponse(pub Txid);
143-
144-
/// Deserializes a JSON string into [`Txid`] and wrap it into [`SendToAddressResponse`]
145-
impl<'de> Deserialize<'de> for SendToAddressResponse {
146-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
147-
where
148-
D: Deserializer<'de>,
149-
{
150-
let hex_str: String = Deserialize::deserialize(deserializer)?;
151-
let txid = Txid::from_hex(&hex_str).map_err(serde::de::Error::custom)?;
152-
Ok(SendToAddressResponse(txid))
153-
}
154-
}
155-
156143
impl BitcoinRpcClient {
157144
/// Retrieve general information about the current state of the blockchain.
158145
///
@@ -170,18 +157,21 @@ impl BitcoinRpcClient {
170157
/// Retrieves and deserializes a raw Bitcoin transaction by its ID.
171158
///
172159
/// # Arguments
173-
/// * `txid` - Transaction ID to fetch.
160+
/// * `txid` - Transaction ID to fetch, which is intended to be created with [`Txid::from_bitcoin_hex`],
161+
/// or an analogous process.
174162
///
175163
/// # Returns
176164
/// A [`Transaction`] struct representing the decoded transaction.
177165
///
178166
/// # Availability
179167
/// - **Since**: Bitcoin Core **v0.7.0**.
180168
pub fn get_raw_transaction(&self, txid: &Txid) -> BitcoinRpcClientResult<Transaction> {
169+
let btc_txid = txid.to_bitcoin_hex();
170+
181171
let raw_hex = self.global_ep.send::<String>(
182172
&self.client_id,
183173
"getrawtransaction",
184-
vec![txid.to_string().into()],
174+
vec![btc_txid.to_string().into()],
185175
)?;
186176
Ok(deserialize_hex(&raw_hex)?)
187177
}
@@ -273,7 +263,7 @@ impl BitcoinRpcClient {
273263
/// * `amount` - Amount to send in BTC (not in satoshis).
274264
///
275265
/// # Returns
276-
/// A [`Txid`] struct representing the transaction ID
266+
/// A [`Txid`] struct representing the transaction ID (storing internally bytes in **little-endian** order)
277267
///
278268
/// # Availability
279269
/// - **Since**: Bitcoin Core **v0.1.0**.
@@ -282,7 +272,7 @@ impl BitcoinRpcClient {
282272
address: &BitcoinAddress,
283273
amount: f64,
284274
) -> BitcoinRpcClientResult<Txid> {
285-
let response = self.wallet_ep.send::<SendToAddressResponse>(
275+
let response = self.wallet_ep.send::<TxidWrapperResponse>(
286276
&self.client_id,
287277
"sendtoaddress",
288278
vec![address.to_string().into(), amount.into()],

stacks-node/src/burnchains/rpc/bitcoin_rpc_client/tests.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ fn test_get_transaction_ok() {
467467

468468
let client = utils::setup_client(&server);
469469

470-
let txid = Txid::from_hex(&txid_hex).unwrap();
470+
let txid = Txid::from_bitcoin_hex(&txid_hex).unwrap();
471471
let info = client.get_transaction(&txid).expect("Should be ok!");
472472
assert_eq!(6, info.confirmations);
473473
}
@@ -501,7 +501,7 @@ fn test_get_raw_transaction_ok() {
501501

502502
let client = utils::setup_client(&server);
503503

504-
let txid = Txid::from_hex(txid_hex).unwrap();
504+
let txid = Txid::from_bitcoin_hex(txid_hex).unwrap();
505505
let raw_tx = client.get_raw_transaction(&txid).expect("Should be ok!");
506506
assert_eq!(txid_hex, raw_tx.txid().to_string());
507507
assert_eq!(expected_tx_hex, serialize_hex(&raw_tx).unwrap());
@@ -623,7 +623,7 @@ fn test_send_raw_transaction_ok_with_defaults() {
623623
let txid = client
624624
.send_raw_transaction(&raw_tx, None, None)
625625
.expect("Should work!");
626-
assert_eq!(expected_txid, txid.to_hex());
626+
assert_eq!(expected_txid, txid.to_bitcoin_hex());
627627
}
628628

629629
#[test]
@@ -659,7 +659,7 @@ fn test_send_raw_transaction_ok_with_custom_params() {
659659
let txid = client
660660
.send_raw_transaction(&raw_tx, Some(0.0), Some(5_000))
661661
.expect("Should work!");
662-
assert_eq!(expected_txid, txid.to_hex());
662+
assert_eq!(expected_txid, txid.to_bitcoin_hex());
663663
}
664664

665665
#[test]
@@ -880,7 +880,7 @@ fn test_send_to_address_ok() {
880880
let txid = client
881881
.send_to_address(&address, amount)
882882
.expect("Should be ok!");
883-
assert_eq!(expected_txid_str, txid.to_hex());
883+
assert_eq!(expected_txid_str, txid.to_bitcoin_hex());
884884
}
885885

886886
#[test]

stacks-node/src/tests/bitcoin_rpc_integrations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ fn test_get_raw_transaction_ok() {
430430
.get_raw_transaction(&txid)
431431
.expect("get raw transaction ok!");
432432

433-
assert_eq!(txid.to_string(), raw_tx.txid().to_string());
433+
assert_eq!(txid.to_bitcoin_hex(), raw_tx.txid().to_string());
434434
}
435435

436436
#[ignore]

0 commit comments

Comments
 (0)