144 lines
5 KiB
C++
144 lines
5 KiB
C++
#include <sidechain/sidechain_proposal_checker.hpp>
|
|
#include <sidechain/sidechain_condensing_tx.hpp>
|
|
|
|
#include <graphene/chain/database.hpp>
|
|
#include <graphene/chain/primary_wallet_vout_object.hpp>
|
|
#include <graphene/chain/bitcoin_address_object.hpp>
|
|
#include <graphene/chain/proposal_object.hpp>
|
|
#include <graphene/chain/bitcoin_transaction_object.hpp>
|
|
#include <graphene/chain/info_for_used_vin_object.hpp>
|
|
|
|
namespace sidechain {
|
|
|
|
bool sidechain_proposal_checker::check_bitcoin_transaction_send_operation( const bitcoin_transaction_send_operation& op )
|
|
{
|
|
bool info_for_pw_vin = check_info_for_pw_vin( op.pw_vin );
|
|
bool info_for_vins = check_info_for_vins( op.vins );
|
|
bool info_for_vouts = check_info_for_vouts( op.vouts );
|
|
bool transaction = check_transaction( op );
|
|
|
|
return info_for_pw_vin && info_for_vins && info_for_vouts && transaction;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_reuse_pw_vin( const fc::sha256& pw_vin )
|
|
{
|
|
const auto& pw_vin_status = pw_vin_ident.insert( pw_vin );
|
|
if( !pw_vin_status.second ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_reuse_user_vins( const std::vector<fc::sha256>& user_vin_identifiers )
|
|
{
|
|
for( const auto& vin : user_vin_identifiers ) {
|
|
const auto& user_vin_status = user_vin_ident.insert( vin );
|
|
if( !user_vin_status.second ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_reuse_vouts( const std::vector<info_for_vout_id_type>& user_vout_ids )
|
|
{
|
|
for( const auto& vout : user_vout_ids ) {
|
|
const auto& user_vout_status = vout_ids.insert( vout );
|
|
if( !user_vout_status.second ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_reuse( const operation& op )
|
|
{
|
|
fc::sha256 pw_vin_identifier;
|
|
std::vector<fc::sha256> user_vin_identifiers;
|
|
std::vector<info_for_vout_id_type> user_vout_ids;
|
|
|
|
if( op.which() == operation::tag<bitcoin_transaction_send_operation>::value ) {
|
|
bitcoin_transaction_send_operation btc_tx_send_op = op.get<bitcoin_transaction_send_operation>();
|
|
|
|
pw_vin_identifier = btc_tx_send_op.pw_vin.identifier;
|
|
user_vout_ids = btc_tx_send_op.vouts;
|
|
for( const auto& vin : btc_tx_send_op.vins ) {
|
|
user_vin_identifiers.push_back( vin.identifier );
|
|
}
|
|
} else if ( op.which() == operation::tag<bitcoin_issue_operation>::value ) {
|
|
bitcoin_issue_operation btc_issue_op = op.get<bitcoin_issue_operation>();
|
|
const auto& bto_itr_idx = db.get_index_type<bitcoin_transaction_index>().indices().get<graphene::chain::by_transaction_id>();
|
|
|
|
for( const auto& id : btc_issue_op.transaction_ids ) {
|
|
const auto& bto_itr = bto_itr_idx.find( id );
|
|
if( bto_itr == bto_itr_idx.end() ) {
|
|
return false;
|
|
}
|
|
|
|
pw_vin_identifier = bto_itr->pw_vin;
|
|
user_vout_ids = bto_itr->vouts;
|
|
user_vin_identifiers = bto_itr->vins;
|
|
}
|
|
}
|
|
|
|
return check_reuse_pw_vin( pw_vin_identifier ) &&
|
|
check_reuse_user_vins( user_vin_identifiers ) &&
|
|
check_reuse_vouts( user_vout_ids );
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_info_for_pw_vin( const info_for_vin& info_for_vin )
|
|
{
|
|
const auto& prevout = db.pw_vout_manager.get_vout( info_for_vin.identifier );
|
|
const auto& pw_address = db.get_latest_PW().address;
|
|
if( !prevout.valid() || info_for_vin.out != prevout->vout ||
|
|
info_for_vin.address != pw_address.get_address() || info_for_vin.script != pw_address.get_witness_script() ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_info_for_vins( const std::vector<info_for_vin>& info_for_vins )
|
|
{
|
|
for( const auto& vin : info_for_vins ) {
|
|
const auto& v = db.i_w_info.find_info_for_vin( vin.identifier );
|
|
if( !v.valid() || *v != vin ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_info_for_vouts( const std::vector<info_for_vout_id_type>& info_for_vout_ids )
|
|
{
|
|
const auto& info_for_vout_idx = db.get_index_type<info_for_vout_index>().indices().get<graphene::chain::by_id>();
|
|
for( const auto& id : info_for_vout_ids ) {
|
|
const auto& itr = info_for_vout_idx.find( id );
|
|
if( itr == info_for_vout_idx.end() ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool sidechain_proposal_checker::check_transaction( const bitcoin_transaction_send_operation& btc_trx_op )
|
|
{
|
|
std::vector<info_for_vout> info_vouts;
|
|
const auto& info_for_vout_idx = db.get_index_type<info_for_vout_index>().indices().get<graphene::chain::by_id>();
|
|
for( const auto& vout_id : btc_trx_op.vouts ) {
|
|
const auto& vout_itr = info_for_vout_idx.find( vout_id );
|
|
if( vout_itr == info_for_vout_idx.end() ) {
|
|
return false;
|
|
}
|
|
info_vouts.push_back( *vout_itr );
|
|
}
|
|
|
|
const auto& temp_full_tx = db.create_btc_transaction( btc_trx_op.vins, info_vouts, btc_trx_op.pw_vin );
|
|
|
|
if( temp_full_tx.first != btc_trx_op.transaction || temp_full_tx.second != btc_trx_op.fee_for_size ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|