Skip to content

Commit e34e9ba

Browse files
[BCH]: Fix Transaction Planning (#4118)
* [BCH]: Fix Transaction Planning * [BCH]: Add BitcoinCash transaction signing V2 test in C++
1 parent 45124dd commit e34e9ba

File tree

5 files changed

+96
-6
lines changed

5 files changed

+96
-6
lines changed

rust/chains/tw_bitcoincash/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use tw_coin_entry::error::prelude::*;
77
use tw_utxo::context::{AddressPrefixes, UtxoContext};
88
use tw_utxo::script::Script;
99

10+
#[derive(Default)]
1011
pub struct BitcoinCashContext;
1112

1213
impl UtxoContext for BitcoinCashContext {

rust/chains/tw_bitcoincash/src/entry.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,14 @@ impl CoinEntry for BitcoinCashEntry {
9292
) -> Self::SigningOutput {
9393
BitcoinCompiler::<BitcoinCashContext>::compile(coin, input, signatures, public_keys)
9494
}
95+
96+
#[inline]
97+
fn plan_builder(&self) -> Option<Self::PlanBuilder> {
98+
Some(BitcoinPlanner::<BitcoinCashContext>::default())
99+
}
100+
101+
#[inline]
102+
fn transaction_util(&self) -> Option<Self::TransactionUtil> {
103+
Some(BitcoinTransactionUtil)
104+
}
95105
}

rust/tw_tests/tests/chains/bitcoincash/bitcoincash_sign.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Copyright © 2017 Trust Wallet.
44

55
use crate::chains::bitcoincash::test_cases::transfer_96ee20;
6-
use crate::chains::common::bitcoin::{btc_info, sign, TransactionOneof};
6+
use crate::chains::common::bitcoin::{btc_info, plan, sign, TransactionOneof};
77
use tw_coin_registry::coin_type::CoinType;
88
use tw_encoding::hex::DecodeHex;
99
use tw_proto::BitcoinV2::Proto;
@@ -20,6 +20,16 @@ fn test_bitcoincash_sign_input_p2pkh_from_to_address() {
2020
..Default::default()
2121
};
2222

23+
plan::BitcoinPlanHelper::new(&signing)
24+
.coin(CoinType::BitcoinCash)
25+
.plan(plan::Expected {
26+
inputs: vec![5151],
27+
outputs: vec![600, 4325],
28+
vsize_estimate: 227,
29+
fee_estimate: 226,
30+
change: 0,
31+
});
32+
2333
// Successfully broadcasted:
2434
// https://blockchair.com/bitcoin-cash/transaction/96ee20002b34e468f9d3c5ee54f6a8ddaa61c118889c4f35395c2cd93ba5bbb4
2535
sign::BitcoinSignHelper::new(&signing)
@@ -29,7 +39,6 @@ fn test_bitcoincash_sign_input_p2pkh_from_to_address() {
2939
txid: transfer_96ee20::TX_ID,
3040
inputs: vec![5151],
3141
outputs: vec![600, 4325],
32-
// `vsize` is different from the estimated value due to the signatures der serialization.
3342
vsize: 226,
3443
weight: 904,
3544
fee: 226,

rust/tw_tests/tests/chains/solana/solana_transaction_ffi.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,17 @@
22
//
33
// Copyright © 2017 Trust Wallet.
44

5-
use tw_any_coin::test_utils::address_utils::test_address_derive;
6-
use tw_any_coin::test_utils::sign_utils::{AnySignerHelper, PreImageHelper};
5+
use tw_any_coin::test_utils::sign_utils::AnySignerHelper;
76
use tw_any_coin::test_utils::transaction_decode_utils::TransactionDecoderHelper;
87
use tw_coin_registry::coin_type::CoinType;
98
use tw_encoding::base64::STANDARD;
10-
use tw_encoding::hex::{DecodeHex, ToHex};
9+
use tw_encoding::hex::DecodeHex;
1110
use tw_encoding::{base58, base64};
1211
use tw_memory::test_utils::tw_data_helper::TWDataHelper;
1312
use tw_memory::test_utils::tw_data_vector_helper::TWDataVectorHelper;
1413
use tw_memory::test_utils::tw_string_helper::TWStringHelper;
1514
use tw_proto::Common::Proto::SigningError;
16-
use tw_proto::Solana::Proto::{self, mod_SigningInput::OneOftransaction_type as TransactionType};
15+
use tw_proto::Solana::Proto::{self};
1716
use tw_solana::SOLANA_ALPHABET;
1817
use wallet_core_rs::ffi::solana::transaction::{
1918
tw_solana_transaction_get_compute_unit_limit, tw_solana_transaction_get_compute_unit_price,

tests/chains/BitcoinCash/TWBitcoinCashTests.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "Bitcoin/SigHashType.h"
77
#include "HexCoding.h"
88
#include "proto/Bitcoin.pb.h"
9+
#include "proto/BitcoinV2.pb.h"
910
#include "TestUtilities.h"
1011

1112
#include <TrustWalletCore/TWBitcoinSigHashType.h>
@@ -161,6 +162,76 @@ TEST(BitcoinCash, SignTransaction) {
161162
"e510000000000000" "1976a9149e089b6889e032d46e3b915a3392edfd616fb1c488ac"
162163
"00000000");
163164
}
165+
166+
TEST(BitcoinCash, SignTransactionV2) {
167+
auto privateKey = parse_hex("7fdafb9db5bc501f2096e7d13d331dc7a75d9594af3d251313ba8b6200f4e384");
168+
auto txId = parse_hex("050d00e2e18ef13969606f1ceee290d3f49bd940684ce39898159352952b8ce2");
169+
std::reverse(txId.begin(), txId.end());
170+
171+
BitcoinV2::Proto::SigningInput signing;
172+
signing.add_private_keys(privateKey.data(), privateKey.size());
173+
signing.mutable_chain_info()->set_p2pkh_prefix(0);
174+
signing.mutable_chain_info()->set_p2sh_prefix(5);
175+
signing.mutable_chain_info()->set_hrp("bitcoincash");
176+
177+
auto& builder = *signing.mutable_builder();
178+
builder.set_version(BitcoinV2::Proto::TransactionVersion::V1);
179+
builder.set_input_selector(BitcoinV2::Proto::InputSelector::UseAll);
180+
builder.set_fixed_dust_threshold(546);
181+
182+
auto& in = *builder.add_inputs();
183+
auto& inOutPoint = *in.mutable_out_point();
184+
inOutPoint.set_hash(txId.data(), txId.size());
185+
inOutPoint.set_vout(2);
186+
in.set_value(5151);
187+
// Cash address without prefix.
188+
in.set_receiver_address("qzhlrcrcne07x94h99thved2pgzdtv8ccujjy73xya");
189+
in.set_sighash_type(TWBitcoinSigHashTypeAll | TWBitcoinSigHashTypeFork);
190+
191+
auto& out0 = *builder.add_outputs();
192+
out0.set_value(600);
193+
// Legacy address.
194+
out0.set_to_address("1Bp9U1ogV3A14FMvKbRJms7ctyso4Z4Tcx");
195+
196+
auto& explicitChangeOutput = *builder.add_outputs();
197+
explicitChangeOutput.set_value(4325);
198+
// Cash address with an explicit prefix.
199+
explicitChangeOutput.set_to_address("bitcoincash:qz0q3xmg38sr94rw8wg45vujah7kzma3cskxymnw06");
200+
201+
Proto::SigningInput legacy;
202+
*legacy.mutable_signing_v2() = signing;
203+
legacy.set_coin_type(TWCoinTypeBitcoinCash);
204+
205+
Proto::TransactionPlan plan;
206+
ANY_PLAN(legacy, plan, TWCoinTypeBitcoin);
207+
208+
ASSERT_EQ(plan.error(), Common::Proto::SigningError::OK);
209+
const auto planV2 = plan.planning_result_v2();
210+
EXPECT_EQ(planV2.error(), Common::Proto::SigningError::OK) << planV2.error_message();
211+
212+
EXPECT_EQ(planV2.inputs_size(), 1);
213+
EXPECT_EQ(planV2.outputs_size(), 2);
214+
EXPECT_EQ(planV2.vsize_estimate(), 227);
215+
EXPECT_EQ(planV2.fee_estimate(), 226);
216+
EXPECT_EQ(planV2.change(), 0);
217+
218+
Proto::SigningOutput output;
219+
ANY_SIGN(legacy, TWCoinTypeBitcoin);
220+
221+
EXPECT_EQ(output.error(), Common::Proto::OK);
222+
ASSERT_TRUE(output.has_signing_result_v2());
223+
const auto outputV2 = output.signing_result_v2();
224+
EXPECT_EQ(outputV2.error(), Common::Proto::SigningError::OK) << outputV2.error_message();
225+
ASSERT_EQ(hex(outputV2.encoded()),
226+
"01000000"
227+
"01"
228+
"e28c2b955293159898e34c6840d99bf4d390e2ee1c6f606939f18ee1e2000d05" "02000000" "6b483045022100b70d158b43cbcded60e6977e93f9a84966bc0cec6f2dfd1463d1223a90563f0d02207548d081069de570a494d0967ba388ff02641d91cadb060587ead95a98d4e3534121038eab72ec78e639d02758e7860cdec018b49498c307791f785aa3019622f4ea5b" "ffffffff"
229+
"02"
230+
"5802000000000000" "1976a914769bdff96a02f9135a1d19b749db6a78fe07dc9088ac"
231+
"e510000000000000" "1976a9149e089b6889e032d46e3b915a3392edfd616fb1c488ac"
232+
"00000000");
233+
}
234+
164235
// clang-format on
165236

166237
} // namespace TW::Bitcoin::tests

0 commit comments

Comments
 (0)