Replace raw with psbt transactions to support parital tx signing (#311)
* RPC calls for PSBT, raw transactions replaced with PSBT * Fix estimatesmartfeerate, extensive RPC calls logging for debugging purposes * Remove dead code * Partial signing functional for deposit and withdrawal * Fix sidechain_type declarations * Depositing Peerplays asset refactored * Partial signing functional for primary wallet funds moving * Prettier logs * Refactor multiple SON support processing * Serialize field complete from sidechain_transaction_sign_operation * Refactor transaction signing in particular order, BTC only (maybe) need it * Add number of required signatures parameter for addmultisigaddress * Change default bitcoin node parameters * Transaction signing only by scheduled son * Removed scheduling log * Prevent PW funds moving to the same address * Refactor sidechain_transaction_object processing, code cleanup * Remove obsolete tests * Decrease logging * Code readability * When updated, import son wallet bitcoin address to bitcoin wallet * When updated, recreate son wallet bitcoin address on each node * Refactor on_changed_objects, move it into task * Add check to prevent deposit/withdrawal double processing * Improved check for sidechain transaction object creation * Single sidechain transaction signature per block allowed only * Unlock wallet on addmultisigaddress * Import both address and redeem script on primary wallet change, fix some compiler warnings * Fix invalid list of signers for PW funds transfer
This commit is contained in:
parent
964aed0bdf
commit
0f97241f1b
39 changed files with 1327 additions and 1039 deletions
|
|
@ -343,13 +343,13 @@ struct get_impacted_account_visitor
|
|||
void operator()( const sidechain_address_delete_operation& op ){
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
void operator()( const bitcoin_transaction_send_operation& op ){
|
||||
void operator()( const sidechain_transaction_create_operation& op ){
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const bitcoin_transaction_sign_operation& op ){
|
||||
void operator()( const sidechain_transaction_sign_operation& op ){
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const bitcoin_send_transaction_process_operation& op ){
|
||||
void operator()( const sidechain_transaction_send_operation& op ){
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ add_library( graphene_chain
|
|||
)
|
||||
|
||||
add_dependencies( graphene_chain build_hardfork_hpp )
|
||||
target_link_libraries( graphene_chain fc graphene_db peerplays_sidechain )
|
||||
target_link_libraries( graphene_chain fc graphene_db )
|
||||
target_include_directories( graphene_chain
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -269,9 +269,9 @@ void database::initialize_evaluators()
|
|||
register_evaluator<add_sidechain_address_evaluator>();
|
||||
register_evaluator<update_sidechain_address_evaluator>();
|
||||
register_evaluator<delete_sidechain_address_evaluator>();
|
||||
register_evaluator<bitcoin_transaction_send_evaluator>();
|
||||
register_evaluator<bitcoin_transaction_sign_evaluator>();
|
||||
register_evaluator<bitcoin_send_transaction_process_evaluator>();
|
||||
register_evaluator<sidechain_transaction_create_evaluator>();
|
||||
register_evaluator<sidechain_transaction_sign_evaluator>();
|
||||
register_evaluator<sidechain_transaction_send_evaluator>();
|
||||
}
|
||||
|
||||
void database::initialize_indexes()
|
||||
|
|
@ -321,7 +321,7 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<son_wallet_withdraw_index> >();
|
||||
|
||||
add_index< primary_index<sidechain_address_index> >();
|
||||
add_index< primary_index<bitcoin_transaction_index> >();
|
||||
add_index< primary_index<sidechain_transaction_index> >();
|
||||
|
||||
//Implementation object indexes
|
||||
add_index< primary_index<transaction_index > >();
|
||||
|
|
|
|||
|
|
@ -330,13 +330,13 @@ struct get_impacted_account_visitor
|
|||
void operator()( const sidechain_address_delete_operation& op ) {
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
void operator()( const bitcoin_transaction_send_operation& op ) {
|
||||
void operator()( const sidechain_transaction_create_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const bitcoin_transaction_sign_operation& op ) {
|
||||
void operator()( const sidechain_transaction_sign_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const bitcoin_send_transaction_process_operation& op ) {
|
||||
void operator()( const sidechain_transaction_send_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
};
|
||||
|
|
@ -443,6 +443,8 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
|
|||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->sidechain_address_account );
|
||||
break;
|
||||
} case sidechain_transaction_object_type:{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
#include <graphene/chain/protocol/protocol.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -157,9 +157,9 @@ namespace graphene { namespace chain {
|
|||
sidechain_address_add_operation,
|
||||
sidechain_address_update_operation,
|
||||
sidechain_address_delete_operation,
|
||||
bitcoin_transaction_send_operation,
|
||||
bitcoin_transaction_sign_operation,
|
||||
bitcoin_send_transaction_process_operation
|
||||
sidechain_transaction_create_operation,
|
||||
sidechain_transaction_sign_operation,
|
||||
sidechain_transaction_send_operation
|
||||
> operation;
|
||||
|
||||
/// @} // operations group
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,60 +1,71 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct bitcoin_transaction_send_operation : public base_operation
|
||||
struct sidechain_transaction_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
|
||||
// TODO: BTC Transaction Structs go here
|
||||
fc::flat_map<son_id_type, std::vector<peerplays_sidechain::bytes>> signatures;
|
||||
sidechain_type sidechain;
|
||||
object_id_type object_id;
|
||||
std::string transaction;
|
||||
std::vector<son_id_type> signers;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const {}
|
||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||
};
|
||||
|
||||
struct bitcoin_transaction_sign_operation : public base_operation
|
||||
struct sidechain_transaction_sign_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
proposal_id_type proposal_id;
|
||||
std::vector<peerplays_sidechain::bytes> signatures;
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
|
||||
sidechain_transaction_id_type sidechain_transaction_id;
|
||||
std::string transaction;
|
||||
block_id_type block;
|
||||
bool complete;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const {}
|
||||
share_type calculate_fee( const fee_parameters_type& k )const { return 0; }
|
||||
};
|
||||
|
||||
struct bitcoin_send_transaction_process_operation : public base_operation
|
||||
struct sidechain_transaction_send_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
|
||||
bitcoin_transaction_id_type bitcoin_transaction_id;
|
||||
sidechain_transaction_id_type sidechain_transaction_id;
|
||||
|
||||
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) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation, (fee)(payer)(signatures) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_create_operation, (fee)(payer)
|
||||
(sidechain)
|
||||
(object_id)
|
||||
(transaction)
|
||||
(signers) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation, (fee)(payer)(proposal_id)(signatures) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation, (fee)(payer)
|
||||
(sidechain_transaction_id)
|
||||
(transaction)
|
||||
(block)
|
||||
(complete) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bitcoin_send_transaction_process_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::bitcoin_send_transaction_process_operation, (fee)(payer)(bitcoin_transaction_id) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_send_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_send_operation, (fee)(payer)
|
||||
(sidechain_transaction_id) )
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
#include <fc/safe.hpp>
|
||||
|
||||
|
|
@ -14,7 +15,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
son_id_type son_id;
|
||||
fc::time_point_sec timestamp;
|
||||
peerplays_sidechain::sidechain_type sidechain;
|
||||
sidechain_type sidechain;
|
||||
std::string sidechain_uid;
|
||||
std::string sidechain_transaction_id;
|
||||
std::string sidechain_from;
|
||||
|
|
@ -46,7 +47,10 @@ namespace graphene { namespace chain {
|
|||
|
||||
FC_REFLECT(graphene::chain::son_wallet_deposit_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_wallet_deposit_create_operation, (fee)(payer)
|
||||
(son_id) (timestamp) (sidechain) (sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_currency) (sidechain_amount) (peerplays_from) (peerplays_to) (peerplays_asset))
|
||||
(son_id) (timestamp) (sidechain)
|
||||
(sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_currency) (sidechain_amount)
|
||||
(peerplays_from) (peerplays_to) (peerplays_asset) )
|
||||
|
||||
FC_REFLECT(graphene::chain::son_wallet_deposit_process_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_wallet_deposit_process_operation, (fee)(payer)
|
||||
(son_wallet_deposit_id))
|
||||
(son_wallet_deposit_id) )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
#include <fc/safe.hpp>
|
||||
|
||||
|
|
@ -14,12 +15,12 @@ namespace graphene { namespace chain {
|
|||
|
||||
son_id_type son_id;
|
||||
fc::time_point_sec timestamp;
|
||||
peerplays_sidechain::sidechain_type sidechain;
|
||||
sidechain_type sidechain;
|
||||
std::string peerplays_uid;
|
||||
std::string peerplays_transaction_id;
|
||||
chain::account_id_type peerplays_from;
|
||||
chain::asset peerplays_asset;
|
||||
peerplays_sidechain::sidechain_type withdraw_sidechain;
|
||||
sidechain_type withdraw_sidechain;
|
||||
std::string withdraw_address;
|
||||
std::string withdraw_currency;
|
||||
safe<int64_t> withdraw_amount;
|
||||
|
|
@ -45,7 +46,10 @@ namespace graphene { namespace chain {
|
|||
|
||||
FC_REFLECT(graphene::chain::son_wallet_withdraw_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_wallet_withdraw_create_operation, (fee)(payer)
|
||||
(son_id) (timestamp) (sidechain) (peerplays_uid) (peerplays_transaction_id) (peerplays_from) (peerplays_asset) (withdraw_sidechain) (withdraw_address) (withdraw_currency) (withdraw_amount) )
|
||||
(son_id) (timestamp) (sidechain)
|
||||
(peerplays_uid) (peerplays_transaction_id) (peerplays_from) (peerplays_asset)
|
||||
(withdraw_sidechain) (withdraw_address) (withdraw_currency) (withdraw_amount) )
|
||||
|
||||
FC_REFLECT(graphene::chain::son_wallet_withdraw_process_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_wallet_withdraw_process_operation, (fee)(payer)
|
||||
(son_wallet_withdraw_id))
|
||||
(son_wallet_withdraw_id) )
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace graphene { namespace chain {
|
|||
son_wallet_deposit_object_type,
|
||||
son_wallet_withdraw_object_type,
|
||||
sidechain_address_object_type,
|
||||
bitcoin_transaction_object_type,
|
||||
sidechain_transaction_object_type,
|
||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
};
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ namespace graphene { namespace chain {
|
|||
class son_wallet_deposit_object;
|
||||
class son_wallet_withdraw_object;
|
||||
class sidechain_address_object;
|
||||
class bitcoin_transaction_object;
|
||||
class sidechain_transaction_object;
|
||||
|
||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||
|
|
@ -252,7 +252,7 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< protocol_ids, son_wallet_deposit_object_type, son_wallet_deposit_object> son_wallet_deposit_id_type;
|
||||
typedef object_id< protocol_ids, son_wallet_withdraw_object_type, son_wallet_withdraw_object> son_wallet_withdraw_id_type;
|
||||
typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type;
|
||||
typedef object_id< protocol_ids, bitcoin_transaction_object_type,bitcoin_transaction_object> bitcoin_transaction_id_type;
|
||||
typedef object_id< protocol_ids, sidechain_transaction_object_type,sidechain_transaction_object> sidechain_transaction_id_type;
|
||||
|
||||
// implementation types
|
||||
class global_property_object;
|
||||
|
|
@ -443,7 +443,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
|||
(son_wallet_deposit_object_type)
|
||||
(son_wallet_withdraw_object_type)
|
||||
(sidechain_address_object_type)
|
||||
(bitcoin_transaction_object_type)
|
||||
(sidechain_transaction_object_type)
|
||||
(OBJECT_TYPE_COUNT)
|
||||
)
|
||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||
|
|
@ -521,7 +521,7 @@ FC_REFLECT_TYPENAME( graphene::chain::son_wallet_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::son_wallet_deposit_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_wallet_withdraw_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::sidechain_address_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::bitcoin_transaction_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::sidechain_transaction_id_type )
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::void_t, )
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
|
|||
26
libraries/chain/include/graphene/chain/sidechain_defs.hpp
Normal file
26
libraries/chain/include/graphene/chain/sidechain_defs.hpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
enum class sidechain_type {
|
||||
bitcoin,
|
||||
ethereum,
|
||||
eos,
|
||||
peerplays
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
using sidechain_type = graphene::chain::sidechain_type;
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT_ENUM(graphene::chain::sidechain_type,
|
||||
(bitcoin)
|
||||
(ethereum)
|
||||
(eos)
|
||||
(peerplays) )
|
||||
|
|
@ -4,32 +4,31 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class bitcoin_transaction_send_evaluator : public evaluator<bitcoin_transaction_send_evaluator>
|
||||
class sidechain_transaction_create_evaluator : public evaluator<sidechain_transaction_create_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bitcoin_transaction_send_operation operation_type;
|
||||
typedef sidechain_transaction_create_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const bitcoin_transaction_send_operation& o);
|
||||
object_id_type do_apply(const bitcoin_transaction_send_operation& o);
|
||||
void_result do_evaluate(const sidechain_transaction_create_operation& o);
|
||||
object_id_type do_apply(const sidechain_transaction_create_operation& o);
|
||||
};
|
||||
|
||||
class bitcoin_transaction_sign_evaluator : public evaluator<bitcoin_transaction_sign_evaluator>
|
||||
class sidechain_transaction_sign_evaluator : public evaluator<sidechain_transaction_sign_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bitcoin_transaction_sign_operation operation_type;
|
||||
typedef sidechain_transaction_sign_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const bitcoin_transaction_sign_operation& o);
|
||||
object_id_type do_apply(const bitcoin_transaction_sign_operation& o);
|
||||
void update_proposal( const bitcoin_transaction_sign_operation& o );
|
||||
void_result do_evaluate(const sidechain_transaction_sign_operation& o);
|
||||
object_id_type do_apply(const sidechain_transaction_sign_operation& o);
|
||||
};
|
||||
|
||||
class bitcoin_send_transaction_process_evaluator : public evaluator<bitcoin_send_transaction_process_evaluator>
|
||||
class sidechain_transaction_send_evaluator : public evaluator<sidechain_transaction_send_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef bitcoin_send_transaction_process_operation operation_type;
|
||||
typedef sidechain_transaction_send_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const bitcoin_send_transaction_process_operation& o);
|
||||
object_id_type do_apply(const bitcoin_send_transaction_process_operation& o);
|
||||
void_result do_evaluate(const sidechain_transaction_send_operation& o);
|
||||
object_id_type do_apply(const sidechain_transaction_send_operation& o);
|
||||
};
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
|
@ -1,39 +1,69 @@
|
|||
#pragma once
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
/**
|
||||
* @class bitcoin_transaction_object
|
||||
* @brief tracks state of bitcoin transaction.
|
||||
* @class sidechain_transaction_object
|
||||
* @brief tracks state of sidechain transaction during signing process.
|
||||
* @ingroup object
|
||||
*/
|
||||
class bitcoin_transaction_object : public abstract_object<bitcoin_transaction_object>
|
||||
class sidechain_transaction_object : public abstract_object<sidechain_transaction_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = bitcoin_transaction_object_type;
|
||||
// Bitcoin structs go here.
|
||||
bool processed = false;
|
||||
fc::flat_map<son_id_type, std::vector<peerplays_sidechain::bytes>> signatures;
|
||||
static const uint8_t type_id = sidechain_transaction_object_type;
|
||||
|
||||
sidechain_type sidechain;
|
||||
object_id_type object_id;
|
||||
std::string transaction;
|
||||
std::vector<std::pair<son_id_type, bool>> signers;
|
||||
|
||||
block_id_type block;
|
||||
bool valid = false;
|
||||
bool complete = false;
|
||||
bool sent = false;
|
||||
};
|
||||
|
||||
struct by_processed;
|
||||
using bitcoin_transaction_multi_index_type = multi_index_container<
|
||||
bitcoin_transaction_object,
|
||||
struct by_object_id;
|
||||
struct by_sidechain_and_complete;
|
||||
struct by_sidechain_and_complete_and_sent;
|
||||
using sidechain_transaction_multi_index_type = multi_index_container<
|
||||
sidechain_transaction_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>,
|
||||
member<object, object_id_type, &object::id>
|
||||
>,
|
||||
ordered_non_unique< tag<by_processed>,
|
||||
member<bitcoin_transaction_object, bool, &bitcoin_transaction_object::processed>
|
||||
ordered_unique< tag<by_object_id>,
|
||||
member<sidechain_transaction_object, object_id_type, &sidechain_transaction_object::object_id>
|
||||
>,
|
||||
ordered_non_unique< tag<by_sidechain_and_complete>,
|
||||
composite_key<sidechain_transaction_object,
|
||||
member<sidechain_transaction_object, sidechain_type, &sidechain_transaction_object::sidechain>,
|
||||
member<sidechain_transaction_object, bool, &sidechain_transaction_object::complete>
|
||||
>
|
||||
>,
|
||||
ordered_non_unique< tag<by_sidechain_and_complete_and_sent>,
|
||||
composite_key<sidechain_transaction_object,
|
||||
member<sidechain_transaction_object, sidechain_type, &sidechain_transaction_object::sidechain>,
|
||||
member<sidechain_transaction_object, bool, &sidechain_transaction_object::complete>,
|
||||
member<sidechain_transaction_object, bool, &sidechain_transaction_object::sent>
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
using bitcoin_transaction_index = generic_index<bitcoin_transaction_object, bitcoin_transaction_multi_index_type>;
|
||||
using sidechain_transaction_index = generic_index<sidechain_transaction_object, sidechain_transaction_multi_index_type>;
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::bitcoin_transaction_object, (graphene::db::object),
|
||||
(processed)(signatures) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::sidechain_transaction_object, (graphene::db::object ),
|
||||
(sidechain)
|
||||
(object_id)
|
||||
(transaction)
|
||||
(signers)
|
||||
(block)
|
||||
(valid)
|
||||
(complete)
|
||||
(sent) )
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
@ -17,7 +18,7 @@ namespace graphene { namespace chain {
|
|||
static const uint8_t type_id = son_wallet_deposit_object_type;
|
||||
|
||||
time_point_sec timestamp;
|
||||
peerplays_sidechain::sidechain_type sidechain;
|
||||
sidechain_type sidechain;
|
||||
std::string sidechain_uid;
|
||||
std::string sidechain_transaction_id;
|
||||
std::string sidechain_from;
|
||||
|
|
@ -45,7 +46,7 @@ namespace graphene { namespace chain {
|
|||
member<object, object_id_type, &object::id>
|
||||
>,
|
||||
ordered_non_unique< tag<by_sidechain>,
|
||||
member<son_wallet_deposit_object, peerplays_sidechain::sidechain_type, &son_wallet_deposit_object::sidechain>
|
||||
member<son_wallet_deposit_object, sidechain_type, &son_wallet_deposit_object::sidechain>
|
||||
>,
|
||||
ordered_unique< tag<by_sidechain_uid>,
|
||||
member<son_wallet_deposit_object, std::string, &son_wallet_deposit_object::sidechain_uid>
|
||||
|
|
@ -55,7 +56,7 @@ namespace graphene { namespace chain {
|
|||
>,
|
||||
ordered_non_unique< tag<by_sidechain_and_processed>,
|
||||
composite_key<son_wallet_deposit_object,
|
||||
member<son_wallet_deposit_object, peerplays_sidechain::sidechain_type, &son_wallet_deposit_object::sidechain>,
|
||||
member<son_wallet_deposit_object, sidechain_type, &son_wallet_deposit_object::sidechain>,
|
||||
member<son_wallet_deposit_object, bool, &son_wallet_deposit_object::processed>
|
||||
>
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/son_info.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
@ -20,7 +20,7 @@ namespace graphene { namespace chain {
|
|||
time_point_sec valid_from;
|
||||
time_point_sec expires;
|
||||
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> addresses;
|
||||
flat_map<sidechain_type, string> addresses;
|
||||
vector<son_info> sons;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
@ -17,12 +18,12 @@ namespace graphene { namespace chain {
|
|||
static const uint8_t type_id = son_wallet_withdraw_object_type;
|
||||
|
||||
time_point_sec timestamp;
|
||||
peerplays_sidechain::sidechain_type sidechain;
|
||||
sidechain_type sidechain;
|
||||
std::string peerplays_uid;
|
||||
std::string peerplays_transaction_id;
|
||||
chain::account_id_type peerplays_from;
|
||||
chain::asset peerplays_asset;
|
||||
peerplays_sidechain::sidechain_type withdraw_sidechain;
|
||||
sidechain_type withdraw_sidechain;
|
||||
std::string withdraw_address;
|
||||
std::string withdraw_currency;
|
||||
safe<int64_t> withdraw_amount;
|
||||
|
|
@ -47,14 +48,14 @@ namespace graphene { namespace chain {
|
|||
member<son_wallet_withdraw_object, std::string, &son_wallet_withdraw_object::peerplays_uid>
|
||||
>,
|
||||
ordered_non_unique< tag<by_withdraw_sidechain>,
|
||||
member<son_wallet_withdraw_object, peerplays_sidechain::sidechain_type, &son_wallet_withdraw_object::withdraw_sidechain>
|
||||
member<son_wallet_withdraw_object, sidechain_type, &son_wallet_withdraw_object::withdraw_sidechain>
|
||||
>,
|
||||
ordered_non_unique< tag<by_processed>,
|
||||
member<son_wallet_withdraw_object, bool, &son_wallet_withdraw_object::processed>
|
||||
>,
|
||||
ordered_non_unique< tag<by_withdraw_sidechain_and_processed>,
|
||||
composite_key<son_wallet_withdraw_object,
|
||||
member<son_wallet_withdraw_object, peerplays_sidechain::sidechain_type, &son_wallet_withdraw_object::withdraw_sidechain>,
|
||||
member<son_wallet_withdraw_object, sidechain_type, &son_wallet_withdraw_object::withdraw_sidechain>,
|
||||
member<son_wallet_withdraw_object, bool, &son_wallet_withdraw_object::processed>
|
||||
>
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,140 +1,128 @@
|
|||
#include <graphene/chain/sidechain_transaction_evaluator.hpp>
|
||||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/sidechain_transaction_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
namespace graphene
|
||||
{
|
||||
namespace chain
|
||||
{
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void_result bitcoin_transaction_send_evaluator::do_evaluate(const bitcoin_transaction_send_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
|
||||
FC_ASSERT( op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer." );
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
void_result sidechain_transaction_create_evaluator::do_evaluate(const sidechain_transaction_create_operation &op)
|
||||
{ try {
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
|
||||
FC_ASSERT( op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer." );
|
||||
|
||||
object_id_type bitcoin_transaction_send_evaluator::do_apply(const bitcoin_transaction_send_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto &new_bitcoin_transaction_object = db().create<bitcoin_transaction_object>([&](bitcoin_transaction_object &obj) {
|
||||
obj.processed = false;
|
||||
obj.signatures = op.signatures;
|
||||
FC_ASSERT((op.object_id.is<son_wallet_id_type>() || op.object_id.is<son_wallet_deposit_id_type>() || op.object_id.is<son_wallet_withdraw_id_type>()), "Invalid object id");
|
||||
|
||||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
|
||||
const auto &sto_obj = sto_idx.find(op.object_id);
|
||||
FC_ASSERT(sto_obj == sto_idx.end(), "Sidechain transaction for a given object is already created");
|
||||
|
||||
FC_ASSERT(!op.transaction.empty(), "Sidechain transaction data not set");
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( ( op ) ) }
|
||||
|
||||
object_id_type sidechain_transaction_create_evaluator::do_apply(const sidechain_transaction_create_operation &op)
|
||||
{ try {
|
||||
const auto &new_sidechain_transaction_object = db().create<sidechain_transaction_object>([&](sidechain_transaction_object &sto) {
|
||||
sto.sidechain = op.sidechain;
|
||||
sto.object_id = op.object_id;
|
||||
sto.transaction = op.transaction;
|
||||
std::transform(op.signers.begin(), op.signers.end(), std::inserter(sto.signers, sto.signers.end()), [](const son_id_type son_id) {
|
||||
return std::make_pair(son_id, false);
|
||||
});
|
||||
return new_bitcoin_transaction_object.id;
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
sto.block = db().head_block_id();
|
||||
sto.valid = true;
|
||||
sto.complete = false;
|
||||
sto.sent = false;
|
||||
});
|
||||
return new_sidechain_transaction_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( ( op ) ) }
|
||||
|
||||
void_result bitcoin_transaction_sign_evaluator::do_evaluate(const bitcoin_transaction_sign_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass
|
||||
const auto &proposal_idx = db().get_index_type<proposal_index>().indices().get<by_id>();
|
||||
const auto &proposal_itr = proposal_idx.find(op.proposal_id);
|
||||
FC_ASSERT(proposal_idx.end() != proposal_itr, "proposal not found");
|
||||
// Checks can this SON approve this proposal
|
||||
auto can_this_son_approve_this_proposal = [&]() {
|
||||
const auto &sidx = db().get_index_type<son_index>().indices().get<graphene::chain::by_account>();
|
||||
auto son_obj = sidx.find(op.payer);
|
||||
if (son_obj == sidx.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// TODO: Check if the SON is included in the PW script.
|
||||
return true;
|
||||
};
|
||||
void_result sidechain_transaction_sign_evaluator::do_evaluate(const sidechain_transaction_sign_operation &op)
|
||||
{ try {
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass
|
||||
|
||||
FC_ASSERT(can_this_son_approve_this_proposal(), "Invalid approval received");
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto &sto_obj = sto_idx.find(op.sidechain_transaction_id);
|
||||
FC_ASSERT(sto_obj != sto_idx.end(), "Sidechain transaction object not found");
|
||||
|
||||
object_id_type bitcoin_transaction_sign_evaluator::do_apply(const bitcoin_transaction_sign_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto &proposal = op.proposal_id(db());
|
||||
const auto &sidx = db().get_index_type<son_index>().indices().get<graphene::chain::by_account>();
|
||||
auto son_obj = sidx.find(op.payer);
|
||||
const auto &son_idx = db().get_index_type<son_index>().indices().get<by_account>();
|
||||
const auto &son_obj = son_idx.find(op.payer);
|
||||
FC_ASSERT(son_obj != son_idx.end(), "SON object not found");
|
||||
|
||||
db().modify(proposal, [&](proposal_object &po) {
|
||||
auto bitcoin_transaction_send_op = po.proposed_transaction.operations[0].get<bitcoin_transaction_send_operation>();
|
||||
bitcoin_transaction_send_op.signatures[son_obj->id] = op.signatures;
|
||||
po.proposed_transaction.operations[0] = bitcoin_transaction_send_op;
|
||||
});
|
||||
|
||||
db().modify( son_obj->statistics( db() ), [&]( son_statistics_object& sso ) {
|
||||
sso.txs_signed += 1;
|
||||
} );
|
||||
|
||||
update_proposal(op);
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
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.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;
|
||||
}
|
||||
|
||||
void_result bitcoin_send_transaction_process_evaluator::do_evaluate(const bitcoin_send_transaction_process_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
|
||||
FC_ASSERT( op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer." );
|
||||
const auto& btidx = db().get_index_type<bitcoin_transaction_index>().indices().get<by_id>();
|
||||
const auto btobj = btidx.find(op.bitcoin_transaction_id);
|
||||
FC_ASSERT(btobj != btidx.end(), "Bitcoin Transaction Object not found");
|
||||
FC_ASSERT(btobj->processed == false, "Bitcoin Transaction already processed");
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
object_id_type bitcoin_send_transaction_process_evaluator::do_apply(const bitcoin_send_transaction_process_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto &btidx = db().get_index_type<bitcoin_transaction_index>().indices().get<by_id>();
|
||||
auto btobj = btidx.find(op.bitcoin_transaction_id);
|
||||
if (btobj != btidx.end())
|
||||
{
|
||||
db().modify(*btobj, [&op](bitcoin_transaction_object &bto) {
|
||||
bto.processed = true;
|
||||
});
|
||||
bool expected = false;
|
||||
for (auto signer : sto_obj->signers) {
|
||||
if (signer.first == son_obj->id) {
|
||||
expected = !signer.second;
|
||||
}
|
||||
return op.bitcoin_transaction_id;
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
FC_ASSERT(expected, "Signer not expected");
|
||||
|
||||
FC_ASSERT(sto_obj->block == op.block, "Sidechain transaction already signed in this block");
|
||||
|
||||
FC_ASSERT(sto_obj->valid, "Transaction not valid");
|
||||
FC_ASSERT(!sto_obj->complete, "Transaction signing completed");
|
||||
FC_ASSERT(!sto_obj->sent, "Transaction already sent");
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( ( op ) ) }
|
||||
|
||||
object_id_type sidechain_transaction_sign_evaluator::do_apply(const sidechain_transaction_sign_operation &op)
|
||||
{ try {
|
||||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
auto sto_obj = sto_idx.find(op.sidechain_transaction_id);
|
||||
|
||||
const auto &son_idx = db().get_index_type<son_index>().indices().get<by_account>();
|
||||
auto son_obj = son_idx.find(op.payer);
|
||||
|
||||
db().modify(*sto_obj, [&](sidechain_transaction_object &sto) {
|
||||
sto.transaction = op.transaction;
|
||||
sto.block = db().head_block_id();
|
||||
sto.complete = op.complete;
|
||||
for (size_t i = 0; i < sto.signers.size(); i++) {
|
||||
if (sto.signers.at(i).first == son_obj->id) {
|
||||
sto.signers.at(i).second = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
db().modify(son_obj->statistics(db()), [&](son_statistics_object& sso) {
|
||||
sso.txs_signed += 1;
|
||||
});
|
||||
|
||||
return op.sidechain_transaction_id;
|
||||
} FC_CAPTURE_AND_RETHROW( ( op ) ) }
|
||||
|
||||
void_result sidechain_transaction_send_evaluator::do_evaluate(const sidechain_transaction_send_operation &op)
|
||||
{ try {
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass
|
||||
|
||||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto &sto_obj = sto_idx.find(op.sidechain_transaction_id);
|
||||
FC_ASSERT(sto_obj != sto_idx.end(), "Sidechain transaction object not found");
|
||||
|
||||
FC_ASSERT(sto_obj->valid, "Transaction not valid");
|
||||
FC_ASSERT(sto_obj->complete, "Transaction signing not complete");
|
||||
FC_ASSERT(!sto_obj->sent, "Transaction already sent");
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( ( op ) ) }
|
||||
|
||||
object_id_type sidechain_transaction_send_evaluator::do_apply(const sidechain_transaction_send_operation &op)
|
||||
{ try {
|
||||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
auto sto_obj = sto_idx.find(op.sidechain_transaction_id);
|
||||
|
||||
db().modify(*sto_obj, [&](sidechain_transaction_object &sto) {
|
||||
sto.block = db().head_block_id();
|
||||
sto.sent = true;
|
||||
});
|
||||
|
||||
return op.sidechain_transaction_id;
|
||||
} FC_CAPTURE_AND_RETHROW( ( op ) ) }
|
||||
|
||||
} // namespace chain
|
||||
} // namespace graphene
|
||||
|
|
|
|||
|
|
@ -23,21 +23,22 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de
|
|||
const auto& idx = db().get_index_type<son_wallet_deposit_index>().indices().get<by_sidechain_uid>();
|
||||
auto itr = idx.find(op.sidechain_uid);
|
||||
if (itr == idx.end()) {
|
||||
const auto& new_son_wallet_deposit_object = db().create<son_wallet_deposit_object>( [&]( son_wallet_deposit_object& swto ){
|
||||
swto.timestamp = op.timestamp;
|
||||
swto.sidechain = op.sidechain;
|
||||
swto.sidechain_uid = op.sidechain_uid;
|
||||
swto.sidechain_transaction_id = op.sidechain_transaction_id;
|
||||
swto.sidechain_from = op.sidechain_from;
|
||||
swto.sidechain_to = op.sidechain_to;
|
||||
swto.sidechain_amount = op.sidechain_amount;
|
||||
swto.peerplays_from = op.peerplays_from;
|
||||
swto.peerplays_to = op.peerplays_to;
|
||||
swto.peerplays_asset = op.peerplays_asset;
|
||||
const auto& new_son_wallet_deposit_object = db().create<son_wallet_deposit_object>( [&]( son_wallet_deposit_object& swdo ){
|
||||
swdo.timestamp = op.timestamp;
|
||||
swdo.sidechain = op.sidechain;
|
||||
swdo.sidechain_uid = op.sidechain_uid;
|
||||
swdo.sidechain_transaction_id = op.sidechain_transaction_id;
|
||||
swdo.sidechain_from = op.sidechain_from;
|
||||
swdo.sidechain_to = op.sidechain_to;
|
||||
swdo.sidechain_currency = op.sidechain_currency;
|
||||
swdo.sidechain_amount = op.sidechain_amount;
|
||||
swdo.peerplays_from = op.peerplays_from;
|
||||
swdo.peerplays_to = op.peerplays_to;
|
||||
swdo.peerplays_asset = op.peerplays_asset;
|
||||
|
||||
auto &gpo = db().get_global_properties();
|
||||
for (auto &si : gpo.active_sons) {
|
||||
swto.expected_reports.insert(si.son_id);
|
||||
swdo.expected_reports.insert(si.son_id);
|
||||
|
||||
auto stats_itr = db().get_index_type<son_stats_index>().indices().get<by_owner>().find(si.son_id);
|
||||
db().modify(*stats_itr, [&op, &si](son_statistics_object &sso) {
|
||||
|
|
@ -48,14 +49,14 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de
|
|||
});
|
||||
}
|
||||
|
||||
swto.received_reports.insert(op.son_id);
|
||||
swdo.received_reports.insert(op.son_id);
|
||||
|
||||
swto.processed = false;
|
||||
swdo.processed = false;
|
||||
});
|
||||
return new_son_wallet_deposit_object.id;
|
||||
} else {
|
||||
db().modify(*itr, [&op](son_wallet_deposit_object &swto) {
|
||||
swto.received_reports.insert(op.son_id);
|
||||
db().modify(*itr, [&op](son_wallet_deposit_object &swdo) {
|
||||
swdo.received_reports.insert(op.son_id);
|
||||
});
|
||||
auto stats_itr = db().get_index_type<son_stats_index>().indices().get<by_owner>().find(op.son_id);
|
||||
db().modify(*stats_itr, [&op](son_statistics_object &sso) {
|
||||
|
|
@ -73,47 +74,8 @@ void_result process_son_wallet_deposit_evaluator::do_evaluate(const son_wallet_d
|
|||
const auto& idx = db().get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
|
||||
const auto& itr = idx.find(op.son_wallet_deposit_id);
|
||||
FC_ASSERT(itr != idx.end(), "Son wallet deposit not found");
|
||||
|
||||
const database& d = db();
|
||||
|
||||
const account_object& from_account = itr->peerplays_to(d); // reversed, for deposit
|
||||
const account_object& to_account = itr->peerplays_from(d); // reversed, for deposit
|
||||
const asset_object& asset_type = itr->peerplays_asset.asset_id(d);
|
||||
|
||||
try {
|
||||
|
||||
GRAPHENE_ASSERT(
|
||||
is_authorized_asset( d, from_account, asset_type ),
|
||||
transfer_from_account_not_whitelisted,
|
||||
"'from' account ${from} is not whitelisted for asset ${asset}",
|
||||
("from",from_account.id)
|
||||
("asset",itr->peerplays_asset.asset_id)
|
||||
);
|
||||
GRAPHENE_ASSERT(
|
||||
is_authorized_asset( d, to_account, asset_type ),
|
||||
transfer_to_account_not_whitelisted,
|
||||
"'to' account ${to} is not whitelisted for asset ${asset}",
|
||||
("to",to_account.id)
|
||||
("asset",itr->peerplays_asset.asset_id)
|
||||
);
|
||||
|
||||
if( asset_type.is_transfer_restricted() )
|
||||
{
|
||||
GRAPHENE_ASSERT(
|
||||
from_account.id == asset_type.issuer || to_account.id == asset_type.issuer,
|
||||
transfer_restricted_transfer_asset,
|
||||
"Asset {asset} has transfer_restricted flag enabled",
|
||||
("asset", itr->peerplays_asset.asset_id)
|
||||
);
|
||||
}
|
||||
|
||||
bool insufficient_balance = d.get_balance( from_account, asset_type ).amount >= itr->peerplays_asset.amount;
|
||||
FC_ASSERT( insufficient_balance,
|
||||
"Insufficient Balance: ${balance}, unable to transfer '${total_transfer}' from account '${a}' to '${t}'",
|
||||
("a",from_account.name)("t",to_account.name)("total_transfer",d.to_pretty_string(itr->peerplays_asset))("balance",d.to_pretty_string(d.get_balance(from_account, asset_type))) );
|
||||
|
||||
return void_result();
|
||||
} FC_RETHROW_EXCEPTIONS( error, "Unable to transfer ${a} from ${f} to ${t}", ("a",d.to_pretty_string(itr->peerplays_asset))("f",from_account.name)("t",to_account.name) );
|
||||
FC_ASSERT(!itr->processed, "Son wallet deposit is already processed");
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type process_son_wallet_deposit_evaluator::do_apply(const son_wallet_deposit_process_operation& op)
|
||||
|
|
@ -122,17 +84,9 @@ object_id_type process_son_wallet_deposit_evaluator::do_apply(const son_wallet_d
|
|||
auto itr = idx.find(op.son_wallet_deposit_id);
|
||||
if(itr != idx.end())
|
||||
{
|
||||
if (itr->processed == false) {
|
||||
db().modify(*itr, [&op](son_wallet_deposit_object &swto) {
|
||||
swto.processed = true;
|
||||
});
|
||||
|
||||
const account_id_type from_account = itr->peerplays_to; // reversed, for deposit
|
||||
const account_id_type to_account = itr->peerplays_from; // reversed, for deposit
|
||||
|
||||
db().adjust_balance( from_account, -itr->peerplays_asset );
|
||||
db().adjust_balance( to_account, itr->peerplays_asset );
|
||||
}
|
||||
db().modify(*itr, [&op](son_wallet_deposit_object &swdo) {
|
||||
swdo.processed = true;
|
||||
});
|
||||
}
|
||||
return op.son_wallet_deposit_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ void_result process_son_wallet_withdraw_evaluator::do_evaluate(const son_wallet_
|
|||
const auto& idx = db().get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
|
||||
const auto& itr = idx.find(op.son_wallet_withdraw_id);
|
||||
FC_ASSERT(itr != idx.end(), "Son wallet withdraw not found");
|
||||
FC_ASSERT(!itr->processed, "Son wallet withdraw is already processed");
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
@ -82,11 +83,9 @@ object_id_type process_son_wallet_withdraw_evaluator::do_apply(const son_wallet_
|
|||
auto itr = idx.find(op.son_wallet_withdraw_id);
|
||||
if(itr != idx.end())
|
||||
{
|
||||
if (itr->processed == false) {
|
||||
db().modify(*itr, [&op](son_wallet_withdraw_object &swto) {
|
||||
swto.processed = true;
|
||||
});
|
||||
}
|
||||
db().modify(*itr, [&op](son_wallet_withdraw_object &swwo) {
|
||||
swwo.processed = true;
|
||||
});
|
||||
}
|
||||
return op.son_wallet_withdraw_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
|
|
|||
|
|
@ -10,16 +10,10 @@
|
|||
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
enum class sidechain_type {
|
||||
bitcoin,
|
||||
ethereum,
|
||||
eos,
|
||||
peerplays
|
||||
};
|
||||
|
||||
using bytes = std::vector<unsigned char>;
|
||||
|
||||
struct prev_out {
|
||||
|
|
@ -76,5 +70,3 @@ struct sidechain_event_data {
|
|||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
||||
FC_REFLECT_ENUM(graphene::peerplays_sidechain::sidechain_type, (bitcoin)(ethereum)(eos)(peerplays))
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <graphene/chain/son_object.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
using namespace chain;
|
||||
|
||||
namespace detail {
|
||||
|
|
@ -26,8 +27,9 @@ public:
|
|||
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
|
||||
|
||||
std::set<chain::son_id_type> &get_sons();
|
||||
son_id_type &get_current_son_id();
|
||||
son_object get_son_object(son_id_type son_id);
|
||||
const son_id_type get_current_son_id();
|
||||
const son_object get_current_son_object();
|
||||
const son_object get_son_object(son_id_type son_id);
|
||||
bool is_active_son(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@
|
|||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <fc/signals.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/chain/sidechain_transaction_object.hpp>
|
||||
#include <graphene/chain/son_wallet_deposit_object.hpp>
|
||||
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
|
||||
|
|
@ -15,7 +20,7 @@ public:
|
|||
sidechain_net_handler(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options);
|
||||
virtual ~sidechain_net_handler();
|
||||
|
||||
graphene::peerplays_sidechain::sidechain_type get_sidechain();
|
||||
sidechain_type get_sidechain();
|
||||
std::vector<std::string> get_sidechain_deposit_addresses();
|
||||
std::vector<std::string> get_sidechain_withdraw_addresses();
|
||||
std::string get_private_key(std::string public_key);
|
||||
|
|
@ -23,23 +28,22 @@ public:
|
|||
void sidechain_event_data_received(const sidechain_event_data &sed);
|
||||
void process_deposits();
|
||||
void process_withdrawals();
|
||||
void process_sidechain_transactions();
|
||||
void send_sidechain_transactions();
|
||||
|
||||
virtual void recreate_primary_wallet() = 0;
|
||||
virtual void process_deposit(const son_wallet_deposit_object &swdo) = 0;
|
||||
virtual void process_withdrawal(const son_wallet_withdraw_object &swwo) = 0;
|
||||
virtual bool process_deposit(const son_wallet_deposit_object &swdo) = 0;
|
||||
virtual bool process_withdrawal(const son_wallet_withdraw_object &swwo) = 0;
|
||||
virtual std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete) = 0;
|
||||
virtual bool send_sidechain_transaction(const sidechain_transaction_object &sto) = 0;
|
||||
|
||||
protected:
|
||||
peerplays_sidechain_plugin &plugin;
|
||||
graphene::chain::database &database;
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain;
|
||||
sidechain_type sidechain;
|
||||
|
||||
std::map<std::string, std::string> private_keys;
|
||||
|
||||
virtual std::string create_multisignature_wallet(const std::vector<std::string> public_keys) = 0;
|
||||
virtual std::string transfer(const std::string &from, const std::string &to, const uint64_t amount) = 0;
|
||||
virtual std::string sign_transaction(const std::string &transaction) = 0;
|
||||
virtual std::string send_transaction(const std::string &transaction) = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include <fc/network/http/connection.hpp>
|
||||
#include <fc/signals.hpp>
|
||||
#include <graphene/chain/son_wallet_deposit_object.hpp>
|
||||
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
|
|
@ -22,23 +20,27 @@ public:
|
|||
class bitcoin_rpc_client {
|
||||
public:
|
||||
bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password);
|
||||
bool connection_is_not_defined() const;
|
||||
|
||||
std::string addmultisigaddress(const std::vector<std::string> public_keys);
|
||||
std::string addmultisigaddress(const uint32_t nrequired, const std::vector<std::string> public_keys);
|
||||
std::string createpsbt(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs);
|
||||
std::string createrawtransaction(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs);
|
||||
std::string createwallet(const std::string &wallet_name);
|
||||
std::string decodepsbt(std::string const &tx_psbt);
|
||||
std::string decoderawtransaction(std::string const &tx_hex);
|
||||
std::string encryptwallet(const std::string &passphrase);
|
||||
uint64_t estimatesmartfee();
|
||||
std::string finalizepsbt(std::string const &tx_psbt);
|
||||
std::string getaddressinfo(const std::string &address);
|
||||
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
|
||||
void importaddress(const std::string &address_or_script);
|
||||
std::vector<btc_txout> listunspent();
|
||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount);
|
||||
std::string loadwallet(const std::string &filename);
|
||||
void sendrawtransaction(const std::string &tx_hex);
|
||||
std::string signrawtransactionwithkey(const std::string &tx_hash, const std::string &private_key);
|
||||
bool sendrawtransaction(const std::string &tx_hex);
|
||||
std::string signrawtransactionwithwallet(const std::string &tx_hash);
|
||||
std::string unloadwallet(const std::string &filename);
|
||||
std::string walletlock();
|
||||
std::string walletprocesspsbt(std::string const &tx_psbt);
|
||||
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60);
|
||||
|
||||
private:
|
||||
|
|
@ -59,9 +61,6 @@ private:
|
|||
class zmq_listener {
|
||||
public:
|
||||
zmq_listener(std::string _ip, uint32_t _zmq);
|
||||
bool connection_is_not_defined() const {
|
||||
return zmq_port == 0;
|
||||
}
|
||||
|
||||
fc::signal<void(const std::string &)> event_received;
|
||||
|
||||
|
|
@ -84,8 +83,10 @@ public:
|
|||
virtual ~sidechain_net_handler_bitcoin();
|
||||
|
||||
void recreate_primary_wallet();
|
||||
void process_deposit(const son_wallet_deposit_object &swdo);
|
||||
void process_withdrawal(const son_wallet_withdraw_object &swwo);
|
||||
bool process_deposit(const son_wallet_deposit_object &swdo);
|
||||
bool process_withdrawal(const son_wallet_withdraw_object &swwo);
|
||||
std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete);
|
||||
bool send_sidechain_transaction(const sidechain_transaction_object &sto);
|
||||
|
||||
private:
|
||||
std::string ip;
|
||||
|
|
@ -99,17 +100,24 @@ private:
|
|||
std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
|
||||
std::unique_ptr<zmq_listener> listener;
|
||||
|
||||
std::string create_multisignature_wallet(const std::vector<std::string> public_keys);
|
||||
std::string transfer(const std::string &from, const std::string &to, const uint64_t amount);
|
||||
std::string sign_transaction(const std::string &transaction);
|
||||
std::string send_transaction(const std::string &transaction);
|
||||
std::string sign_and_send_transaction_with_wallet(const std::string &tx_json);
|
||||
std::string transfer_all_btc(const std::string &from_address, const std::string &to_address);
|
||||
std::string transfer_deposit_to_primary_wallet(const son_wallet_deposit_object &swdo);
|
||||
std::string transfer_withdrawal_from_primary_wallet(const son_wallet_withdraw_object &swwo);
|
||||
fc::future<void> on_changed_objects_task;
|
||||
|
||||
std::string create_transaction(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs);
|
||||
std::string sign_transaction(const std::string &tx, bool &complete);
|
||||
bool send_transaction(const std::string &tx);
|
||||
|
||||
std::string create_transaction_raw(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs);
|
||||
std::string create_transaction_psbt(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs);
|
||||
std::string create_transaction_standalone(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs);
|
||||
|
||||
std::string sign_transaction_raw(const std::string &tx, bool &complete);
|
||||
std::string sign_transaction_psbt(const std::string &tx, bool &complete);
|
||||
std::string sign_transaction_standalone(const std::string &tx, bool &complete);
|
||||
|
||||
void handle_event(const std::string &event_data);
|
||||
std::vector<info_for_vin> extract_info_from_block(const std::string &_block);
|
||||
void on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||
void on_changed_objects_cb(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -14,15 +14,12 @@ public:
|
|||
virtual ~sidechain_net_handler_peerplays();
|
||||
|
||||
void recreate_primary_wallet();
|
||||
void process_deposit(const son_wallet_deposit_object &swdo);
|
||||
void process_withdrawal(const son_wallet_withdraw_object &swwo);
|
||||
bool process_deposit(const son_wallet_deposit_object &swdo);
|
||||
bool process_withdrawal(const son_wallet_withdraw_object &swwo);
|
||||
std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete);
|
||||
bool send_sidechain_transaction(const sidechain_transaction_object &sto);
|
||||
|
||||
private:
|
||||
std::string create_multisignature_wallet(const std::vector<std::string> public_keys);
|
||||
std::string transfer(const std::string &from, const std::string &to, const uint64_t amount);
|
||||
std::string sign_transaction(const std::string &transaction);
|
||||
std::string send_transaction(const std::string &transaction);
|
||||
|
||||
void on_applied_block(const signed_block &b);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
|
|
@ -15,10 +15,12 @@ public:
|
|||
sidechain_net_manager(peerplays_sidechain_plugin &_plugin);
|
||||
virtual ~sidechain_net_manager();
|
||||
|
||||
bool create_handler(peerplays_sidechain::sidechain_type sidechain, const boost::program_options::variables_map &options);
|
||||
bool create_handler(sidechain_type sidechain, const boost::program_options::variables_map &options);
|
||||
void recreate_primary_wallet();
|
||||
void process_deposits();
|
||||
void process_withdrawals();
|
||||
void process_sidechain_transactions();
|
||||
void send_sidechain_transactions();
|
||||
|
||||
private:
|
||||
peerplays_sidechain_plugin &plugin;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@ public:
|
|||
void plugin_startup();
|
||||
|
||||
std::set<chain::son_id_type> &get_sons();
|
||||
son_id_type &get_current_son_id();
|
||||
son_object get_son_object(son_id_type son_id);
|
||||
const son_id_type get_current_son_id();
|
||||
const son_object get_current_son_object();
|
||||
const son_object get_son_object(son_id_type son_id);
|
||||
bool is_active_son(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
|
||||
|
|
@ -49,6 +50,8 @@ public:
|
|||
void recreate_primary_wallet();
|
||||
void process_deposits();
|
||||
void process_withdrawals();
|
||||
void process_sidechain_transactions();
|
||||
void send_sidechain_transactions();
|
||||
|
||||
private:
|
||||
peerplays_sidechain_plugin &plugin;
|
||||
|
|
@ -67,6 +70,7 @@ private:
|
|||
fc::future<void> _heartbeat_task;
|
||||
fc::future<void> _son_processing_task;
|
||||
|
||||
bool first_block_skipped;
|
||||
void on_applied_block(const signed_block &b);
|
||||
};
|
||||
|
||||
|
|
@ -76,7 +80,8 @@ peerplays_sidechain_plugin_impl::peerplays_sidechain_plugin_impl(peerplays_sidec
|
|||
config_ready_bitcoin(false),
|
||||
config_ready_peerplays(false),
|
||||
current_son_id(son_id_type(std::numeric_limits<uint32_t>().max())),
|
||||
net_manager(nullptr) {
|
||||
net_manager(nullptr),
|
||||
first_block_skipped(false) {
|
||||
}
|
||||
|
||||
peerplays_sidechain_plugin_impl::~peerplays_sidechain_plugin_impl() {
|
||||
|
|
@ -110,9 +115,9 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
cli.add_options()("son-ids", bpo::value<string>(), ("IDs of multiple SONs controlled by this node (e.g. [" + son_id_example + ", " + son_id_example2 + "], quotes are required)").c_str());
|
||||
cli.add_options()("peerplays-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
|
||||
"Tuple of [PublicKey, WIF private key] (may specify multiple times)");
|
||||
cli.add_options()("bitcoin-node-ip", bpo::value<string>()->default_value("99.79.189.95"), "IP address of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-ip", bpo::value<string>()->default_value("127.0.0.1"), "IP address of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-zmq-port", bpo::value<uint32_t>()->default_value(11111), "ZMQ port of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-rpc-port", bpo::value<uint32_t>()->default_value(22222), "RPC port of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-rpc-port", bpo::value<uint32_t>()->default_value(8332), "RPC port of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-rpc-user", bpo::value<string>()->default_value("1"), "Bitcoin RPC user");
|
||||
cli.add_options()("bitcoin-node-rpc-password", bpo::value<string>()->default_value("1"), "Bitcoin RPC password");
|
||||
cli.add_options()("bitcoin-wallet", bpo::value<string>(), "Bitcoin wallet");
|
||||
|
|
@ -222,11 +227,15 @@ std::set<chain::son_id_type> &peerplays_sidechain_plugin_impl::get_sons() {
|
|||
return sons;
|
||||
}
|
||||
|
||||
son_id_type &peerplays_sidechain_plugin_impl::get_current_son_id() {
|
||||
const son_id_type peerplays_sidechain_plugin_impl::get_current_son_id() {
|
||||
return current_son_id;
|
||||
}
|
||||
|
||||
son_object peerplays_sidechain_plugin_impl::get_son_object(son_id_type son_id) {
|
||||
const son_object peerplays_sidechain_plugin_impl::get_current_son_object() {
|
||||
return get_son_object(current_son_id);
|
||||
}
|
||||
|
||||
const son_object peerplays_sidechain_plugin_impl::get_son_object(son_id_type son_id) {
|
||||
const auto &idx = plugin.database().get_index_type<chain::son_index>().indices().get<by_id>();
|
||||
auto son_obj = idx.find(son_id);
|
||||
if (son_obj == idx.end())
|
||||
|
|
@ -285,7 +294,7 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() {
|
|||
for (son_id_type son_id : sons) {
|
||||
if (is_active_son(son_id) || get_son_object(son_id).status == chain::son_status::in_maintenance) {
|
||||
|
||||
ilog("peerplays_sidechain_plugin: sending heartbeat for SON ${son}", ("son", son_id));
|
||||
ilog("Sending heartbeat for SON ${son}", ("son", son_id));
|
||||
chain::son_heartbeat_operation op;
|
||||
op.owner_account = get_son_object(son_id).son_account;
|
||||
op.son_id = son_id;
|
||||
|
|
@ -298,7 +307,7 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() {
|
|||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception e) {
|
||||
ilog("peerplays_sidechain_plugin_impl: sending heartbeat failed with exception ${e}", ("e", e.what()));
|
||||
elog("Sending heartbeat failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -324,34 +333,56 @@ void peerplays_sidechain_plugin_impl::son_processing() {
|
|||
return;
|
||||
}
|
||||
|
||||
chain::son_id_type next_son_id = plugin.database().get_scheduled_son(1);
|
||||
ilog("peerplays_sidechain_plugin_impl: Scheduled SON ${son}", ("son", next_son_id));
|
||||
fc::time_point now_fine = fc::time_point::now();
|
||||
fc::time_point_sec now = now_fine + fc::microseconds(500000);
|
||||
if (plugin.database().get_slot_time(1) < now) {
|
||||
return; // Not synced
|
||||
}
|
||||
|
||||
// Tasks that are executed by all active SONs, no matter if scheduled
|
||||
// E.g. sending approvals and signing
|
||||
approve_proposals();
|
||||
chain::son_id_type scheduled_son_id = plugin.database().get_scheduled_son(1);
|
||||
ilog("Scheduled SON: ${scheduled_son_id} Now: ${now} ",
|
||||
("scheduled_son_id", scheduled_son_id)("now", now));
|
||||
|
||||
// Tasks that are executed by scheduled and active SON
|
||||
if (sons.find(next_son_id) != sons.end()) {
|
||||
for (son_id_type son_id : plugin.get_sons()) {
|
||||
|
||||
current_son_id = next_son_id;
|
||||
if (plugin.is_active_son(son_id)) {
|
||||
|
||||
create_son_down_proposals();
|
||||
current_son_id = son_id;
|
||||
|
||||
create_son_deregister_proposals();
|
||||
// Tasks that are executed by all active SONs, no matter if scheduled
|
||||
// E.g. sending approvals and signing (only signing that can be done in parallel)
|
||||
approve_proposals();
|
||||
|
||||
recreate_primary_wallet();
|
||||
// Tasks that are executed by scheduled and active SON
|
||||
if (current_son_id == scheduled_son_id) {
|
||||
|
||||
process_deposits();
|
||||
create_son_down_proposals();
|
||||
|
||||
process_withdrawals();
|
||||
create_son_deregister_proposals();
|
||||
|
||||
recreate_primary_wallet();
|
||||
|
||||
process_deposits();
|
||||
|
||||
process_withdrawals();
|
||||
|
||||
process_sidechain_transactions();
|
||||
|
||||
send_sidechain_transactions();
|
||||
}
|
||||
} else {
|
||||
// Tasks that are executed by previously active SONs
|
||||
// E.g. sending approvals and signing that SON was required to do while it was active
|
||||
//approve_leftover_proposals(); ???
|
||||
//process_leftover_sidechain_transactions(); ???
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::approve_proposals() {
|
||||
|
||||
auto approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_id_type &proposal_id) {
|
||||
ilog("peerplays_sidechain_plugin: sending approval for ${p} from ${s}", ("p", proposal_id)("s", son_id));
|
||||
ilog("Sending approval for ${p} from ${s}", ("p", proposal_id)("s", son_id));
|
||||
chain::proposal_update_operation puo;
|
||||
puo.fee_paying_account = get_son_object(son_id).son_account;
|
||||
puo.proposal = proposal_id;
|
||||
|
|
@ -364,7 +395,7 @@ void peerplays_sidechain_plugin_impl::approve_proposals() {
|
|||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception e) {
|
||||
ilog("peerplays_sidechain_plugin_impl: sending approval failed with exception ${e}", ("e", e.what()));
|
||||
elog("Sending approval failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -378,57 +409,71 @@ void peerplays_sidechain_plugin_impl::approve_proposals() {
|
|||
}
|
||||
|
||||
for (const auto proposal_id : proposals) {
|
||||
for (son_id_type son_id : sons) {
|
||||
if (!is_active_son(son_id)) {
|
||||
|
||||
const object *obj = plugin.database().find_object(proposal_id);
|
||||
const chain::proposal_object *proposal_ptr = dynamic_cast<const chain::proposal_object *>(obj);
|
||||
if (proposal_ptr == nullptr) {
|
||||
continue;
|
||||
}
|
||||
const proposal_object proposal = *proposal_ptr;
|
||||
|
||||
if (proposal.available_active_approvals.find(get_current_son_object().son_account) != proposal.available_active_approvals.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1) {
|
||||
int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which();
|
||||
|
||||
if (op_idx_0 == chain::operation::tag<chain::son_report_down_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
const object *obj = plugin.database().find_object(proposal_id);
|
||||
const chain::proposal_object *proposal_ptr = dynamic_cast<const chain::proposal_object *>(obj);
|
||||
if (proposal_ptr == nullptr) {
|
||||
continue;
|
||||
}
|
||||
const proposal_object proposal = *proposal_ptr;
|
||||
|
||||
if (proposal.available_active_approvals.find(get_son_object(son_id).son_account) != proposal.available_active_approvals.end()) {
|
||||
if (op_idx_0 == chain::operation::tag<chain::son_delete_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_report_down_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
if (op_idx_0 == chain::operation::tag<chain::son_wallet_update_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_delete_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
if (op_idx_0 == chain::operation::tag<chain::son_wallet_deposit_create_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_update_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
if (op_idx_0 == chain::operation::tag<chain::son_wallet_withdraw_create_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_deposit_create_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
if (op_idx_0 == chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_deposit_process_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_withdraw_create_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value) {
|
||||
approve_proposal(son_id, proposal.id);
|
||||
if (op_idx_0 == chain::operation::tag<chain::sidechain_transaction_create_operation>::value) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (proposal.proposed_transaction.operations.size() == 2) {
|
||||
int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which();
|
||||
int32_t op_idx_1 = proposal.proposed_transaction.operations[1].which();
|
||||
|
||||
if ((op_idx_0 == chain::operation::tag<chain::son_wallet_deposit_process_operation>::value) &&
|
||||
(op_idx_1 == chain::operation::tag<chain::transfer_operation>::value)) {
|
||||
approve_proposal(get_current_son_id(), proposal.id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ilog("==================================================");
|
||||
ilog("Proposal not approved ${proposal}", ("proposal", proposal));
|
||||
ilog("==================================================");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -443,8 +488,8 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
|
|||
son_down_op.down_ts = last_active_ts;
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = get_son_object(plugin.get_current_son_id()).son_account;
|
||||
proposal_op.proposed_ops.push_back(op_wrapper(son_down_op));
|
||||
proposal_op.fee_paying_account = get_current_son_object().son_account;
|
||||
proposal_op.proposed_ops.emplace_back(op_wrapper(son_down_op));
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(d.head_block_time().sec_since_epoch() + lifetime);
|
||||
return proposal_op;
|
||||
|
|
@ -467,7 +512,7 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
|
|||
int64_t down_threshold = gpo.parameters.son_down_time();
|
||||
if (((son_obj->status == chain::son_status::active) || (son_obj->status == chain::son_status::request_maintenance)) &&
|
||||
((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) {
|
||||
ilog("peerplays_sidechain_plugin: sending son down proposal for ${t} from ${s}", ("t", std::string(object_id_type(son_obj->id)))("s", std::string(object_id_type(my_son_id))));
|
||||
ilog("Sending son down proposal for ${t} from ${s}", ("t", std::string(object_id_type(son_obj->id)))("s", std::string(object_id_type(my_son_id))));
|
||||
chain::proposal_create_operation op = create_son_down_proposal(son_inf.son_id, last_active_ts);
|
||||
chain::signed_transaction trx = d.create_signed_transaction(plugin.get_private_key(get_son_object(my_son_id).signing_key), op);
|
||||
fc::future<bool> fut = fc::async([&]() {
|
||||
|
|
@ -477,7 +522,7 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
|
|||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception e) {
|
||||
ilog("peerplays_sidechain_plugin_impl: sending son down proposal failed with exception ${e}", ("e", e.what()));
|
||||
elog("Sending son down proposal failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -502,7 +547,7 @@ void peerplays_sidechain_plugin_impl::create_son_deregister_proposals() {
|
|||
auto op = d.create_son_deregister_proposal(son, get_son_object(my_son_id).son_account);
|
||||
if (op.valid()) {
|
||||
// Signing and pushing into the txs to be included in the block
|
||||
ilog("peerplays_sidechain_plugin: sending son deregister proposal for ${p} from ${s}", ("p", son)("s", my_son_id));
|
||||
ilog("Sending son deregister proposal for ${p} from ${s}", ("p", son)("s", my_son_id));
|
||||
chain::signed_transaction trx = d.create_signed_transaction(plugin.get_private_key(get_son_object(my_son_id).signing_key), *op);
|
||||
fc::future<bool> fut = fc::async([&]() {
|
||||
try {
|
||||
|
|
@ -511,7 +556,7 @@ void peerplays_sidechain_plugin_impl::create_son_deregister_proposals() {
|
|||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception e) {
|
||||
ilog("peerplays_sidechain_plugin_impl: sending son dereg proposal failed with exception ${e}", ("e", e.what()));
|
||||
elog("Sending son deregister proposal failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -534,11 +579,23 @@ void peerplays_sidechain_plugin_impl::process_withdrawals() {
|
|||
net_manager->process_withdrawals();
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::on_applied_block(const signed_block &b) {
|
||||
schedule_son_processing();
|
||||
void peerplays_sidechain_plugin_impl::process_sidechain_transactions() {
|
||||
net_manager->process_sidechain_transactions();
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
void peerplays_sidechain_plugin_impl::send_sidechain_transactions() {
|
||||
net_manager->send_sidechain_transactions();
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::on_applied_block(const signed_block &b) {
|
||||
if (first_block_skipped) {
|
||||
schedule_son_processing();
|
||||
} else {
|
||||
first_block_skipped = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
peerplays_sidechain_plugin::peerplays_sidechain_plugin() :
|
||||
my(new detail::peerplays_sidechain_plugin_impl(*this)) {
|
||||
|
|
@ -559,24 +616,30 @@ void peerplays_sidechain_plugin::plugin_set_program_options(
|
|||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options::variables_map &options) {
|
||||
ilog("peerplays sidechain plugin: plugin_initialize()");
|
||||
ilog("peerplays sidechain plugin: plugin_initialize() begin");
|
||||
my->plugin_initialize(options);
|
||||
ilog("peerplays sidechain plugin: plugin_initialize() end");
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_startup() {
|
||||
ilog("peerplays sidechain plugin: plugin_startup()");
|
||||
ilog("peerplays sidechain plugin: plugin_startup() begin");
|
||||
my->plugin_startup();
|
||||
ilog("peerplays sidechain plugin: plugin_startup() end");
|
||||
}
|
||||
|
||||
std::set<chain::son_id_type> &peerplays_sidechain_plugin::get_sons() {
|
||||
return my->get_sons();
|
||||
}
|
||||
|
||||
son_id_type &peerplays_sidechain_plugin::get_current_son_id() {
|
||||
const son_id_type peerplays_sidechain_plugin::get_current_son_id() {
|
||||
return my->get_current_son_id();
|
||||
}
|
||||
|
||||
son_object peerplays_sidechain_plugin::get_son_object(son_id_type son_id) {
|
||||
const son_object peerplays_sidechain_plugin::get_current_son_object() {
|
||||
return my->get_current_son_object();
|
||||
}
|
||||
|
||||
const son_object peerplays_sidechain_plugin::get_son_object(son_id_type son_id) {
|
||||
return my->get_son_object(son_id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/chain/son_wallet_deposit_object.hpp>
|
||||
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/smart_ref_fwd.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
|
|
@ -16,7 +13,7 @@ sidechain_net_handler::sidechain_net_handler(peerplays_sidechain_plugin &_plugin
|
|||
sidechain_net_handler::~sidechain_net_handler() {
|
||||
}
|
||||
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain_net_handler::get_sidechain() {
|
||||
sidechain_type sidechain_net_handler::get_sidechain() {
|
||||
return sidechain;
|
||||
}
|
||||
|
||||
|
|
@ -94,17 +91,17 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
|||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account;
|
||||
proposal_op.proposed_ops.emplace_back(op_wrapper(op));
|
||||
proposal_op.proposed_ops.emplace_back(op);
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
||||
try {
|
||||
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));
|
||||
} catch (fc::exception e) {
|
||||
ilog("sidechain_net_handler: sending proposal for son wallet deposit create operation by ${son} failed with exception ${e}", ("son", son_id)("e", e.what()));
|
||||
elog("Sending proposal for son wallet deposit create operation by ${son} failed with exception ${e}", ("son", son_id)("e", e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,17 +137,17 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
|||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account;
|
||||
proposal_op.proposed_ops.emplace_back(op_wrapper(op));
|
||||
proposal_op.proposed_ops.emplace_back(op);
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
||||
try {
|
||||
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));
|
||||
} catch (fc::exception e) {
|
||||
ilog("sidechain_net_handler: sending proposal for son wallet withdraw create operation by ${son} failed with exception ${e}", ("son", son_id)("e", e.what()));
|
||||
elog("Sending proposal for son wallet withdraw create operation by ${son} failed with exception ${e}", ("son", son_id)("e", e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -161,83 +158,170 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
|||
}
|
||||
|
||||
void sidechain_net_handler::process_deposits() {
|
||||
const auto &idx = plugin.database().get_index_type<son_wallet_deposit_index>().indices().get<by_sidechain_and_processed>();
|
||||
const auto &idx = database.get_index_type<son_wallet_deposit_index>().indices().get<by_sidechain_and_processed>();
|
||||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, false));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second,
|
||||
[&](const son_wallet_deposit_object &swdo) {
|
||||
ilog("Deposit to process: ${swdo}", ("swdo", swdo));
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const son_wallet_deposit_object &swdo) {
|
||||
ilog("Deposit to process: ${swdo}", ("swdo", swdo));
|
||||
|
||||
process_deposit(swdo);
|
||||
bool process_deposit_result = process_deposit(swdo);
|
||||
|
||||
const chain::global_property_object &gpo = plugin.database().get_global_properties();
|
||||
if (!process_deposit_result) {
|
||||
wlog("Deposit not processed: ${swdo}", ("swdo", swdo));
|
||||
return;
|
||||
}
|
||||
|
||||
son_wallet_deposit_process_operation p_op;
|
||||
p_op.payer = gpo.parameters.son_account();
|
||||
p_op.son_wallet_deposit_id = swdo.id;
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account;
|
||||
proposal_op.proposed_ops.emplace_back(op_wrapper(p_op));
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(plugin.database().head_block_time().sec_since_epoch() + lifetime);
|
||||
son_wallet_deposit_process_operation swdp_op;
|
||||
swdp_op.payer = gpo.parameters.son_account();
|
||||
swdp_op.son_wallet_deposit_id = swdo.id;
|
||||
|
||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
trx.validate();
|
||||
try {
|
||||
plugin.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));
|
||||
} catch (fc::exception e) {
|
||||
ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
});
|
||||
transfer_operation t_op;
|
||||
t_op.fee = asset(2000000);
|
||||
t_op.from = swdo.peerplays_to; // gpo.parameters.son_account()
|
||||
t_op.to = swdo.peerplays_from;
|
||||
t_op.amount = swdo.peerplays_asset;
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
proposal_op.proposed_ops.emplace_back(swdp_op);
|
||||
proposal_op.proposed_ops.emplace_back(t_op);
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
trx.validate();
|
||||
try {
|
||||
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));
|
||||
} catch (fc::exception e) {
|
||||
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sidechain_net_handler::process_withdrawals() {
|
||||
const auto &idx = plugin.database().get_index_type<son_wallet_withdraw_index>().indices().get<by_withdraw_sidechain_and_processed>();
|
||||
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_withdraw_sidechain_and_processed>();
|
||||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, false));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second,
|
||||
[&](const son_wallet_withdraw_object &swwo) {
|
||||
ilog("Withdraw to process: ${swwo}", ("swwo", swwo));
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const son_wallet_withdraw_object &swwo) {
|
||||
ilog("Withdraw to process: ${swwo}", ("swwo", swwo));
|
||||
|
||||
process_withdrawal(swwo);
|
||||
bool process_withdrawal_result = process_withdrawal(swwo);
|
||||
|
||||
const chain::global_property_object &gpo = plugin.database().get_global_properties();
|
||||
if (!process_withdrawal_result) {
|
||||
wlog("Withdraw not processed: ${swwo}", ("swwo", swwo));
|
||||
return;
|
||||
}
|
||||
|
||||
son_wallet_withdraw_process_operation p_op;
|
||||
p_op.payer = gpo.parameters.son_account();
|
||||
p_op.son_wallet_withdraw_id = swwo.id;
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account;
|
||||
proposal_op.proposed_ops.emplace_back(op_wrapper(p_op));
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(plugin.database().head_block_time().sec_since_epoch() + lifetime);
|
||||
son_wallet_withdraw_process_operation swwp_op;
|
||||
swwp_op.payer = gpo.parameters.son_account();
|
||||
swwp_op.son_wallet_withdraw_id = swwo.id;
|
||||
|
||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
trx.validate();
|
||||
try {
|
||||
plugin.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));
|
||||
} catch (fc::exception e) {
|
||||
ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
});
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
proposal_op.proposed_ops.emplace_back(swwp_op);
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
trx.validate();
|
||||
try {
|
||||
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));
|
||||
} catch (fc::exception e) {
|
||||
elog("Sending proposal for withdraw sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sidechain_net_handler::process_sidechain_transactions() {
|
||||
const auto &idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_sidechain_and_complete>();
|
||||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, false));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) {
|
||||
ilog("Sidechain transaction to process: ${sto}", ("sto", sto));
|
||||
|
||||
bool complete = false;
|
||||
std::string processed_sidechain_tx = process_sidechain_transaction(sto, complete);
|
||||
|
||||
if (processed_sidechain_tx.empty()) {
|
||||
wlog("Sidechain transaction not processed: ${sto}", ("sto", sto));
|
||||
return;
|
||||
}
|
||||
|
||||
sidechain_transaction_sign_operation sts_op;
|
||||
sts_op.payer = plugin.get_current_son_object().son_account;
|
||||
sts_op.sidechain_transaction_id = sto.id;
|
||||
sts_op.transaction = processed_sidechain_tx;
|
||||
sts_op.block = sto.block;
|
||||
sts_op.complete = complete;
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), sts_op);
|
||||
trx.validate();
|
||||
try {
|
||||
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));
|
||||
} catch (fc::exception e) {
|
||||
elog("Sending proposal for sidechain transaction sign operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sidechain_net_handler::send_sidechain_transactions() {
|
||||
const auto &idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_sidechain_and_complete_and_sent>();
|
||||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, true, false));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) {
|
||||
ilog("Sidechain transaction to send: ${sto}", ("sto", sto));
|
||||
|
||||
bool sent = send_sidechain_transaction(sto);
|
||||
|
||||
if (!sent) {
|
||||
wlog("Sidechain transaction not sent: ${sto}", ("sto", sto));
|
||||
return;
|
||||
}
|
||||
|
||||
sidechain_transaction_send_operation sts_op;
|
||||
sts_op.payer = plugin.get_current_son_object().son_account;
|
||||
sts_op.sidechain_transaction_id = sto.id;
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), sts_op);
|
||||
trx.validate();
|
||||
try {
|
||||
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));
|
||||
} catch (fc::exception e) {
|
||||
elog("Sending proposal for sidechain transaction send operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sidechain_net_handler::recreate_primary_wallet() {
|
||||
FC_ASSERT(false, "recreate_primary_wallet not implemented");
|
||||
}
|
||||
|
||||
void sidechain_net_handler::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
bool sidechain_net_handler::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
FC_ASSERT(false, "process_deposit not implemented");
|
||||
}
|
||||
|
||||
void sidechain_net_handler::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||
bool sidechain_net_handler::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||
FC_ASSERT(false, "process_withdrawal not implemented");
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler::process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete) {
|
||||
FC_ASSERT(false, "process_sidechain_transaction not implemented");
|
||||
}
|
||||
|
||||
bool sidechain_net_handler::send_sidechain_transaction(const sidechain_transaction_object &sto) {
|
||||
FC_ASSERT(false, "send_sidechain_transaction not implemented");
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/protocol/son_wallet.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/chain/son_info.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
|
||||
|
|
@ -22,7 +21,7 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
|
||||
sidechain_net_handler(_plugin, options) {
|
||||
sidechain = sidechain_type::peerplays;
|
||||
plugin.database().applied_block.connect([&](const signed_block &b) {
|
||||
database.applied_block.connect([&](const signed_block &b) {
|
||||
on_applied_block(b);
|
||||
});
|
||||
}
|
||||
|
|
@ -31,28 +30,24 @@ sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() {
|
|||
}
|
||||
|
||||
void sidechain_net_handler_peerplays::recreate_primary_wallet() {
|
||||
return;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_peerplays::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
bool sidechain_net_handler_peerplays::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_peerplays::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||
bool sidechain_net_handler_peerplays::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_peerplays::create_multisignature_wallet(const std::vector<std::string> public_keys) {
|
||||
return "";
|
||||
std::string sidechain_net_handler_peerplays::process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete) {
|
||||
complete = true;
|
||||
return sto.transaction;
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_peerplays::transfer(const std::string &from, const std::string &to, const uint64_t amount) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_peerplays::sign_transaction(const std::string &transaction) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_peerplays::send_transaction(const std::string &transaction) {
|
||||
return "";
|
||||
bool sidechain_net_handler_peerplays::send_sidechain_transaction(const sidechain_transaction_object &sto) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_peerplays::on_applied_block(const signed_block &b) {
|
||||
|
|
@ -72,18 +67,18 @@ void sidechain_net_handler_peerplays::on_applied_block(const signed_block &b) {
|
|||
std::string sidechain_uid = ss.str();
|
||||
|
||||
sidechain_event_data sed;
|
||||
sed.timestamp = plugin.database().head_block_time();
|
||||
sed.timestamp = database.head_block_time();
|
||||
sed.sidechain = sidechain_type::peerplays;
|
||||
sed.sidechain_uid = sidechain_uid;
|
||||
sed.sidechain_transaction_id = trx.id().str();
|
||||
sed.sidechain_from = fc::to_string(transfer_op.from.space_id) + "." + fc::to_string(transfer_op.from.type_id) + "." + fc::to_string((uint64_t)transfer_op.from.instance);
|
||||
sed.sidechain_to = fc::to_string(transfer_op.to.space_id) + "." + fc::to_string(transfer_op.to.type_id) + "." + fc::to_string((uint64_t)transfer_op.to.instance);
|
||||
sed.sidechain_currency = fc::to_string(transfer_op.amount.asset_id.space_id) + "." + fc::to_string(transfer_op.amount.asset_id.type_id) + "." + fc::to_string((uint64_t)transfer_op.amount.asset_id.instance); //transfer_op.amount.asset_id(plugin.database()).symbol;
|
||||
sed.sidechain_currency = fc::to_string(transfer_op.amount.asset_id.space_id) + "." + fc::to_string(transfer_op.amount.asset_id.type_id) + "." + fc::to_string((uint64_t)transfer_op.amount.asset_id.instance); //transfer_op.amount.asset_id(database).symbol;
|
||||
sed.sidechain_amount = transfer_op.amount.amount;
|
||||
sed.peerplays_from = transfer_op.from;
|
||||
sed.peerplays_to = transfer_op.to;
|
||||
// We should calculate exchange rate between CORE/TEST and other Peerplays asset
|
||||
sed.peerplays_asset = asset(transfer_op.amount.amount / transfer_op.amount.asset_id(plugin.database()).options.core_exchange_rate.quote.amount);
|
||||
sed.peerplays_asset = asset(transfer_op.amount.amount / transfer_op.amount.asset_id(database).options.core_exchange_rate.quote.amount);
|
||||
sidechain_event_data_received(sed);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ sidechain_net_manager::sidechain_net_manager(peerplays_sidechain_plugin &_plugin
|
|||
sidechain_net_manager::~sidechain_net_manager() {
|
||||
}
|
||||
|
||||
bool sidechain_net_manager::create_handler(peerplays_sidechain::sidechain_type sidechain, const boost::program_options::variables_map &options) {
|
||||
bool sidechain_net_manager::create_handler(sidechain_type sidechain, const boost::program_options::variables_map &options) {
|
||||
|
||||
bool ret_val = false;
|
||||
|
||||
|
|
@ -57,4 +57,16 @@ void sidechain_net_manager::process_withdrawals() {
|
|||
}
|
||||
}
|
||||
|
||||
void sidechain_net_manager::process_sidechain_transactions() {
|
||||
for (size_t i = 0; i < net_handlers.size(); i++) {
|
||||
net_handlers.at(i)->process_sidechain_transactions();
|
||||
}
|
||||
}
|
||||
|
||||
void sidechain_net_manager::send_sidechain_transactions() {
|
||||
for (size_t i = 0; i < net_handlers.size(); i++) {
|
||||
net_handlers.at(i)->send_sidechain_transactions();
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
#include <graphene/chain/rock_paper_scissors.hpp>
|
||||
|
||||
#include <graphene/bookie/bookie_api.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <graphene/utilities/git_revision.hpp>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
using namespace graphene::chain;
|
||||
using namespace graphene::chain::test;
|
||||
|
|
|
|||
|
|
@ -1,386 +0,0 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "../common/database_fixture.hpp"
|
||||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/sidechain_transaction_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
using namespace graphene;
|
||||
using namespace graphene::chain;
|
||||
using namespace graphene::chain::test;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(sidechain_transaction_tests, database_fixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bitcoin_transaction_send_test)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
BOOST_TEST_MESSAGE("bitcoin_transaction_send_test");
|
||||
|
||||
generate_blocks(HARDFORK_SON_TIME);
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
ACTORS((alice)(bob));
|
||||
|
||||
upgrade_to_lifetime_member(alice);
|
||||
upgrade_to_lifetime_member(bob);
|
||||
|
||||
transfer(committee_account, alice_id, asset(500000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||
transfer(committee_account, bob_id, asset(500000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
std::string test_url = "https://create_son_test";
|
||||
|
||||
// create deposit vesting
|
||||
vesting_balance_id_type deposit_alice;
|
||||
{
|
||||
vesting_balance_create_operation op;
|
||||
op.creator = alice_id;
|
||||
op.owner = alice_id;
|
||||
op.amount = asset(500 * GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::son;
|
||||
op.policy = dormant_vesting_policy_initializer{};
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
deposit_alice = ptx.operation_results[0].get<object_id_type>();
|
||||
}
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// create payment normal vesting
|
||||
vesting_balance_id_type payment_alice;
|
||||
{
|
||||
vesting_balance_create_operation op;
|
||||
op.creator = alice_id;
|
||||
op.owner = alice_id;
|
||||
op.amount = asset(500 * GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::normal;
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
payment_alice = ptx.operation_results[0].get<object_id_type>();
|
||||
}
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// alice becomes son
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin address";
|
||||
|
||||
son_create_operation op;
|
||||
op.owner_account = alice_id;
|
||||
op.url = test_url;
|
||||
op.deposit = deposit_alice;
|
||||
op.pay_vb = payment_alice;
|
||||
op.signing_key = alice_public_key;
|
||||
op.sidechain_public_keys = sidechain_public_keys;
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// create deposit vesting
|
||||
vesting_balance_id_type deposit_bob;
|
||||
{
|
||||
vesting_balance_create_operation op;
|
||||
op.creator = bob_id;
|
||||
op.owner = bob_id;
|
||||
op.amount = asset(500 * GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::son;
|
||||
op.policy = dormant_vesting_policy_initializer{};
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, bob_private_key);
|
||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
deposit_bob = ptx.operation_results[0].get<object_id_type>();
|
||||
}
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// create payment normal vesting
|
||||
vesting_balance_id_type payment_bob;
|
||||
{
|
||||
vesting_balance_create_operation op;
|
||||
op.creator = bob_id;
|
||||
op.owner = bob_id;
|
||||
op.amount = asset(500 * GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::normal;
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, bob_private_key);
|
||||
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
payment_bob = ptx.operation_results[0].get<object_id_type>();
|
||||
}
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
// bob becomes son
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin address";
|
||||
|
||||
son_create_operation op;
|
||||
op.owner_account = bob_id;
|
||||
op.url = test_url;
|
||||
op.deposit = deposit_bob;
|
||||
op.pay_vb = payment_bob;
|
||||
op.signing_key = bob_public_key;
|
||||
op.sidechain_public_keys = sidechain_public_keys;
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
generate_block();
|
||||
|
||||
generate_block();
|
||||
|
||||
const auto& acc_idx = db.get_index_type<account_index>().indices().get<by_id>();
|
||||
auto acc_itr = acc_idx.find(db.get_global_properties().parameters.son_account());
|
||||
BOOST_REQUIRE(acc_itr != acc_idx.end());
|
||||
db.modify(*acc_itr, [&](account_object &obj) {
|
||||
obj.active.account_auths.clear();
|
||||
obj.active.add_authority(bob_id, 1);
|
||||
obj.active.add_authority(alice_id, 1);
|
||||
obj.active.weight_threshold = 2;
|
||||
obj.owner.account_auths.clear();
|
||||
obj.owner.add_authority(bob_id, 1);
|
||||
obj.owner.add_authority(alice_id, 1);
|
||||
obj.owner.weight_threshold = 2;
|
||||
});
|
||||
|
||||
/*const auto &son_btc_account = db.create<account_object>([&](account_object &obj) {
|
||||
obj.name = "son_btc_account";
|
||||
obj.statistics = db.create<account_statistics_object>([&](account_statistics_object &acc_stat) { acc_stat.owner = obj.id; }).id;
|
||||
obj.membership_expiration_date = time_point_sec::maximum();
|
||||
obj.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
||||
obj.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
||||
|
||||
obj.owner.add_authority(bob_id, 1);
|
||||
obj.active.add_authority(bob_id, 1);
|
||||
obj.owner.add_authority(alice_id, 1);
|
||||
obj.active.add_authority(alice_id, 1);
|
||||
obj.active.weight_threshold = 2;
|
||||
obj.owner.weight_threshold = 2;
|
||||
});
|
||||
|
||||
db.modify( db.get_global_properties(), [&]( global_property_object& _gpo )
|
||||
{
|
||||
_gpo.parameters.extensions.value.son_btc_account = son_btc_account.get_id();
|
||||
if( _gpo.pending_parameters )
|
||||
_gpo.pending_parameters->extensions.value.son_btc_account = son_btc_account.get_id();
|
||||
});*/
|
||||
|
||||
generate_block();
|
||||
|
||||
const global_property_object &gpo = db.get_global_properties();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send bitcoin_transaction_send_operation");
|
||||
|
||||
bitcoin_transaction_send_operation send_op;
|
||||
|
||||
send_op.payer = gpo.parameters.son_account();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = alice_id;
|
||||
proposal_op.proposed_ops.push_back(op_wrapper(send_op));
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(db.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
trx.operations.push_back(proposal_op);
|
||||
set_expiration(db, trx);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE("Check proposal results");
|
||||
|
||||
const auto &idx = db.get_index_type<proposal_index>().indices().get<by_id>();
|
||||
BOOST_REQUIRE(idx.size() == 1);
|
||||
auto obj = idx.find(proposal_id_type(0));
|
||||
BOOST_REQUIRE(obj != idx.end());
|
||||
|
||||
const auto& btidx = db.get_index_type<bitcoin_transaction_index>().indices().get<by_id>();
|
||||
BOOST_REQUIRE(btidx.size() == 0);
|
||||
|
||||
std::vector<unsigned char> a1 = {'a', 'l', 'i', 'c', 'e', '1'};
|
||||
std::vector<unsigned char> a2 = {'a', 'l', 'i', 'c', 'e', '2'};
|
||||
std::vector<unsigned char> a3 = {'a', 'l', 'i', 'c', 'e', '3'};
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send bitcoin_transaction_sign_operation");
|
||||
|
||||
bitcoin_transaction_sign_operation sign_op;
|
||||
|
||||
sign_op.payer = alice_id;
|
||||
sign_op.proposal_id = proposal_id_type(0);
|
||||
sign_op.signatures.push_back(a1);
|
||||
sign_op.signatures.push_back(a2);
|
||||
sign_op.signatures.push_back(a3);
|
||||
|
||||
trx.operations.push_back(sign_op);
|
||||
set_expiration(db, trx);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
|
||||
generate_block();
|
||||
|
||||
BOOST_REQUIRE(idx.size() == 1);
|
||||
BOOST_REQUIRE(btidx.size() == 0);
|
||||
auto pobj = idx.find(proposal_id_type(0));
|
||||
BOOST_REQUIRE(pobj != idx.end());
|
||||
|
||||
const auto& sidx = db.get_index_type<son_index>().indices().get<graphene::chain::by_account>();
|
||||
const auto son_obj1 = sidx.find( alice_id );
|
||||
BOOST_REQUIRE(son_obj1 != sidx.end());
|
||||
|
||||
auto bitcoin_transaction_send_op = pobj->proposed_transaction.operations[0].get<bitcoin_transaction_send_operation>();
|
||||
BOOST_REQUIRE(bitcoin_transaction_send_op.signatures.size() == 1);
|
||||
BOOST_REQUIRE(bitcoin_transaction_send_op.signatures[son_obj1->id][0] == a1);
|
||||
BOOST_REQUIRE(bitcoin_transaction_send_op.signatures[son_obj1->id][1] == a2);
|
||||
BOOST_REQUIRE(bitcoin_transaction_send_op.signatures[son_obj1->id][2] == a3);
|
||||
|
||||
std::vector<unsigned char> b1 = {'b', 'o', 'b', '1'};
|
||||
std::vector<unsigned char> b2 = {'b', 'o', 'b', '2'};
|
||||
std::vector<unsigned char> b3 = {'b', 'o', 'b', '3'};
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send bitcoin_transaction_sign_operation");
|
||||
|
||||
bitcoin_transaction_sign_operation sign_op;
|
||||
|
||||
sign_op.payer = bob_id;
|
||||
sign_op.proposal_id = proposal_id_type(0);
|
||||
sign_op.signatures.push_back(b1);
|
||||
sign_op.signatures.push_back(b2);
|
||||
sign_op.signatures.push_back(b3);
|
||||
|
||||
trx.operations.push_back(sign_op);
|
||||
set_expiration(db, trx);
|
||||
sign(trx, bob_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
|
||||
generate_block();
|
||||
|
||||
BOOST_REQUIRE(idx.size() == 0);
|
||||
|
||||
const auto son_obj2 = sidx.find( bob_id );
|
||||
BOOST_REQUIRE(son_obj2 != sidx.end());
|
||||
|
||||
BOOST_REQUIRE(btidx.size() == 1);
|
||||
|
||||
const auto btobj = btidx.find(bitcoin_transaction_id_type(0));
|
||||
BOOST_REQUIRE(btobj != btidx.end());
|
||||
|
||||
BOOST_REQUIRE(btobj->processed == false);
|
||||
|
||||
auto stats1 = son_obj1->statistics( db );
|
||||
auto stats2 = son_obj2->statistics( db );
|
||||
|
||||
BOOST_REQUIRE(stats1.txs_signed == 1);
|
||||
BOOST_REQUIRE(stats2.txs_signed == 1);
|
||||
|
||||
auto sigs = btobj->signatures;
|
||||
|
||||
BOOST_REQUIRE(sigs[son_obj1->id][0] == a1);
|
||||
BOOST_REQUIRE(sigs[son_obj1->id][1] == a2);
|
||||
BOOST_REQUIRE(sigs[son_obj1->id][2] == a3);
|
||||
|
||||
BOOST_REQUIRE(sigs[son_obj2->id][0] == b1);
|
||||
BOOST_REQUIRE(sigs[son_obj2->id][1] == b2);
|
||||
BOOST_REQUIRE(sigs[son_obj2->id][2] == b3);
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send bitcoin_send_transaction_process_operation");
|
||||
|
||||
bitcoin_send_transaction_process_operation process_op;
|
||||
process_op.bitcoin_transaction_id = bitcoin_transaction_id_type(0);
|
||||
process_op.payer = db.get_global_properties().parameters.son_account();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = alice_id;
|
||||
proposal_op.proposed_ops.push_back(op_wrapper(process_op));
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(db.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
trx.operations.push_back(proposal_op);
|
||||
set_expiration(db, trx);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
|
||||
generate_block();
|
||||
BOOST_REQUIRE(idx.size() == 1);
|
||||
obj = idx.find(proposal_id_type(1));
|
||||
BOOST_REQUIRE(obj != idx.end());
|
||||
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send proposal_update_operation");
|
||||
|
||||
proposal_update_operation puo;
|
||||
puo.fee_paying_account = bob_id;
|
||||
puo.proposal = obj->id;
|
||||
puo.active_approvals_to_add = { bob_id };
|
||||
|
||||
trx.operations.push_back(puo);
|
||||
set_expiration(db, trx);
|
||||
sign(trx, bob_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
generate_block();
|
||||
BOOST_REQUIRE(idx.size() == 1);
|
||||
obj = idx.find(proposal_id_type(1));
|
||||
BOOST_REQUIRE(obj != idx.end());
|
||||
|
||||
BOOST_REQUIRE(btobj != btidx.end());
|
||||
BOOST_REQUIRE(btobj->processed == false);
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send proposal_update_operation");
|
||||
|
||||
proposal_update_operation puo;
|
||||
puo.fee_paying_account = alice_id;
|
||||
puo.proposal = obj->id;
|
||||
puo.active_approvals_to_add = { alice_id };
|
||||
|
||||
trx.operations.push_back(puo);
|
||||
set_expiration(db, trx);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
trx.clear();
|
||||
}
|
||||
generate_block();
|
||||
BOOST_REQUIRE(idx.size() == 0);
|
||||
|
||||
BOOST_REQUIRE(btobj != btidx.end());
|
||||
BOOST_REQUIRE(btobj->processed == true);
|
||||
}
|
||||
FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/chain/sidechain_defs.hpp>
|
||||
|
||||
using namespace graphene;
|
||||
using namespace graphene::chain;
|
||||
|
|
|
|||
Loading…
Reference in a new issue