Added check_bitcoin_transaction_revert_operation
This commit is contained in:
parent
7428c10414
commit
fa2eff74c2
6 changed files with 152 additions and 18 deletions
|
|
@ -132,6 +132,15 @@ void database::processing_sidechain_proposals( const witness_object& current_wit
|
||||||
|
|
||||||
sidechain_proposal_checker checker( *this );
|
sidechain_proposal_checker checker( *this );
|
||||||
|
|
||||||
|
auto approve_propose = [ & ]( const proposal_id_type& id )
|
||||||
|
{
|
||||||
|
proposal_update_operation puo;
|
||||||
|
puo.fee_paying_account = current_witness.witness_account;
|
||||||
|
puo.proposal = id;
|
||||||
|
puo.active_approvals_to_add = { current_witness.witness_account };
|
||||||
|
_pending_tx.insert( _pending_tx.begin(), create_signed_transaction( private_key, puo ) );
|
||||||
|
};
|
||||||
|
|
||||||
for( auto& sidechain_proposal : sidechain_proposal_idx ) {
|
for( auto& sidechain_proposal : sidechain_proposal_idx ) {
|
||||||
|
|
||||||
const auto& proposal = proposal_idx.find( sidechain_proposal.proposal_id );
|
const auto& proposal = proposal_idx.find( sidechain_proposal.proposal_id );
|
||||||
|
|
@ -143,11 +152,7 @@ void database::processing_sidechain_proposals( const witness_object& current_wit
|
||||||
|
|
||||||
switch( sidechain_proposal.proposal_type ) {
|
switch( sidechain_proposal.proposal_type ) {
|
||||||
case sidechain_proposal_type::ISSUE_BTC :{
|
case sidechain_proposal_type::ISSUE_BTC :{
|
||||||
proposal_update_operation puo;
|
approve_propose( proposal->id );
|
||||||
puo.fee_paying_account = current_witness.witness_account;
|
|
||||||
puo.proposal = proposal->id;
|
|
||||||
puo.active_approvals_to_add = { current_witness.witness_account };
|
|
||||||
_pending_tx.insert( _pending_tx.begin(), create_signed_transaction( private_key, puo ) );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sidechain_proposal_type::SEND_BTC_TRANSACTION :{
|
case sidechain_proposal_type::SEND_BTC_TRANSACTION :{
|
||||||
|
|
@ -159,7 +164,12 @@ void database::processing_sidechain_proposals( const witness_object& current_wit
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sidechain_proposal_type::RETURN_PBTC_BACK :{}
|
case sidechain_proposal_type::REVERT_BTC_TRANSACTION :{
|
||||||
|
bitcoin_transaction_revert_operation op = proposal->proposed_transaction.operations.back().get<bitcoin_transaction_revert_operation>();
|
||||||
|
if( checker.check_bitcoin_transaction_revert_operation( op ) )
|
||||||
|
approve_propose( proposal->id );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,14 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
fc::sha256 transaction_id;
|
fc::sha256 transaction_id;
|
||||||
std::set< fc::sha256 > valid_vins;
|
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 bitcoin_transaction_revert_operation : public base_operation
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ public:
|
||||||
|
|
||||||
bool check_witness_opportunity_to_approve( const witness_object& current_witness, const proposal_object& proposal );
|
bool check_witness_opportunity_to_approve( const witness_object& current_witness, const proposal_object& proposal );
|
||||||
|
|
||||||
|
bool check_bitcoin_transaction_revert_operation( const bitcoin_transaction_revert_operation& op );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool check_info_for_pw_vin( const info_for_vin& info_for_vin );
|
bool check_info_for_pw_vin( const info_for_vin& info_for_vin );
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ enum class sidechain_proposal_type
|
||||||
{
|
{
|
||||||
ISSUE_BTC,
|
ISSUE_BTC,
|
||||||
SEND_BTC_TRANSACTION,
|
SEND_BTC_TRANSACTION,
|
||||||
RETURN_PBTC_BACK
|
REVERT_BTC_TRANSACTION
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prev_out
|
struct prev_out
|
||||||
|
|
@ -56,5 +56,5 @@ struct prev_out
|
||||||
}
|
}
|
||||||
|
|
||||||
FC_REFLECT_ENUM( sidechain::payment_type, (NULLDATA)(P2PK)(P2PKH)(P2SH)(P2WPKH)(P2WSH)(P2SH_WPKH)(P2SH_WSH) );
|
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)(RETURN_PBTC_BACK) );
|
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) );
|
FC_REFLECT( sidechain::prev_out, (hash_tx)(n_vout)(amount) );
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,21 @@ bool sidechain_proposal_checker::check_reuse( const operation& op )
|
||||||
std::vector<fc::sha256> user_vin_identifiers;
|
std::vector<fc::sha256> user_vin_identifiers;
|
||||||
std::vector<info_for_vout_id_type> user_vout_ids;
|
std::vector<info_for_vout_id_type> user_vout_ids;
|
||||||
|
|
||||||
|
auto get_bto_tx_info = [ & ]( fc::sha256 trx_id ) {
|
||||||
|
const auto& bto_itr_idx = db.get_index_type<bitcoin_transaction_index>().indices().get<graphene::chain::by_transaction_id>();
|
||||||
|
const auto& bto_itr = bto_itr_idx.find( trx_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 true;
|
||||||
|
};
|
||||||
|
|
||||||
if( op.which() == operation::tag<bitcoin_transaction_send_operation>::value ) {
|
if( op.which() == operation::tag<bitcoin_transaction_send_operation>::value ) {
|
||||||
bitcoin_transaction_send_operation btc_tx_send_op = op.get<bitcoin_transaction_send_operation>();
|
bitcoin_transaction_send_operation btc_tx_send_op = op.get<bitcoin_transaction_send_operation>();
|
||||||
|
|
||||||
pw_vin_identifier = btc_tx_send_op.pw_vin.identifier;
|
pw_vin_identifier = btc_tx_send_op.pw_vin.identifier;
|
||||||
user_vout_ids = btc_tx_send_op.vouts;
|
user_vout_ids = btc_tx_send_op.vouts;
|
||||||
for( const auto& vin : btc_tx_send_op.vins ) {
|
for( const auto& vin : btc_tx_send_op.vins ) {
|
||||||
|
|
@ -67,17 +79,15 @@ bool sidechain_proposal_checker::check_reuse( const operation& op )
|
||||||
}
|
}
|
||||||
} else if ( op.which() == operation::tag<bitcoin_issue_operation>::value ) {
|
} else if ( op.which() == operation::tag<bitcoin_issue_operation>::value ) {
|
||||||
bitcoin_issue_operation btc_issue_op = op.get<bitcoin_issue_operation>();
|
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 ) {
|
for( const auto& id : btc_issue_op.transaction_ids ) {
|
||||||
const auto& bto_itr = bto_itr_idx.find( id );
|
if ( !get_bto_tx_info( id ) )
|
||||||
if( bto_itr == bto_itr_idx.end() ) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if ( op.which() == operation::tag<bitcoin_transaction_revert_operation>::value ) {
|
||||||
pw_vin_identifier = bto_itr->pw_vin;
|
bitcoin_transaction_revert_operation btc_tx_revert_op = op.get<bitcoin_transaction_revert_operation>();
|
||||||
user_vout_ids = bto_itr->vouts;
|
for( auto trx_info: btc_tx_revert_op.transactions_info ) {
|
||||||
user_vin_identifiers = bto_itr->vins;
|
if ( !get_bto_tx_info( trx_info.transaction_id ) )
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,4 +169,20 @@ bool sidechain_proposal_checker::check_witness_opportunity_to_approve( const wit
|
||||||
return is_active_witness() && does_the_witness_have_authority();
|
return is_active_witness() && does_the_witness_have_authority();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sidechain_proposal_checker::check_bitcoin_transaction_revert_operation( const bitcoin_transaction_revert_operation& op )
|
||||||
|
{
|
||||||
|
const auto& btc_trx_idx = db.get_index_type<bitcoin_transaction_index>().indices().get<by_transaction_id>();
|
||||||
|
|
||||||
|
for( auto trx_info: op.transactions_info )
|
||||||
|
{
|
||||||
|
auto value = db.bitcoin_confirmations.find<sidechain::by_hash>( trx_info.transaction_id );
|
||||||
|
if( !value.valid() ||
|
||||||
|
btc_trx_idx.find( value->transaction_id ) == btc_trx_idx.end() ||
|
||||||
|
trx_info != revert_trx_info( value->transaction_id, value->valid_vins ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !op.transactions_info.empty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <graphene/chain/proposal_object.hpp>
|
#include <graphene/chain/proposal_object.hpp>
|
||||||
#include <graphene/chain/proposal_evaluator.hpp>
|
#include <graphene/chain/proposal_evaluator.hpp>
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
|
#include <graphene/chain/bitcoin_transaction_object.hpp>
|
||||||
|
|
||||||
using namespace sidechain;
|
using namespace sidechain;
|
||||||
|
|
||||||
|
|
@ -244,4 +245,91 @@ BOOST_AUTO_TEST_CASE( not_account_auths_wit_try_to_approve_btc_send_test )
|
||||||
BOOST_CHECK( !checker.check_witness_opportunity_to_approve( *itr, *proposal_idx.begin() ) );
|
BOOST_CHECK( !checker.check_witness_opportunity_to_approve( *itr, *proposal_idx.begin() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_missing_bto( graphene::chain::database& db, uint32_t amount )
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE( amount < 9 );
|
||||||
|
while( amount-- > 0 ) {
|
||||||
|
std::set<fc::sha256> vins { fc::sha256( std::string( 64,'1' + amount ) ), fc::sha256( std::string( 64,'2' + amount ) ) };
|
||||||
|
sidechain::bitcoin_transaction_confirmations btc_trx_conf ( fc::sha256( std::string( 64,'1' + amount ) ), vins );
|
||||||
|
btc_trx_conf.missing = true;
|
||||||
|
db.bitcoin_confirmations.insert( btc_trx_conf );
|
||||||
|
|
||||||
|
db.create<graphene::chain::bitcoin_transaction_object>( [&]( graphene::chain::bitcoin_transaction_object& obj ){
|
||||||
|
obj.transaction_id = fc::sha256( std::string( 64,'1' + amount ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector< revert_trx_info > get_transactions_info( graphene::chain::database& db, uint32_t amount )
|
||||||
|
{
|
||||||
|
using iter_by_missing = btc_tx_confirmations_index::index<by_missing_first>::type::iterator;
|
||||||
|
std::vector< revert_trx_info > transactions_info;
|
||||||
|
const auto& btc_trx_idx = db.get_index_type<graphene::chain::bitcoin_transaction_index>().indices().get<graphene::chain::by_transaction_id>();
|
||||||
|
BOOST_CHECK_EQUAL( btc_trx_idx.size() , amount );
|
||||||
|
|
||||||
|
db.bitcoin_confirmations.safe_for<by_missing_first>([&]( iter_by_missing itr_b, iter_by_missing itr_e ){
|
||||||
|
for(auto iter = itr_b; iter != itr_e; iter++) {
|
||||||
|
if( !iter->missing ) return;
|
||||||
|
const auto& btc_tx = btc_trx_idx.find( iter->transaction_id );
|
||||||
|
if( btc_tx == btc_trx_idx.end() ) continue;
|
||||||
|
transactions_info.push_back( revert_trx_info( iter->transaction_id, iter->valid_vins ) );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return transactions_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( bitcoin_transaction_revert_operation_checker_test )
|
||||||
|
{
|
||||||
|
using namespace graphene::chain;
|
||||||
|
const uint32_t amount = 5;
|
||||||
|
|
||||||
|
create_missing_bto( db, amount );
|
||||||
|
sidechain_proposal_checker checker( db );
|
||||||
|
|
||||||
|
bitcoin_transaction_revert_operation op;
|
||||||
|
|
||||||
|
std::vector< revert_trx_info > transactions_info = get_transactions_info( db, amount );
|
||||||
|
|
||||||
|
op.transactions_info = transactions_info;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( transactions_info.size(), amount );
|
||||||
|
BOOST_CHECK( checker.check_bitcoin_transaction_revert_operation( op ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( bitcoin_transaction_revert_operation_checker_failed_test )
|
||||||
|
{
|
||||||
|
using namespace graphene::chain;
|
||||||
|
const uint32_t amount = 5;
|
||||||
|
|
||||||
|
create_missing_bto( db, amount );
|
||||||
|
|
||||||
|
std::set<fc::sha256> vins { fc::sha256( std::string( 64,'1' + 6 ) ), fc::sha256( std::string( 64,'1' + 8 ) ) };
|
||||||
|
fc::sha256 trx_id( std::string( 64,'1' + 8 ) );
|
||||||
|
sidechain::bitcoin_transaction_confirmations btc_trx_conf ( trx_id, vins );
|
||||||
|
db.bitcoin_confirmations.insert( btc_trx_conf );
|
||||||
|
db.create<graphene::chain::bitcoin_transaction_object>( [&]( graphene::chain::bitcoin_transaction_object& obj ){
|
||||||
|
obj.transaction_id = fc::sha256( std::string( 64,'1' + 7 ) );
|
||||||
|
} );
|
||||||
|
|
||||||
|
sidechain_proposal_checker checker( db );
|
||||||
|
|
||||||
|
bitcoin_transaction_revert_operation op;
|
||||||
|
std::vector< revert_trx_info > transactions_info = get_transactions_info( db, amount + 1 );
|
||||||
|
|
||||||
|
op.transactions_info = transactions_info;
|
||||||
|
op.transactions_info.push_back( revert_trx_info( trx_id, vins) );
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( op.transactions_info.size(), amount + 1 );
|
||||||
|
BOOST_CHECK( !checker.check_bitcoin_transaction_revert_operation( op ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( no_btc_trx_to_revert_test )
|
||||||
|
{
|
||||||
|
sidechain_proposal_checker checker( db );
|
||||||
|
|
||||||
|
bitcoin_transaction_revert_operation op;
|
||||||
|
BOOST_CHECK( !checker.check_bitcoin_transaction_revert_operation( op ) );
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue