Skip to content

Commit

Permalink
Use pre-segwit transaction serialization for fundrawtransaction (#2865)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Dec 16, 2023
1 parent 2a1e8db commit e44cce8
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
14 changes: 13 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,27 @@ fn fund_raw_transaction(
fee_rate: FeeRate,
unfunded_transaction: &Transaction,
) -> Result<Vec<u8>> {
let mut buffer = Vec::new();

{
unfunded_transaction.version.consensus_encode(&mut buffer)?;
unfunded_transaction.input.consensus_encode(&mut buffer)?;
unfunded_transaction.output.consensus_encode(&mut buffer)?;
unfunded_transaction
.lock_time
.consensus_encode(&mut buffer)?;
}

Ok(
client
.fund_raw_transaction(
unfunded_transaction,
&buffer,
Some(&bitcoincore_rpc::json::FundRawTransactionOptions {
// NB. This is `fundrawtransaction`'s `feeRate`, which is fee per kvB
// and *not* fee per vB. So, we multiply the fee rate given by the user
// by 1000.
fee_rate: Some(Amount::from_sat((fee_rate.n() * 1000.0).ceil() as u64)),
change_position: Some(unfunded_transaction.output.len().try_into()?),
..Default::default()
}),
Some(false),
Expand Down
2 changes: 2 additions & 0 deletions test-bitcoincore-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ impl From<OutPoint> for JsonOutPoint {
struct FundRawTransactionOptions {
#[serde(with = "bitcoin::amount::serde::as_btc::opt")]
fee_rate: Option<Amount>,
#[serde(skip_serializing_if = "Option::is_none")]
change_position: Option<u32>,
}

#[derive(Deserialize, Clone, PartialEq, Eq, Debug, Serialize)]
Expand Down
25 changes: 23 additions & 2 deletions test-bitcoincore-rpc/src/server.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use {
super::*,
bitcoin::{
consensus::Decodable,
secp256k1::{rand, KeyPair, Secp256k1, XOnlyPublicKey},
Witness,
},
std::io::Cursor,
};

pub(crate) struct Server {
Expand Down Expand Up @@ -243,7 +245,26 @@ impl Api for Server {
options: Option<FundRawTransactionOptions>,
_is_witness: Option<bool>,
) -> Result<FundRawTransactionResult, jsonrpc_core::Error> {
let mut transaction: Transaction = deserialize(&hex::decode(tx).unwrap()).unwrap();
let options = options.unwrap();

let mut cursor = Cursor::new(hex::decode(tx).unwrap());

let version = i32::consensus_decode_from_finite_reader(&mut cursor).unwrap();
let input = Vec::<TxIn>::consensus_decode_from_finite_reader(&mut cursor).unwrap();
let output = Decodable::consensus_decode_from_finite_reader(&mut cursor).unwrap();
let lock_time = Decodable::consensus_decode_from_finite_reader(&mut cursor).unwrap();

let mut transaction = Transaction {
version,
input,
output,
lock_time,
};

assert_eq!(
options.change_position,
Some(transaction.output.len().try_into().unwrap())
);

let state = self.state();

Expand Down Expand Up @@ -294,7 +315,7 @@ impl Api for Server {
script_pubkey: ScriptBuf::new(),
});

let fee = if let Some(fee_rate) = options.and_then(|options| options.fee_rate) {
let fee = if let Some(fee_rate) = options.fee_rate {
// increase vsize to account for the witness that `fundrawtransaction` will add
let funded_vsize = transaction.vsize() as f64 + 68.0 / 4.0;
let funded_kwu = funded_vsize / 1000.0;
Expand Down

0 comments on commit e44cce8

Please sign in to comment.