From 6f34dabeab25bc05204c0d581272c8f76ae59e2b Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Mon, 16 Sep 2019 21:34:36 +0200 Subject: [PATCH] WIP, Moving Bitcoin listener to plugin - Fix include paths - Add missing files --- .../bitcoin_rpc_client.cpp | 2 +- .../peerplays_sidechain/serialize.hpp | 360 ++++++++++++++++++ .../sidechain_network_manager.hpp | 4 +- .../sidechain_network_manager.cpp | 6 +- 4 files changed, 366 insertions(+), 6 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp diff --git a/libraries/plugins/peerplays_sidechain/bitcoin_rpc_client.cpp b/libraries/plugins/peerplays_sidechain/bitcoin_rpc_client.cpp index 4e4286df..73ce4b66 100644 --- a/libraries/plugins/peerplays_sidechain/bitcoin_rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin_rpc_client.cpp @@ -1,4 +1,4 @@ -#include +#include #include diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp new file mode 100644 index 00000000..12b6e7fb --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/serialize.hpp @@ -0,0 +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 ); +} + +} diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_network_manager.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_network_manager.hpp index bce5ddd3..4afd3f87 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_network_manager.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_network_manager.hpp @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include #include namespace sidechain { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_network_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_network_manager.cpp index 3d577581..25d65374 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_network_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_network_manager.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include #include #include