Compare commits

...

2 commits

Author SHA1 Message Date
satyakoneru
62f621c00a fix tests 2020-05-07 19:46:25 +00:00
Koneru Satyanarayana
501495d995 Deposit address enhancements 2020-05-07 19:51:55 +10:00
15 changed files with 248 additions and 169 deletions

View file

@ -1938,7 +1938,8 @@ vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addr
const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_account>().equal_range(account); const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_account>().equal_range(account);
std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second, std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second,
[&result] (const sidechain_address_object& sao) { [&result] (const sidechain_address_object& sao) {
result.push_back(sao); if( sao.expires == time_point_sec::maximum() )
result.push_back(sao);
}); });
return result; return result;
} }
@ -1954,7 +1955,8 @@ vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addr
const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_sidechain>().equal_range(sidechain); const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_sidechain>().equal_range(sidechain);
std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second, std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second,
[&result] (const sidechain_address_object& sao) { [&result] (const sidechain_address_object& sao) {
result.push_back(sao); if( sao.expires == time_point_sec::maximum() )
result.push_back(sao);
}); });
return result; return result;
} }
@ -1966,8 +1968,8 @@ fc::optional<sidechain_address_object> database_api::get_sidechain_address_by_ac
fc::optional<sidechain_address_object> database_api_impl::get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain)const fc::optional<sidechain_address_object> database_api_impl::get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain)const
{ {
const auto& idx = _db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& idx = _db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
auto itr = idx.find( boost::make_tuple( account, sidechain ) ); auto itr = idx.find( boost::make_tuple( account, sidechain, time_point_sec::maximum() ) );
if( itr != idx.end() ) if( itr != idx.end() )
return *itr; return *itr;
return {}; return {};

View file

@ -240,6 +240,28 @@ bool database::is_son_dereg_valid( son_id_type son_id )
(head_block_time() - son->statistics(*this).last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time()))); (head_block_time() - son->statistics(*this).last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time())));
} }
bool database::is_son_active( son_id_type son_id )
{
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
auto son = son_idx.find( son_id );
if(son == son_idx.end())
{
return false;
}
const global_property_object& gpo = get_global_properties();
vector<son_id_type> active_son_ids;
active_son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(active_son_ids, active_son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
auto it_son = std::find(active_son_ids.begin(), active_son_ids.end(), son_id);
return (it_son != active_son_ids.end());
}
const account_statistics_object& database::get_account_stats_by_owner( account_id_type owner )const const account_statistics_object& database::get_account_stats_by_owner( account_id_type owner )const
{ {
auto& idx = get_index_type<account_stats_index>().indices().get<by_owner>(); auto& idx = get_index_type<account_stats_index>().indices().get<by_owner>();

View file

@ -307,6 +307,7 @@ namespace graphene { namespace chain {
fc::optional<operation> create_son_deregister_proposal( son_id_type son_id, account_id_type paying_son ); fc::optional<operation> create_son_deregister_proposal( son_id_type son_id, account_id_type paying_son );
signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op ); signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op );
bool is_son_dereg_valid( son_id_type son_id ); bool is_son_dereg_valid( son_id_type son_id );
bool is_son_active( son_id_type son_id );
const witness_schedule_object& get_witness_schedule_object()const; const witness_schedule_object& get_witness_schedule_object()const;
time_point_sec head_block_time()const; time_point_sec head_block_time()const;

View file

@ -27,6 +27,8 @@ namespace graphene { namespace chain {
string deposit_address_data; string deposit_address_data;
string withdraw_public_key; string withdraw_public_key;
string withdraw_address; string withdraw_address;
time_point_sec valid_from;
time_point_sec expires;
sidechain_address_object() : sidechain_address_object() :
sidechain(sidechain_type::bitcoin), sidechain(sidechain_type::bitcoin),
@ -38,10 +40,10 @@ namespace graphene { namespace chain {
struct by_account; struct by_account;
struct by_sidechain; struct by_sidechain;
struct by_deposit_public_key; struct by_sidechain_and_deposit_public_key_and_expires;
struct by_withdraw_public_key; struct by_withdraw_public_key;
struct by_account_and_sidechain; struct by_account_and_sidechain_and_expires;
struct by_sidechain_and_deposit_address; struct by_sidechain_and_deposit_address_and_expires;
using sidechain_address_multi_index_type = multi_index_container< using sidechain_address_multi_index_type = multi_index_container<
sidechain_address_object, sidechain_address_object,
indexed_by< indexed_by<
@ -54,22 +56,28 @@ namespace graphene { namespace chain {
ordered_non_unique< tag<by_sidechain>, ordered_non_unique< tag<by_sidechain>,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain> member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>
>, >,
ordered_non_unique< tag<by_deposit_public_key>, ordered_unique< tag<by_sidechain_and_deposit_public_key_and_expires>,
member<sidechain_address_object, std::string, &sidechain_address_object::deposit_public_key>
>,
ordered_non_unique< tag<by_withdraw_public_key>,
member<sidechain_address_object, std::string, &sidechain_address_object::withdraw_public_key>
>,
ordered_unique< tag<by_account_and_sidechain>,
composite_key<sidechain_address_object,
member<sidechain_address_object, account_id_type, &sidechain_address_object::sidechain_address_account>,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>
>
>,
ordered_unique< tag<by_sidechain_and_deposit_address>,
composite_key<sidechain_address_object, composite_key<sidechain_address_object,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>, member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>,
member<sidechain_address_object, std::string, &sidechain_address_object::deposit_address> member<sidechain_address_object, string, &sidechain_address_object::deposit_public_key>,
member<sidechain_address_object, time_point_sec, &sidechain_address_object::expires>
>
>,
ordered_non_unique< tag<by_withdraw_public_key>,
member<sidechain_address_object, string, &sidechain_address_object::withdraw_public_key>
>,
ordered_non_unique< tag<by_account_and_sidechain_and_expires>,
composite_key<sidechain_address_object,
member<sidechain_address_object, account_id_type, &sidechain_address_object::sidechain_address_account>,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>,
member<sidechain_address_object, time_point_sec, &sidechain_address_object::expires>
>
>,
ordered_non_unique< tag<by_sidechain_and_deposit_address_and_expires>,
composite_key<sidechain_address_object,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>,
member<sidechain_address_object, string, &sidechain_address_object::deposit_address>,
member<sidechain_address_object, time_point_sec, &sidechain_address_object::expires>
> >
> >
> >
@ -81,4 +89,4 @@ namespace graphene { namespace chain {
FC_REFLECT_DERIVED( graphene::chain::sidechain_address_object, (graphene::db::object), FC_REFLECT_DERIVED( graphene::chain::sidechain_address_object, (graphene::db::object),
(sidechain_address_account) (sidechain) (sidechain_address_account) (sidechain)
(deposit_public_key) (deposit_address) (deposit_address_data) (deposit_public_key) (deposit_address) (deposit_address_data)
(withdraw_public_key) (withdraw_address) ) (withdraw_public_key) (withdraw_address) (valid_from) (expires) )

View file

@ -1,6 +1,7 @@
#include <graphene/chain/sidechain_address_evaluator.hpp> #include <graphene/chain/sidechain_address_evaluator.hpp>
#include <graphene/chain/database.hpp> #include <graphene/chain/database.hpp>
#include <graphene/chain/son_object.hpp>
#include <graphene/chain/sidechain_address_object.hpp> #include <graphene/chain/sidechain_address_object.hpp>
#include <graphene/chain/hardfork.hpp> #include <graphene/chain/hardfork.hpp>
@ -8,48 +9,85 @@ namespace graphene { namespace chain {
void_result add_sidechain_address_evaluator::do_evaluate(const sidechain_address_add_operation& op) void_result add_sidechain_address_evaluator::do_evaluate(const sidechain_address_add_operation& op)
{ try{ { try{
FC_ASSERT( op.deposit_public_key.length() > 0 && op.deposit_address.length() == 0 && op.deposit_address_data.length() == 0, "User should add a valid deposit public key and a null deposit address");
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& sdpke_idx = db().get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_public_key_and_expires>();
FC_ASSERT( idx.find(boost::make_tuple(op.sidechain_address_account, op.sidechain)) == idx.end(), "Duplicated item" ); FC_ASSERT( sdpke_idx.find(boost::make_tuple(op.sidechain, op.deposit_public_key, time_point_sec::maximum())) == sdpke_idx.end(), "An active deposit key already exists" );
return void_result(); return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }
object_id_type add_sidechain_address_evaluator::do_apply(const sidechain_address_add_operation& op) object_id_type add_sidechain_address_evaluator::do_apply(const sidechain_address_add_operation& op)
{ try { { try {
const auto &sidechain_addresses_idx = db().get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(op.sidechain_address_account, op.sidechain, time_point_sec::maximum()));
if (addr_itr != sidechain_addresses_idx.end())
{
db().modify(*addr_itr, [&](sidechain_address_object &sao) {
sao.expires = db().head_block_time();
});
}
const auto& new_sidechain_address_object = db().create<sidechain_address_object>( [&]( sidechain_address_object& obj ){ const auto& new_sidechain_address_object = db().create<sidechain_address_object>( [&]( sidechain_address_object& obj ){
obj.sidechain_address_account = op.sidechain_address_account; obj.sidechain_address_account = op.sidechain_address_account;
obj.sidechain = op.sidechain; obj.sidechain = op.sidechain;
obj.deposit_public_key = op.deposit_public_key; obj.deposit_public_key = op.deposit_public_key;
obj.deposit_address = op.deposit_address; obj.deposit_address = "";
obj.deposit_address_data = op.deposit_address_data; obj.deposit_address_data = "";
obj.withdraw_public_key = op.withdraw_public_key; obj.withdraw_public_key = op.withdraw_public_key;
obj.withdraw_address = op.withdraw_address; obj.withdraw_address = op.withdraw_address;
obj.valid_from = db().head_block_time();
obj.expires = time_point_sec::maximum();
}); });
return new_sidechain_address_object.id; return new_sidechain_address_object.id;
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }
void_result update_sidechain_address_evaluator::do_evaluate(const sidechain_address_update_operation& op) void_result update_sidechain_address_evaluator::do_evaluate(const sidechain_address_update_operation& op)
{ try { { try {
FC_ASSERT(db().get(op.sidechain_address_id).sidechain_address_account == op.sidechain_address_account); const auto& sidx = db().get_index_type<son_index>().indices().get<by_account>();
const auto& son_obj = sidx.find(op.payer);
FC_ASSERT( son_obj != sidx.end() && db().is_son_active(son_obj->id), "Non active SON trying to update deposit address object" );
const auto& sdpke_idx = db().get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_public_key_and_expires>();
FC_ASSERT( op.deposit_address.valid() && op.deposit_public_key.valid() && op.deposit_address_data.valid(), "Update operation by SON is not valid");
FC_ASSERT( (*op.deposit_address).length() > 0 && (*op.deposit_public_key).length() > 0 && (*op.deposit_address_data).length() > 0, "SON should create a valid deposit address with valid deposit public key");
FC_ASSERT( sdpke_idx.find(boost::make_tuple(op.sidechain, *op.deposit_public_key, time_point_sec::maximum())) != sdpke_idx.end(), "Invalid update operation by SON" );
FC_ASSERT( db().get(op.sidechain_address_id).sidechain_address_account == op.sidechain_address_account, "Invalid sidechain address account" );
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>(); const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
FC_ASSERT( idx.find(op.sidechain_address_id) != idx.end() ); FC_ASSERT( idx.find(op.sidechain_address_id) != idx.end(), "Invalid sidechain address ID" );
return void_result(); return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }
object_id_type update_sidechain_address_evaluator::do_apply(const sidechain_address_update_operation& op) object_id_type update_sidechain_address_evaluator::do_apply(const sidechain_address_update_operation& op)
{ try { { try {
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>(); const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
auto itr = idx.find(op.sidechain_address_id); auto itr = idx.find(op.sidechain_address_id);
if(itr != idx.end()) if(itr != idx.end())
{ {
db().modify(*itr, [&op](sidechain_address_object &sao) { // Case of change of Active SONs, store the outgoing address object with proper valid_from and expires updated
if(op.deposit_public_key.valid()) sao.deposit_public_key = *op.deposit_public_key; if(itr->deposit_address.length() > 0) {
if(op.deposit_address.valid()) sao.deposit_address = *op.deposit_address; const auto& new_sidechain_address_object = db().create<sidechain_address_object>( [&]( sidechain_address_object& obj ) {
if(op.deposit_address_data.valid()) sao.deposit_address_data = *op.deposit_address_data; obj.sidechain_address_account = op.sidechain_address_account;
if(op.withdraw_public_key.valid()) sao.withdraw_public_key = *op.withdraw_public_key; obj.sidechain = op.sidechain;
if(op.withdraw_address.valid()) sao.withdraw_address = *op.withdraw_address; obj.deposit_public_key = *op.deposit_public_key;
}); obj.deposit_address = itr->deposit_address;
} obj.deposit_address_data = itr->deposit_address_data;
obj.withdraw_public_key = *op.withdraw_public_key;
obj.withdraw_address = *op.withdraw_address;
obj.valid_from = itr->valid_from;
obj.expires = db().head_block_time();
});
db().modify(*itr, [&](sidechain_address_object &sao) {
if(op.deposit_address.valid()) sao.deposit_address = *op.deposit_address;
if(op.deposit_address_data.valid()) sao.deposit_address_data = *op.deposit_address_data;
sao.valid_from = db().head_block_time();
});
} else {
// Case of SON creating deposit address for a user input
db().modify(*itr, [&op](sidechain_address_object &sao) {
if(op.deposit_address.valid()) sao.deposit_address = *op.deposit_address;
if(op.deposit_address_data.valid()) sao.deposit_address_data = *op.deposit_address_data;
});
}
}
return op.sidechain_address_id; return op.sidechain_address_id;
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }
@ -66,7 +104,9 @@ void_result delete_sidechain_address_evaluator::do_apply(const sidechain_address
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>(); const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
auto sidechain_address = idx.find(op.sidechain_address_id); auto sidechain_address = idx.find(op.sidechain_address_id);
if(sidechain_address != idx.end()) { if(sidechain_address != idx.end()) {
db().remove(*sidechain_address); db().modify(*sidechain_address, [&](sidechain_address_object &sao) {
sao.expires = db().head_block_time();
});
} }
return void_result(); return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -32,6 +32,7 @@ public:
void process_proposals(); void process_proposals();
void process_active_sons_change(); void process_active_sons_change();
void create_deposit_addresses();
void process_deposits(); void process_deposits();
void process_withdrawals(); void process_withdrawals();
void process_sidechain_transactions(); void process_sidechain_transactions();

View file

@ -18,6 +18,7 @@ public:
bool create_handler(sidechain_type sidechain, const boost::program_options::variables_map &options); bool create_handler(sidechain_type sidechain, const boost::program_options::variables_map &options);
void process_proposals(); void process_proposals();
void process_active_sons_change(); void process_active_sons_change();
void create_deposit_addresses();
void process_deposits(); void process_deposits();
void process_withdrawals(); void process_withdrawals();
void process_sidechain_transactions(); void process_sidechain_transactions();

View file

@ -54,6 +54,7 @@ public:
void process_proposals(); void process_proposals();
void process_active_sons_change(); void process_active_sons_change();
void create_deposit_addresses();
void process_deposits(); void process_deposits();
void process_withdrawals(); void process_withdrawals();
void process_sidechain_transactions(); void process_sidechain_transactions();
@ -415,6 +416,8 @@ void peerplays_sidechain_plugin_impl::son_processing() {
process_active_sons_change(); process_active_sons_change();
create_deposit_addresses();
process_deposits(); process_deposits();
process_withdrawals(); process_withdrawals();
@ -596,6 +599,10 @@ void peerplays_sidechain_plugin_impl::process_active_sons_change() {
net_manager->process_active_sons_change(); net_manager->process_active_sons_change();
} }
void peerplays_sidechain_plugin_impl::create_deposit_addresses() {
net_manager->create_deposit_addresses();
}
void peerplays_sidechain_plugin_impl::process_deposits() { void peerplays_sidechain_plugin_impl::process_deposits() {
net_manager->process_deposits(); net_manager->process_deposits();
} }

View file

@ -216,8 +216,8 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
// Withdrawal request // Withdrawal request
if (withdraw_condition) { if (withdraw_condition) {
// BTC Payout only (for now) // BTC Payout only (for now)
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain_type::bitcoin)); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain_type::bitcoin, time_point_sec::maximum()));
if (addr_itr == sidechain_addresses_idx.end()) if (addr_itr == sidechain_addresses_idx.end())
return; return;
@ -356,6 +356,12 @@ void sidechain_net_handler::process_proposals() {
void sidechain_net_handler::process_active_sons_change() { void sidechain_net_handler::process_active_sons_change() {
process_primary_wallet(); process_primary_wallet();
}
void sidechain_net_handler::create_deposit_addresses() {
if (database.get_global_properties().active_sons.size() < database.get_chain_properties().immutable_parameters.min_son_count) {
return;
}
process_sidechain_addresses(); process_sidechain_addresses();
} }
@ -372,8 +378,8 @@ void sidechain_net_handler::process_deposits() {
return; return;
} }
//Ignore the deposits which are not valid anymore, considered refunds. //Ignore the deposits which are not valid anymore, considered refunds.
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address>(); const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_to)); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_to, time_point_sec::maximum()));
if (addr_itr == sidechain_addresses_idx.end()) { if (addr_itr == sidechain_addresses_idx.end()) {
return; return;
} }

View file

@ -1349,34 +1349,36 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() {
const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain); const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second, std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
[&](const sidechain_address_object &sao) { [&](const sidechain_address_object &sao) {
auto usr_pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(sao.deposit_public_key))); if (sao.expires == time_point_sec::maximum()) {
auto usr_pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(sao.deposit_public_key)));
btc_one_or_weighted_multisig_address addr(usr_pubkey, pubkeys, network_type); btc_one_or_weighted_multisig_address addr(usr_pubkey, pubkeys, network_type);
std::string address_data = "{ \"redeemScript\": \"" + fc::to_hex(addr.get_redeem_script()) + std::string address_data = "{ \"redeemScript\": \"" + fc::to_hex(addr.get_redeem_script()) +
"\", \"witnessScript\": \"" + fc::to_hex(addr.get_witness_script()) + "\" }"; "\", \"witnessScript\": \"" + fc::to_hex(addr.get_witness_script()) + "\" }";
if (addr.get_address() != sao.deposit_address) { if (addr.get_address() != sao.deposit_address) {
sidechain_address_update_operation op; sidechain_address_update_operation op;
op.payer = plugin.get_current_son_object().son_account; op.payer = plugin.get_current_son_object().son_account;
op.sidechain_address_id = sao.id; op.sidechain_address_id = sao.id;
op.sidechain_address_account = sao.sidechain_address_account; op.sidechain_address_account = sao.sidechain_address_account;
op.sidechain = sao.sidechain; op.sidechain = sao.sidechain;
op.deposit_public_key = sao.deposit_public_key; op.deposit_public_key = sao.deposit_public_key;
op.deposit_address = addr.get_address(); op.deposit_address = addr.get_address();
op.deposit_address_data = address_data; op.deposit_address_data = address_data;
op.withdraw_public_key = sao.withdraw_public_key; op.withdraw_public_key = sao.withdraw_public_key;
op.withdraw_address = sao.withdraw_address; op.withdraw_address = sao.withdraw_address;
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op); signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op);
try { try {
trx.validate(); trx.validate();
database.push_transaction(trx, database::validation_steps::skip_block_size_check); database.push_transaction(trx, database::validation_steps::skip_block_size_check);
if (plugin.app().p2p_node()) if (plugin.app().p2p_node())
plugin.app().p2p_node()->broadcast(net::trx_message(trx)); plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true; return true;
} catch (fc::exception e) { } catch (fc::exception e) {
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
return false; return false;
}
} }
} }
}); });
@ -1779,11 +1781,11 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data)
if (block != "") { if (block != "") {
const auto &vins = extract_info_from_block(block); const auto &vins = extract_info_from_block(block);
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address>(); const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
for (const auto &v : vins) { for (const auto &v : vins) {
// !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address)); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address, time_point_sec::maximum()));
if (addr_itr == sidechain_addresses_idx.end()) if (addr_itr == sidechain_addresses_idx.end())
continue; continue;
@ -1813,8 +1815,8 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data)
std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(const std::string &user_address) { std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(const std::string &user_address) {
using namespace bitcoin; using namespace bitcoin;
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address>(); const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, user_address)); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, user_address, time_point_sec::maximum()));
if (addr_itr == sidechain_addresses_idx.end()) { if (addr_itr == sidechain_addresses_idx.end()) {
return ""; return "";
} }

View file

@ -124,6 +124,38 @@ void sidechain_net_handler_peerplays::process_primary_wallet() {
} }
void sidechain_net_handler_peerplays::process_sidechain_addresses() { void sidechain_net_handler_peerplays::process_sidechain_addresses() {
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>();
const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
[&](const sidechain_address_object &sao) {
if (sao.expires == time_point_sec::maximum()) {
if (sao.deposit_address == "") {
sidechain_address_update_operation op;
op.payer = plugin.get_current_son_object().son_account;
op.sidechain_address_id = sao.id;
op.sidechain_address_account = sao.sidechain_address_account;
op.sidechain = sao.sidechain;
op.deposit_public_key = sao.deposit_public_key;
op.deposit_address = sao.withdraw_address;
op.deposit_address_data = sao.withdraw_address;
op.withdraw_public_key = sao.withdraw_public_key;
op.withdraw_address = sao.withdraw_address;
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op);
try {
trx.validate();
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
if (plugin.app().p2p_node())
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true;
} catch (fc::exception e) {
elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what()));
return false;
}
}
}
});
return; return;
} }

View file

@ -51,6 +51,12 @@ void sidechain_net_manager::process_active_sons_change() {
} }
} }
void sidechain_net_manager::create_deposit_addresses() {
for (size_t i = 0; i < net_handlers.size(); i++) {
net_handlers.at(i)->create_deposit_addresses();
}
}
void sidechain_net_manager::process_deposits() { void sidechain_net_manager::process_deposits() {
for (size_t i = 0; i < net_handlers.size(); i++) { for (size_t i = 0; i < net_handlers.size(); i++) {
net_handlers.at(i)->process_deposits(); net_handlers.at(i)->process_deposits();

View file

@ -1440,7 +1440,6 @@ class wallet_api
* @param account the name or id of the account who owns the address * @param account the name or id of the account who owns the address
* @param sidechain a sidechain to whom address belongs * @param sidechain a sidechain to whom address belongs
* @param deposit_public_key sidechain public key used for deposit address * @param deposit_public_key sidechain public key used for deposit address
* @param deposit_address sidechain address for deposits
* @param withdraw_public_key sidechain public key used for withdraw address * @param withdraw_public_key sidechain public key used for withdraw address
* @param withdraw_address sidechain address for withdrawals * @param withdraw_address sidechain address for withdrawals
* @param broadcast true to broadcast the transaction on the network * @param broadcast true to broadcast the transaction on the network
@ -1449,28 +1448,6 @@ class wallet_api
signed_transaction add_sidechain_address(string account, signed_transaction add_sidechain_address(string account,
sidechain_type sidechain, sidechain_type sidechain,
string deposit_public_key, string deposit_public_key,
string deposit_address,
string withdraw_public_key,
string withdraw_address,
bool broadcast = false);
/** Updates existing sidechain address owned by the given account for a given sidechain.
*
* Only address, private key and public key might be updated.
*
* @param account the name or id of the account who owns the address
* @param sidechain a sidechain to whom address belongs
* @param deposit_public_key sidechain public key used for deposit address
* @param deposit_address sidechain address for deposits
* @param withdraw_public_key sidechain public key used for withdraw address
* @param withdraw_address sidechain address for withdrawals
* @param broadcast true to broadcast the transaction on the network
* @returns the signed transaction updating sidechain address
*/
signed_transaction update_sidechain_address(string account,
sidechain_type sidechain,
string deposit_public_key,
string deposit_address,
string withdraw_public_key, string withdraw_public_key,
string withdraw_address, string withdraw_address,
bool broadcast = false); bool broadcast = false);
@ -2323,7 +2300,6 @@ FC_API( graphene::wallet::wallet_api,
(get_son_wallet_by_time_point) (get_son_wallet_by_time_point)
(get_son_wallets) (get_son_wallets)
(add_sidechain_address) (add_sidechain_address)
(update_sidechain_address)
(delete_sidechain_address) (delete_sidechain_address)
(get_sidechain_addresses_by_account) (get_sidechain_addresses_by_account)
(get_sidechain_addresses_by_sidechain) (get_sidechain_addresses_by_sidechain)

View file

@ -2080,7 +2080,6 @@ public:
signed_transaction add_sidechain_address(string account, signed_transaction add_sidechain_address(string account,
sidechain_type sidechain, sidechain_type sidechain,
string deposit_public_key, string deposit_public_key,
string deposit_address,
string withdraw_public_key, string withdraw_public_key,
string withdraw_address, string withdraw_address,
bool broadcast /* = false */) bool broadcast /* = false */)
@ -2092,38 +2091,6 @@ public:
op.sidechain_address_account = sidechain_address_account_id; op.sidechain_address_account = sidechain_address_account_id;
op.sidechain = sidechain; op.sidechain = sidechain;
op.deposit_public_key = deposit_public_key; op.deposit_public_key = deposit_public_key;
op.deposit_address = deposit_address;
op.withdraw_public_key = withdraw_public_key;
op.withdraw_address = withdraw_address;
signed_transaction tx;
tx.operations.push_back( op );
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees);
tx.validate();
return sign_transaction( tx, broadcast );
} FC_CAPTURE_AND_RETHROW() }
signed_transaction update_sidechain_address(string account,
sidechain_type sidechain,
string deposit_public_key,
string deposit_address,
string withdraw_public_key,
string withdraw_address,
bool broadcast /* = false */)
{ try {
account_id_type sidechain_address_account_id = get_account_id(account);
fc::optional<sidechain_address_object> sao = _remote_db->get_sidechain_address_by_account_and_sidechain(sidechain_address_account_id, sidechain);
if (!sao)
FC_THROW("No sidechain address for account ${account} and sidechain ${sidechain}", ("account", sidechain_address_account_id)("sidechain", sidechain));
sidechain_address_update_operation op;
op.payer = sidechain_address_account_id;
op.sidechain_address_id = sao->id;
op.sidechain_address_account = sidechain_address_account_id;
op.sidechain = sidechain;
op.deposit_public_key = deposit_public_key;
op.deposit_address = deposit_address;
op.withdraw_public_key = withdraw_public_key; op.withdraw_public_key = withdraw_public_key;
op.withdraw_address = withdraw_address; op.withdraw_address = withdraw_address;
@ -4804,23 +4771,11 @@ vector<optional<son_wallet_object>> wallet_api::get_son_wallets(uint32_t limit)
signed_transaction wallet_api::add_sidechain_address(string account, signed_transaction wallet_api::add_sidechain_address(string account,
sidechain_type sidechain, sidechain_type sidechain,
string deposit_public_key, string deposit_public_key,
string deposit_address,
string withdraw_public_key, string withdraw_public_key,
string withdraw_address, string withdraw_address,
bool broadcast /* = false */) bool broadcast /* = false */)
{ {
return my->add_sidechain_address(account, sidechain, deposit_public_key, deposit_address, withdraw_public_key, withdraw_address, broadcast); return my->add_sidechain_address(account, sidechain, deposit_public_key, withdraw_public_key, withdraw_address, broadcast);
}
signed_transaction wallet_api::update_sidechain_address(string account,
sidechain_type sidechain,
string deposit_public_key,
string deposit_address,
string withdraw_public_key,
string withdraw_address,
bool broadcast /* = false */)
{
return my->update_sidechain_address(account, sidechain, deposit_public_key, deposit_address, withdraw_public_key, withdraw_address, broadcast);
} }
signed_transaction wallet_api::delete_sidechain_address(string account, signed_transaction wallet_api::delete_sidechain_address(string account,

View file

@ -3,6 +3,7 @@
#include "../common/database_fixture.hpp" #include "../common/database_fixture.hpp"
#include <graphene/chain/hardfork.hpp> #include <graphene/chain/hardfork.hpp>
#include <graphene/chain/son_object.hpp>
#include <graphene/chain/sidechain_address_object.hpp> #include <graphene/chain/sidechain_address_object.hpp>
#include <graphene/chain/sidechain_defs.hpp> #include <graphene/chain/sidechain_defs.hpp>
@ -31,7 +32,6 @@ BOOST_AUTO_TEST_CASE( sidechain_address_add_test ) {
op.sidechain_address_account = alice_id; op.sidechain_address_account = alice_id;
op.sidechain = sidechain_type::bitcoin; op.sidechain = sidechain_type::bitcoin;
op.deposit_public_key = "deposit_public_key"; op.deposit_public_key = "deposit_public_key";
op.deposit_address = "deposit_address";
op.withdraw_public_key = "withdraw_public_key"; op.withdraw_public_key = "withdraw_public_key";
op.withdraw_address = "withdraw_address"; op.withdraw_address = "withdraw_address";
@ -43,66 +43,83 @@ BOOST_AUTO_TEST_CASE( sidechain_address_add_test ) {
BOOST_TEST_MESSAGE("Check sidechain_address_add_operation results"); BOOST_TEST_MESSAGE("Check sidechain_address_add_operation results");
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
BOOST_REQUIRE( idx.size() == 1 ); BOOST_REQUIRE( idx.size() == 1 );
auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin ) ); auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin, time_point_sec::maximum() ) );
BOOST_REQUIRE( obj != idx.end() ); BOOST_REQUIRE( obj != idx.end() );
BOOST_CHECK( obj->sidechain_address_account == alice_id ); BOOST_CHECK( obj->sidechain_address_account == alice_id );
BOOST_CHECK( obj->sidechain == sidechain_type::bitcoin ); BOOST_CHECK( obj->sidechain == sidechain_type::bitcoin );
BOOST_CHECK( obj->deposit_public_key == "deposit_public_key" ); BOOST_CHECK( obj->deposit_public_key == "deposit_public_key" );
BOOST_CHECK( obj->deposit_address == "deposit_address" ); BOOST_CHECK( obj->deposit_address == "" );
BOOST_CHECK( obj->deposit_address_data == "" );
BOOST_CHECK( obj->withdraw_public_key == "withdraw_public_key" ); BOOST_CHECK( obj->withdraw_public_key == "withdraw_public_key" );
BOOST_CHECK( obj->withdraw_address == "withdraw_address" ); BOOST_CHECK( obj->withdraw_address == "withdraw_address" );
} }
BOOST_AUTO_TEST_CASE( sidechain_address_update_test ) { BOOST_AUTO_TEST_CASE( sidechain_address_update_test ) {
BOOST_TEST_MESSAGE("sidechain_address_update_test"); BOOST_TEST_MESSAGE("sidechain_address_update_test");
generate_blocks(HARDFORK_SON_TIME);
generate_block();
INVOKE(sidechain_address_add_test); INVOKE(sidechain_address_add_test);
GET_ACTOR(alice); GET_ACTOR(alice);
ACTORS((bob));
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
BOOST_REQUIRE( idx.size() == 1 ); BOOST_REQUIRE( idx.size() == 1 );
auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin ) ); auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin, time_point_sec::maximum() ) );
BOOST_REQUIRE( obj != idx.end() ); BOOST_REQUIRE( obj != idx.end() );
std::string new_deposit_public_key = "deposit_public_key";
std::string new_deposit_public_key = "new_deposit_public_key";
std::string new_deposit_address = "new_deposit_address"; std::string new_deposit_address = "new_deposit_address";
std::string new_withdraw_public_key = "new_withdraw_public_key"; std::string new_deposit_address_data = "new_deposit_address_data";
std::string new_withdraw_address = "new_withdraw_address"; std::string new_withdraw_public_key = "withdraw_public_key";
std::string new_withdraw_address = "withdraw_address";
generate_block();
auto& son = db.create<son_object>( [&]( son_object& sobj )
{
sobj.son_account = bob_id;
sobj.statistics = db.create<son_statistics_object>([&](son_statistics_object& s){s.owner = sobj.id;}).id;
});
generate_block();
db.modify( db.get_global_properties(), [&]( global_property_object& _gpo )
{
son_info sinfo;
sinfo.son_id = son.id;
_gpo.active_sons.push_back(sinfo);
});
generate_block();
{ {
BOOST_TEST_MESSAGE("Send sidechain_address_update_operation"); BOOST_TEST_MESSAGE("Send sidechain_address_update_operation");
trx.clear();
sidechain_address_update_operation op; sidechain_address_update_operation op;
op.payer = alice_id; op.payer = bob_id;
op.sidechain_address_id = sidechain_address_id_type(0); op.sidechain_address_id = sidechain_address_id_type(0);
op.sidechain_address_account = obj->sidechain_address_account; op.sidechain_address_account = obj->sidechain_address_account;
op.sidechain = obj->sidechain; op.sidechain = obj->sidechain;
op.deposit_public_key = new_deposit_public_key; op.deposit_public_key = new_deposit_public_key;
op.deposit_address = new_deposit_address; op.deposit_address = new_deposit_address;
op.deposit_address_data = new_deposit_address_data;
op.withdraw_public_key = new_withdraw_public_key; op.withdraw_public_key = new_withdraw_public_key;
op.withdraw_address = new_withdraw_address; op.withdraw_address = new_withdraw_address;
trx.operations.push_back(op); trx.operations.push_back(op);
sign(trx, alice_private_key); sign(trx, bob_private_key);
PUSH_TX(db, trx, ~0); PUSH_TX(db, trx, ~0);
} }
generate_block(); generate_block();
{ {
BOOST_TEST_MESSAGE("Check sidechain_address_update_operation results"); BOOST_TEST_MESSAGE("Check sidechain_address_update_operation results");
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
BOOST_REQUIRE( idx.size() == 1 ); BOOST_REQUIRE( idx.size() == 1 );
auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin ) ); auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin, time_point_sec::maximum() ) );
BOOST_REQUIRE( obj != idx.end() ); BOOST_REQUIRE( obj != idx.end() );
BOOST_CHECK( obj->sidechain_address_account == obj->sidechain_address_account ); BOOST_CHECK( obj->sidechain_address_account == obj->sidechain_address_account );
BOOST_CHECK( obj->sidechain == obj->sidechain ); BOOST_CHECK( obj->sidechain == obj->sidechain );
BOOST_CHECK( obj->deposit_public_key == new_deposit_public_key ); BOOST_CHECK( obj->deposit_public_key == new_deposit_public_key );
BOOST_CHECK( obj->deposit_address == new_deposit_address ); BOOST_CHECK( obj->deposit_address == new_deposit_address );
BOOST_CHECK( obj->deposit_address_data == new_deposit_address_data );
BOOST_CHECK( obj->withdraw_public_key == new_withdraw_public_key ); BOOST_CHECK( obj->withdraw_public_key == new_withdraw_public_key );
BOOST_CHECK( obj->withdraw_address == new_withdraw_address ); BOOST_CHECK( obj->withdraw_address == new_withdraw_address );
} }
@ -116,9 +133,9 @@ BOOST_AUTO_TEST_CASE( sidechain_address_delete_test ) {
GET_ACTOR(alice); GET_ACTOR(alice);
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
BOOST_REQUIRE( idx.size() == 1 ); BOOST_REQUIRE( idx.size() == 1 );
auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin ) ); auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin, time_point_sec::maximum() ) );
BOOST_REQUIRE( obj != idx.end() ); BOOST_REQUIRE( obj != idx.end() );
{ {
@ -134,15 +151,18 @@ BOOST_AUTO_TEST_CASE( sidechain_address_delete_test ) {
sign(trx, alice_private_key); sign(trx, alice_private_key);
PUSH_TX(db, trx, ~0); PUSH_TX(db, trx, ~0);
} }
time_point_sec now = db.head_block_time();
generate_block(); generate_block();
{ {
BOOST_TEST_MESSAGE("Check sidechain_address_delete_operation results"); BOOST_TEST_MESSAGE("Check sidechain_address_delete_operation results");
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>(); const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
BOOST_REQUIRE( idx.size() == 0 ); BOOST_REQUIRE( idx.size() == 1 );
auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin ) ); auto obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin, time_point_sec::maximum() ) );
BOOST_REQUIRE( obj == idx.end() ); BOOST_REQUIRE( obj == idx.end() );
auto expired_obj = idx.find( boost::make_tuple( alice_id, sidechain_type::bitcoin, now ) );
BOOST_REQUIRE( expired_obj != idx.end() );
} }
} }