From 7a6fca9180de91c2b46433ea6da532864ce45a43 Mon Sep 17 00:00:00 2001 From: Anzhy Cherrnyavski Date: Mon, 21 Jan 2019 16:12:35 +0300 Subject: [PATCH] Added mechanism sign bitcoin transaction. --- libraries/sidechain/bitcoin_transaction.cpp | 1 + .../include/sidechain/bitcoin_transaction.hpp | 156 -------- .../sidechain/include/sidechain/serialize.hpp | 372 +++++++++++++++--- .../sidechain/sign_bitcoin_transaction.hpp | 26 ++ .../sidechain/include/sidechain/utils.hpp | 2 + .../sidechain/sign_bitcoin_transaction.cpp | 121 ++++++ libraries/sidechain/utils.cpp | 15 + tests/tests/bitcoin_sign_tests.cpp | 173 ++++++++ tests/tests/bitcoin_transaction_tests.cpp | 1 + 9 files changed, 653 insertions(+), 214 deletions(-) create mode 100644 libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp create mode 100644 libraries/sidechain/sign_bitcoin_transaction.cpp create mode 100644 tests/tests/bitcoin_sign_tests.cpp diff --git a/libraries/sidechain/bitcoin_transaction.cpp b/libraries/sidechain/bitcoin_transaction.cpp index 1c57de2b..40f59dee 100644 --- a/libraries/sidechain/bitcoin_transaction.cpp +++ b/libraries/sidechain/bitcoin_transaction.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace sidechain { diff --git a/libraries/sidechain/include/sidechain/bitcoin_transaction.hpp b/libraries/sidechain/include/sidechain/bitcoin_transaction.hpp index 180a6db3..467dd116 100644 --- a/libraries/sidechain/include/sidechain/bitcoin_transaction.hpp +++ b/libraries/sidechain/include/sidechain/bitcoin_transaction.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include namespace sidechain { @@ -84,161 +83,6 @@ private: }; -template -inline void pack( Stream& s, const out_point& op ) -{ - fc::sha256 reversed( op.hash ); - std::reverse( reversed.data(), reversed.data() + reversed.data_size() ); - s.write( reversed.data(), reversed.data_size() ); - pack( s, op.n ); -} - -template -inline void unpack( Stream& s, out_point& op ) -{ - uint64_t hash_size = op.hash.data_size(); - std::unique_ptr hash_data( new char[hash_size] ); - s.read( hash_data.get(), hash_size ); - std::reverse( hash_data.get(), hash_data.get() + hash_size ); - - op.hash = fc::sha256( hash_data.get(), hash_size ); - unpack( s, op.n ); -} - -template -inline void pack( Stream& s, const tx_in& in ) -{ - pack( s, in.prevout ); - pack( s, in.scriptSig ); - pack( s, in.nSequence ); -} - -template -inline void unpack( Stream& s, tx_in& in ) -{ - unpack( s, in.prevout ); - unpack( s, in.scriptSig ); - unpack( s, in.nSequence ); -} - -template -inline void pack( Stream& s, const tx_out& out ) -{ - pack( s, out.value ); - pack( s, out.scriptPubKey ); -} - -template -inline void unpack( Stream& s, tx_out& out ) -{ - unpack( s, out.value ); - unpack( s, out.scriptPubKey ); -} - -template -inline void pack( Stream& s, const bitcoin_transaction& tx, bool with_witness = true ) -{ - uint8_t flags = 0; - - if ( with_witness ) { - for ( const auto& in : tx.vin ) { - if ( !in.scriptWitness.empty() ) { - flags |= 1; - break; - } - } - } - - pack( s, tx.nVersion ); - - if ( flags ) { - pack_compact_size( s, 0 ); - pack( s, flags ); - } - - pack_compact_size( s, tx.vin.size() ); - for ( const auto& in : tx.vin ) - pack( s, in ); - - pack_compact_size( s, tx.vout.size() ); - for ( const auto& out : tx.vout ) - pack( s, out ); - - if ( flags & 1 ) { - for ( const auto in : tx.vin ) { - pack_compact_size( s, in.scriptWitness.size() ); - for ( const auto& sc : in.scriptWitness ) - pack( s, sc ); - } - } - - pack( s, tx.nLockTime ); -} - -template -inline void unpack( Stream& s, bitcoin_transaction& tx ) { - uint8_t flags = 0; - - unpack( s, tx.nVersion ); - - auto vin_size = unpack_compact_size( s ); - if ( vin_size == 0 ) { - unpack( s, flags ); - vin_size = unpack_compact_size( s ); - } - - tx.vin.reserve( vin_size ); - for ( size_t i = 0; i < vin_size; i++ ) { - tx_in in; - unpack( s, in ); - tx.vin.push_back( in ); - } - - const auto vout_size = unpack_compact_size( s ); - tx.vout.reserve( vout_size ); - for ( size_t i = 0; i < vout_size; i++ ) { - tx_out out; - unpack( s, out ); - tx.vout.push_back( out ); - } - - if ( flags & 1 ) { - for ( auto& in : tx.vin ) { - uint64_t stack_size = unpack_compact_size( s ); - in.scriptWitness.reserve( stack_size ); - for ( uint64_t i = 0; i < stack_size; i++ ) { - std::vector script; - unpack( s, script ); - in.scriptWitness.push_back( script ); - } - } - } - - unpack( s, tx.nLockTime ); -} - -inline std::vector pack( const bitcoin_transaction& v, bool with_witness = true ) { - fc::datastream ps; - pack( ps, v, with_witness ); - std::vector vec( ps.tellp() ); - - if( !vec.empty() ) { - fc::datastream ds( vec.data(), size_t(vec.size()) ); - pack( ds, v, with_witness ); - } - return vec; -} - -inline bitcoin_transaction unpack( const std::vector& s ) -{ try { - bitcoin_transaction tmp; - if( !s.empty() ) { - fc::datastream ds( s.data(), size_t(s.size()) ); - unpack(ds, tmp); - } - return tmp; -} FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type","transaction" ) ) } - } FC_REFLECT( sidechain::out_point, (hash)(n) ) diff --git a/libraries/sidechain/include/sidechain/serialize.hpp b/libraries/sidechain/include/sidechain/serialize.hpp index 2c9c2041..12b6e7fb 100644 --- a/libraries/sidechain/include/sidechain/serialize.hpp +++ b/libraries/sidechain/include/sidechain/serialize.hpp @@ -1,104 +1,360 @@ #pragma once #include +#include namespace sidechain { -inline void write_compact_size(bytes& vec, size_t size) { +inline void write_compact_size( bytes& vec, size_t size ) +{ bytes sb; - sb.reserve(2); - if (size < 253) { - sb.insert(sb.end(), static_cast(size)); - } else if (size <= std::numeric_limits::max()) { - uint16_t tmp = htole16(static_cast(size)); - sb.insert(sb.end(), static_cast(253)); - sb.insert(sb.end(), reinterpret_cast(tmp), reinterpret_cast(tmp) + sizeof(tmp)); - } else if (size <= std::numeric_limits::max()) { - uint32_t tmp = htole32(static_cast(size)); - sb.insert(sb.end(), static_cast(254)); - sb.insert(sb.end(), reinterpret_cast(tmp), reinterpret_cast(tmp) + sizeof(tmp)); + sb.reserve( 2 ); + if ( size < 253 ) { + sb.insert( sb.end(), static_cast( size ) ); + } else if ( size <= std::numeric_limits::max() ) { + uint16_t tmp = htole16( static_cast( size ) ); + sb.insert( sb.end(), static_cast( 253 ) ); + sb.insert( sb.end(), reinterpret_cast( tmp ), reinterpret_cast( tmp ) + sizeof( tmp ) ); + } else if ( size <= std::numeric_limits::max() ) { + uint32_t tmp = htole32( static_cast( size ) ); + sb.insert( sb.end(), static_cast( 254 ) ); + sb.insert( sb.end(), reinterpret_cast( tmp ), reinterpret_cast( tmp ) + sizeof( tmp ) ); } else { - uint64_t tmp = htole64(static_cast(size)); - sb.insert(sb.end(), static_cast(255)); - sb.insert(sb.end(), reinterpret_cast(tmp), reinterpret_cast(tmp) + sizeof(tmp)); + uint64_t tmp = htole64( static_cast( size ) ); + sb.insert( sb.end(), static_cast( 255 ) ); + sb.insert( sb.end(), reinterpret_cast( tmp ), reinterpret_cast( tmp ) + sizeof( tmp ) ); } - vec.insert(vec.end(), sb.begin(), sb.end()); + vec.insert( vec.end(), sb.begin(), sb.end() ); } template -inline void pack_compact_size(Stream& s, size_t size) { - if (size < 253) { - fc::raw::pack(s, static_cast(size)); - } else if (size <= std::numeric_limits::max()) { - fc::raw::pack(s, static_cast(253)); - fc::raw::pack(s, htole16(static_cast(size))); - } else if (size <= std::numeric_limits::max()) { - fc::raw::pack(s, static_cast(254)); - fc::raw::pack(s, htole32(static_cast(size))); +inline void pack_compact_size(Stream& s, size_t size) +{ + if ( size < 253 ) { + fc::raw::pack( s, static_cast( size ) ); + } else if ( size <= std::numeric_limits::max() ) { + fc::raw::pack( s, static_cast( 253 ) ); + fc::raw::pack( s, htole16( static_cast( size ) ) ); + } else if ( size <= std::numeric_limits::max() ) { + fc::raw::pack( s, static_cast( 254 ) ); + fc::raw::pack( s, htole32(static_cast( size ) ) ); } else { - fc::raw::pack(s, static_cast(255)); - fc::raw::pack(s, htole64(static_cast(size))); + fc::raw::pack( s, static_cast( 255 ) ); + fc::raw::pack( s, htole64( static_cast( size ) ) ); } } template -inline uint64_t unpack_compact_size(Stream& s) { +inline uint64_t unpack_compact_size( Stream& s ) +{ uint8_t size; uint64_t size_ret; - fc::raw::unpack(s, size); + fc::raw::unpack( s, size ); if (size < 253) { size_ret = size; - } else if (size == 253) { + } else if ( size == 253 ) { uint16_t tmp; - fc::raw::unpack(s, tmp); - size_ret = le16toh(tmp); - if (size_ret < 253) - FC_THROW_EXCEPTION(fc::parse_error_exception, "non-canonical unpack_compact_size()"); - } else if (size == 254) { + fc::raw::unpack( s, tmp ); + size_ret = le16toh( tmp ); + if ( size_ret < 253 ) + FC_THROW_EXCEPTION( fc::parse_error_exception, "non-canonical unpack_compact_size()" ); + } else if ( size == 254 ) { uint32_t tmp; - fc::raw::unpack(s, tmp); - size_ret = le32toh(tmp); - if (size_ret < 0x10000u) - FC_THROW_EXCEPTION(fc::parse_error_exception, "non-canonical unpack_compact_size()"); + fc::raw::unpack( s, tmp ); + size_ret = le32toh( tmp ); + if ( size_ret < 0x10000u ) + FC_THROW_EXCEPTION( fc::parse_error_exception, "non-canonical unpack_compact_size()" ); } else { uint32_t tmp; - fc::raw::unpack(s, tmp); - size_ret = le64toh(tmp); - if (size_ret < 0x100000000ULL) - FC_THROW_EXCEPTION(fc::parse_error_exception, "non-canonical unpack_compact_size()"); + fc::raw::unpack( s, tmp ); + size_ret = le64toh( tmp ); + if ( size_ret < 0x100000000ULL ) + FC_THROW_EXCEPTION( fc::parse_error_exception, "non-canonical unpack_compact_size()" ); } - if (size_ret > 0x08000000) - FC_THROW_EXCEPTION(fc::parse_error_exception, "unpack_compact_size(): size too large"); + if ( size_ret > 0x08000000 ) + FC_THROW_EXCEPTION( fc::parse_error_exception, "unpack_compact_size(): size too large" ); return size_ret; } template -inline void pack(Stream& s, const std::vector& v) { - pack_compact_size(s, v.size()); - if (!v.empty()) - s.write(v.data(), v.size()); +inline void pack( Stream& s, const std::vector& v ) +{ + pack_compact_size( s, v.size() ); + if ( !v.empty() ) + s.write( v.data(), v.size() ); } template -inline void unpack(Stream& s, std::vector& v) { - const auto size = unpack_compact_size(s); - v.resize(size); - if (size) - s.read(v.data(), size); +inline void unpack( Stream& s, std::vector& v ) +{ + const auto size = unpack_compact_size( s ); + v.resize( size ); + if ( size ) + s.read( v.data(), size ); } template -inline void pack(Stream& s, const T& val) { - fc::raw::pack(s, val); +inline void pack( Stream& s, const T& val ) +{ + fc::raw::pack( s, val ); } template -inline void unpack(Stream& s, T& val) { - fc::raw::unpack(s, val); +inline void unpack( Stream& s, T& val ) +{ + fc::raw::unpack( s, val ); +} + +template +inline void pack( Stream& s, const out_point& op ) +{ + fc::sha256 reversed( op.hash ); + std::reverse( reversed.data(), reversed.data() + reversed.data_size() ); + s.write( reversed.data(), reversed.data_size() ); + pack( s, op.n ); +} + +template +inline void unpack( Stream& s, out_point& op ) +{ + uint64_t hash_size = op.hash.data_size(); + std::unique_ptr hash_data( new char[hash_size] ); + s.read( hash_data.get(), hash_size ); + std::reverse( hash_data.get(), hash_data.get() + hash_size ); + + op.hash = fc::sha256( hash_data.get(), hash_size ); + unpack( s, op.n ); +} + +template +inline void pack( Stream& s, const tx_in& in ) +{ + pack( s, in.prevout ); + pack( s, in.scriptSig ); + pack( s, in.nSequence ); +} + +template +inline void unpack( Stream& s, tx_in& in ) +{ + unpack( s, in.prevout ); + unpack( s, in.scriptSig ); + unpack( s, in.nSequence ); +} + +template +inline void pack( Stream& s, const tx_out& out ) +{ + pack( s, out.value ); + pack( s, out.scriptPubKey ); +} + +template +inline void unpack( Stream& s, tx_out& out ) +{ + unpack( s, out.value ); + unpack( s, out.scriptPubKey ); +} + +template +inline void pack( Stream& s, const bitcoin_transaction& tx, bool with_witness = true ) +{ + uint8_t flags = 0; + + if ( with_witness ) { + for ( const auto& in : tx.vin ) { + if ( !in.scriptWitness.empty() ) { + flags |= 1; + break; + } + } + } + + pack( s, tx.nVersion ); + + if ( flags ) { + pack_compact_size( s, 0 ); + pack( s, flags ); + } + + pack_compact_size( s, tx.vin.size() ); + for ( const auto& in : tx.vin ) + pack( s, in ); + + pack_compact_size( s, tx.vout.size() ); + for ( const auto& out : tx.vout ) + pack( s, out ); + + if ( flags & 1 ) { + for ( const auto in : tx.vin ) { + pack_compact_size( s, in.scriptWitness.size() ); + for ( const auto& sc : in.scriptWitness ) + pack( s, sc ); + } + } + + pack( s, tx.nLockTime ); +} + +template +inline void unpack( Stream& s, bitcoin_transaction& tx ) +{ + uint8_t flags = 0; + + unpack( s, tx.nVersion ); + + auto vin_size = unpack_compact_size( s ); + if ( vin_size == 0 ) { + unpack( s, flags ); + vin_size = unpack_compact_size( s ); + } + + tx.vin.reserve( vin_size ); + for ( size_t i = 0; i < vin_size; i++ ) { + tx_in in; + unpack( s, in ); + tx.vin.push_back( in ); + } + + const auto vout_size = unpack_compact_size( s ); + tx.vout.reserve( vout_size ); + for ( size_t i = 0; i < vout_size; i++ ) { + tx_out out; + unpack( s, out ); + tx.vout.push_back( out ); + } + + if ( flags & 1 ) { + for ( auto& in : tx.vin ) { + uint64_t stack_size = unpack_compact_size( s ); + in.scriptWitness.reserve( stack_size ); + for ( uint64_t i = 0; i < stack_size; i++ ) { + std::vector script; + unpack( s, script ); + in.scriptWitness.push_back( script ); + } + } + } + + unpack( s, tx.nLockTime ); +} + +inline std::vector pack( const bitcoin_transaction& v, bool with_witness = true ) +{ + fc::datastream ps; + pack( ps, v, with_witness ); + std::vector vec( ps.tellp() ); + + if( !vec.empty() ) { + fc::datastream ds( vec.data(), size_t( vec.size() ) ); + pack( ds, v, with_witness ); + } + return vec; +} + +inline bitcoin_transaction unpack( const std::vector& s ) +{ try { + bitcoin_transaction tmp; + if( !s.empty() ) { + fc::datastream ds( s.data(), size_t( s.size() ) ); + unpack(ds, tmp); + } + return tmp; +} FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type","transaction" ) ) } + +template +inline void pack_tx_signature( Stream& s, const std::vector& scriptPubKey, const bitcoin_transaction& tx, unsigned int in_index, int hash_type ) +{ + pack( s, tx.nVersion ); + + pack_compact_size( s, tx.vin.size() ); + for ( size_t i = 0; i < tx.vin.size(); i++ ) { + const auto& in = tx.vin[i]; + pack( s, in.prevout ); + if ( i == in_index ) + pack( s, scriptPubKey ); + else + pack_compact_size( s, 0 ); // Blank signature + pack( s, in.nSequence ); + } + + pack_compact_size( s, tx.vout.size() ); + for ( const auto& out : tx.vout ) + pack( s, out ); + + pack( s, tx.nLockTime ); + pack( s, hash_type ); +} + +template +inline void pack_tx_witness_signature( Stream& s, const std::vector& scriptCode, const bitcoin_transaction& tx, unsigned int in_index, int64_t amount, int hash_type ) +{ + + fc::sha256 hash_prevouts; + fc::sha256 hash_sequence; + fc::sha256 hash_output; + + { + fc::datastream ps; + for ( const auto in : tx.vin ) + pack( ps, in.prevout ); + + std::vector vec( ps.tellp() ); + if ( vec.size() ) { + fc::datastream ds( vec.data(), size_t( vec.size() ) ); + for ( const auto in : tx.vin ) + pack( ds, in.prevout ); + } + + hash_prevouts = fc::sha256::hash( fc::sha256::hash( vec.data(), vec.size() ) ); + } + + { + fc::datastream ps; + for ( const auto in : tx.vin ) + pack( ps, in.nSequence ); + + std::vector vec( ps.tellp() ); + if ( vec.size() ) { + fc::datastream ds( vec.data(), size_t( vec.size() ) ); + for ( const auto in : tx.vin ) + pack( ds, in.nSequence ); + } + + hash_sequence = fc::sha256::hash( fc::sha256::hash( vec.data(), vec.size() ) ); + }; + + { + fc::datastream ps; + for ( const auto out : tx.vout ) + pack( ps, out ); + + std::vector vec( ps.tellp() ); + if ( vec.size() ) { + fc::datastream ds( vec.data(), size_t( vec.size() ) ); + for ( const auto out : tx.vout ) + pack( ds, out ); + } + + hash_output = fc::sha256::hash( fc::sha256::hash( vec.data(), vec.size() ) ); + } + + pack( s, tx.nVersion ); + pack( s, hash_prevouts ); + pack( s, hash_sequence ); + + pack( s, tx.vin[in_index].prevout ); + pack( s, scriptCode ); + pack( s, amount ); + pack( s, tx.vin[in_index].nSequence ); + + pack( s, hash_output ); + pack( s, tx.nLockTime ); + pack( s, hash_type ); } } diff --git a/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp b/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp new file mode 100644 index 00000000..fc045f7c --- /dev/null +++ b/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +namespace sidechain { + +class bitcoin_transaction; + +fc::sha256 get_signature_hash( const bitcoin_transaction& tx, const bytes& scriptPubKey, int64_t amount, + size_t in_index, int hash_type, bool is_witness ); + +std::vector privkey_sign( const bytes& privkey, const fc::sha256 &hash, const secp256k1_context_t* context_sign = nullptr ); + +std::vector< bytes > sign_witness_transaction_part( const bitcoin_transaction& tx, const std::vector& info_vins, + const bytes& privkey, const secp256k1_context_t* context_sign = nullptr, int hash_type = 1 ); + +void sign_witness_transaction_finalize( bitcoin_transaction& tx, const std::vector< bytes >& redeemScripts ); + +bool verify_sig( const bytes& sig, const bytes& pubkey, const bytes& msg, const secp256k1_context_t* context ); + +std::vector> sort_sigs( const bitcoin_transaction& tx, const std::vector& info_vins, + const secp256k1_context_t* context ); + +} diff --git a/libraries/sidechain/include/sidechain/utils.hpp b/libraries/sidechain/include/sidechain/utils.hpp index e9b624fd..21427a26 100644 --- a/libraries/sidechain/include/sidechain/utils.hpp +++ b/libraries/sidechain/include/sidechain/utils.hpp @@ -7,4 +7,6 @@ namespace sidechain { bytes parse_hex( const std::string& str ); +std::vector get_pubkey_from_redeemScript( bytes script ); + } diff --git a/libraries/sidechain/sign_bitcoin_transaction.cpp b/libraries/sidechain/sign_bitcoin_transaction.cpp new file mode 100644 index 00000000..75b8a13c --- /dev/null +++ b/libraries/sidechain/sign_bitcoin_transaction.cpp @@ -0,0 +1,121 @@ +#include +#include + +namespace sidechain { + +fc::sha256 get_signature_hash( const bitcoin_transaction& tx, const bytes& scriptCode, int64_t amount, + size_t in_index, int hash_type, bool is_witness ) +{ + fc::datastream ps; + if ( is_witness ) + pack_tx_witness_signature( ps, scriptCode, tx, in_index, amount, hash_type ); + else + pack_tx_signature( ps, scriptCode, tx, in_index, hash_type ); + + std::vector vec( ps.tellp() ); + if ( !vec.empty() ) { + fc::datastream ds( vec.data(), vec.size() ); + if ( is_witness ) + pack_tx_witness_signature( ds, scriptCode, tx, in_index, amount, hash_type ); + else + pack_tx_signature( ds, scriptCode, tx, in_index, hash_type ); + } + + return fc::sha256::hash( fc::sha256::hash( vec.data(), vec.size() ) ); +} + +std::vector privkey_sign( const bytes& privkey, const fc::sha256 &hash, const secp256k1_context_t* context_sign ) +{ + bytes sig; + sig.resize( 72 ); + int sig_len = sig.size(); + + FC_ASSERT( secp256k1_ecdsa_sign( + context_sign, + reinterpret_cast( hash.data() ), + reinterpret_cast( sig.data() ), + &sig_len, + reinterpret_cast( privkey.data() ), + secp256k1_nonce_function_rfc6979, + nullptr ) ); // TODO: replace assert with exception + + sig.resize( sig_len ); + + return sig; +} + +std::vector sign_witness_transaction_part( const bitcoin_transaction& tx, const std::vector& info_vins, + const bytes& privkey, const secp256k1_context_t* context_sign, int hash_type ) +{ + FC_ASSERT( tx.vin.size() == info_vins.size() ); + FC_ASSERT( !privkey.empty() ); + + std::vector< bytes > signatures; + for( size_t i = 0; i < tx.vin.size(); i++ ) { + const auto sighash = get_signature_hash( tx, info_vins[i].script, static_cast( info_vins[i].out.amount ), i, hash_type, true ); + auto sig = privkey_sign( privkey, sighash, context_sign ); + sig.push_back( static_cast( hash_type ) ); + + signatures.push_back( sig ); + } + return signatures; +} + +void sign_witness_transaction_finalize( bitcoin_transaction& tx, const std::vector& redeemScripts ) +{ + FC_ASSERT( tx.vin.size() == redeemScripts.size() ); + + for( size_t i = 0; i < tx.vin.size(); i++ ) { + tx.vin[i].scriptWitness.insert( tx.vin[i].scriptWitness.begin(), bytes() ); // Bitcoin workaround CHECKMULTISIG bug + tx.vin[i].scriptWitness.push_back( redeemScripts[i] ); + } +} + +bool verify_sig( const bytes& sig, const bytes& pubkey, const bytes& msg, const secp256k1_context_t* context ) +{ + std::vector sig_temp( sig.begin(), sig.end() ); + std::vector pubkey_temp( pubkey.begin(), pubkey.end() ); + std::vector msg_temp( msg.begin(), msg.end() ); + + int result = secp256k1_ecdsa_verify( context, msg_temp.data(), sig_temp.data(), sig_temp.size(), pubkey_temp.data(), pubkey_temp.size() ); + return result == 1; +} + +std::vector> sort_sigs( const bitcoin_transaction& tx, const std::vector& info_vins, const secp256k1_context_t* context ) +{ + using data = std::pair; + struct comp { + bool operator() (const data& lhs, const data& rhs) const { return lhs.first < rhs.first; } + }; + + std::vector> new_stacks; + + for( size_t i = 0; i < info_vins.size(); i++ ) { + const std::vector& keys = get_pubkey_from_redeemScript( info_vins[i].script ); + const auto& sighash = get_signature_hash( tx, info_vins[i].script, static_cast( info_vins[i].out.amount ), i, 1, true ).str(); + bytes sighash_temp( parse_hex( sighash ) ); + + std::vector stack( tx.vin[i].scriptWitness ); + std::vector marker( tx.vin[i].scriptWitness.size(), false ); + std::set sigs; + + for( size_t j = 0; j < keys.size(); j++ ) { + for( size_t l = 0; l < stack.size(); l++ ) { + if( !verify_sig( stack[l], keys[j], sighash_temp, context ) || marker[l] ) + continue; + sigs.insert(std::make_pair(j, stack[l])); + marker[l] = true; + break; + } + } + + std::vector temp_sig; + for( auto s : sigs ) { + temp_sig.push_back( s.second ); + } + new_stacks.push_back( temp_sig ); + } + return new_stacks; +} + +} diff --git a/libraries/sidechain/utils.cpp b/libraries/sidechain/utils.cpp index ce4c329a..fff59cbc 100644 --- a/libraries/sidechain/utils.cpp +++ b/libraries/sidechain/utils.cpp @@ -9,4 +9,19 @@ bytes parse_hex( const std::string& str ) return vec; } +std::vector get_pubkey_from_redeemScript( bytes script ) +{ + FC_ASSERT( script.size() >= 37 ); + + script.erase( script.begin() ); + script.erase( script.end() - 2, script.end() ); + + std::vector result; + uint64_t count = script.size() / 34; + for( size_t i = 0; i < count; i++ ) { + result.push_back( bytes( script.begin() + (34 * i) + 1, script.begin() + (34 * (i + 1)) ) ); + } + return result; +} + } diff --git a/tests/tests/bitcoin_sign_tests.cpp b/tests/tests/bitcoin_sign_tests.cpp new file mode 100644 index 00000000..f3094551 --- /dev/null +++ b/tests/tests/bitcoin_sign_tests.cpp @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include + +using namespace sidechain; + +BOOST_AUTO_TEST_SUITE( bitcoin_sign_tests ) + +inline bytes get_privkey_bytes( const std::string& privkey_base58 ) +{ + const auto privkey = fc::from_base58( privkey_base58 ); + // Remove version and hash + return bytes( privkey.cbegin() + 1, privkey.cbegin() + 1 + 32 ); +} + +BOOST_AUTO_TEST_CASE( btc_tx_witness_signature_test ) +{ + bitcoin_transaction tx; + tx.nVersion = 1; + tx.vin.resize( 1 ); + tx.vout.resize( 1 ); + tx.nLockTime = 0; + + tx.vin[0].prevout.hash = fc::sha256( "0a510f49749aaaa2638048132eafea959dd8e47e79332dbcb2a14189870e3145" ); + tx.vin[0].prevout.n = 1; + tx.vin[0].scriptSig = parse_hex( "220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1" ); + tx.vin[0].nSequence = 4294967295; + + tx.vout[0].value = 20000000; + tx.vout[0].scriptPubKey = parse_hex( "76a9143ebc40e411ed3c76f86711507ab952300890397288ac" ); + + const auto privkey_1 = get_privkey_bytes( "cQPUeypiYqp8J8Y8dGXUhvWGPHXTYYs3haryjdquwvMLAabXAnzF" ); + const auto privkey_2 = get_privkey_bytes( "cTG9AXoZjPbUmU2rx4ojeUBm3P88q3ZvRR6YWTUeVJHyke5KbVPM" ); + const auto redeemScript = parse_hex( "522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae"); + uint64_t amount = 20021300; + int32_t hash_type = 1; + + info_for_vin vin; + vin.out.amount = amount; + vin.script = redeemScript; + + secp256k1_context_t* context_sign = secp256k1_context_create( SECP256K1_CONTEXT_SIGN ); + tx.vin[0].scriptWitness.push_back( sign_witness_transaction_part( tx, { vin }, privkey_1, context_sign, hash_type)[0] ); + tx.vin[0].scriptWitness.push_back( sign_witness_transaction_part( tx, { vin }, privkey_2, context_sign, hash_type)[0] ); + sign_witness_transaction_finalize( tx, { redeemScript } ); + + BOOST_CHECK( fc::to_hex( pack( tx ) ) == "0100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000" ); + + secp256k1_context_destroy( context_sign ); +} + +BOOST_AUTO_TEST_CASE( verify_sig_test ) +{ + std::string hash( "df074d23cbedea48308aa2161c5b0da3893cc898e143c285ae4d5d787b366f10" ); + bytes vec_hash( parse_hex( hash ) ); + + std::string key1( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ); + bytes vec_key1( parse_hex( key1 ) ); + + std::string sig( "3044022051641c36fc6bc1e7ddd0022259c3f3a8dce0ac7fa4538c8b303c49e14b216b5302204e64c88a7f0279d902ccb338ffd42941ccdbbd7ddf8ba17d1ebf693f1f0b3ed901" ); + bytes vec_sig( parse_hex( sig ) ); + + secp256k1_context_t* context_verify = secp256k1_context_create( SECP256K1_CONTEXT_VERIFY ); + BOOST_CHECK( verify_sig( vec_sig, vec_key1, vec_hash, context_verify ) ); + + std::string key2( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435ca" ); + bytes vec_key2( parse_hex( key2 ) ); + + BOOST_CHECK( !verify_sig( vec_sig, vec_key2, vec_hash, context_verify ) ); + + secp256k1_context_destroy( context_verify ); +} + +BOOST_AUTO_TEST_CASE( get_pubkey_from_redeemScript_test ) +{ + std::string script( "5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf5bae"); + + std::vector keys = {parse_hex( "025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" ), + parse_hex( "02c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf" )}; + + std::vector keys_from_script = get_pubkey_from_redeemScript( parse_hex( script ) ); + + BOOST_CHECK( keys.size() == keys_from_script.size() ); + for( size_t i = 0; i < keys.size(); i++ ) { + BOOST_CHECK( keys[i] == keys_from_script[i] ); + } + + std::string script2( "5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e95bae" ); + + std::vector keys_from_script2 = get_pubkey_from_redeemScript( parse_hex( script2 ) ); + BOOST_CHECK( keys_from_script2.size() == 1 ); + BOOST_CHECK( keys_from_script2[0] == parse_hex( "025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9" ) ); +} + +std::vector create_info_vins( const std::vector& scripts, const std::vector& amounts ) +{ + std::vector info_vins; + for( size_t i = 0; i < scripts.size(); i++ ) { + info_for_vin vin; + vin.out.amount = amounts[i]; + vin.script = scripts[i]; + info_vins.push_back( vin ); + } + return info_vins; +} + +void test_sort_sigs( const bitcoin_transaction& trx, const std::vector& scripts, + const std::vector& amounts, const std::vector>& results ) +{ + std::vector info_vins( create_info_vins( scripts, amounts ) ); + + secp256k1_context_t* context_verify = secp256k1_context_create( SECP256K1_CONTEXT_VERIFY ); + auto new_stacks = sort_sigs( trx, info_vins, context_verify ); + secp256k1_context_destroy( context_verify ); + + for( size_t i = 0; i < trx.vin.size(); i++ ) { + BOOST_CHECK( new_stacks[i] == results[i] ); + } +} + +BOOST_AUTO_TEST_CASE( sort_sig_test ) +{ + bitcoin_transaction trx( fc::json::from_string( "{\"nVersion\":1,\"vin\":[{\"prevout\":{\"hash\":\"e937fd2942f0f14dd46a122e138d00cfabd93572b4876da77ab57c2a76ee73af\",\"n\":0},\"scriptSig\":\"\",\"nSequence\":4294967295,\"scriptWitness\":[\"30440220772bd2e8afe8c39d28e0c08ea81281d14239033cb93c92edf52250da542fa7c2022059ca93f98b194c9bcc8017ba3de19893fad06c8ea74430dc5fbe7eb81844598d01\",\"30440220098d274e3de29da36577f88ff851d030051b417a0309b61ba1c90d1750eee432022013946f9434893e4d9cbc23b68ec8243ed935823948d701f007edb6ccc46ac29801\",\"3045022100c2cb782558909109d5971ff29e23011b8eb4cd99e86030ac81a15b3312d897530220690080ce113caf84373ac04cc16e7f62ee5eeaf47b26d8017d2509c5d5510c0201\",\"3045022100888c5c9b5d2a4f3a17713cf665c2c65f3b9e954c2bcf3506deb9e410a33f6ca50220604f2a37e3650aded4c5811826098f8fa18af62fe07273c138440c16bdae074401\",\"3045022100cd4e8db4154b100077a30063654c4fc8473c3856064264293b931968fff9cee9022028ab2c8694218853756cca3e5ef5857694037e56e559a0004b292c7122ab355401\"]},{\"prevout\":{\"hash\":\"ae34ad50ab112e6cc51e6e3a87c48798b67255f8c8a8af9d427cbf55207ecfd1\",\"n\":0},\"scriptSig\":\"220020d85971e91d6e46473104e3f7e5eb67d885304a08dd17b3e1a0eeebe5a15f54a6\",\"nSequence\":4294967295,\"scriptWitness\":[\"3045022100b93623da6ed9a3f75082dbd77fab5492e64ae96ad4cdbb70f5a9ff1b2b30aa2602205df026319f3f21ba6f69f0be2469155c62dcf54ddfaf5f7d489d969b8364a3e401\",\"3044022010a60381cdb91d1f45579cc1d06df44b57c5af98b475089c8b349ad96a9d84fd02200840cff73d4053521dc4e7b210d20114ca82926ae96eb74633284f03f9d9861c01\",\"304402205639d8b13a6d912a3fd086abd34eb7455320aeb6b7ff148452a469f90fe636c80220035aad331677b67590845a5c6e9f8a6805d7add98cbab7047362a91717934e0001\",\"304402202945a632fe13b14099c80eb29fe6144597ca33b6fe10995a4b8756725149b5d902202b2e6a2b7bb39c7441877feaa1be68d144859ac755099704bd49eac41e12c92e01\",\"304402200e4fd2d3001736fbdabc65d50a3a04b6f99a80dc7a50b7257d65d7ced844c2320220613d8704833c50c445f56769b27067ca68299f8a462e2b62fb9e55d7c3e7046701\"]},{\"prevout\":{\"hash\":\"e04ee70b6aa2180caa32aaa4ff00c80b62e5572c369e05986d3a0e0b6d9d7455\",\"n\":0},\"scriptSig\":\"220020d85971e91d6e46473104e3f7e5eb67d885304a08dd17b3e1a0eeebe5a15f54a6\",\"nSequence\":4294967295,\"scriptWitness\":[\"30440220762212bfd15454036502ecd635314f7f81be982ea16dddf892693815745b32c7022069846f5b22b0246737396834123439556c9f8cd640006ad1ef8c70d86ca70a3e01\",\"30450221009f1c1053f45450a9e20c7735b645eb3825587ecd9dcb39a0d6de35926dbb252802204bad14928faacca9481d69960d5add5acbf7072e5230a146a7ecb6d9193b7d5001\",\"3045022100f32581419b4b46b3aa3bab0ad80202ba559fa1b086b6b02d003a2aac19782d6b02204e3132c43a12411e52f0d8b3714cb77d82136752a1e939af87d865ccda75b0ec01\",\"3045022100e145ab07653d0b2d472ebc393b5e82eee725c65573dfb458c36c7717aba5994002201cd00d40dca3120db7b38239da801765f042e248785c8d44ce4a0b8b1d57b36901\",\"3045022100f7f48205bdbb5e1690e635bf02205e4790c57aadb3f65adabd4890eb4285cfd5022056a0013f35f59c73dc2048697e0330a439e7b35804b655dbda938bdfc77ced9301\"]},{\"prevout\":{\"hash\":\"6bc22ed725ba7c164df3a878113a11e4fbc3d1bbffee0083e75cb14e7bb5bd38\",\"n\":1},\"scriptSig\":\"220020d85971e91d6e46473104e3f7e5eb67d885304a08dd17b3e1a0eeebe5a15f54a6\",\"nSequence\":4294967295,\"scriptWitness\":[\"3045022100c8a830255c4ea9ca205126701fc435d39993eca2d7024817958beea76ad3785102201cb27c7613031a4f55bc3c43683aa57f04a4f73291ad9c1076c5281bc49dc4d101\",\"304402202c1bcbd436f95e42364122f9f552466122597050962524850434bfeb0b1a721e02200f5f7cfc4d7c43c550a59918d43ee52e76e04c8da381303558f4fc83cc64e19201\",\"304402201669a5580624132b2f1e8d2a51831816846c5f93505623dc03ea6a9f01f023ed022054c69ae28483cd40ac144b7d4af4ff29292813cda425373eabd8d14624c61aae01\",\"3045022100f1b787c0466e88bbc663df7f5584dfa68416c106ab806e0b9f959c6f51b7221b022042633dfc95cde470690a52d5cc468e2f9a745fc1db2fee692b8f31cfce28c0cb01\",\"304402206468ea767ad5aa2fbe837c29ae2fee4f87063d25b9e97fc6f7f679a036a892bf022055e78030476a78d8fc9177bf2e64ccece65005493a8fc6bd1352741153e7eea601\"]}],\"vout\":[{\"value\":\"9590365272\",\"scriptPubKey\":\"00206a19177b8e4d76408c574118681f204c1a7065040636d5288af41f67c25a85f0\"},{\"value\":240000,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":240000,\"scriptPubKey\":\"2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471bac\"},{\"value\":240000,\"scriptPubKey\":\"2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c80ac\"},{\"value\":240000,\"scriptPubKey\":\"21021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d99390091ac\"},{\"value\":240000,\"scriptPubKey\":\"2103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b0ac\"},{\"value\":240000,\"scriptPubKey\":\"21028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfaac\"},{\"value\":240000,\"scriptPubKey\":\"21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcdeac\"},{\"value\":240000,\"scriptPubKey\":\"2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de51ac\"},{\"value\":240000,\"scriptPubKey\":\"2103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6ac\"},{\"value\":240000,\"scriptPubKey\":\"210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d29ac\"},{\"value\":240000,\"scriptPubKey\":\"2103c6206bca3492f93b27a877362ffc25a57177fe0be4a7aaad661daead7703232fac\"}],\"nLockTime\":0}" ).as< bitcoin_transaction >() ); + std::vector scripts( fc::json::from_string( "[\"552102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d292103c6206bca3492f93b27a877362ffc25a57177fe0be4a7aaad661daead7703232f5bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\"]" ).as< std::vector >() ); + std::vector amounts( fc::json::from_string( "[5993981520,1200000000,1200000000,1200000000]" ).as< std::vector >() ); + std::vector> results( fc::json::from_string( "[[\"30440220098d274e3de29da36577f88ff851d030051b417a0309b61ba1c90d1750eee432022013946f9434893e4d9cbc23b68ec8243ed935823948d701f007edb6ccc46ac29801\",\"3045022100c2cb782558909109d5971ff29e23011b8eb4cd99e86030ac81a15b3312d897530220690080ce113caf84373ac04cc16e7f62ee5eeaf47b26d8017d2509c5d5510c0201\",\"3045022100888c5c9b5d2a4f3a17713cf665c2c65f3b9e954c2bcf3506deb9e410a33f6ca50220604f2a37e3650aded4c5811826098f8fa18af62fe07273c138440c16bdae074401\",\"3045022100cd4e8db4154b100077a30063654c4fc8473c3856064264293b931968fff9cee9022028ab2c8694218853756cca3e5ef5857694037e56e559a0004b292c7122ab355401\",\"30440220772bd2e8afe8c39d28e0c08ea81281d14239033cb93c92edf52250da542fa7c2022059ca93f98b194c9bcc8017ba3de19893fad06c8ea74430dc5fbe7eb81844598d01\"],[\"3044022010a60381cdb91d1f45579cc1d06df44b57c5af98b475089c8b349ad96a9d84fd02200840cff73d4053521dc4e7b210d20114ca82926ae96eb74633284f03f9d9861c01\",\"304402205639d8b13a6d912a3fd086abd34eb7455320aeb6b7ff148452a469f90fe636c80220035aad331677b67590845a5c6e9f8a6805d7add98cbab7047362a91717934e0001\",\"304402202945a632fe13b14099c80eb29fe6144597ca33b6fe10995a4b8756725149b5d902202b2e6a2b7bb39c7441877feaa1be68d144859ac755099704bd49eac41e12c92e01\",\"304402200e4fd2d3001736fbdabc65d50a3a04b6f99a80dc7a50b7257d65d7ced844c2320220613d8704833c50c445f56769b27067ca68299f8a462e2b62fb9e55d7c3e7046701\",\"3045022100b93623da6ed9a3f75082dbd77fab5492e64ae96ad4cdbb70f5a9ff1b2b30aa2602205df026319f3f21ba6f69f0be2469155c62dcf54ddfaf5f7d489d969b8364a3e401\"],[\"30450221009f1c1053f45450a9e20c7735b645eb3825587ecd9dcb39a0d6de35926dbb252802204bad14928faacca9481d69960d5add5acbf7072e5230a146a7ecb6d9193b7d5001\",\"3045022100f32581419b4b46b3aa3bab0ad80202ba559fa1b086b6b02d003a2aac19782d6b02204e3132c43a12411e52f0d8b3714cb77d82136752a1e939af87d865ccda75b0ec01\",\"3045022100e145ab07653d0b2d472ebc393b5e82eee725c65573dfb458c36c7717aba5994002201cd00d40dca3120db7b38239da801765f042e248785c8d44ce4a0b8b1d57b36901\",\"3045022100f7f48205bdbb5e1690e635bf02205e4790c57aadb3f65adabd4890eb4285cfd5022056a0013f35f59c73dc2048697e0330a439e7b35804b655dbda938bdfc77ced9301\",\"30440220762212bfd15454036502ecd635314f7f81be982ea16dddf892693815745b32c7022069846f5b22b0246737396834123439556c9f8cd640006ad1ef8c70d86ca70a3e01\"],[\"304402202c1bcbd436f95e42364122f9f552466122597050962524850434bfeb0b1a721e02200f5f7cfc4d7c43c550a59918d43ee52e76e04c8da381303558f4fc83cc64e19201\",\"304402201669a5580624132b2f1e8d2a51831816846c5f93505623dc03ea6a9f01f023ed022054c69ae28483cd40ac144b7d4af4ff29292813cda425373eabd8d14624c61aae01\",\"3045022100f1b787c0466e88bbc663df7f5584dfa68416c106ab806e0b9f959c6f51b7221b022042633dfc95cde470690a52d5cc468e2f9a745fc1db2fee692b8f31cfce28c0cb01\",\"304402206468ea767ad5aa2fbe837c29ae2fee4f87063d25b9e97fc6f7f679a036a892bf022055e78030476a78d8fc9177bf2e64ccece65005493a8fc6bd1352741153e7eea601\",\"3045022100c8a830255c4ea9ca205126701fc435d39993eca2d7024817958beea76ad3785102201cb27c7613031a4f55bc3c43683aa57f04a4f73291ad9c1076c5281bc49dc4d101\"]]" ).as< std::vector> >() ); + + test_sort_sigs( trx, scripts, amounts, results ); +} + +BOOST_AUTO_TEST_CASE( already_sorted_sigs ) +{ + bitcoin_transaction trx( fc::json::from_string( "{\"nVersion\":1,\"vin\":[{\"prevout\":{\"hash\":\"e937fd2942f0f14dd46a122e138d00cfabd93572b4876da77ab57c2a76ee73af\",\"n\":0},\"scriptSig\":\"\",\"nSequence\":4294967295,\"scriptWitness\":[\"30440220098d274e3de29da36577f88ff851d030051b417a0309b61ba1c90d1750eee432022013946f9434893e4d9cbc23b68ec8243ed935823948d701f007edb6ccc46ac29801\",\"3045022100c2cb782558909109d5971ff29e23011b8eb4cd99e86030ac81a15b3312d897530220690080ce113caf84373ac04cc16e7f62ee5eeaf47b26d8017d2509c5d5510c0201\",\"3045022100888c5c9b5d2a4f3a17713cf665c2c65f3b9e954c2bcf3506deb9e410a33f6ca50220604f2a37e3650aded4c5811826098f8fa18af62fe07273c138440c16bdae074401\",\"3045022100cd4e8db4154b100077a30063654c4fc8473c3856064264293b931968fff9cee9022028ab2c8694218853756cca3e5ef5857694037e56e559a0004b292c7122ab355401\",\"30440220772bd2e8afe8c39d28e0c08ea81281d14239033cb93c92edf52250da542fa7c2022059ca93f98b194c9bcc8017ba3de19893fad06c8ea74430dc5fbe7eb81844598d01\"]},{\"prevout\":{\"hash\":\"ae34ad50ab112e6cc51e6e3a87c48798b67255f8c8a8af9d427cbf55207ecfd1\",\"n\":0},\"scriptSig\":\"220020d85971e91d6e46473104e3f7e5eb67d885304a08dd17b3e1a0eeebe5a15f54a6\",\"nSequence\":4294967295,\"scriptWitness\":[\"3044022010a60381cdb91d1f45579cc1d06df44b57c5af98b475089c8b349ad96a9d84fd02200840cff73d4053521dc4e7b210d20114ca82926ae96eb74633284f03f9d9861c01\",\"304402205639d8b13a6d912a3fd086abd34eb7455320aeb6b7ff148452a469f90fe636c80220035aad331677b67590845a5c6e9f8a6805d7add98cbab7047362a91717934e0001\",\"304402202945a632fe13b14099c80eb29fe6144597ca33b6fe10995a4b8756725149b5d902202b2e6a2b7bb39c7441877feaa1be68d144859ac755099704bd49eac41e12c92e01\",\"304402200e4fd2d3001736fbdabc65d50a3a04b6f99a80dc7a50b7257d65d7ced844c2320220613d8704833c50c445f56769b27067ca68299f8a462e2b62fb9e55d7c3e7046701\",\"3045022100b93623da6ed9a3f75082dbd77fab5492e64ae96ad4cdbb70f5a9ff1b2b30aa2602205df026319f3f21ba6f69f0be2469155c62dcf54ddfaf5f7d489d969b8364a3e401\"]},{\"prevout\":{\"hash\":\"e04ee70b6aa2180caa32aaa4ff00c80b62e5572c369e05986d3a0e0b6d9d7455\",\"n\":0},\"scriptSig\":\"220020d85971e91d6e46473104e3f7e5eb67d885304a08dd17b3e1a0eeebe5a15f54a6\",\"nSequence\":4294967295,\"scriptWitness\":[\"30450221009f1c1053f45450a9e20c7735b645eb3825587ecd9dcb39a0d6de35926dbb252802204bad14928faacca9481d69960d5add5acbf7072e5230a146a7ecb6d9193b7d5001\",\"3045022100f32581419b4b46b3aa3bab0ad80202ba559fa1b086b6b02d003a2aac19782d6b02204e3132c43a12411e52f0d8b3714cb77d82136752a1e939af87d865ccda75b0ec01\",\"3045022100e145ab07653d0b2d472ebc393b5e82eee725c65573dfb458c36c7717aba5994002201cd00d40dca3120db7b38239da801765f042e248785c8d44ce4a0b8b1d57b36901\",\"3045022100f7f48205bdbb5e1690e635bf02205e4790c57aadb3f65adabd4890eb4285cfd5022056a0013f35f59c73dc2048697e0330a439e7b35804b655dbda938bdfc77ced9301\",\"30440220762212bfd15454036502ecd635314f7f81be982ea16dddf892693815745b32c7022069846f5b22b0246737396834123439556c9f8cd640006ad1ef8c70d86ca70a3e01\"]},{\"prevout\":{\"hash\":\"6bc22ed725ba7c164df3a878113a11e4fbc3d1bbffee0083e75cb14e7bb5bd38\",\"n\":1},\"scriptSig\":\"220020d85971e91d6e46473104e3f7e5eb67d885304a08dd17b3e1a0eeebe5a15f54a6\",\"nSequence\":4294967295,\"scriptWitness\":[\"304402202c1bcbd436f95e42364122f9f552466122597050962524850434bfeb0b1a721e02200f5f7cfc4d7c43c550a59918d43ee52e76e04c8da381303558f4fc83cc64e19201\",\"304402201669a5580624132b2f1e8d2a51831816846c5f93505623dc03ea6a9f01f023ed022054c69ae28483cd40ac144b7d4af4ff29292813cda425373eabd8d14624c61aae01\",\"3045022100f1b787c0466e88bbc663df7f5584dfa68416c106ab806e0b9f959c6f51b7221b022042633dfc95cde470690a52d5cc468e2f9a745fc1db2fee692b8f31cfce28c0cb01\",\"304402206468ea767ad5aa2fbe837c29ae2fee4f87063d25b9e97fc6f7f679a036a892bf022055e78030476a78d8fc9177bf2e64ccece65005493a8fc6bd1352741153e7eea601\",\"3045022100c8a830255c4ea9ca205126701fc435d39993eca2d7024817958beea76ad3785102201cb27c7613031a4f55bc3c43683aa57f04a4f73291ad9c1076c5281bc49dc4d101\"]}],\"vout\":[{\"value\":\"9590365272\",\"scriptPubKey\":\"00206a19177b8e4d76408c574118681f204c1a7065040636d5288af41f67c25a85f0\"},{\"value\":240000,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":240000,\"scriptPubKey\":\"2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471bac\"},{\"value\":240000,\"scriptPubKey\":\"2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c80ac\"},{\"value\":240000,\"scriptPubKey\":\"21021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d99390091ac\"},{\"value\":240000,\"scriptPubKey\":\"2103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b0ac\"},{\"value\":240000,\"scriptPubKey\":\"21028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfaac\"},{\"value\":240000,\"scriptPubKey\":\"21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcdeac\"},{\"value\":240000,\"scriptPubKey\":\"2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de51ac\"},{\"value\":240000,\"scriptPubKey\":\"2103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6ac\"},{\"value\":240000,\"scriptPubKey\":\"210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d29ac\"},{\"value\":240000,\"scriptPubKey\":\"2103c6206bca3492f93b27a877362ffc25a57177fe0be4a7aaad661daead7703232fac\"}],\"nLockTime\":0}" ).as< bitcoin_transaction >() ); + std::vector scripts( fc::json::from_string( "[\"552102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d292103c6206bca3492f93b27a877362ffc25a57177fe0be4a7aaad661daead7703232f5bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102ec74848d166af51b430f6d130606896e1436688e935dd8407c3aa15c38d4471b2102cd19bf004e5d533de24bcc55d8573fe5fada438860512a9bbe37118733b34c8021021d2559f259df45f16287d8f55ab41c1c2fb7099a75cc99a3f250611d993900912103e4857a5da1e9483ba14644421489790120555baccb9cf130848e0261464bb7b021028ba26c831fb21084c9bbb7059f76debbf442822adc286ee43ea3092fd666bcfa21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\"]" ).as< std::vector >() ); + std::vector amounts( fc::json::from_string( "[5993981520,1200000000,1200000000,1200000000]" ).as< std::vector >() ); + std::vector> results( fc::json::from_string( "[[\"30440220098d274e3de29da36577f88ff851d030051b417a0309b61ba1c90d1750eee432022013946f9434893e4d9cbc23b68ec8243ed935823948d701f007edb6ccc46ac29801\",\"3045022100c2cb782558909109d5971ff29e23011b8eb4cd99e86030ac81a15b3312d897530220690080ce113caf84373ac04cc16e7f62ee5eeaf47b26d8017d2509c5d5510c0201\",\"3045022100888c5c9b5d2a4f3a17713cf665c2c65f3b9e954c2bcf3506deb9e410a33f6ca50220604f2a37e3650aded4c5811826098f8fa18af62fe07273c138440c16bdae074401\",\"3045022100cd4e8db4154b100077a30063654c4fc8473c3856064264293b931968fff9cee9022028ab2c8694218853756cca3e5ef5857694037e56e559a0004b292c7122ab355401\",\"30440220772bd2e8afe8c39d28e0c08ea81281d14239033cb93c92edf52250da542fa7c2022059ca93f98b194c9bcc8017ba3de19893fad06c8ea74430dc5fbe7eb81844598d01\"],[\"3044022010a60381cdb91d1f45579cc1d06df44b57c5af98b475089c8b349ad96a9d84fd02200840cff73d4053521dc4e7b210d20114ca82926ae96eb74633284f03f9d9861c01\",\"304402205639d8b13a6d912a3fd086abd34eb7455320aeb6b7ff148452a469f90fe636c80220035aad331677b67590845a5c6e9f8a6805d7add98cbab7047362a91717934e0001\",\"304402202945a632fe13b14099c80eb29fe6144597ca33b6fe10995a4b8756725149b5d902202b2e6a2b7bb39c7441877feaa1be68d144859ac755099704bd49eac41e12c92e01\",\"304402200e4fd2d3001736fbdabc65d50a3a04b6f99a80dc7a50b7257d65d7ced844c2320220613d8704833c50c445f56769b27067ca68299f8a462e2b62fb9e55d7c3e7046701\",\"3045022100b93623da6ed9a3f75082dbd77fab5492e64ae96ad4cdbb70f5a9ff1b2b30aa2602205df026319f3f21ba6f69f0be2469155c62dcf54ddfaf5f7d489d969b8364a3e401\"],[\"30450221009f1c1053f45450a9e20c7735b645eb3825587ecd9dcb39a0d6de35926dbb252802204bad14928faacca9481d69960d5add5acbf7072e5230a146a7ecb6d9193b7d5001\",\"3045022100f32581419b4b46b3aa3bab0ad80202ba559fa1b086b6b02d003a2aac19782d6b02204e3132c43a12411e52f0d8b3714cb77d82136752a1e939af87d865ccda75b0ec01\",\"3045022100e145ab07653d0b2d472ebc393b5e82eee725c65573dfb458c36c7717aba5994002201cd00d40dca3120db7b38239da801765f042e248785c8d44ce4a0b8b1d57b36901\",\"3045022100f7f48205bdbb5e1690e635bf02205e4790c57aadb3f65adabd4890eb4285cfd5022056a0013f35f59c73dc2048697e0330a439e7b35804b655dbda938bdfc77ced9301\",\"30440220762212bfd15454036502ecd635314f7f81be982ea16dddf892693815745b32c7022069846f5b22b0246737396834123439556c9f8cd640006ad1ef8c70d86ca70a3e01\"],[\"304402202c1bcbd436f95e42364122f9f552466122597050962524850434bfeb0b1a721e02200f5f7cfc4d7c43c550a59918d43ee52e76e04c8da381303558f4fc83cc64e19201\",\"304402201669a5580624132b2f1e8d2a51831816846c5f93505623dc03ea6a9f01f023ed022054c69ae28483cd40ac144b7d4af4ff29292813cda425373eabd8d14624c61aae01\",\"3045022100f1b787c0466e88bbc663df7f5584dfa68416c106ab806e0b9f959c6f51b7221b022042633dfc95cde470690a52d5cc468e2f9a745fc1db2fee692b8f31cfce28c0cb01\",\"304402206468ea767ad5aa2fbe837c29ae2fee4f87063d25b9e97fc6f7f679a036a892bf022055e78030476a78d8fc9177bf2e64ccece65005493a8fc6bd1352741153e7eea601\",\"3045022100c8a830255c4ea9ca205126701fc435d39993eca2d7024817958beea76ad3785102201cb27c7613031a4f55bc3c43683aa57f04a4f73291ad9c1076c5281bc49dc4d101\"]]" ).as< std::vector> >() ); + + test_sort_sigs( trx, scripts, amounts, results ); +} + +BOOST_AUTO_TEST_CASE( all_signatures_are_same ) +{ + bitcoin_transaction trx( fc::json::from_string( "{\"nVersion\":1,\"vin\":[{\"prevout\":{\"hash\":\"e35635fce1cbe1e347a5f8a3c5dccd79db9d43a6fb4b27991894a8bce1a70e03\",\"n\":0},\"scriptSig\":\"\",\"nSequence\":4294967295,\"scriptWitness\":[\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\"]},{\"prevout\":{\"hash\":\"1826f1ba0ed5034806cf1cb3eaa5dc9abf04a319048ae1e73e3df75dcc9f0bca\",\"n\":1},\"scriptSig\":\"2200203b9e077c0043e8f394a273baffc0aed01d10d8c894ad39810257d63be9a315e0\",\"nSequence\":4294967295,\"scriptWitness\":[\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\"]}],\"vout\":[{\"value\":1997997990,\"scriptPubKey\":\"0020a40e801531fdca0fb550013a9140aaaf8d9eb106c427258fbc86d0e0c52c432d\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"}],\"nLockTime\":0}" ).as< bitcoin_transaction >() ); + std::vector scripts( fc::json::from_string( "[\"552102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf5bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf5bae\"]" ).as< std::vector >() ); + std::vector amounts( fc::json::from_string( "[998998995,1000000000]" ).as< std::vector >() ); + std::vector> results( fc::json::from_string( "[[\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\",\"304402205370c8999e097e4018b04fa3be9c27e2ff16f0c21ef363c35dfd45b4290bf0740220775506660ece404703801a3f5a13fe24c96821c7d7eb42448abe35a1035cd8c801\"],[\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\",\"3045022100ced739a6c04cf3c5e5bc760272bb6f41ecb3fa3671aa78ac1bc47629e39bb7ba02207a8693778d3b5a0c045fddc1ab23fcd971640460f150252b39993587151ff27d01\"]]" ).as< std::vector> >() ); + + test_sort_sigs( trx, scripts, amounts, results ); +} + +BOOST_AUTO_TEST_CASE( same_signatures ) +{ + bitcoin_transaction trx( fc::json::from_string( "{\"nVersion\":1,\"vin\":[{\"prevout\":{\"hash\":\"f8d70d29817a78e160c53dcffcf6a783008f1cc43c64f7efb49e4de3a23ef016\",\"n\":0},\"scriptSig\":\"\",\"nSequence\":4294967295,\"scriptWitness\":[\"30440220228c930388a0420aa9a17acdf414763bec0f57f92ecf8db51f02e3f8d82428aa0220417f2d0fbc5fd00d5d158a2e7fe7188857119b8d16d11f82f513594a28dbcbfa01\",\"304402204cc6d437f1f46263c36bc0605686b6072f0fb7c5991690e8ea06e8126f06a77f02205cfaa0f2e05ab9187fde9b10fbfee3ad06ae8b7120d455277186d1f8fd31b16c01\",\"3045022100d95008906e848a8165fbc0d3ed6d11643bc4814d4f8ae84c8c84a97c8c14885002206a2d703ffcca22309b843b55b746994fb08c15fbbf0aadbf900398e8768c62dc01\",\"304402204cc6d437f1f46263c36bc0605686b6072f0fb7c5991690e8ea06e8126f06a77f02205cfaa0f2e05ab9187fde9b10fbfee3ad06ae8b7120d455277186d1f8fd31b16c01\",\"304402204cc6d437f1f46263c36bc0605686b6072f0fb7c5991690e8ea06e8126f06a77f02205cfaa0f2e05ab9187fde9b10fbfee3ad06ae8b7120d455277186d1f8fd31b16c01\"]},{\"prevout\":{\"hash\":\"dd54a8c470be54b02cd937a1758761863c2faf920b2645d2dd35bd0308ef0dfb\",\"n\":1},\"scriptSig\":\"220020f38dc1aecea9e28bea4410e6aa807be49cf6472b9a718750080b9703e80d9fe9\",\"nSequence\":4294967295,\"scriptWitness\":[\"3045022100bdc4d1151d0567bb4e377b473100eaf41544bb547bc6d82b0a0dae8e8e833a6d022013caa911c553558abe6fdf1a6853ca6bab6912d90676595cfd4d11afd4f7966301\",\"3045022100c4d233c9183d91fd9f1821fb68e1180bbd6493eb66caf36438bccd8cb46a247302200d3a16ff3180fb9ffe8dd16c8ea71f461e7b940baea4c302c8d8e2ba9bf74b9201\",\"3045022100e1262b0e14df0f6f99d850651caa6b8881f7cbf811ad549cb0d6a1b1369beec902204232af72b6bfcb21a83d555374dc622275b7c2cac31b4f56d76b87d88fdc586e01\",\"3045022100c4d233c9183d91fd9f1821fb68e1180bbd6493eb66caf36438bccd8cb46a247302200d3a16ff3180fb9ffe8dd16c8ea71f461e7b940baea4c302c8d8e2ba9bf74b9201\",\"3045022100c4d233c9183d91fd9f1821fb68e1180bbd6493eb66caf36438bccd8cb46a247302200d3a16ff3180fb9ffe8dd16c8ea71f461e7b940baea4c302c8d8e2ba9bf74b9201\"]}],\"vout\":[{\"value\":2996996985,\"scriptPubKey\":\"0020a4d938999fff18a140d830009f8c9a2c5ab00d61cc3ffea10ee703b7d9b24b9a\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cfac\"},{\"value\":66667,\"scriptPubKey\":\"21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcdeac\"},{\"value\":66667,\"scriptPubKey\":\"2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de51ac\"},{\"value\":66667,\"scriptPubKey\":\"2103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6ac\"},{\"value\":66667,\"scriptPubKey\":\"210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d29ac\"},{\"value\":66667,\"scriptPubKey\":\"2103c6206bca3492f93b27a877362ffc25a57177fe0be4a7aaad661daead7703232fac\"}],\"nLockTime\":0}" ).as< bitcoin_transaction >() ); + std::vector scripts( fc::json::from_string( "[\"552102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d292103c6206bca3492f93b27a877362ffc25a57177fe0be4a7aaad661daead7703232f5bae\",\"5521025feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e92102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf2102c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf21030d9f1f4be73391d5814bb00cdb6ae10b4a1182a32a77672b5b744efa2e88dcde2102096d78d32f51a1051c8e4f58ea99427ce335e76f6ea00c915cf6d7ac1270de512103b0184a0323802226dfaa767d0bc93e261762d3ae4457c04ca2613215365d2dc6210226d279da5bfd81f7ab9ab804a3d0b44a06dd883a1f29d4671d4da4793b9d0d295bae\"]" ).as< std::vector >() ); + std::vector amounts( fc::json::from_string( "[1997997990,1000000000]" ).as< std::vector >() ); + std::vector> results( fc::json::from_string( "[[\"304402204cc6d437f1f46263c36bc0605686b6072f0fb7c5991690e8ea06e8126f06a77f02205cfaa0f2e05ab9187fde9b10fbfee3ad06ae8b7120d455277186d1f8fd31b16c01\",\"304402204cc6d437f1f46263c36bc0605686b6072f0fb7c5991690e8ea06e8126f06a77f02205cfaa0f2e05ab9187fde9b10fbfee3ad06ae8b7120d455277186d1f8fd31b16c01\",\"304402204cc6d437f1f46263c36bc0605686b6072f0fb7c5991690e8ea06e8126f06a77f02205cfaa0f2e05ab9187fde9b10fbfee3ad06ae8b7120d455277186d1f8fd31b16c01\"\"30440220228c930388a0420aa9a17acdf414763bec0f57f92ecf8db51f02e3f8d82428aa0220417f2d0fbc5fd00d5d158a2e7fe7188857119b8d16d11f82f513594a28dbcbfa01\",\"3045022100d95008906e848a8165fbc0d3ed6d11643bc4814d4f8ae84c8c84a97c8c14885002206a2d703ffcca22309b843b55b746994fb08c15fbbf0aadbf900398e8768c62dc01\"],[\"3045022100c4d233c9183d91fd9f1821fb68e1180bbd6493eb66caf36438bccd8cb46a247302200d3a16ff3180fb9ffe8dd16c8ea71f461e7b940baea4c302c8d8e2ba9bf74b9201\",\"3045022100c4d233c9183d91fd9f1821fb68e1180bbd6493eb66caf36438bccd8cb46a247302200d3a16ff3180fb9ffe8dd16c8ea71f461e7b940baea4c302c8d8e2ba9bf74b9201\",\"3045022100c4d233c9183d91fd9f1821fb68e1180bbd6493eb66caf36438bccd8cb46a247302200d3a16ff3180fb9ffe8dd16c8ea71f461e7b940baea4c302c8d8e2ba9bf74b9201\",\"3045022100bdc4d1151d0567bb4e377b473100eaf41544bb547bc6d82b0a0dae8e8e833a6d022013caa911c553558abe6fdf1a6853ca6bab6912d90676595cfd4d11afd4f7966301\",\"3045022100e1262b0e14df0f6f99d850651caa6b8881f7cbf811ad549cb0d6a1b1369beec902204232af72b6bfcb21a83d555374dc622275b7c2cac31b4f56d76b87d88fdc586e01\"]]" ).as< std::vector> >() ); + + test_sort_sigs( trx, scripts, amounts, results ); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/tests/bitcoin_transaction_tests.cpp b/tests/tests/bitcoin_transaction_tests.cpp index 89bc331e..d96e1847 100644 --- a/tests/tests/bitcoin_transaction_tests.cpp +++ b/tests/tests/bitcoin_transaction_tests.cpp @@ -1,6 +1,7 @@ #include #include #include +#include using namespace sidechain;