-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(btc): Add
TWBitcoinPsbtSign
and TWBitcoinPsbtPlan
C interface
- Loading branch information
1 parent
c7d8407
commit 0af0634
Showing
8 changed files
with
173 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
#pragma once | ||
|
||
#include "TWBase.h" | ||
#include "TWBitcoinSigHashType.h" | ||
#include "TWCoinType.h" | ||
#include "TWData.h" | ||
#include "TWPublicKey.h" | ||
|
||
TW_EXTERN_C_BEGIN | ||
|
||
/// Represents a signer to sign/plan PSBT for Bitcoin blockchains. | ||
TW_EXPORT_CLASS | ||
struct TWBitcoinPsbt; | ||
|
||
/// Signs a PSBT (Partially Signed Bitcoin Transaction) specified by the signing input and coin type. | ||
/// | ||
/// \param input The serialized data of a signing input (e.g. `TW.BitcoinV2.Proto.PsbtSigningInput`) | ||
/// \param coin The given coin type to sign the PSBT for. | ||
/// \return The serialized data of a `Proto.PsbtSigningOutput` proto object (e.g. `TW.BitcoinV2.Proto.PsbtSigningOutput`). | ||
TW_EXPORT_STATIC_METHOD | ||
TWData* _Nonnull TWBitcoinPsbtSign(TWData* _Nonnull input, enum TWCoinType coin); | ||
|
||
/// Plans a PSBT (Partially Signed Bitcoin Transaction). | ||
/// Can be used to get the transaction detailed decoded from PSBT. | ||
/// | ||
/// \param input The serialized data of a signing input (e.g. `TW.BitcoinV2.Proto.PsbtSigningInput`) | ||
/// \param coin The given coin type to sign the PSBT for. | ||
/// \return The serialized data of a `Proto.TransactionPlan` proto object (e.g. `TW.BitcoinV2.Proto.TransactionPlan`). | ||
TW_EXPORT_STATIC_METHOD | ||
TWData* _Nonnull TWBitcoinPsbtPlan(TWData* _Nonnull input, enum TWCoinType coin); | ||
|
||
TW_EXTERN_C_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
#include "Psbt.h" | ||
#include "rust/Wrapper.h" | ||
|
||
namespace TW::Bitcoin { | ||
|
||
Data Psbt::sign(const Data &input, TWCoinType coin) { | ||
const Rust::TWDataWrapper inputRust = input; | ||
const Rust::TWDataWrapper outputRust = Rust::tw_bitcoin_psbt_sign(inputRust.get(), static_cast<uint32_t>(coin)); | ||
return outputRust.toDataOrDefault(); | ||
} | ||
|
||
Data Psbt::plan(const Data& input, TWCoinType coin) { | ||
const Rust::TWDataWrapper inputRust = input; | ||
const Rust::TWDataWrapper outputRust = Rust::tw_bitcoin_psbt_plan(inputRust.get(), static_cast<uint32_t>(coin)); | ||
return outputRust.toDataOrDefault(); | ||
} | ||
|
||
} // namespace TW::Bitcoin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
#pragma once | ||
|
||
#include "Data.h" | ||
#include "TrustWalletCore/TWCoinType.h" | ||
|
||
namespace TW::Bitcoin { | ||
|
||
class Psbt { | ||
public: | ||
/// Signs a PSBT (Partially Signed Bitcoin Transaction) specified by the signing input and coin type. | ||
static Data sign(const Data& input, TWCoinType coin); | ||
|
||
/// Plans a PSBT (Partially Signed Bitcoin Transaction). | ||
/// Can be used to get the transaction detailed decoded from PSBT. | ||
static Data plan(const Data& input, TWCoinType coin); | ||
}; | ||
|
||
} // namespace TW::Bitcoin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
#include "TrustWalletCore/TWBitcoinPsbt.h" | ||
#include "Bitcoin/Psbt.h" | ||
|
||
using namespace TW; | ||
|
||
TWData* _Nonnull TWBitcoinPsbtSign(TWData* _Nonnull input, enum TWCoinType coin) { | ||
const Data& dataIn = *(reinterpret_cast<const Data*>(input)); | ||
const auto dataOut = Bitcoin::Psbt::sign(dataIn, coin); | ||
return TWDataCreateWithBytes(dataOut.data(), dataOut.size()); | ||
} | ||
|
||
TWData* _Nonnull TWBitcoinPsbtPlan(TWData* _Nonnull input, enum TWCoinType coin) { | ||
const Data& dataIn = *(reinterpret_cast<const Data*>(input)); | ||
const auto dataOut = Bitcoin::Psbt::plan(dataIn, coin); | ||
return TWDataCreateWithBytes(dataOut.data(), dataOut.size()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Copyright © 2017 Trust Wallet. | ||
|
||
#include "HexCoding.h" | ||
#include "proto/BitcoinV2.pb.h" | ||
#include "PrivateKey.h" | ||
#include "TestUtilities.h" | ||
|
||
#include "TrustWalletCore/TWBitcoinPsbt.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
namespace TW::Bitcoin::PsbtTests { | ||
|
||
const auto gPrivateKey = PrivateKey(parse_hex("f00ffbe44c5c2838c13d2778854ac66b75e04eb6054f0241989e223223ad5e55")); | ||
const auto gPsbt = parse_hex("70736274ff0100bc0200000001147010db5fbcf619067c1090fec65c131443fbc80fb4aaeebe940e44206098c60000000000ffffffff0360ea000000000000160014f22a703617035ef7f490743d50f26ae08c30d0a70000000000000000426a403d3a474149412e41544f4d3a636f736d6f7331737377797a666d743675396a373437773537753438746778646575393573757a666c6d7175753a303a743a35303e12000000000000160014b139199ec796f36fc42e637f42da8e3e6720aa9d000000000001011f6603010000000000160014b139199ec796f36fc42e637f42da8e3e6720aa9d00000000"); | ||
|
||
TEST(TWBitcoinPsbt, SignThorSwap) { | ||
BitcoinV2::Proto::PsbtSigningInput input; | ||
input.set_psbt(gPsbt.data(), gPsbt.size()); | ||
input.add_private_keys(gPrivateKey.bytes.data(), gPrivateKey.bytes.size()); | ||
|
||
const auto inputData = data(input.SerializeAsString()); | ||
const auto inputPtr = WRAPD(TWDataCreateWithBytes(inputData.data(), inputData.size())); | ||
|
||
const auto outputPtr = WRAPD(TWBitcoinPsbtSign(inputPtr.get(), TWCoinTypeBitcoin)); | ||
|
||
BitcoinV2::Proto::PsbtSigningOutput output; | ||
output.ParseFromArray( | ||
TWDataBytes(outputPtr.get()), | ||
static_cast<int>(TWDataSize(outputPtr.get())) | ||
); | ||
|
||
EXPECT_EQ(output.error(), Common::Proto::SigningError::OK); | ||
EXPECT_EQ(hex(output.psbt()), "70736274ff0100bc0200000001147010db5fbcf619067c1090fec65c131443fbc80fb4aaeebe940e44206098c60000000000ffffffff0360ea000000000000160014f22a703617035ef7f490743d50f26ae08c30d0a70000000000000000426a403d3a474149412e41544f4d3a636f736d6f7331737377797a666d743675396a373437773537753438746778646575393573757a666c6d7175753a303a743a35303e12000000000000160014b139199ec796f36fc42e637f42da8e3e6720aa9d000000000001011f6603010000000000160014b139199ec796f36fc42e637f42da8e3e6720aa9d01086c02483045022100b1229a008f20691639767bf925d6b8956ea957ccc633ad6b5de3618733a55e6b02205774d3320489b8a57a6f8de07f561de3e660ff8e587f6ac5422c49020cd4dc9101210306d8c664ea8fd2683eebea1d3114d90e0a5429e5783ba49b80ddabce04ff28f300000000"); | ||
EXPECT_EQ(hex(output.encoded()), "02000000000101147010db5fbcf619067c1090fec65c131443fbc80fb4aaeebe940e44206098c60000000000ffffffff0360ea000000000000160014f22a703617035ef7f490743d50f26ae08c30d0a70000000000000000426a403d3a474149412e41544f4d3a636f736d6f7331737377797a666d743675396a373437773537753438746778646575393573757a666c6d7175753a303a743a35303e12000000000000160014b139199ec796f36fc42e637f42da8e3e6720aa9d02483045022100b1229a008f20691639767bf925d6b8956ea957ccc633ad6b5de3618733a55e6b02205774d3320489b8a57a6f8de07f561de3e660ff8e587f6ac5422c49020cd4dc9101210306d8c664ea8fd2683eebea1d3114d90e0a5429e5783ba49b80ddabce04ff28f300000000"); | ||
} | ||
|
||
TEST(TWBitcoinPsbt, PlanThorSwap) { | ||
const auto publicKey = gPrivateKey.getPublicKey(TWPublicKeyTypeSECP256k1); | ||
|
||
BitcoinV2::Proto::PsbtSigningInput input; | ||
input.set_psbt(gPsbt.data(), gPsbt.size()); | ||
input.add_public_keys(publicKey.bytes.data(), publicKey.bytes.size()); | ||
|
||
const auto inputData = data(input.SerializeAsString()); | ||
const auto inputPtr = WRAPD(TWDataCreateWithBytes(inputData.data(), inputData.size())); | ||
|
||
const auto planPtr = WRAPD(TWBitcoinPsbtPlan(inputPtr.get(), TWCoinTypeBitcoin)); | ||
|
||
BitcoinV2::Proto::TransactionPlan plan; | ||
plan.ParseFromArray( | ||
TWDataBytes(planPtr.get()), | ||
static_cast<int>(TWDataSize(planPtr.get())) | ||
); | ||
|
||
EXPECT_EQ(plan.error(), Common::Proto::SigningError::OK); | ||
EXPECT_EQ(plan.send_amount(), 66'406); | ||
EXPECT_EQ(plan.fee_estimate(), 1'736); | ||
} | ||
|
||
} |