Added mechanism create proposal (send_btc_transaction)

This commit is contained in:
Anzhy Cherrnyavski 2019-01-29 15:02:39 +03:00
parent f22d61855b
commit ffc51ba1ea
16 changed files with 210 additions and 69 deletions

View file

@ -26,7 +26,6 @@ object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_trans
bitcoin_transaction_send_operation& mutable_op = const_cast<bitcoin_transaction_send_operation&>( op );
database& d = db();
std::vector< info_for_used_vin_id_type > new_vins;
sidechain::prev_out new_pw_vout = { "", 0, 0 };
sidechain::bytes wit_script;
finalize_bitcoin_transaction( mutable_op );
@ -53,6 +52,7 @@ object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_trans
obj.confirm = false;
});
sidechain::prev_out new_pw_vout = { "", 0, 0 };
if( btc_tx.transaction.vout[0].is_p2wsh() && btc_tx.transaction.vout[0].scriptPubKey == wit_script )
new_pw_vout = { btc_tx.transaction.get_txid(), 0, btc_tx.transaction.vout[0].value };

View file

@ -409,6 +409,13 @@ signed_block database::_generate_block(
_pending_tx_session.reset();
_pending_tx_session = _undo_db.start_undo_session();
if( !is_sidechain_fork_needed() ) {
auto op = create_send_btc_tx_proposal( witness_obj );
if( op.valid() ) {
_pending_tx.insert( _pending_tx.begin(), create_signed_transaction( block_signing_private_key, *op ) );
}
}
uint64_t postponed_tx_count = 0;
// pop pending state (reset to head block state)
for( const processed_transaction& tx : _pending_tx )

View file

@ -42,6 +42,7 @@ database::database() :
initialize_evaluators();
context_sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
estimated_feerate = 0;
}
database::~database()

View file

@ -1,5 +1,11 @@
#include <graphene/chain/database.hpp>
#include <graphene/chain/bitcoin_address_object.hpp>
#include <graphene/chain/sidechain_proposal_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <sidechain/sidechain_condensing_tx.hpp>
#include <graphene/chain/protocol/asset.hpp>
using namespace sidechain;
namespace graphene { namespace chain {
@ -77,9 +83,11 @@ void database::perform_sidechain_fork()
pw.owner = sidechain_account.get_id();
pw.count_invalid_pub_key = 1;
});
pw_vout_manager.create_new_vout( {"", 0, 0 } );
}
const sidechain::sidechain_parameters_extension& database::get_sidechain_params() const
const sidechain_parameters_extension& database::get_sidechain_params() const
{
const auto& params = get_global_properties().parameters.extensions.value.sidechain_parameters;
FC_ASSERT( params.valid() );
@ -103,5 +111,102 @@ bitcoin_address_object database::get_latest_PW() const
return *(--itr);
}
int64_t database::get_estimated_fee( size_t tx_vsize, uint64_t estimated_feerate ) {
static const uint64_t default_feerate = 1000;
static const uint64_t min_relay_fee = 1000;
const auto feerate = std::max( default_feerate, estimated_feerate );
const auto fee = feerate * int64_t( tx_vsize ) / 1000;
return std::max( min_relay_fee, fee );
}
void database::processing_sidechain_proposals( const witness_object& current_witness, const fc::ecc::private_key& private_key )
{
const auto& sidechain_proposal_idx = get_index_type<sidechain_proposal_index>().indices().get< by_id >();
const auto& proposal_idx = get_index_type<proposal_index>().indices().get< by_id >();
for( auto& sidechain_proposal : sidechain_proposal_idx ) {
const auto& proposal = proposal_idx.find( sidechain_proposal.proposal_id );
FC_ASSERT( proposal != proposal_idx.end() );
switch( sidechain_proposal.proposal_type ) {
case sidechain_proposal_type::ISSUE_PBTC :{}
case sidechain_proposal_type::SEND_BTC_TRANSACTION :{}
case sidechain_proposal_type::WITHDRAW_PBTC :{}
case sidechain_proposal_type::RETURN_PBTC_BACK :{}
}
}
}
full_btc_transaction database::create_btc_transaction( const std::vector<info_for_vin>& info_vins,
const std::vector<info_for_vout>& info_vouts,
const fc::optional<info_for_vin>& info_pw_vin )
{
sidechain_condensing_tx ctx( info_vins, info_vouts );
if( info_pw_vin->identifier != SIDECHAIN_NULL_HASH ) {
ctx.create_pw_vin( *info_pw_vin );
}
const auto& pw_address = get_latest_PW().address;
if( info_vouts.size() > 0 ) {
ctx.create_vouts_for_witness_fee( pw_address.witnesses_keys );
}
const uint64_t& change = ctx.get_amount_vins() - ctx.get_amount_transfer_to_bitcoin();
if( change > 0 ) {
ctx.create_pw_vout( change, pw_address.get_witness_script() );
}
const uint64_t& size_fee = get_estimated_fee( ctx.get_estimate_tx_size( pw_address.witnesses_keys.size() ), estimated_feerate.load() );
ctx.subtract_fee( size_fee, SIDECHAIN_DEFAULT_PERCENTAGE_PAYMENT_TO_WIT );
return std::make_pair( ctx.get_transaction(), size_fee );
}
fc::optional<operation> database::create_send_btc_tx_proposal( const witness_object& current_witness )
{
const auto& info_vins = i_w_info.get_info_for_vins();
const auto& info_vouts = i_w_info.get_info_for_vouts();
const auto& info_pw_vin = i_w_info.get_info_for_pw_vin();
if( info_pw_vin.valid() && ( info_vins.size() || info_vouts.size() ) ) {
const auto& btc_tx_and_size_fee = create_btc_transaction( info_vins, info_vouts, info_pw_vin );
bitcoin_transaction_send_operation btc_send_op;
btc_send_op.payer = get_sidechain_account_id();
btc_send_op.pw_vin = info_pw_vin->identifier != SIDECHAIN_NULL_HASH ? info_pw_vin->identifier : fc::optional< fc::sha256 >();
btc_send_op.vins = info_vins;
for( auto& out : info_vouts ) {
btc_send_op.vouts.push_back( out.get_id() );
}
btc_send_op.transaction = btc_tx_and_size_fee.first;
btc_send_op.fee_for_size = btc_tx_and_size_fee.second;
proposal_create_operation proposal_op;
proposal_op.fee_paying_account = current_witness.witness_account;
proposal_op.proposed_ops.push_back( op_wrapper( btc_send_op ) );
uint32_t lifetime = ( get_global_properties().parameters.block_interval * get_global_properties().active_witnesses.size() ) * 3;
proposal_op.expiration_time = time_point_sec( head_block_time().sec_since_epoch() + lifetime );
return proposal_op;
}
return fc::optional<operation>();
}
signed_transaction database::create_signed_transaction( const private_key& signing_private_key, const operation& op )
{
signed_transaction processed_trx;
auto dyn_props = get_dynamic_global_properties();
processed_trx.set_reference_block( dyn_props.head_block_id );
processed_trx.set_expiration( head_block_time() + get_global_properties().parameters.maximum_time_until_expiration );
processed_trx.operations.push_back( op );
current_fee_schedule().set_fee( processed_trx.operations.back() );
processed_trx.sign( signing_private_key, get_chain_id() );
return processed_trx;
}
} }

View file

@ -236,4 +236,6 @@
#define SIDECHAIN_DEFAULT_NUMBER_SIG_MULTISIG 5
#define SIDECHAIN_DEFAULT_CONDENSING_TX_VINS_NUMBER 5
#define SIDECHAIN_DEFAULT_CONDENSING_TX_VOUTS_NUMBER 5
#define SIDECHAIN_DEFAULT_PERCENTAGE_PAYMENT_TO_WIT 0.001
#define SIDECHAIN_NULL_HASH fc::sha256( "5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9" ) // fc::sha256::hash( "" + std::to_string( 0 ) );
//////////////////////////////////////////////////////////////////////

View file

@ -42,12 +42,15 @@
#include <sidechain/input_withdrawal_info.hpp>
#include <sidechain/primary_wallet_vout_manager.hpp>
#include <atomic>
#include <fc/log/logger.hpp>
#include <map>
#include <secp256k1.h>
using namespace fc::ecc;
namespace graphene { namespace chain {
using graphene::db::abstract_object;
using graphene::db::object;
@ -520,13 +523,24 @@ namespace graphene { namespace chain {
const sidechain::sidechain_parameters_extension& get_sidechain_params() const;
const account_id_type& get_sidechain_account_id() const;
const asset_id_type& get_sidechain_asset_id() const;
int64_t get_estimated_fee( size_t tx_vsize, uint64_t estimated_feerate );
void processing_sidechain_proposals( const witness_object& current_witness, const private_key& signing_private_key );
sidechain::full_btc_transaction create_btc_transaction( const std::vector<sidechain::info_for_vin>& info_vins,
const std::vector<sidechain::info_for_vout>& info_vouts,
const fc::optional<sidechain::info_for_vin>& info_pw_vin );
fc::optional<operation> create_send_btc_tx_proposal( const witness_object& current_witness );
signed_transaction create_signed_transaction( const private_key& signing_private_key, const operation& op );
fc::signal<void( const sidechain::bitcoin_transaction& )> send_btc_tx;
sidechain::input_withdrawal_info i_w_info;
sidechain::primary_wallet_vout_manager pw_vout_manager;
fc::signal<void( const sidechain::bitcoin_transaction& )> send_btc_tx;
std::atomic<uint64_t> estimated_feerate;
secp256k1_context_t* context_sign;

View file

@ -35,13 +35,14 @@ namespace graphene { namespace chain {
public:
typedef void result_type;
database& db;
proposal_id_type prop_id;
sidechain_hardfork_visitor( database& _db ) : db(_db) {}
sidechain_hardfork_visitor( database& _db, const proposal_id_type& _prop_id ) : db( _db ), prop_id( _prop_id ) {}
template<typename T>
void operator()( const T &v, const proposal_id_type prop_id ) const {}
void operator()( const T &v ) const {}
void operator()( const bitcoin_transaction_send_operation &v, const proposal_id_type prop_id );
void operator()( const bitcoin_transaction_send_operation &v );
};
class proposal_create_evaluator : public evaluator<proposal_create_evaluator>

View file

@ -143,7 +143,7 @@ struct proposal_operation_hardfork_visitor
}
};
void sidechain_hardfork_visitor::operator()( const bitcoin_transaction_send_operation &v, const proposal_id_type prop_id )
void sidechain_hardfork_visitor::operator()( const bitcoin_transaction_send_operation &v )
{
db.create<sidechain_proposal_object>([&]( sidechain_proposal_object& sch_prop ) {
sch_prop.proposal_type = sidechain::sidechain_proposal_type::SEND_BTC_TRANSACTION;
@ -163,7 +163,7 @@ void sidechain_hardfork_visitor::operator()( const bitcoin_transaction_send_oper
db.i_w_info.mark_as_used_vout( *itr.second );
}
fc::sha256 hashid = fc::sha256::hash(v.transaction.vin[0].prevout.hash.str() + std::to_string(v.transaction.vin[0].prevout.n));
fc::sha256 hashid = v.pw_vin.valid() ? *v.pw_vin : SIDECHAIN_NULL_HASH;
db.pw_vout_manager.use_latest_vout( hashid );
}
@ -227,7 +227,6 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
object_id_type proposal_create_evaluator::do_apply(const proposal_create_operation& o)
{ try {
database& d = db();
sidechain_hardfork_visitor sidechain_vtor( d );
const proposal_object& proposal = d.create<proposal_object>([&](proposal_object& proposal) {
_proposed_trx.expiration = o.expiration_time;
@ -252,7 +251,9 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
std::inserter(proposal.required_active_approvals, proposal.required_active_approvals.begin()));
});
sidechain_vtor( o.proposed_ops[0].op, proposal.id );
sidechain_hardfork_visitor sidechain_vtor( d , proposal.id );
o.proposed_ops[0].op.visit( sidechain_vtor );
return proposal.id;
} FC_CAPTURE_AND_RETHROW( (o) ) }

View file

@ -67,6 +67,9 @@ public:
input_withdrawal_info( graphene::chain::database& _db ) : db( _db ) {}
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() );
void modify_info_for_vin( const info_for_vin& obj, const std::function<void( info_for_vin& e )>& func );

View file

@ -6,6 +6,9 @@
namespace graphene { namespace chain { class database; } }
using graphene::chain::primary_wallet_vout_object;
using graphene::chain::primary_wallet_vout_id_type;
namespace sidechain {
class primary_wallet_vout_manager
@ -16,9 +19,9 @@ public:
bool is_reach_max_unconfirmaed_vout() const;
fc::optional< graphene::chain::primary_wallet_vout_object > get_latest_unused_vout() const;
fc::optional< primary_wallet_vout_object > get_latest_unused_vout() const;
fc::optional< graphene::chain::primary_wallet_vout_object > get_vout( fc::sha256 hash_id ) const;
fc::optional< primary_wallet_vout_object > get_vout( fc::sha256 hash_id ) const;
void create_new_vout( const sidechain::prev_out& out );
@ -30,7 +33,7 @@ public:
private:
fc::optional< graphene::chain::primary_wallet_vout_id_type > get_vout_id( fc::sha256 hash_id ) const;
fc::optional< primary_wallet_vout_id_type > get_vout_id( fc::sha256 hash_id ) const;
graphene::chain::database& db;

View file

@ -6,26 +6,6 @@ using namespace sidechain;
namespace sidechain {
// void example()
// {
// std::vector<info_for_vin> vin_infos { ... };
// std::vector<info_for_vout> vout_infos { ... };
// sidechain_condensing_tx sct( vin_infos, vout_infos );
// if( pw_vin_info ) {
// sct.create_pw_vin( pw_vin_info );
// }
// if( vout_infos.size() ) {
// sct.create_vouts_for_witness_fee( keys );
// }
// if( ( vin_infos.sum() - vout_infos.sum() ) > 0 ) {
// sct.create_pw_vout( vin_infos.sum() - vout_infos.sum(), bytes{ 0x0d, 0x0d, 0x0d } );
// }
// }
class sidechain_condensing_tx
{
@ -33,11 +13,11 @@ public:
sidechain_condensing_tx( const std::vector<info_for_vin>& vin_info, const std::vector<info_for_vout>& vout_info );
void create_pw_vin( const info_for_vin& vin_info );
void create_pw_vin( const info_for_vin& vin_info, bool front = true );
void create_pw_vout( const uint64_t amount, const bytes& wit_script_out );
void create_pw_vout( const uint64_t amount, const bytes& wit_script_out, bool front = true );
void create_vouts_for_witness_fee( const accounts_keys& witness_active_keys );
void create_vouts_for_witness_fee( const accounts_keys& witness_active_keys, bool front = true );
uint64_t get_estimate_tx_size( size_t number_witness ) const;
@ -69,6 +49,4 @@ private:
};
int64_t get_estimated_fee( size_t tx_vsize, uint64_t estimated_feerate ); // move db_sidechain
}

View file

@ -9,9 +9,12 @@
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
{

View file

@ -1,5 +1,7 @@
#include <sidechain/input_withdrawal_info.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/primary_wallet_vout_object.hpp>
#include <graphene/chain/bitcoin_address_object.hpp>
namespace sidechain {
@ -13,6 +15,24 @@ bool info_for_vin::comparer::operator() ( const info_for_vin& lhs, const info_fo
return lhs.id < rhs.id;
}
fc::optional<info_for_vin> input_withdrawal_info::get_info_for_pw_vin()
{
fc::optional< primary_wallet_vout_object > vout = db.pw_vout_manager.get_latest_unused_vout();
if( !vout.valid() ) {
return fc::optional<info_for_vin>();
}
const auto& pw_address = db.get_latest_PW().address;
info_for_vin vin;
vin.identifier = vout->hash_id;
vin.out = vout->vout;
vin.address = pw_address.get_address();
vin.script = pw_address.get_witness_script();
return vin;
}
void input_withdrawal_info::insert_info_for_vin( const prev_out& out, const std::string& address, bytes script )
{
info_for_vins.insert( info_for_vin( out, address, script ) );
@ -44,6 +64,8 @@ std::vector<info_for_vin> input_withdrawal_info::get_info_for_vins()
{
std::vector<info_for_vin> result;
const auto& addr_idx = db.get_index_type<bitcoin_address_index>().indices().get<by_address>();
info_for_vins.safe_for<by_id_and_not_created>( [&]( info_for_vin_index::index<by_id_and_not_created>::type::iterator itr_b,
info_for_vin_index::index<by_id_and_not_created>::type::iterator itr_e )
{
@ -55,7 +77,9 @@ std::vector<info_for_vin> input_withdrawal_info::get_info_for_vins()
vin.out.n_vout = itr_b->out.n_vout;
vin.out.amount = itr_b->out.amount;
vin.address = itr_b->address;
// vin.script = get account address, from the address get the script
const auto& address_itr = addr_idx.find( itr_b->address );
FC_ASSERT( address_itr != addr_idx.end() );
vin.script = address_itr->address.get_witness_script();
result.push_back( vin );
++itr_b;

View file

@ -9,6 +9,8 @@
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <graphene/chain/bitcoin_address_object.hpp>
namespace sidechain {
sidechain_net_manager::sidechain_net_manager( graphene::chain::database* _db, std::string _ip,
@ -56,6 +58,8 @@ std::vector<info_for_vin> sidechain_net_manager::extract_info_from_block( const
std::vector<info_for_vin> result;
const auto& addr_idx = db->get_index_type<bitcoin_address_index>().indices().get<by_address>();
for (const auto& tx_child : block.get_child("tx")) {
const auto& tx = tx_child.second;
@ -67,7 +71,7 @@ std::vector<info_for_vin> sidechain_net_manager::extract_info_from_block( const
for (const auto& addr : script.get_child("addresses")) { // in which cases there can be more addresses?
const auto address_base58 = addr.second.get_value<std::string>();
// if( !test.count( address_base58 ) ) continue; // there is such an address in graphene
if( !addr_idx.count( address_base58 ) ) continue;
info_for_vin vin;
vin.out.hash_tx = tx.get_child("txid").get_value<std::string>();

View file

@ -12,7 +12,7 @@ bool primary_wallet_vout_manager::is_reach_max_unconfirmaed_vout() const
return !( PW_vout_idx.size() < SIDECHAIN_DEFAULT_NUMBER_UNCONFIRMED_VINS );
}
fc::optional< graphene::chain::primary_wallet_vout_object > primary_wallet_vout_manager::get_latest_unused_vout() const
fc::optional< primary_wallet_vout_object > primary_wallet_vout_manager::get_latest_unused_vout() const
{
const auto& PW_vout_idx = db.get_index_type<graphene::chain::primary_wallet_vout_index>().indices().get< graphene::chain::by_id >();
auto itr = PW_vout_idx.end();
@ -20,22 +20,22 @@ fc::optional< graphene::chain::primary_wallet_vout_object > primary_wallet_vout_
itr--;
if( itr->used )
return fc::optional< graphene::chain::primary_wallet_vout_object >();
return fc::optional< graphene::chain::primary_wallet_vout_object > (*itr);
return fc::optional< primary_wallet_vout_object >();
return fc::optional< primary_wallet_vout_object > (*itr);
}
fc::optional< graphene::chain::primary_wallet_vout_object > primary_wallet_vout_manager::get_vout( fc::sha256 hash_id ) const
fc::optional< primary_wallet_vout_object > primary_wallet_vout_manager::get_vout( fc::sha256 hash_id ) const
{
const auto& PW_vout_by_hash_id = db.get_index_type<graphene::chain::primary_wallet_vout_index>().indices().get< graphene::chain::by_hash_id >();
const auto& itr_hash_id = PW_vout_by_hash_id.find( hash_id );
if( itr_hash_id == PW_vout_by_hash_id.end() )
return fc::optional< graphene::chain::primary_wallet_vout_object >();
return fc::optional< graphene::chain::primary_wallet_vout_object >( *itr_hash_id );
return fc::optional< primary_wallet_vout_object >();
return fc::optional< primary_wallet_vout_object >( *itr_hash_id );
}
void primary_wallet_vout_manager::create_new_vout( const sidechain::prev_out& out )
{
db.create<graphene::chain::primary_wallet_vout_object>([&]( graphene::chain::primary_wallet_vout_object& obj ) {
db.create<primary_wallet_vout_object>([&]( primary_wallet_vout_object& obj ) {
obj.vout = out;
obj.hash_id = fc::sha256::hash( out.hash_tx + std::to_string( out.n_vout ) );
obj.confirmed = false;
@ -68,7 +68,7 @@ void primary_wallet_vout_manager::confirm_vout( fc::sha256 hash_id )
auto itr = PW_vout_by_id.find( *vout_id );
db.modify(*itr, [&]( graphene::chain::primary_wallet_vout_object& PW_vout ) {
db.modify(*itr, [&]( primary_wallet_vout_object& PW_vout ) {
PW_vout.confirmed = true;
});
@ -87,7 +87,7 @@ void primary_wallet_vout_manager::use_latest_vout( fc::sha256 hash_id )
auto itr = PW_vout_by_id.find( *vout_id );
db.modify(*itr, [&]( graphene::chain::primary_wallet_vout_object& PW_vout ) {
db.modify(*itr, [&]( primary_wallet_vout_object& PW_vout ) {
PW_vout.used = true;
});

View file

@ -8,18 +8,18 @@ sidechain_condensing_tx::sidechain_condensing_tx( const std::vector<info_for_vin
create_vouts_for_condensing_tx( vout_info );
}
void sidechain_condensing_tx::create_pw_vin( const info_for_vin& vin_info )
void sidechain_condensing_tx::create_pw_vin( const info_for_vin& vin_info, bool front )
{
bytes witness_script_temp = {0x22};
witness_script_temp.insert( witness_script_temp.end(), vin_info.script.begin(), vin_info.script.end() );
tb.add_in( payment_type::P2WSH, fc::sha256( vin_info.out.hash_tx ), vin_info.out.n_vout, witness_script_temp, true );
tb.add_in( payment_type::P2WSH, fc::sha256( vin_info.out.hash_tx ), vin_info.out.n_vout, witness_script_temp, front );
amount_vins += vin_info.out.amount;
}
void sidechain_condensing_tx::create_pw_vout( const uint64_t amount, const bytes& wit_script_out )
void sidechain_condensing_tx::create_pw_vout( const uint64_t amount, const bytes& wit_script_out, bool front )
{
tb.add_out( payment_type::P2WSH, amount, bytes(wit_script_out.begin() + 2, wit_script_out.end()), true );
tb.add_out( payment_type::P2WSH, amount, bytes(wit_script_out.begin() + 2, wit_script_out.end()), front );
}
void sidechain_condensing_tx::create_vins_for_condensing_tx( const std::vector<info_for_vin>& vin_info )
@ -42,10 +42,10 @@ void sidechain_condensing_tx::create_vouts_for_condensing_tx( const std::vector<
}
}
void sidechain_condensing_tx::create_vouts_for_witness_fee( const accounts_keys& witness_active_keys )
void sidechain_condensing_tx::create_vouts_for_witness_fee( const accounts_keys& witness_active_keys, bool front )
{
for( auto& key : witness_active_keys ) {
tb.add_out( payment_type::P2PK, 0, key.second, true );
tb.add_out( payment_type::P2PK, 0, key.second, front );
count_witness_vout++;
}
}
@ -77,8 +77,13 @@ void sidechain_condensing_tx::subtract_fee( const uint64_t& fee, const double& w
fee_size += 1;
}
bool is_pw_vin = tx.vout.size() > ( count_witness_vout + count_transfer_vout );
if( is_pw_vin ) {
tx.vout[0].value = tx.vout[0].value - fee_size;
}
uint64_t fee_witnesses = 0;
size_t offset = tx.vout.size() > ( count_witness_vout + count_transfer_vout ) ? 1 + count_witness_vout : count_witness_vout;
size_t offset = is_pw_vin ? 1 + count_witness_vout : count_witness_vout;
for( ; offset < tx.vout.size(); offset++ ) {
uint64_t amount_without_fee_size = tx.vout[offset].value - fee_size;
uint64_t amount_fee_witness = amount_without_fee_size * witness_percentage;
@ -89,10 +94,10 @@ void sidechain_condensing_tx::subtract_fee( const uint64_t& fee, const double& w
if( count_witness_vout > 0 ) {
uint64_t fee_witness = fee_witnesses / count_witness_vout;
size_t limit = tx.vout.size() > ( count_witness_vout + count_transfer_vout ) ? 1 + count_witness_vout : count_witness_vout;
offset = tx.vout.size() > ( count_witness_vout + count_transfer_vout ) ? 1 : 0;
size_t limit = is_pw_vin ? 1 + count_witness_vout : count_witness_vout;
size_t offset = is_pw_vin ? 1 : 0;
FC_ASSERT( fee_witness > 0 );
for( ; offset < limit; offset++ ) {
for( offset = 0; offset < limit; offset++ ) {
tx.vout[offset].value += fee_witness;
}
}
@ -100,14 +105,4 @@ void sidechain_condensing_tx::subtract_fee( const uint64_t& fee, const double& w
tb = std::move( bitcoin_transaction_builder( tx ) );
}
int64_t get_estimated_fee( size_t tx_vsize, uint64_t estimated_feerate ) {
static const uint64_t default_feerate = 1000;
static const uint64_t min_relay_fee = 1000;
const auto feerate = std::max( default_feerate, estimated_feerate );
const auto fee = feerate * int64_t( tx_vsize ) / 1000;
return std::max( min_relay_fee, fee );
}
}