Added sign_btc_transaction_operation and sign_btc_transaction_evaluator
This commit is contained in:
parent
6babaf2c6a
commit
df264442da
11 changed files with 390 additions and 25 deletions
|
|
@ -294,6 +294,10 @@ struct get_impacted_account_visitor
|
|||
{
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const bitcoin_transaction_sign_operation& op )
|
||||
{
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
};
|
||||
|
||||
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||
|
|
|
|||
|
|
@ -3,11 +3,18 @@
|
|||
#include <graphene/chain/exceptions.hpp>
|
||||
#include <graphene/chain/bitcoin_transaction_object.hpp>
|
||||
#include <graphene/chain/info_for_used_vin_object.hpp>
|
||||
#include <graphene/chain/sidechain_proposal_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
|
||||
#include <sidechain/sign_bitcoin_transaction.hpp>
|
||||
#include <sidechain/input_withdrawal_info.hpp>
|
||||
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
using namespace sidechain;
|
||||
|
||||
void_result bitcoin_transaction_send_evaluator::do_evaluate( const bitcoin_transaction_send_operation& op )
|
||||
{
|
||||
// FC_ASSERT( db().get_sidechain_account_id() == op.payer );
|
||||
|
|
@ -77,4 +84,104 @@ void bitcoin_transaction_send_evaluator::send_bitcoin_transaction( const bitcoin
|
|||
}
|
||||
}
|
||||
|
||||
void_result bitcoin_transaction_sign_evaluator::do_evaluate( const bitcoin_transaction_sign_operation& op )
|
||||
{
|
||||
database& d = db();
|
||||
|
||||
const auto& sidechain_proposal_idx = d.get_index_type<sidechain_proposal_index>().indices().get<by_id>();
|
||||
const auto& sidechain_proposal_itr = sidechain_proposal_idx.find( op.sidechain_proposal_id );
|
||||
FC_ASSERT( sidechain_proposal_idx.end() != sidechain_proposal_itr,
|
||||
"sidechain_proposal not found");
|
||||
|
||||
witness_id_type scheduled_witness = d.get_scheduled_witness( 1 );
|
||||
const auto& witness_obj = d.get< witness_object >( scheduled_witness );
|
||||
FC_ASSERT( witness_obj.witness_account == op.payer, "Incorrect witness." );
|
||||
|
||||
sidechain::bytes public_key( public_key_data_to_bytes( witness_obj.signing_key.key_data ) );
|
||||
const auto& proposal = sidechain_proposal_itr->proposal_id( d );
|
||||
auto btc_send_op = proposal.proposed_transaction.operations[0].get<bitcoin_transaction_send_operation>();
|
||||
FC_ASSERT( check_sigs( public_key, op.signatures, btc_send_op.vins, btc_send_op.transaction ) ); // Add pw_vin
|
||||
|
||||
// const auto& proposal = sidechain_proposal_itr->proposal_id( d );
|
||||
// FC_ASSERT( d.check_witness( witness_obj, *btc_tx, proposal ), "Can't sign this transaction" );
|
||||
|
||||
return void_result();
|
||||
}
|
||||
|
||||
void_result bitcoin_transaction_sign_evaluator::do_apply( const bitcoin_transaction_sign_operation& op )
|
||||
{
|
||||
database& d = db();
|
||||
|
||||
const auto& sidechain_proposal = op.sidechain_proposal_id( d );
|
||||
const auto& proposal = sidechain_proposal.proposal_id( d );
|
||||
|
||||
d.modify( proposal, [&]( proposal_object& po ) {
|
||||
auto bitcoin_transaction_send_op = po.proposed_transaction.operations[0].get<bitcoin_transaction_send_operation>();
|
||||
for( size_t i = 0; i < op.signatures.size(); i++ ) {
|
||||
bitcoin_transaction_send_op.transaction.vin[i].scriptWitness.push_back( op.signatures[i] );
|
||||
}
|
||||
po.proposed_transaction.operations[0] = bitcoin_transaction_send_op;
|
||||
});
|
||||
|
||||
update_proposal( op );
|
||||
|
||||
return void_result();
|
||||
}
|
||||
|
||||
void bitcoin_transaction_sign_evaluator::update_proposal( const bitcoin_transaction_sign_operation& op )
|
||||
{
|
||||
database& d = db();
|
||||
proposal_update_operation update_op;
|
||||
|
||||
update_op.fee_paying_account = op.payer;
|
||||
update_op.proposal = op.sidechain_proposal_id( d ).proposal_id;
|
||||
update_op.active_approvals_to_add = { op.payer };
|
||||
|
||||
bool skip_fee_old = trx_state->skip_fee;
|
||||
bool skip_fee_schedule_check_old = trx_state->skip_fee_schedule_check;
|
||||
trx_state->skip_fee = true;
|
||||
trx_state->skip_fee_schedule_check = true;
|
||||
|
||||
d.apply_operation( *trx_state, update_op );
|
||||
|
||||
trx_state->skip_fee = skip_fee_old;
|
||||
trx_state->skip_fee_schedule_check = skip_fee_schedule_check_old;
|
||||
}
|
||||
|
||||
bool bitcoin_transaction_sign_evaluator::check_sigs( const bytes& key_data, const std::vector<bytes>& sigs,
|
||||
const std::vector<sidechain::info_for_vin>& info_for_vins,
|
||||
const bitcoin_transaction& tx )
|
||||
{
|
||||
FC_ASSERT( sigs.size() == info_for_vins.size() && sigs.size() == tx.vin.size() );
|
||||
|
||||
for( size_t i = 0; i < tx.vin.size(); i++ ) {
|
||||
const bytes& script = info_for_vins[i].script;
|
||||
const auto& sighash_str = get_signature_hash( tx, script, static_cast<int64_t>( info_for_vins[i].out.amount ), i, 1, true ).str();
|
||||
const bytes& sighash_hex = parse_hex( sighash_str );
|
||||
|
||||
if( !verify_sig( sigs[i], key_data, sighash_hex, db().context_verify ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t count_sigs = 0;
|
||||
for( auto& s : tx.vin[i].scriptWitness ) {
|
||||
if( verify_sig( s, key_data, sighash_hex, db().context_verify ) ) {
|
||||
count_sigs++;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<bytes> pubkeys = get_pubkey_from_redeemScript( script );
|
||||
size_t count_pubkeys = std::count( pubkeys.begin(), pubkeys.end(), key_data );
|
||||
if( count_sigs >= count_pubkeys ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t position = std::find( op_num.begin(), op_num.end(), script[0] ) - op_num.begin();
|
||||
if( !( position >= 0 && position < op_num.size() ) || tx.vin[i].scriptWitness.size() == position + 1 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -250,6 +250,7 @@ void database::initialize_evaluators()
|
|||
register_evaluator<withdraw_pbtc_evaluator>();
|
||||
register_evaluator<bitcoin_address_create_evaluator>();
|
||||
register_evaluator<bitcoin_transaction_send_evaluator>();
|
||||
register_evaluator<bitcoin_transaction_sign_evaluator>();
|
||||
}
|
||||
|
||||
void database::initialize_indexes()
|
||||
|
|
|
|||
|
|
@ -281,6 +281,10 @@ struct get_impacted_account_visitor
|
|||
{
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const bitcoin_transaction_sign_operation& op )
|
||||
{
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
};
|
||||
|
||||
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
|
||||
namespace sidechain { class info_for_vin; }
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class bitcoin_transaction_send_evaluator : public evaluator<bitcoin_transaction_send_evaluator>
|
||||
|
|
@ -18,4 +20,22 @@ public:
|
|||
void send_bitcoin_transaction( const bitcoin_transaction_object& btc_tx );
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
class bitcoin_transaction_sign_evaluator : public evaluator<bitcoin_transaction_sign_evaluator>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef bitcoin_transaction_sign_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const bitcoin_transaction_sign_operation& op );
|
||||
|
||||
void_result do_apply( const bitcoin_transaction_sign_operation& op );
|
||||
|
||||
void update_proposal( const bitcoin_transaction_sign_operation& op );
|
||||
|
||||
bool check_sigs( const sidechain::bytes& key_data, const std::vector<sidechain::bytes>& sigs,
|
||||
const std::vector<sidechain::info_for_vin>& info_for_vins, const sidechain::bitcoin_transaction& tx );
|
||||
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -31,7 +31,28 @@ namespace graphene { namespace chain {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
sidechain_proposal_id_type sidechain_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; }
|
||||
};
|
||||
|
||||
} } // 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)(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)(sidechain_proposal_id)(signatures) )
|
||||
|
|
|
|||
|
|
@ -135,7 +135,8 @@ namespace graphene { namespace chain {
|
|||
affiliate_referral_payout_operation, // VIRTUAL
|
||||
withdraw_pbtc_operation,
|
||||
bitcoin_address_create_operation,
|
||||
bitcoin_transaction_send_operation
|
||||
bitcoin_transaction_send_operation,
|
||||
bitcoin_transaction_sign_operation
|
||||
> operation;
|
||||
|
||||
/// @} // operations group
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <sidechain/types.hpp>
|
||||
#include <sidechain/utils.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <sidechain/types.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
|
||||
namespace sidechain {
|
||||
|
||||
|
|
@ -9,4 +10,6 @@ bytes parse_hex( const std::string& str );
|
|||
|
||||
std::vector<bytes> get_pubkey_from_redeemScript( bytes script );
|
||||
|
||||
bytes public_key_data_to_bytes( const fc::ecc::public_key_data& key );
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,4 +24,12 @@ std::vector<bytes> get_pubkey_from_redeemScript( bytes script )
|
|||
return result;
|
||||
}
|
||||
|
||||
bytes public_key_data_to_bytes( const fc::ecc::public_key_data& key )
|
||||
{
|
||||
bytes result;
|
||||
result.resize( key.size() );
|
||||
std::copy( key.begin(), key.end(), result.begin() );
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue