Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra Decred signer tests and fixes #949

Merged
merged 11 commits into from
May 8, 2020
3 changes: 3 additions & 0 deletions src/Bitcoin/TransactionSigner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Result<Transaction> TransactionSigner<Transaction, TransactionBuilder>::sign() {
std::copy(std::begin(transaction.inputs), std::end(transaction.inputs),
std::back_inserter(signedInputs));

if (plan.utxos.size() == 0) {
return Result<Transaction>::failure("Plan without UTXOs");
}
const auto hashSingle = hashTypeIsSingle(static_cast<enum TWBitcoinSigHashType>(input.hash_type()));
for (auto i = 0; i < plan.utxos.size(); i += 1) {
auto& utxo = plan.utxos[i];
Expand Down
4 changes: 3 additions & 1 deletion src/Bitcoin/TransactionSigner.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@ class TransactionSigner {
/// \returns the signed transaction or an error.
Result<Transaction> sign();

// internal, public for testability and Decred
static Data pushAll(const std::vector<Data>& results);

private:
Result<void> sign(Script script, size_t index, const Proto::UnspentTransaction& utxo);
Result<std::vector<Data>> signStep(Script script, size_t index,
const Proto::UnspentTransaction& utxo, uint32_t version);
Data createSignature(const Transaction& transaction, const Script& script, const Data& key,
size_t index, Amount amount, uint32_t version);
Data pushAll(const std::vector<Data>& results);

/// Returns the private key for the given public key hash.
Data keyForPublicKeyHash(const Data& hash) const;
Expand Down
30 changes: 5 additions & 25 deletions src/Decred/Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "TransactionInput.h"
#include "TransactionOutput.h"
#include "../Bitcoin/SigHashType.h"
#include "../Bitcoin/TransactionSigner.h"

#include "../BinaryCoding.h"
#include "../Hash.h"
Expand Down Expand Up @@ -50,6 +51,9 @@ Result<Transaction> Signer::sign() {
std::copy(std::begin(transaction.inputs), std::end(transaction.inputs),
std::back_inserter(signedInputs));

if (txPlan.utxos.size() == 0) {
return Result<Transaction>::failure("Plan without UTXOs");
}
const auto hashSingle = Bitcoin::hashTypeIsSingle(static_cast<enum TWBitcoinSigHashType>(input.hash_type()));
for (auto i = 0; i < txPlan.utxos.size(); i += 1) {
auto& utxo = txPlan.utxos[i];
Expand Down Expand Up @@ -96,7 +100,7 @@ Result<Bitcoin::Script> Signer::sign(Bitcoin::Script script, size_t index) {
results.push_back(redeemScript.bytes);
}

return Result<Bitcoin::Script>::success(Bitcoin::Script(pushAll(results)));
return Result<Bitcoin::Script>::success(Bitcoin::Script(Bitcoin::TransactionSigner<Bitcoin::Transaction, Bitcoin::TransactionBuilder>::pushAll(results)));
}

Result<std::vector<Data>> Signer::signStep(Bitcoin::Script script, size_t index) {
Expand Down Expand Up @@ -182,30 +186,6 @@ Data Signer::createSignature(const Transaction& transaction, const Bitcoin::Scri
return signature;
}

Data Signer::pushAll(const std::vector<Data>& results) {
auto data = Data{};
for (auto& result : results) {
if (result.empty()) {
data.push_back(OP_0);
} else if (result.size() == 1 && result[0] >= 1 && result[0] <= 16) {
data.push_back(Bitcoin::Script::encodeNumber(result[0]));
} else if (result.size() < OP_PUSHDATA1) {
data.push_back(static_cast<uint8_t>(result.size()));
} else if (result.size() <= 0xff) {
data.push_back(OP_PUSHDATA1);
data.push_back(static_cast<uint8_t>(result.size()));
} else if (result.size() <= 0xffff) {
data.push_back(OP_PUSHDATA2);
encode16LE(static_cast<uint16_t>(result.size()), data);
} else {
data.push_back(OP_PUSHDATA4);
encode32LE(static_cast<uint32_t>(result.size()), data);
}
std::copy(begin(result), end(result), back_inserter(data));
}
return data;
}

Data Signer::keyForPublicKeyHash(const Data& hash) const {
for (auto& key : input.private_key()) {
auto publicKey = PrivateKey(key).getPublicKey(TWPublicKeyTypeSECP256k1);
Expand Down
1 change: 0 additions & 1 deletion src/Decred/Signer.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ class Signer {
Result<std::vector<Data>> signStep(Bitcoin::Script script, size_t index);
Data createSignature(const Transaction& transaction, const Bitcoin::Script& script,
const Data& key, size_t index);
Data pushAll(const std::vector<Data>& results);

/// Returns the private key for the given public key hash.
Data keyForPublicKeyHash(const Data& hash) const;
Expand Down
1 change: 0 additions & 1 deletion src/Decred/TransactionBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ struct TransactionBuilder {
auto input = TransactionInput();
input.previousOutput = utxo.out_point();
input.sequence = utxo.out_point().sequence();
input.sequence = utxo.out_point().sequence();
tx.inputs.push_back(std::move(input));
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Aion/TWAnySignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ TEST(TWAnySignerAion, Sign) {
auto gasPrice = store(uint256_t(20000000000));
input.set_gas_price(gasPrice.data(), gasPrice.size());
auto gasLimit = store(uint256_t(21000));
input.set_gas_limit(gasLimit.data(), gasLimit.size());;
input.set_gas_limit(gasLimit.data(), gasLimit.size());
auto nonce = store(uint256_t(9));
input.set_nonce(nonce.data(), nonce.size());
input.set_private_key(privateKey.data(), privateKey.size());
Expand Down
47 changes: 47 additions & 0 deletions tests/Bitcoin/BitcoinScriptTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// file LICENSE at the root of the source code distribution tree.

#include "Bitcoin/Script.h"
#include "Bitcoin/TransactionSigner.h"
#include "../interface/TWTestUtilities.h"
#include "HexCoding.h"

Expand Down Expand Up @@ -283,3 +284,49 @@ TEST(BitcoinScript, MatchMultiSig) {
EXPECT_EQ(hex(keys[1]), "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1");
EXPECT_EQ(hex(keys[2]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432");
}

TEST(BitcoinTransactionSigner, PushAllEmpty) {
{
std::vector<Data> input = {};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), "");
}
{
std::vector<Data> input = {parse_hex("")};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), "00");
}
{
std::vector<Data> input = {parse_hex("09")};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), "59" "09");
}
{
std::vector<Data> input = {parse_hex("00010203040506070809")};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), "0a" "00010203040506070809");
}
{
std::vector<Data> input = {parse_hex("0001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809")};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), "4c50" "0001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809");
}
{
// 2-byte len
Data in1 = Data(256 + 10);
Data expected = parse_hex("4d" "0a01");
TW::append(expected, in1);
std::vector<Data> input = {in1};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), hex(expected));
}
{
// 4-byte len
Data in1 = Data(65536 + 256 + 10);
Data expected = parse_hex("4e" "0a010100");
TW::append(expected, in1);
std::vector<Data> input = {in1};
Data res = TransactionSigner<Transaction, TransactionBuilder>::pushAll(input);
EXPECT_EQ(hex(res), hex(expected));
}
}
Loading