WIP, Moving Bitcoin listener to plugin
- Fix include paths - Add missing files
This commit is contained in:
parent
6f34dabeab
commit
6bc81fdb35
9 changed files with 714 additions and 0 deletions
279
libraries/plugins/peerplays_sidechain/bitcoin_transaction.cpp
Normal file
279
libraries/plugins/peerplays_sidechain/bitcoin_transaction.cpp
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
#include <sidechain/bitcoin_transaction.hpp>
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <sidechain/bitcoin_script.hpp>
|
||||
#include <sidechain/serialize.hpp>
|
||||
|
||||
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<char>(0x00) && scriptPubKey[1] == static_cast<char>(0x20) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tx_out::is_p2wpkh() const
|
||||
{
|
||||
if( scriptPubKey.size() == 22 && scriptPubKey[0] == static_cast<char>(0x00) && scriptPubKey[1] == static_cast<char>(0x14) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tx_out::is_p2pkh() const
|
||||
{
|
||||
if( scriptPubKey.size() == 25 && scriptPubKey[0] == static_cast<char>(0x76) && scriptPubKey[1] == static_cast<char>(0xa9) &&
|
||||
scriptPubKey[2] == static_cast<char>(0x14) && scriptPubKey[23] == static_cast<char>(0x88) && scriptPubKey[24] == static_cast<char>(0xac) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tx_out::is_p2sh() const
|
||||
{
|
||||
if( scriptPubKey.size() == 23 && scriptPubKey[0] == static_cast<char>(0xa9) &&
|
||||
scriptPubKey[1] == static_cast<char>(0x14) && scriptPubKey[22] == static_cast<char>(0x87) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tx_out::is_p2pk() const
|
||||
{
|
||||
if( scriptPubKey.size() == 35 && scriptPubKey[0] == static_cast<char>(0x21) && scriptPubKey[34] == static_cast<char>(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<size_t> no_wit_ds;
|
||||
pack( no_wit_ds, *this, false );
|
||||
|
||||
fc::datastream<size_t> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct bitcoin_address_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
account_id_type owner;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const {}
|
||||
share_type calculate_fee( const fee_parameters_type& k )const {
|
||||
return k.fee;
|
||||
}
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::bitcoin_address_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_address_create_operation, (fee)(payer)(owner) )
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/peerplays_sidechain/input_withdrawal_info.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin_transaction.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct bitcoin_transaction_send_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 0;
|
||||
uint32_t price_per_kbyte = 0;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
|
||||
sidechain::info_for_vin pw_vin;
|
||||
std::vector< sidechain::info_for_vin > vins;
|
||||
std::vector< info_for_vout_id_type > vouts;
|
||||
|
||||
sidechain::bitcoin_transaction transaction;
|
||||
uint64_t fee_for_size;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const {}
|
||||
share_type calculate_fee( const fee_parameters_type& k )const {
|
||||
share_type fee_required = k.fee;
|
||||
fee_required += calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
return fee_required;
|
||||
}
|
||||
};
|
||||
|
||||
struct bitcoin_transaction_sign_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 0;
|
||||
uint32_t price_per_kbyte = 0;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
proposal_id_type proposal_id;
|
||||
std::vector<sidechain::bytes> signatures;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const {}
|
||||
share_type calculate_fee( const fee_parameters_type& k )const { return 0; }
|
||||
};
|
||||
|
||||
struct revert_trx_info
|
||||
{
|
||||
revert_trx_info() = default;
|
||||
revert_trx_info( fc::sha256 trx_id, std::set< fc::sha256 > vins ): transaction_id( trx_id ), valid_vins( vins ) {}
|
||||
|
||||
fc::sha256 transaction_id;
|
||||
std::set< fc::sha256 > valid_vins;
|
||||
|
||||
bool operator ==( const revert_trx_info& trx_info ){
|
||||
return this->transaction_id == trx_info.transaction_id && this->valid_vins == trx_info.valid_vins;
|
||||
}
|
||||
|
||||
bool operator !=( const revert_trx_info& trx_info ){
|
||||
return this->transaction_id != trx_info.transaction_id || this->valid_vins != trx_info.valid_vins;
|
||||
}
|
||||
};
|
||||
|
||||
struct bitcoin_transaction_revert_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 0;
|
||||
uint32_t price_per_kbyte = 0;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
|
||||
std::vector< revert_trx_info > transactions_info;
|
||||
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const {}
|
||||
share_type calculate_fee( const fee_parameters_type& k )const { return k.fee; }
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation, (fee)(payer)(pw_vin)(vins)(vouts)(transaction)(fee_for_size) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation, (fee)(payer)(proposal_id)(signatures) )
|
||||
|
||||
FC_REFLECT( graphene::chain::revert_trx_info, (transaction_id)(valid_vins) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_revert_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_revert_operation, (fee)(payer)(transactions_info) )
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <graphene/peerplays_sidechain/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin_address.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class info_for_vout_object : public abstract_object<info_for_vout_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = info_for_vout_object_type;
|
||||
|
||||
struct comparer {
|
||||
bool operator()( const info_for_vout_object& lhs, const info_for_vout_object& rhs ) const {
|
||||
if( lhs.used != rhs.used )
|
||||
return lhs.used < rhs.used;
|
||||
return lhs.id < rhs.id;
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==( const info_for_vout_object& ifv ) const {
|
||||
return ( this->payer == ifv.payer ) &&
|
||||
( this->address == ifv.address ) &&
|
||||
( this->amount == ifv.amount );
|
||||
}
|
||||
|
||||
info_for_vout_id_type get_id()const { return id; }
|
||||
|
||||
account_id_type payer;
|
||||
sidechain::bitcoin_address address;
|
||||
uint64_t amount;
|
||||
|
||||
bool used = false;
|
||||
};
|
||||
|
||||
struct by_created;
|
||||
struct by_id_and_not_used;
|
||||
|
||||
typedef boost::multi_index_container<
|
||||
info_for_vout_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >,
|
||||
ordered_non_unique< tag< by_created >, member< info_for_vout_object, bool, &info_for_vout_object::used > >,
|
||||
ordered_non_unique<tag<by_id_and_not_used>, identity< info_for_vout_object >, info_for_vout_object::comparer >
|
||||
>
|
||||
> info_for_vout_multi_index_container;
|
||||
typedef generic_index<info_for_vout_object, info_for_vout_multi_index_container> info_for_vout_index;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::info_for_vout_object, (graphene::chain::object), (payer)(address)(amount)(used) )
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
#pragma once
|
||||
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
|
||||
#include <fc/crypto/sha256.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/thread_safe_index.hpp>
|
||||
#include <graphene/peerplays_sidechain/info_for_vout_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/types.hpp>
|
||||
|
||||
using boost::multi_index_container;
|
||||
using namespace boost::multi_index;
|
||||
|
||||
namespace graphene { namespace chain { class database; } }
|
||||
|
||||
namespace sidechain {
|
||||
|
||||
struct info_for_vin
|
||||
{
|
||||
info_for_vin() = default;
|
||||
|
||||
info_for_vin( const prev_out& _out, const std::string& _address, bytes _script = bytes(), bool _resend = false );
|
||||
|
||||
bool operator!=( const info_for_vin& obj ) const;
|
||||
|
||||
struct comparer {
|
||||
bool operator() ( const info_for_vin& lhs, const info_for_vin& rhs ) const;
|
||||
};
|
||||
|
||||
static uint64_t count_id_info_for_vin;
|
||||
uint64_t id;
|
||||
|
||||
fc::sha256 identifier;
|
||||
|
||||
prev_out out;
|
||||
std::string address;
|
||||
bytes script;
|
||||
|
||||
bool used = false;
|
||||
bool resend = false;
|
||||
};
|
||||
|
||||
struct by_id;
|
||||
struct by_identifier;
|
||||
struct by_id_resend_not_used;
|
||||
|
||||
using info_for_vin_index = boost::multi_index_container<info_for_vin,
|
||||
indexed_by<
|
||||
ordered_unique<tag<by_id>, member<info_for_vin, uint64_t, &info_for_vin::id>>,
|
||||
ordered_unique<tag<by_identifier>, member<info_for_vin, fc::sha256, &info_for_vin::identifier>>,
|
||||
ordered_non_unique<tag<by_id_resend_not_used>, identity< info_for_vin >, info_for_vin::comparer >
|
||||
>
|
||||
>;
|
||||
|
||||
class input_withdrawal_info
|
||||
{
|
||||
|
||||
public:
|
||||
input_withdrawal_info( graphene::chain::database& _db ) : db( _db ) {}
|
||||
|
||||
|
||||
std::vector<sidechain::bytes> get_redeem_scripts( const std::vector<info_for_vin>& info_vins );
|
||||
|
||||
std::vector<uint64_t> get_amounts( const std::vector<info_for_vin>& info_vins );
|
||||
|
||||
|
||||
fc::optional<info_for_vin> get_info_for_pw_vin();
|
||||
|
||||
|
||||
void insert_info_for_vin( const prev_out& out, const std::string& address, bytes script = bytes(), bool resend = false );
|
||||
|
||||
void modify_info_for_vin( const info_for_vin& obj, const std::function<void( info_for_vin& e )>& func );
|
||||
|
||||
void mark_as_used_vin( const info_for_vin& obj );
|
||||
|
||||
void mark_as_unused_vin( const info_for_vin& obj );
|
||||
|
||||
void remove_info_for_vin( const info_for_vin& obj );
|
||||
|
||||
fc::optional<info_for_vin> find_info_for_vin( fc::sha256 identifier );
|
||||
|
||||
size_t size_info_for_vins() { return info_for_vins.size(); }
|
||||
|
||||
std::vector<info_for_vin> get_info_for_vins();
|
||||
|
||||
|
||||
void insert_info_for_vout( const graphene::chain::account_id_type& payer, const std::string& data, const uint64_t& amount );
|
||||
|
||||
void mark_as_used_vout( const graphene::chain::info_for_vout_object& obj );
|
||||
|
||||
void mark_as_unused_vout( const graphene::chain::info_for_vout_object& obj );
|
||||
|
||||
void remove_info_for_vout( const info_for_vout& obj );
|
||||
|
||||
fc::optional<graphene::chain::info_for_vout_object> find_info_for_vout( graphene::chain::info_for_vout_id_type id );
|
||||
|
||||
size_t size_info_for_vouts();
|
||||
|
||||
std::vector<info_for_vout> get_info_for_vouts();
|
||||
|
||||
private:
|
||||
|
||||
graphene::chain::database& db;
|
||||
|
||||
thread_safe_index<info_for_vin_index> info_for_vins;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
FC_REFLECT( sidechain::info_for_vin, (identifier)(out)(address)(script)(used)(resend) )
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/zmq_listener.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin_transaction.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin_rpc_client.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <fc/optional.hpp>
|
||||
|
||||
namespace sidechain {
|
||||
|
||||
template<class T1>
|
||||
class thread_safe_index
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using iterator = typename T1::iterator;
|
||||
|
||||
std::pair<iterator,bool> insert( const typename T1::value_type& value ) {
|
||||
std::lock_guard<std::recursive_mutex> locker( lock );
|
||||
return data.insert( value );
|
||||
}
|
||||
|
||||
template<class T2, typename Key>
|
||||
bool modify( const Key _key, const std::function<void( typename T1::value_type& e)>& func ) {
|
||||
std::lock_guard<std::recursive_mutex> locker( lock );
|
||||
const auto option = find_iterator<T2>( _key );
|
||||
if( !option )
|
||||
return false;
|
||||
data.modify( data.iterator_to( **option ), [&func]( typename T1::value_type& obj ) { func( obj ); } );
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T2, typename Key>
|
||||
bool remove( const Key _key ) {
|
||||
std::lock_guard<std::recursive_mutex> locker( lock );
|
||||
const auto option = find_iterator<T2>( _key );
|
||||
if( !option )
|
||||
return false;
|
||||
data.erase( data.iterator_to( **option ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
std::lock_guard<std::recursive_mutex> locker( lock );
|
||||
return data.size();
|
||||
}
|
||||
|
||||
template<class T2, typename Key>
|
||||
fc::optional<typename T1::value_type> find( const Key _key ) {
|
||||
std::lock_guard<std::recursive_mutex> locker( lock );
|
||||
auto& index = data.template get<T2>();
|
||||
auto it = index.find( _key );
|
||||
if( it != index.end() ) {
|
||||
return fc::optional<typename T1::value_type>(*it);
|
||||
}
|
||||
return fc::optional<typename T1::value_type>();
|
||||
}
|
||||
|
||||
template<class T2>
|
||||
void safe_for(std::function<void(typename T1::template index<T2>::type::iterator itr1,
|
||||
typename T1::template index<T2>::type::iterator itr2)> func) {
|
||||
std::lock_guard<std::recursive_mutex> locker( lock );
|
||||
auto& index = data.template get<T2>();
|
||||
func(index.begin(), index.end());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<class T2, typename Key>
|
||||
fc::optional<typename T1::template index<T2>::type::iterator> find_iterator( const Key _key ) {
|
||||
auto& index = data.template get<T2>();
|
||||
auto it = index.find( _key );
|
||||
if( it == index.end() )
|
||||
return fc::optional<typename T1::template index<T2>::type::iterator>();
|
||||
return it;
|
||||
}
|
||||
|
||||
std::recursive_mutex lock;
|
||||
|
||||
T1 data;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace sidechain {
|
||||
|
||||
class bitcoin_transaction;
|
||||
|
||||
using bytes = std::vector<char>;
|
||||
using accounts_keys = std::map< graphene::chain::account_id_type, graphene::chain::public_key_type >;
|
||||
using info_for_vout = graphene::chain::info_for_vout_object;
|
||||
using full_btc_transaction = std::pair<bitcoin_transaction, uint64_t>;
|
||||
|
||||
enum class payment_type
|
||||
{
|
||||
NULLDATA,
|
||||
P2PK,
|
||||
P2PKH,
|
||||
P2SH,
|
||||
P2WPKH,
|
||||
P2WSH,
|
||||
P2SH_WPKH,
|
||||
P2SH_WSH
|
||||
};
|
||||
|
||||
enum class sidechain_proposal_type
|
||||
{
|
||||
ISSUE_BTC,
|
||||
SEND_BTC_TRANSACTION,
|
||||
REVERT_BTC_TRANSACTION
|
||||
};
|
||||
|
||||
struct prev_out
|
||||
{
|
||||
bool operator!=( const prev_out& obj ) const
|
||||
{
|
||||
if( this->hash_tx != obj.hash_tx ||
|
||||
this->n_vout != obj.n_vout ||
|
||||
this->amount != obj.amount )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string hash_tx;
|
||||
uint32_t n_vout;
|
||||
uint64_t amount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
FC_REFLECT_ENUM( sidechain::payment_type, (NULLDATA)(P2PK)(P2PKH)(P2SH)(P2WPKH)(P2WSH)(P2SH_WPKH)(P2SH_WSH) );
|
||||
FC_REFLECT_ENUM( sidechain::sidechain_proposal_type, (ISSUE_BTC)(SEND_BTC_TRANSACTION)(REVERT_BTC_TRANSACTION) );
|
||||
FC_REFLECT( sidechain::prev_out, (hash_tx)(n_vout)(amount) );
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <graphene/peerplays_sidechain/sidechain_network_manager.hpp>
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
namespace detail
|
||||
|
|
|
|||
Loading…
Reference in a new issue