From bfa6babfd2c01295621ed4de589745c739515302 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 17 Sep 2019 21:43:44 +0200 Subject: [PATCH] WIP, Moving Bitcoin listener to plugin - Add missing files - Remove few parts --- .../peerplays_sidechain/bitcoin_address.cpp | 258 +++++++ .../bitcoin_transaction.cpp | 558 +++++++------- .../peerplays_sidechain/serialize.hpp | 720 +++++++++--------- 3 files changed, 897 insertions(+), 639 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/bitcoin_address.cpp diff --git a/libraries/plugins/peerplays_sidechain/bitcoin_address.cpp b/libraries/plugins/peerplays_sidechain/bitcoin_address.cpp new file mode 100644 index 00000000..f4a234c4 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/bitcoin_address.cpp @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include + +namespace sidechain { + +bool bitcoin_address::operator==( const bitcoin_address& btc_addr ) const { + return ( this->address == btc_addr.address ) && + ( this->type == btc_addr.type ) && + ( this->raw_address == btc_addr.raw_address ); +} + +bytes bitcoin_address::get_script() const +{ + switch ( type ) { + case payment_type::NULLDATA: + return script_builder() << op::RETURN << raw_address; + case payment_type::P2PK: + return script_builder() << raw_address << op::CHECKSIG; + case payment_type::P2PKH: + return script_builder() << op::DUP << op::HASH160 << raw_address << op::EQUALVERIFY << op::CHECKSIG; + case payment_type::P2SH: + case payment_type::P2SH_WPKH: + case payment_type::P2SH_WSH: + return script_builder() << op::HASH160 << raw_address << op::EQUAL; + case payment_type::P2WPKH: + case payment_type::P2WSH: + return script_builder() << op::_0 << raw_address; + default: + return raw_address; + } +} + +payment_type bitcoin_address::determine_type() +{ + if( is_p2pk() ) { + return payment_type::P2PK; + } else if( is_p2wpkh() ) { + return payment_type::P2WPKH; + } else if( is_p2wsh() ) { + return payment_type::P2WSH; + } else if( is_p2pkh() ) { + return payment_type::P2PKH; + } else if( is_p2sh() ) { + return payment_type::P2SH; + } else { + return payment_type::NULLDATA; + } +} + +bytes bitcoin_address::determine_raw_address() +{ + bytes result; + switch( type ) { + case payment_type::P2PK : { + result = parse_hex( address ); + break; + } + case payment_type::P2WPKH : + case payment_type::P2WSH : { + std::string prefix( address.compare(0,4,"bcrt") == 0 ? std::string( address.begin(), address.begin() + 4 ) : + std::string( address.begin(), address.begin() + 2 ) ); + const auto& decode_bech32 = segwit_addr::decode( prefix, address ); + result = bytes( decode_bech32.second.begin(), decode_bech32.second.end() ); + break; + } + case payment_type::P2SH_WPKH : + case payment_type::P2SH_WSH : + case payment_type::P2PKH : + case payment_type::P2SH : { + bytes hex_addr = fc::from_base58( address ); + result = bytes( hex_addr.begin() + 1, hex_addr.begin() + 21 ); + break; + } + case payment_type::NULLDATA : return result; + } + return result; +} + +bool bitcoin_address::check_segwit_address( const size_segwit_address& size ) const { + if( !address.compare(0,4,"bcrt") || !address.compare(0,2,"bc") || !address.compare(0,2,"tb") ) { + std::string prefix( !address.compare(0,4,"bcrt") ? std::string(address.begin(), address.begin() + 4) : + std::string(address.begin(), address.begin() + 2) ); + + const auto& decode_bech32 = segwit_addr::decode( prefix, address ); + + if( decode_bech32.first == -1 || decode_bech32.second.size() != size ) { + return false; + } + + return true; + } + return false; +} + +bool bitcoin_address::is_p2pk() const +{ + try { + bool prefix = !address.compare(0,2,"02") || !address.compare(0,2,"03"); + if( address.size() == 66 && prefix ) { + parse_hex( address ); + return true; + } + } catch( fc::exception e ) { + return false; + } + return false; +} + +bool bitcoin_address::is_p2wpkh() const +{ + return check_segwit_address( size_segwit_address::P2WPKH ); +} + +bool bitcoin_address::is_p2wsh() const +{ + return check_segwit_address( size_segwit_address::P2WSH ); +} + +bool bitcoin_address::is_p2pkh() const +{ + try { + bytes hex_addr = fc::from_base58( address ); + if( hex_addr.size() == 25 && ( static_cast( hex_addr[0] ) == 0x00 || + static_cast( hex_addr[0] ) == 0x6f ) ) { + return true; + } + return false; + } catch( fc::exception e ) { + return false; + } +} + +bool bitcoin_address::is_p2sh() const +{ + try { + bytes hex_addr = fc::from_base58( address ); + if( hex_addr.size() == 25 && ( static_cast( hex_addr[0] ) == 0x05 || + static_cast( hex_addr[0] ) == 0xc4 ) ) { + return true; + } + return false; + } catch( fc::exception e ) { + return false; + } +} + +btc_multisig_address::btc_multisig_address( const size_t n_required, const accounts_keys& keys ) : + keys_required ( n_required ), witnesses_keys( keys ) +{ + create_redeem_script(); + create_address(); + type = payment_type::P2SH; +} + +size_t btc_multisig_address::count_intersection( const accounts_keys& keys ) const +{ + FC_ASSERT( keys.size() > 0 ); + + int intersections_count = 0; + for( auto& key : keys ) { + auto witness_key = witnesses_keys.find( key.first ); + if( witness_key == witnesses_keys.end() ) continue; + if( key.second == witness_key->second ) + intersections_count++; + } + return intersections_count; +} + +void btc_multisig_address::create_redeem_script() +{ + FC_ASSERT( keys_required > 0 ); + FC_ASSERT( keys_required < witnesses_keys.size() ); + redeem_script.clear(); + redeem_script.push_back( op_num[keys_required - 1] ); + for( const auto& key : witnesses_keys ) { + std::stringstream ss; + ss << std::hex << key.second.key_data.size(); + auto key_size_hex = sidechain::parse_hex( ss.str() ); + redeem_script.insert( redeem_script.end(), key_size_hex.begin(), key_size_hex.end() ); + redeem_script.insert( redeem_script.end(), key.second.key_data.begin(), key.second.key_data.end() ); + } + redeem_script.push_back( op_num[witnesses_keys.size() - 1] ); + redeem_script.push_back( OP_CHECKMULTISIG ); +} + +void btc_multisig_address::create_address() +{ + FC_ASSERT( redeem_script.size() > 0 ); + raw_address.clear(); + fc::sha256 hash256 = fc::sha256::hash( redeem_script.data(), redeem_script.size() ); + fc::ripemd160 hash160 = fc::ripemd160::hash( hash256.data(), hash256.data_size() ); + bytes temp_addr_hash( sidechain::parse_hex( hash160.str() ) ); + + raw_address.push_back( OP_HASH160 ); + std::stringstream ss; + ss << std::hex << temp_addr_hash.size(); + auto address_size_hex = sidechain::parse_hex( ss.str() ); + raw_address.insert( raw_address.end(), address_size_hex.begin(), address_size_hex.end() ); + raw_address.insert( raw_address.end(), temp_addr_hash.begin(), temp_addr_hash.end() ); + raw_address.push_back( OP_EQUAL ); +} + +btc_multisig_segwit_address::btc_multisig_segwit_address( const size_t n_required, const accounts_keys& keys ) : + btc_multisig_address( n_required, keys ) +{ + create_witness_script(); + create_segwit_address(); + type = payment_type::P2SH; +} + +bool btc_multisig_segwit_address::operator==( const btc_multisig_segwit_address& addr ) const +{ + if( address != addr.address || redeem_script != addr.redeem_script || + witnesses_keys != addr.witnesses_keys || witness_script != addr.witness_script || + raw_address != addr.raw_address ) + return false; + return true; +} + +std::vector btc_multisig_segwit_address::get_keys() { + std::vector keys; + for( const auto& k : witnesses_keys ) { + keys.push_back( k.second ); + } + return keys; +} + +void btc_multisig_segwit_address::create_witness_script() +{ + const auto redeem_sha256 = fc::sha256::hash( redeem_script.data(), redeem_script.size() ); + witness_script.push_back( OP_0 ); + witness_script.push_back( 0x20 ); // PUSH_32 + witness_script.insert( witness_script.end(), redeem_sha256.data(), redeem_sha256.data() + redeem_sha256.data_size() ); +} + +void btc_multisig_segwit_address::create_segwit_address() +{ + fc::sha256 hash256 = fc::sha256::hash( witness_script.data(), witness_script.size() ); + fc::ripemd160 hash160 = fc::ripemd160::hash( hash256.data(), hash256.data_size() ); + + raw_address = bytes(hash160.data(), hash160.data() + hash160.data_size() ); + address = fc::to_base58( get_address_bytes( raw_address ) ); +} + +bytes btc_multisig_segwit_address::get_address_bytes( const bytes& script_hash ) +{ + bytes address_bytes( 1, TESTNET_SCRIPT ); // 1 byte version + address_bytes.insert( address_bytes.end(), script_hash.begin(), script_hash.end() ); + fc::sha256 hash256 = fc::sha256::hash( fc::sha256::hash( address_bytes.data(), address_bytes.size() ) ); + address_bytes.insert( address_bytes.end(), hash256.data(), hash256.data() + 4 ); // 4 byte checksum + + return address_bytes; +} + +} diff --git a/libraries/plugins/peerplays_sidechain/bitcoin_transaction.cpp b/libraries/plugins/peerplays_sidechain/bitcoin_transaction.cpp index e099cd3f..4f44a096 100644 --- a/libraries/plugins/peerplays_sidechain/bitcoin_transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin_transaction.cpp @@ -1,279 +1,279 @@ -#include -#include -#include -#include - -namespace sidechain { - -bool out_point::operator==( const out_point& op ) const -{ - if( this->hash == op.hash && - this->n == op.n ) - { - return true; - } - return false; -} - -bool tx_in::operator==( const tx_in& ti ) const -{ - if( this->prevout == ti.prevout && - this->scriptSig == ti.scriptSig && - this->nSequence == ti.nSequence ) - { - return true; - } - return false; -} - -bool tx_out::operator==( const tx_out& to ) const -{ - if( this->value == to.value && - this->scriptPubKey == to.scriptPubKey ) - { - return true; - } - return false; -} - -bool tx_out::is_p2wsh() const -{ - if( scriptPubKey.size() == 34 && scriptPubKey[0] == static_cast(0x00) && scriptPubKey[1] == static_cast(0x20) ) { - return true; - } - return false; -} - -bool tx_out::is_p2wpkh() const -{ - if( scriptPubKey.size() == 22 && scriptPubKey[0] == static_cast(0x00) && scriptPubKey[1] == static_cast(0x14) ) { - return true; - } - return false; -} - -bool tx_out::is_p2pkh() const -{ - if( scriptPubKey.size() == 25 && scriptPubKey[0] == static_cast(0x76) && scriptPubKey[1] == static_cast(0xa9) && - scriptPubKey[2] == static_cast(0x14) && scriptPubKey[23] == static_cast(0x88) && scriptPubKey[24] == static_cast(0xac) ) { - return true; - } - return false; -} - -bool tx_out::is_p2sh() const -{ - if( scriptPubKey.size() == 23 && scriptPubKey[0] == static_cast(0xa9) && - scriptPubKey[1] == static_cast(0x14) && scriptPubKey[22] == static_cast(0x87) ) { - return true; - } - return false; -} - -bool tx_out::is_p2pk() const -{ - if( scriptPubKey.size() == 35 && scriptPubKey[0] == static_cast(0x21) && scriptPubKey[34] == static_cast(0xac) ) { - return true; - } - return false; -} - -bytes tx_out::get_data_or_script() const -{ - if( is_p2pkh() ) { - return bytes( scriptPubKey.begin() + 3, scriptPubKey.begin() + 23 ); - } else if( is_p2sh() || is_p2wpkh() ) { - return bytes( scriptPubKey.begin() + 2, scriptPubKey.begin() + 22 ); - } else if( is_p2wsh() ) { - return bytes( scriptPubKey.begin() + 2, scriptPubKey.begin() + 34 ); - } else if( is_p2pk() ) { - return bytes( scriptPubKey.begin() + 1, scriptPubKey.begin() + 34 ); - } - return scriptPubKey; -} - -bool bitcoin_transaction::operator!=( const bitcoin_transaction& bt ) const -{ - if( this->nVersion != bt.nVersion || - this->vin != bt.vin || - this->vout != bt.vout || - this->nLockTime != bt.nLockTime ) - { - return true; - } - return false; -} - -fc::sha256 bitcoin_transaction::get_hash() const -{ - const auto bytes = pack( *this, true) ; - const auto hash = fc::sha256::hash( fc::sha256::hash(bytes.data(), bytes.size()) ); - std::reverse( hash.data(), hash.data() + hash.data_size() ); - return hash; -} - -fc::sha256 bitcoin_transaction::get_txid() const -{ - const auto bytes = pack( *this, false ); - const auto hash = fc::sha256::hash( fc::sha256::hash(bytes.data(), bytes.size()) ); - std::reverse( hash.data(), hash.data() + hash.data_size() ); - return hash; -} - -size_t bitcoin_transaction::get_vsize() const -{ - static const auto witness_scale_factor = 4; - - fc::datastream no_wit_ds; - pack( no_wit_ds, *this, false ); - - fc::datastream wit_ds; - pack( wit_ds, *this, true ); - - const size_t weight = no_wit_ds.tellp() * ( witness_scale_factor - 1 ) + wit_ds.tellp(); - const size_t vsize = ( weight + witness_scale_factor - 1 ) / witness_scale_factor; - - return vsize; -} - -void bitcoin_transaction_builder::set_version( int32_t version ) -{ - tx.nVersion = version; -} - -void bitcoin_transaction_builder::set_locktime(uint32_t lock_time) -{ - tx.nLockTime = lock_time; -} - -void bitcoin_transaction_builder::add_in( payment_type type, const fc::sha256& txid, uint32_t n_out, const bytes& script_code, bool front, uint32_t sequence ) -{ - out_point prevout; - prevout.hash = txid; - prevout.n = n_out; - - tx_in txin; - txin.prevout = prevout; - txin.nSequence = sequence; - - add_in( type, txin, script_code, front ); -} - -void bitcoin_transaction_builder::add_in( payment_type type, tx_in txin, const bytes& script_code, bool front ) -{ - switch ( type ) { - case payment_type::P2SH_WPKH: - case payment_type::P2SH_WSH: - FC_ASSERT( script_code != bytes() ); - txin.scriptSig = script_code; - break; - default:{ - if( txin.prevout.hash == fc::sha256("0000000000000000000000000000000000000000000000000000000000000000") ) { //coinbase - FC_ASSERT( script_code != bytes() ); - txin.scriptSig = script_code; - } - break; - } - } - - if( front ) { - tx.vin.insert( tx.vin.begin(), txin ); - } else { - tx.vin.push_back( txin ); - } -} - -void bitcoin_transaction_builder::add_out( payment_type type, int64_t amount, const std::string& base58_address, bool front ) -{ - // TODO: add checks - const auto address_bytes = fc::from_base58(base58_address); - add_out( type, amount, bytes( address_bytes.begin() + 1, address_bytes.begin() + 1 + 20 ), front ); -} - -void bitcoin_transaction_builder::add_out( payment_type type, int64_t amount, const fc::ecc::public_key_data& pubkey, bool front ) -{ - FC_ASSERT( is_payment_to_pubkey( type ) ); - - if ( type == payment_type::P2PK ) { - const auto pubkey_bytes = bytes( pubkey.begin(), pubkey.begin() + pubkey.size() ); - add_out( type, amount, pubkey_bytes, front ); - } else { - const auto hash256 = fc::sha256::hash( pubkey.begin(), pubkey.size() ); - const auto hash160 = fc::ripemd160::hash( hash256.data(), hash256.data_size() ); - add_out( type, amount, bytes( hash160.data(), hash160.data() + hash160.data_size() ), front ); - } -} - -void bitcoin_transaction_builder::add_out( payment_type type, int64_t amount, const bytes& script_code, bool front ) -{ - tx_out out; - out.value = amount; - out.scriptPubKey = get_script_pubkey( type, script_code ); - - if( front ) { - tx.vout.insert( tx.vout.begin(), out ); - } else { - tx.vout.push_back( out ); - } -} - -void bitcoin_transaction_builder::add_out_all_type( const uint64_t& amount, const bitcoin_address& address, bool front ) -{ - switch( address.get_type() ) { - case payment_type::P2PK: { - bytes raw_address( address.get_raw_address() ); - fc::ecc::public_key_data public_key; - std::copy( raw_address.begin(), raw_address.end(), public_key.begin() ); - add_out( address.get_type(), amount, public_key, front ); - break; - } - case payment_type::P2PKH: - case payment_type::P2SH: - case payment_type::P2SH_WPKH: - case payment_type::P2SH_WSH: { - add_out( address.get_type(), amount, address.get_address(), front ); - break; - } - case payment_type::P2WPKH: - case payment_type::P2WSH: { - add_out( address.get_type(), amount, address.get_raw_address(), front ); - break; - } - } -} - -inline bool bitcoin_transaction_builder::is_payment_to_pubkey( payment_type type ) -{ - switch ( type ) { - case payment_type::P2PK: - case payment_type::P2PKH: - case payment_type::P2WPKH: - case payment_type::P2SH_WPKH: - return true; - default: - return false; - } -} - -bytes bitcoin_transaction_builder::get_script_pubkey( payment_type type, const bytes& script_code ) -{ - switch ( type ) { - case payment_type::NULLDATA: - return script_builder() << op::RETURN << script_code; - case payment_type::P2PK: - return script_builder() << script_code << op::CHECKSIG; - case payment_type::P2PKH: - return script_builder() << op::DUP << op::HASH160 << script_code << op::EQUALVERIFY << op::CHECKSIG; - case payment_type::P2SH: - case payment_type::P2SH_WPKH: - case payment_type::P2SH_WSH: - return script_builder() << op::HASH160 << script_code << op::EQUAL; - case payment_type::P2WPKH: - case payment_type::P2WSH: - return script_builder() << op::_0 << script_code; - default: - return script_code; - } -} - -} +//#include +//#include +//#include +//#include +// +//namespace sidechain { +// +//bool out_point::operator==( const out_point& op ) const +//{ +// if( this->hash == op.hash && +// this->n == op.n ) +// { +// return true; +// } +// return false; +//} +// +//bool tx_in::operator==( const tx_in& ti ) const +//{ +// if( this->prevout == ti.prevout && +// this->scriptSig == ti.scriptSig && +// this->nSequence == ti.nSequence ) +// { +// return true; +// } +// return false; +//} +// +//bool tx_out::operator==( const tx_out& to ) const +//{ +// if( this->value == to.value && +// this->scriptPubKey == to.scriptPubKey ) +// { +// return true; +// } +// return false; +//} +// +//bool tx_out::is_p2wsh() const +//{ +// if( scriptPubKey.size() == 34 && scriptPubKey[0] == static_cast(0x00) && scriptPubKey[1] == static_cast(0x20) ) { +// return true; +// } +// return false; +//} +// +//bool tx_out::is_p2wpkh() const +//{ +// if( scriptPubKey.size() == 22 && scriptPubKey[0] == static_cast(0x00) && scriptPubKey[1] == static_cast(0x14) ) { +// return true; +// } +// return false; +//} +// +//bool tx_out::is_p2pkh() const +//{ +// if( scriptPubKey.size() == 25 && scriptPubKey[0] == static_cast(0x76) && scriptPubKey[1] == static_cast(0xa9) && +// scriptPubKey[2] == static_cast(0x14) && scriptPubKey[23] == static_cast(0x88) && scriptPubKey[24] == static_cast(0xac) ) { +// return true; +// } +// return false; +//} +// +//bool tx_out::is_p2sh() const +//{ +// if( scriptPubKey.size() == 23 && scriptPubKey[0] == static_cast(0xa9) && +// scriptPubKey[1] == static_cast(0x14) && scriptPubKey[22] == static_cast(0x87) ) { +// return true; +// } +// return false; +//} +// +//bool tx_out::is_p2pk() const +//{ +// if( scriptPubKey.size() == 35 && scriptPubKey[0] == static_cast(0x21) && scriptPubKey[34] == static_cast(0xac) ) { +// return true; +// } +// return false; +//} +// +//bytes tx_out::get_data_or_script() const +//{ +// if( is_p2pkh() ) { +// return bytes( scriptPubKey.begin() + 3, scriptPubKey.begin() + 23 ); +// } else if( is_p2sh() || is_p2wpkh() ) { +// return bytes( scriptPubKey.begin() + 2, scriptPubKey.begin() + 22 ); +// } else if( is_p2wsh() ) { +// return bytes( scriptPubKey.begin() + 2, scriptPubKey.begin() + 34 ); +// } else if( is_p2pk() ) { +// return bytes( scriptPubKey.begin() + 1, scriptPubKey.begin() + 34 ); +// } +// return scriptPubKey; +//} +// +//bool bitcoin_transaction::operator!=( const bitcoin_transaction& bt ) const +//{ +// if( this->nVersion != bt.nVersion || +// this->vin != bt.vin || +// this->vout != bt.vout || +// this->nLockTime != bt.nLockTime ) +// { +// return true; +// } +// return false; +//} +// +//fc::sha256 bitcoin_transaction::get_hash() const +//{ +// const auto bytes = pack( *this, true) ; +// const auto hash = fc::sha256::hash( fc::sha256::hash(bytes.data(), bytes.size()) ); +// std::reverse( hash.data(), hash.data() + hash.data_size() ); +// return hash; +//} +// +//fc::sha256 bitcoin_transaction::get_txid() const +//{ +// const auto bytes = pack( *this, false ); +// const auto hash = fc::sha256::hash( fc::sha256::hash(bytes.data(), bytes.size()) ); +// std::reverse( hash.data(), hash.data() + hash.data_size() ); +// return hash; +//} +// +//size_t bitcoin_transaction::get_vsize() const +//{ +// static const auto witness_scale_factor = 4; +// +// fc::datastream no_wit_ds; +// pack( no_wit_ds, *this, false ); +// +// fc::datastream wit_ds; +// pack( wit_ds, *this, true ); +// +// const size_t weight = no_wit_ds.tellp() * ( witness_scale_factor - 1 ) + wit_ds.tellp(); +// const size_t vsize = ( weight + witness_scale_factor - 1 ) / witness_scale_factor; +// +// return vsize; +//} +// +//void bitcoin_transaction_builder::set_version( int32_t version ) +//{ +// tx.nVersion = version; +//} +// +//void bitcoin_transaction_builder::set_locktime(uint32_t lock_time) +//{ +// tx.nLockTime = lock_time; +//} +// +//void bitcoin_transaction_builder::add_in( payment_type type, const fc::sha256& txid, uint32_t n_out, const bytes& script_code, bool front, uint32_t sequence ) +//{ +// out_point prevout; +// prevout.hash = txid; +// prevout.n = n_out; +// +// tx_in txin; +// txin.prevout = prevout; +// txin.nSequence = sequence; +// +// add_in( type, txin, script_code, front ); +//} +// +//void bitcoin_transaction_builder::add_in( payment_type type, tx_in txin, const bytes& script_code, bool front ) +//{ +// switch ( type ) { +// case payment_type::P2SH_WPKH: +// case payment_type::P2SH_WSH: +// FC_ASSERT( script_code != bytes() ); +// txin.scriptSig = script_code; +// break; +// default:{ +// if( txin.prevout.hash == fc::sha256("0000000000000000000000000000000000000000000000000000000000000000") ) { //coinbase +// FC_ASSERT( script_code != bytes() ); +// txin.scriptSig = script_code; +// } +// break; +// } +// } +// +// if( front ) { +// tx.vin.insert( tx.vin.begin(), txin ); +// } else { +// tx.vin.push_back( txin ); +// } +//} +// +//void bitcoin_transaction_builder::add_out( payment_type type, int64_t amount, const std::string& base58_address, bool front ) +//{ +// // TODO: add checks +// const auto address_bytes = fc::from_base58(base58_address); +// add_out( type, amount, bytes( address_bytes.begin() + 1, address_bytes.begin() + 1 + 20 ), front ); +//} +// +//void bitcoin_transaction_builder::add_out( payment_type type, int64_t amount, const fc::ecc::public_key_data& pubkey, bool front ) +//{ +// FC_ASSERT( is_payment_to_pubkey( type ) ); +// +// if ( type == payment_type::P2PK ) { +// const auto pubkey_bytes = bytes( pubkey.begin(), pubkey.begin() + pubkey.size() ); +// add_out( type, amount, pubkey_bytes, front ); +// } else { +// const auto hash256 = fc::sha256::hash( pubkey.begin(), pubkey.size() ); +// const auto hash160 = fc::ripemd160::hash( hash256.data(), hash256.data_size() ); +// add_out( type, amount, bytes( hash160.data(), hash160.data() + hash160.data_size() ), front ); +// } +//} +// +//void bitcoin_transaction_builder::add_out( payment_type type, int64_t amount, const bytes& script_code, bool front ) +//{ +// tx_out out; +// out.value = amount; +// out.scriptPubKey = get_script_pubkey( type, script_code ); +// +// if( front ) { +// tx.vout.insert( tx.vout.begin(), out ); +// } else { +// tx.vout.push_back( out ); +// } +//} +// +//void bitcoin_transaction_builder::add_out_all_type( const uint64_t& amount, const bitcoin_address& address, bool front ) +//{ +// switch( address.get_type() ) { +// case payment_type::P2PK: { +// bytes raw_address( address.get_raw_address() ); +// fc::ecc::public_key_data public_key; +// std::copy( raw_address.begin(), raw_address.end(), public_key.begin() ); +// add_out( address.get_type(), amount, public_key, front ); +// break; +// } +// case payment_type::P2PKH: +// case payment_type::P2SH: +// case payment_type::P2SH_WPKH: +// case payment_type::P2SH_WSH: { +// add_out( address.get_type(), amount, address.get_address(), front ); +// break; +// } +// case payment_type::P2WPKH: +// case payment_type::P2WSH: { +// add_out( address.get_type(), amount, address.get_raw_address(), front ); +// break; +// } +// } +//} +// +//inline bool bitcoin_transaction_builder::is_payment_to_pubkey( payment_type type ) +//{ +// switch ( type ) { +// case payment_type::P2PK: +// case payment_type::P2PKH: +// case payment_type::P2WPKH: +// case payment_type::P2SH_WPKH: +// return true; +// default: +// return false; +// } +//} +// +//bytes bitcoin_transaction_builder::get_script_pubkey( payment_type type, const bytes& script_code ) +//{ +// switch ( type ) { +// case payment_type::NULLDATA: +// return script_builder() << op::RETURN << script_code; +// case payment_type::P2PK: +// return script_builder() << script_code << op::CHECKSIG; +// case payment_type::P2PKH: +// return script_builder() << op::DUP << op::HASH160 << script_code << op::EQUALVERIFY << op::CHECKSIG; +// case payment_type::P2SH: +// case payment_type::P2SH_WPKH: +// case payment_type::P2SH_WSH: +// return script_builder() << op::HASH160 << script_code << op::EQUAL; +// case payment_type::P2WPKH: +// case payment_type::P2WSH: +// return script_builder() << op::_0 << script_code; +// default: +// return script_code; +// } +//} +// +//} diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp index 12b6e7fb..c8984b4a 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp @@ -1,360 +1,360 @@ -#pragma once - -#include -#include - -namespace sidechain { - -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 ) ); - } 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 ) ); - } - 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 ) ) ); - } else { - fc::raw::pack( s, static_cast( 255 ) ); - fc::raw::pack( s, htole64( static_cast( size ) ) ); - } -} - -template -inline uint64_t unpack_compact_size( Stream& s ) -{ - uint8_t size; - uint64_t size_ret; - - fc::raw::unpack( s, size ); - - if (size < 253) { - size_ret = size; - } 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 ) { - 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()" ); - } 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()" ); - } - - 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() ); -} - -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 ); -} - -template -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 ); -} - -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 ); -} - -} +//#pragma once +// +//#include +//#include +// +//namespace sidechain { +// +//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 ) ); +// } 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 ) ); +// } +// 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 ) ) ); +// } else { +// fc::raw::pack( s, static_cast( 255 ) ); +// fc::raw::pack( s, htole64( static_cast( size ) ) ); +// } +//} +// +//template +//inline uint64_t unpack_compact_size( Stream& s ) +//{ +// uint8_t size; +// uint64_t size_ret; +// +// fc::raw::unpack( s, size ); +// +// if (size < 253) { +// size_ret = size; +// } 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 ) { +// 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()" ); +// } 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()" ); +// } +// +// 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() ); +//} +// +//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 ); +//} +// +//template +//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 ); +//} +// +//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 ); +//} +// +//}