Compare commits
92 commits
master
...
feature/SO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4b72504c1 | ||
|
|
b92ea617c7 | ||
|
|
e2ef5a6db1 | ||
|
|
71c9483798 | ||
|
|
4991c2a31d | ||
|
|
3b166f576f | ||
|
|
7712b594e0 | ||
|
|
224f01269c | ||
|
|
974821d0d1 | ||
|
|
5d12cdb4f5 | ||
|
|
d91899b1d0 | ||
|
|
bccc17f872 | ||
|
|
001fe06501 | ||
|
|
f09ff36f1a | ||
|
|
1e27c0b4ba | ||
|
|
c953864c39 | ||
|
|
d2fdca7dad | ||
|
|
b3904bb2e6 | ||
|
|
4a7e70c8d6 | ||
|
|
9e30f8866a | ||
|
|
cbfaefde83 | ||
|
|
22c12f5041 | ||
|
|
9ac8bbe06a | ||
|
|
5a37d3ecd1 | ||
|
|
1d304993e9 | ||
|
|
caba98cfe3 | ||
|
|
4b01d8064f | ||
|
|
188a412143 | ||
|
|
7e596a67e6 | ||
|
|
deef8b4456 | ||
|
|
992b245d5b | ||
|
|
b927ffa4d0 | ||
|
|
75626254fa | ||
|
|
0d14b481a4 | ||
|
|
da7b161d3d | ||
|
|
df369df421 | ||
|
|
95ad384f0c | ||
|
|
532afc062f | ||
|
|
7f56e8e661 | ||
|
|
69cad0f1bd | ||
|
|
98ebbbd69b | ||
|
|
2cc90a8794 | ||
|
|
5b1dea0d39 | ||
|
|
9056ba6d07 | ||
|
|
bb8d334e6c | ||
|
|
01f1b6137a | ||
|
|
23458ee917 | ||
|
|
bbd2e35014 | ||
|
|
89ca9167d3 | ||
|
|
9db6179f79 | ||
|
|
5c57f5d9c8 | ||
|
|
703c577d90 | ||
|
|
263ba5d15b | ||
|
|
ca112b1eb6 | ||
|
|
f62a46e789 | ||
|
|
5b7dd86ab9 | ||
|
|
2bb3fc79d7 | ||
|
|
c5ea418321 | ||
|
|
afcb1ace1b | ||
|
|
0c7ef96178 | ||
|
|
95b515c09a | ||
|
|
01a1f584df | ||
|
|
f6c1da53df | ||
|
|
d048873601 | ||
|
|
42b7d25a99 | ||
|
|
775fdf8980 | ||
|
|
6055576aa4 | ||
|
|
1808082d59 | ||
|
|
9c1eb63d15 | ||
|
|
4590f919dc | ||
|
|
be60f65612 | ||
|
|
df7ee459f9 | ||
|
|
0142348a9c | ||
|
|
8399008e7d | ||
|
|
7ceed83a95 | ||
|
|
a6e14af38f | ||
|
|
7abfa78ad6 | ||
|
|
0b491510c4 | ||
|
|
f0a8e8e376 | ||
|
|
c25108f228 | ||
|
|
23cb5310b0 | ||
|
|
ebb6662210 | ||
|
|
1dc0eee6b6 | ||
|
|
b06e1d680a | ||
|
|
2615c41224 | ||
|
|
6f0c025462 | ||
|
|
61b8ff0cc7 | ||
|
|
2b8a39e332 | ||
|
|
ba255da679 | ||
|
|
0e47eeccf2 | ||
|
|
6421d5e852 | ||
|
|
2e124b07c6 |
9 changed files with 516 additions and 453 deletions
127
.clang-format
Executable file
127
.clang-format
Executable file
|
|
@ -0,0 +1,127 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -3
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: false
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortLambdasOnASingleLine: None
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 0
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: true
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 6
|
||||||
|
ContinuationIndentWidth: 6
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 3
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 3
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
|
|
||||||
|
|
@ -28,6 +28,7 @@ class peerplays_sidechain_plugin : public graphene::app::plugin
|
||||||
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
|
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
|
||||||
|
|
||||||
std::set<chain::son_id_type>& get_sons();
|
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);
|
son_object get_son_object(son_id_type son_id);
|
||||||
bool is_active_son(son_id_type son_id);
|
bool is_active_son(son_id_type son_id);
|
||||||
std::map<chain::public_key_type, fc::ecc::private_key>& get_private_keys();
|
std::map<chain::public_key_type, fc::ecc::private_key>& get_private_keys();
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,6 @@ protected:
|
||||||
virtual std::string transfer( const std::string& from, const std::string& to, const uint64_t amount ) = 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 sign_transaction( const std::string& transaction ) = 0;
|
||||||
virtual std::string send_transaction( const std::string& transaction ) = 0;
|
virtual std::string send_transaction( const std::string& transaction ) = 0;
|
||||||
//virtual std::string transfer_deposit_to_primary_wallet (const sidechain_event_data& sed) = 0;
|
|
||||||
//virtual std::string transfer_withdrawal_from_primary_wallet(const std::string& user_address, double sidechain_amount) = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <fc/signals.hpp>
|
#include <fc/signals.hpp>
|
||||||
#include <fc/network/http/connection.hpp>
|
#include <fc/network/http/connection.hpp>
|
||||||
|
#include <graphene/chain/son_wallet_deposit_object.hpp>
|
||||||
|
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain {
|
namespace graphene { namespace peerplays_sidechain {
|
||||||
|
|
||||||
|
|
@ -21,20 +23,18 @@ public:
|
||||||
class bitcoin_rpc_client {
|
class bitcoin_rpc_client {
|
||||||
public:
|
public:
|
||||||
bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::string _user, std::string _password) ;
|
bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::string _user, std::string _password) ;
|
||||||
std::string receive_full_block( const std::string& block_hash );
|
|
||||||
int32_t receive_confirmations_tx( const std::string& tx_hash );
|
|
||||||
bool receive_mempool_entry_tx( const std::string& tx_hash );
|
|
||||||
uint64_t receive_estimated_fee();
|
|
||||||
void send_btc_tx( const std::string& tx_hex );
|
|
||||||
std::string add_multisig_address( const std::vector<std::string> public_keys );
|
|
||||||
bool connection_is_not_defined() const;
|
bool connection_is_not_defined() const;
|
||||||
std::string create_raw_transaction(const std::string& txid, const std::string& vout, const std::string& out_address, double transfer_amount);
|
|
||||||
std::string sign_raw_transaction_with_wallet(const std::string& tx_hash);
|
std::string addmultisigaddress( const std::vector<std::string> public_keys );
|
||||||
std::string sign_raw_transaction_with_privkey(const std::string& tx_hash, const std::string& private_key);
|
std::string createrawtransaction(const std::vector<btc_txout>& ins, const fc::flat_map<std::string, double> outs);
|
||||||
void import_address( const std::string& address_or_script);
|
uint64_t estimatesmartfee();
|
||||||
std::vector<btc_txout> list_unspent();
|
std::string getblock( const std::string& block_hash, int32_t verbosity = 2 );
|
||||||
std::vector<btc_txout> list_unspent_by_address_and_amount(const std::string& address, double transfer_amount);
|
void importaddress( const std::string& address_or_script);
|
||||||
std::string prepare_tx(const std::vector<btc_txout>& ins, const fc::flat_map<std::string, double> outs);
|
std::vector<btc_txout> listunspent();
|
||||||
|
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string& address, double transfer_amount);
|
||||||
|
void sendrawtransaction( const std::string& tx_hex );
|
||||||
|
std::string signrawtransactionwithkey(const std::string& tx_hash, const std::string& private_key);
|
||||||
|
std::string signrawtransactionwithwallet(const std::string& tx_hash);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
@ -86,8 +86,8 @@ public:
|
||||||
std::string send_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 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_all_btc(const std::string& from_address, const std::string& to_address);
|
||||||
std::string transfer_deposit_to_primary_wallet (const sidechain_event_data& sed);
|
std::string transfer_deposit_to_primary_wallet (const son_wallet_deposit_object &swdo);
|
||||||
std::string transfer_withdrawal_from_primary_wallet(const std::string& user_address, double sidechain_amount);
|
std::string transfer_withdrawal_from_primary_wallet(const son_wallet_withdraw_object &swwo);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void on_block_applied(const signed_block& b);
|
void on_applied_block(const signed_block& b);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ class peerplays_sidechain_plugin_impl
|
||||||
void plugin_startup();
|
void plugin_startup();
|
||||||
|
|
||||||
std::set<chain::son_id_type>& get_sons();
|
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);
|
son_object get_son_object(son_id_type son_id);
|
||||||
bool is_active_son(son_id_type son_id);
|
bool is_active_son(son_id_type son_id);
|
||||||
std::map<chain::public_key_type, fc::ecc::private_key>& get_private_keys();
|
std::map<chain::public_key_type, fc::ecc::private_key>& get_private_keys();
|
||||||
|
|
@ -55,13 +56,15 @@ class peerplays_sidechain_plugin_impl
|
||||||
bool config_ready_bitcoin;
|
bool config_ready_bitcoin;
|
||||||
bool config_ready_peerplays;
|
bool config_ready_peerplays;
|
||||||
|
|
||||||
|
son_id_type current_son_id;
|
||||||
|
|
||||||
std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager;
|
std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager;
|
||||||
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
||||||
std::set<chain::son_id_type> _sons;
|
std::set<chain::son_id_type> _sons;
|
||||||
fc::future<void> _heartbeat_task;
|
fc::future<void> _heartbeat_task;
|
||||||
|
|
||||||
void on_block_applied( const signed_block& b );
|
void on_applied_block( const signed_block& b );
|
||||||
void on_objects_new(const vector<object_id_type>& new_object_ids);
|
void on_new_objects(const vector<object_id_type>& new_object_ids);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -70,6 +73,7 @@ peerplays_sidechain_plugin_impl::peerplays_sidechain_plugin_impl(peerplays_sidec
|
||||||
config_ready_son(false),
|
config_ready_son(false),
|
||||||
config_ready_bitcoin(false),
|
config_ready_bitcoin(false),
|
||||||
config_ready_peerplays(false),
|
config_ready_peerplays(false),
|
||||||
|
current_son_id(son_id_type(std::numeric_limits<uint32_t>().max())),
|
||||||
net_manager(nullptr)
|
net_manager(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -158,8 +162,8 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.database().applied_block.connect( [&] (const signed_block& b) { on_block_applied(b); } );
|
plugin.database().applied_block.connect( [&] (const signed_block& b) { on_applied_block(b); } );
|
||||||
plugin.database().new_objects.connect( [&] (const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts) { on_objects_new(ids); } );
|
plugin.database().new_objects.connect( [&] (const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts) { on_new_objects(ids); } );
|
||||||
|
|
||||||
net_manager = std::unique_ptr<sidechain_net_manager>(new sidechain_net_manager(plugin));
|
net_manager = std::unique_ptr<sidechain_net_manager>(new sidechain_net_manager(plugin));
|
||||||
|
|
||||||
|
|
@ -225,6 +229,10 @@ std::set<chain::son_id_type>& peerplays_sidechain_plugin_impl::get_sons()
|
||||||
return _sons;
|
return _sons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
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>();
|
const auto& idx = plugin.database().get_index_type<chain::son_index>().indices().get<by_id>();
|
||||||
|
|
@ -388,7 +396,7 @@ void peerplays_sidechain_plugin_impl::process_withdrawals()
|
||||||
net_manager->process_withdrawals();
|
net_manager->process_withdrawals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b )
|
void peerplays_sidechain_plugin_impl::on_applied_block( const signed_block& b )
|
||||||
{
|
{
|
||||||
chain::database& d = plugin.database();
|
chain::database& d = plugin.database();
|
||||||
const chain::global_property_object& gpo = d.get_global_properties();
|
const chain::global_property_object& gpo = d.get_global_properties();
|
||||||
|
|
@ -403,6 +411,8 @@ void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b )
|
||||||
// check if we control scheduled SON
|
// check if we control scheduled SON
|
||||||
if( _sons.find( next_son_id ) != _sons.end() ) {
|
if( _sons.find( next_son_id ) != _sons.end() ) {
|
||||||
|
|
||||||
|
current_son_id = next_son_id;
|
||||||
|
|
||||||
create_son_down_proposals();
|
create_son_down_proposals();
|
||||||
|
|
||||||
recreate_primary_wallet();
|
recreate_primary_wallet();
|
||||||
|
|
@ -414,7 +424,7 @@ void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void peerplays_sidechain_plugin_impl::on_objects_new(const vector<object_id_type>& new_object_ids)
|
void peerplays_sidechain_plugin_impl::on_new_objects(const vector<object_id_type>& new_object_ids)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto approve_proposal = [ & ]( const chain::son_id_type& son_id, const chain::proposal_id_type& proposal_id )
|
auto approve_proposal = [ & ]( const chain::son_id_type& son_id, const chain::proposal_id_type& proposal_id )
|
||||||
|
|
@ -536,6 +546,10 @@ std::set<chain::son_id_type>& peerplays_sidechain_plugin::get_sons()
|
||||||
return my->get_sons();
|
return my->get_sons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
son_object peerplays_sidechain_plugin::get_son_object(son_id_type son_id)
|
||||||
{
|
{
|
||||||
return my->get_son_object(son_id);
|
return my->get_son_object(son_id);
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
||||||
uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3;
|
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 );
|
proposal_op.expiration_time = time_point_sec( database.head_block_time().sec_since_epoch() + lifetime );
|
||||||
|
|
||||||
ilog("sidechain_net_handler: sending proposal for son wallet deposit create operation by ${son}", ("son", son_id));
|
//ilog("sidechain_net_handler: sending proposal for son wallet deposit create operation by ${son}", ("son", son_id));
|
||||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
||||||
try {
|
try {
|
||||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||||
|
|
@ -130,7 +130,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
||||||
uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3;
|
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 );
|
proposal_op.expiration_time = time_point_sec( database.head_block_time().sec_since_epoch() + lifetime );
|
||||||
|
|
||||||
ilog("sidechain_net_handler: sending proposal for son wallet withdraw create operation by ${son}", ("son", son_id));
|
//ilog("sidechain_net_handler: sending proposal for son wallet withdraw create operation by ${son}", ("son", son_id));
|
||||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
||||||
try {
|
try {
|
||||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||||
|
|
@ -158,35 +158,30 @@ void sidechain_net_handler::process_deposits() {
|
||||||
std::for_each(idx_range.first, idx_range.second,
|
std::for_each(idx_range.first, idx_range.second,
|
||||||
[&] (const son_wallet_deposit_object& swdo) {
|
[&] (const son_wallet_deposit_object& swdo) {
|
||||||
|
|
||||||
|
ilog("Deposit to process: ${swdo}", ("swdo", swdo));
|
||||||
|
|
||||||
process_deposit(swdo);
|
process_deposit(swdo);
|
||||||
|
|
||||||
const chain::global_property_object& gpo = plugin.database().get_global_properties();
|
const chain::global_property_object& gpo = plugin.database().get_global_properties();
|
||||||
|
|
||||||
for (son_id_type son_id : plugin.get_sons()) {
|
son_wallet_deposit_process_operation p_op;
|
||||||
if (plugin.is_active_son(son_id)) {
|
p_op.payer = GRAPHENE_SON_ACCOUNT;
|
||||||
|
p_op.son_wallet_deposit_id = swdo.id;
|
||||||
|
|
||||||
son_wallet_deposit_process_operation p_op;
|
proposal_create_operation proposal_op;
|
||||||
p_op.payer = GRAPHENE_SON_ACCOUNT;
|
proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account;
|
||||||
p_op.son_wallet_deposit_id = swdo.id;
|
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 );
|
||||||
|
|
||||||
proposal_create_operation proposal_op;
|
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||||
proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account;
|
trx.validate();
|
||||||
proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) );
|
try {
|
||||||
uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3;
|
plugin.database().push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||||
proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime );
|
if(plugin.app().p2p_node())
|
||||||
|
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||||
ilog("sidechain_net_handler: sending proposal for transfer operation ${swdo} by ${son}", ("swdo", swdo.id) ("son", son_id));
|
} catch(fc::exception e){
|
||||||
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what()));
|
||||||
trx.validate();
|
|
||||||
ilog("sidechain_net_handler: transaction validated ${swdo} by ${son}", ("swdo", swdo.id) ("son", son_id));
|
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -198,36 +193,30 @@ void sidechain_net_handler::process_withdrawals() {
|
||||||
std::for_each(idx_range.first, idx_range.second,
|
std::for_each(idx_range.first, idx_range.second,
|
||||||
[&] (const son_wallet_withdraw_object& swwo) {
|
[&] (const son_wallet_withdraw_object& swwo) {
|
||||||
|
|
||||||
|
ilog("Withdraw to process: ${swwo}", ("swwo", swwo));
|
||||||
|
|
||||||
process_withdrawal(swwo);
|
process_withdrawal(swwo);
|
||||||
|
|
||||||
const chain::global_property_object& gpo = plugin.database().get_global_properties();
|
const chain::global_property_object& gpo = plugin.database().get_global_properties();
|
||||||
|
|
||||||
for (son_id_type son_id : plugin.get_sons()) {
|
son_wallet_withdraw_process_operation p_op;
|
||||||
if (plugin.is_active_son(son_id)) {
|
p_op.payer = GRAPHENE_SON_ACCOUNT;
|
||||||
|
p_op.son_wallet_withdraw_id = swwo.id;
|
||||||
|
|
||||||
ilog("SON ${son_id}: Withdraw to process: ${swwo}", ("son_id", son_id) ("swwo", swwo));
|
proposal_create_operation proposal_op;
|
||||||
//son_wallet_withdraw_process_operation p_op;
|
proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account;
|
||||||
//p_op.payer = GRAPHENE_SON_ACCOUNT;
|
proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) );
|
||||||
//p_op.son_wallet_withdraw_id = swwo.id;
|
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 );
|
||||||
//proposal_create_operation proposal_op;
|
|
||||||
//proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account;
|
signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||||
//proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) );
|
trx.validate();
|
||||||
//uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3;
|
try {
|
||||||
//proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime );
|
plugin.database().push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||||
//
|
if(plugin.app().p2p_node())
|
||||||
//ilog("sidechain_net_handler: sending proposal for transfer operation ${swwo} by ${son}", ("swwo", swwo.id) ("son", son_id));
|
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||||
//signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op);
|
} catch(fc::exception e){
|
||||||
//trx.validate();
|
ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what()));
|
||||||
//ilog("sidechain_net_handler: transaction validated ${swwo} by ${son}", ("swwo", swwo.id) ("son", son_id));
|
|
||||||
//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()));
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@
|
||||||
#include <graphene/chain/sidechain_address_object.hpp>
|
#include <graphene/chain/sidechain_address_object.hpp>
|
||||||
#include <graphene/chain/son_info.hpp>
|
#include <graphene/chain/son_info.hpp>
|
||||||
#include <graphene/chain/son_wallet_object.hpp>
|
#include <graphene/chain/son_wallet_object.hpp>
|
||||||
#include <graphene/chain/son_wallet_deposit_object.hpp>
|
|
||||||
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
|
||||||
#include <graphene/chain/protocol/son_wallet.hpp>
|
#include <graphene/chain/protocol/son_wallet.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain {
|
namespace graphene { namespace peerplays_sidechain {
|
||||||
|
|
@ -30,116 +28,13 @@ bitcoin_rpc_client::bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::str
|
||||||
authorization.val = "Basic " + fc::base64_encode( user + ":" + password );
|
authorization.val = "Basic " + fc::base64_encode( user + ":" + password );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string bitcoin_rpc_client::receive_full_block( const std::string& block_hash )
|
bool bitcoin_rpc_client::connection_is_not_defined() const {
|
||||||
{
|
return ip.empty() || rpc_port == 0 || user.empty() || password.empty();
|
||||||
fc::http::connection conn;
|
|
||||||
conn.connect_to( fc::ip::endpoint( fc::ip::address( ip ), rpc_port ) );
|
|
||||||
|
|
||||||
const auto url = "http://" + ip + ":" + std::to_string( rpc_port ) + "/rest/block/" + block_hash + ".json";
|
|
||||||
|
|
||||||
const auto reply = conn.request( "GET", url );
|
|
||||||
if ( reply.status != 200 )
|
|
||||||
return "";
|
|
||||||
|
|
||||||
ilog( "Receive Bitcoin block: ${hash}", ( "hash", block_hash ) );
|
|
||||||
return std::string( reply.body.begin(), reply.body.end() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//int32_t bitcoin_rpc_client::receive_confirmations_tx( const std::string& tx_hash )
|
std::string bitcoin_rpc_client::addmultisigaddress(const std::vector<std::string> public_keys) {
|
||||||
//{
|
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"addmultisigaddress\", "
|
||||||
// const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"getrawtransaction\", \"params\": [") +
|
"\"method\": \"addmultisigaddress\", \"params\": [");
|
||||||
// std::string("\"") + tx_hash + std::string("\"") + ", " + "true" + std::string("] }");
|
|
||||||
//
|
|
||||||
// const auto reply = send_post_request( body );
|
|
||||||
//
|
|
||||||
// if ( reply.status != 200 )
|
|
||||||
// return 0;
|
|
||||||
//
|
|
||||||
// const auto result = std::string( reply.body.begin(), reply.body.end() );
|
|
||||||
//
|
|
||||||
// std::stringstream ss( result );
|
|
||||||
// boost::property_tree::ptree tx;
|
|
||||||
// boost::property_tree::read_json( ss, tx );
|
|
||||||
//
|
|
||||||
// if( tx.count( "result" ) ) {
|
|
||||||
// if( tx.get_child( "result" ).count( "confirmations" ) ) {
|
|
||||||
// return tx.get_child( "result" ).get_child( "confirmations" ).get_value<int64_t>();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool bitcoin_rpc_client::receive_mempool_entry_tx( const std::string& tx_hash )
|
|
||||||
{
|
|
||||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"getmempoolentry\", \"params\": [") +
|
|
||||||
std::string("\"") + tx_hash + std::string("\"") + std::string("] }");
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
if ( reply.status != 200 )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t bitcoin_rpc_client::receive_estimated_fee()
|
|
||||||
{
|
|
||||||
static const auto confirmation_target_blocks = 6;
|
|
||||||
|
|
||||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimated_feerate\", \"method\": \"estimatesmartfee\", \"params\": [") +
|
|
||||||
std::to_string(confirmation_target_blocks) + std::string("] }");
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
if( reply.status != 200 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
std::stringstream ss( std::string( reply.body.begin(), reply.body.end() ) );
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( json.count( "result" ) )
|
|
||||||
if ( json.get_child( "result" ).count( "feerate" ) ) {
|
|
||||||
auto feerate_str = json.get_child( "result" ).get_child( "feerate" ).get_value<std::string>();
|
|
||||||
feerate_str.erase( std::remove( feerate_str.begin(), feerate_str.end(), '.' ), feerate_str.end() );
|
|
||||||
return std::stoll( feerate_str );
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bitcoin_rpc_client::send_btc_tx( const std::string& tx_hex )
|
|
||||||
{
|
|
||||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"send_tx\", \"method\": \"sendrawtransaction\", \"params\": [") +
|
|
||||||
std::string("\"") + tx_hex + std::string("\"") + std::string("] }");
|
|
||||||
|
|
||||||
ilog(body);
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
if( reply.body.empty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
idump(( tx_hex ));
|
|
||||||
return;
|
|
||||||
} else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
|
||||||
const auto error_code = json.get_child( "error" ).get_child( "code" ).get_value<int>();
|
|
||||||
if( error_code == -27 ) // transaction already in block chain
|
|
||||||
return;
|
|
||||||
|
|
||||||
wlog( "BTC tx is not sent! Reply: ${msg}", ("msg", reply_str) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string bitcoin_rpc_client::add_multisig_address( const std::vector<std::string> public_keys )
|
|
||||||
{
|
|
||||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"addmultisigaddress\", \"method\": \"addmultisigaddress\", \"params\": [");
|
|
||||||
std::string params = "2, [";
|
std::string params = "2, [";
|
||||||
std::string pubkeys = "";
|
std::string pubkeys = "";
|
||||||
for (std::string pubkey : public_keys) {
|
for (std::string pubkey : public_keys) {
|
||||||
|
|
@ -151,225 +46,42 @@ std::string bitcoin_rpc_client::add_multisig_address( const std::vector<std::str
|
||||||
params = params + pubkeys + std::string("]");
|
params = params + pubkeys + std::string("]");
|
||||||
body = body + params + std::string("] }");
|
body = body + params + std::string("] }");
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
if( reply.body.empty() )
|
if (reply.body.empty()) {
|
||||||
return "";
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return std::string();
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
return reply_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
wlog( "BTC multisig address creation failed! Reply: ${msg}", ("msg", reply_str) );
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
wlog("BTC multisig address creation failed! Reply: ${msg}", ("msg", ss.str()));
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string bitcoin_rpc_client::create_raw_transaction(const std::string& txid, const std::string& nvout, const std::string& out_address, double transfer_amount)
|
std::string bitcoin_rpc_client::createrawtransaction(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs) {
|
||||||
{
|
std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"createrawtransaction\", "
|
||||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"createrawtransaction\", \"method\": \"createrawtransaction\", \"params\": [");
|
"\"method\": \"createrawtransaction\", \"params\": [");
|
||||||
std::string params = "";
|
|
||||||
std::string input = std::string("[{\"txid\":\"") + txid + std::string("\",\"vout\":")+ nvout +std::string("}]");
|
|
||||||
std::string output = std::string("[{\"") + out_address + std::string("\":") + std::to_string(transfer_amount) + std::string("}]");
|
|
||||||
params = params + input + std::string(",") + output;
|
|
||||||
body = body + params + std::string("]}");
|
|
||||||
|
|
||||||
ilog(body);
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
if( reply.body.empty() )
|
|
||||||
return "";
|
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
return reply_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
|
||||||
wlog( "BTC createrawtransaction failed! Reply: ${msg}", ("msg", reply_str) );
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string bitcoin_rpc_client::sign_raw_transaction_with_wallet(const std::string& tx_hash)
|
|
||||||
{
|
|
||||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"signrawtransactionwithwallet\", \"method\": \"signrawtransactionwithwallet\", \"params\": [");
|
|
||||||
std::string params = "\"" + tx_hash + "\"";
|
|
||||||
body = body + params + std::string("]}");
|
|
||||||
|
|
||||||
ilog(body);
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
if( reply.body.empty() )
|
|
||||||
return "";
|
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
return reply_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
|
||||||
wlog( "BTC sign_raw_transaction_with_wallet failed! Reply: ${msg}", ("msg", reply_str) );
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string bitcoin_rpc_client::sign_raw_transaction_with_privkey(const std::string& tx_hash, const std::string& private_key)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bitcoin_rpc_client::connection_is_not_defined() const
|
|
||||||
{
|
|
||||||
return ip.empty() || rpc_port == 0 || user.empty() || password.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void bitcoin_rpc_client::import_address(const std::string &address_or_script)
|
|
||||||
{
|
|
||||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"importaddress\", \"params\": [") +
|
|
||||||
std::string("\"") + address_or_script + std::string("\"") + std::string("] }");
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
if( reply.body.empty() )
|
|
||||||
{
|
|
||||||
wlog("Failed to import address [${addr}]", ("addr", address_or_script));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
idump((address_or_script)(reply_str));
|
|
||||||
return;
|
|
||||||
} else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
|
||||||
wlog( "Failed to import address [${addr}]! Reply: ${msg}", ("addr", address_or_script)("msg", reply_str) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<btc_txout> bitcoin_rpc_client::list_unspent()
|
|
||||||
{
|
|
||||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"listunspent\", \"params\": [] }");
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
std::vector<btc_txout> result;
|
|
||||||
if( reply.body.empty() )
|
|
||||||
{
|
|
||||||
wlog("Failed to list unspent txo");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
idump((reply_str));
|
|
||||||
if( json.count( "result" ) )
|
|
||||||
{
|
|
||||||
for(auto& entry: json.get_child("result"))
|
|
||||||
{
|
|
||||||
btc_txout txo;
|
|
||||||
txo.txid_ = entry.second.get_child("txid").get_value<std::string>();
|
|
||||||
txo.out_num_ = entry.second.get_child("vout").get_value<unsigned int>();
|
|
||||||
txo.amount_ = entry.second.get_child("amount").get_value<double>();
|
|
||||||
result.push_back(txo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
|
||||||
wlog( "Failed to list unspent txo! Reply: ${msg}", ("msg", reply_str) );
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<btc_txout> bitcoin_rpc_client::list_unspent_by_address_and_amount(const std::string& address, double minimum_amount)
|
|
||||||
{
|
|
||||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"listunspent\", \"params\": [");
|
|
||||||
body += std::string("1,999999,[\"");
|
|
||||||
body += address;
|
|
||||||
body += std::string("\"],true,{\"minimumAmount\":");
|
|
||||||
body += std::to_string(minimum_amount);
|
|
||||||
body += std::string("}] }");
|
|
||||||
|
|
||||||
ilog(body);
|
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
|
||||||
|
|
||||||
std::vector<btc_txout> result;
|
|
||||||
if( reply.body.empty() )
|
|
||||||
{
|
|
||||||
wlog("Failed to list unspent txo");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json( ss, json );
|
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
|
||||||
idump((reply_str));
|
|
||||||
if( json.count( "result" ) )
|
|
||||||
{
|
|
||||||
for(auto& entry: json.get_child("result"))
|
|
||||||
{
|
|
||||||
btc_txout txo;
|
|
||||||
txo.txid_ = entry.second.get_child("txid").get_value<std::string>();
|
|
||||||
txo.out_num_ = entry.second.get_child("vout").get_value<unsigned int>();
|
|
||||||
txo.amount_ = entry.second.get_child("amount").get_value<double>();
|
|
||||||
result.push_back(txo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
|
||||||
wlog( "Failed to list unspent txo! Reply: ${msg}", ("msg", reply_str) );
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string bitcoin_rpc_client::prepare_tx(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs)
|
|
||||||
{
|
|
||||||
std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"createrawtransaction\", \"params\": [");
|
|
||||||
body += "[";
|
body += "[";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for(const auto& entry: ins)
|
for (const auto &entry : ins) {
|
||||||
{
|
if (!first)
|
||||||
if(!first)
|
|
||||||
body += ",";
|
body += ",";
|
||||||
body += "{\"txid\":\"" + entry.txid_ + "\",\"vout\":" + std::to_string(entry.out_num_) + "}";
|
body += "{\"txid\":\"" + entry.txid_ + "\",\"vout\":" + std::to_string(entry.out_num_) + "}";
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
body += "],[";
|
body += "],[";
|
||||||
first = true;
|
first = true;
|
||||||
for(const auto& entry: outs)
|
for (const auto &entry : outs) {
|
||||||
{
|
if (!first)
|
||||||
if(!first)
|
|
||||||
body += ",";
|
body += ",";
|
||||||
body += "{\"" + entry.first + "\":" + std::to_string(entry.second) + "}";
|
body += "{\"" + entry.first + "\":" + std::to_string(entry.second) + "}";
|
||||||
first = false;
|
first = false;
|
||||||
|
|
@ -378,30 +90,237 @@ std::string bitcoin_rpc_client::prepare_tx(const std::vector<btc_txout> &ins, co
|
||||||
|
|
||||||
ilog(body);
|
ilog(body);
|
||||||
|
|
||||||
const auto reply = send_post_request( body );
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
if( reply.body.empty() )
|
if (reply.body.empty()) {
|
||||||
{
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
wlog("Failed to create raw transaction: [${body}]", ("body", body));
|
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string reply_str( reply.body.begin(), reply.body.end() );
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
|
||||||
boost::property_tree::ptree json;
|
boost::property_tree::ptree json;
|
||||||
boost::property_tree::read_json( ss, json );
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
if( reply.status == 200 ) {
|
if (reply.status == 200) {
|
||||||
idump((reply_str));
|
if (json.count("result"))
|
||||||
if( json.count( "result" ) )
|
return ss.str();
|
||||||
return reply_str;
|
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
} else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) {
|
wlog("Failed to create raw transaction: [${body}]! Reply: ${msg}", ("body", body)("msg", ss.str()));
|
||||||
wlog( "Failed to create raw transaction: [${body}]! Reply: ${msg}", ("body", body)("msg", reply_str) );
|
|
||||||
}
|
}
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t bitcoin_rpc_client::estimatesmartfee() {
|
||||||
|
static const auto confirmation_target_blocks = 6;
|
||||||
|
|
||||||
|
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimatesmartfee\", "
|
||||||
|
"\"method\": \"estimatesmartfee\", \"params\": [") +
|
||||||
|
std::to_string(confirmation_target_blocks) + std::string("] }");
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (json.count("result"))
|
||||||
|
if (json.get_child("result").count("feerate")) {
|
||||||
|
auto feerate_str = json.get_child("result").get_child("feerate").get_value<std::string>();
|
||||||
|
feerate_str.erase(std::remove(feerate_str.begin(), feerate_str.end(), '.'), feerate_str.end());
|
||||||
|
return std::stoll(feerate_str);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) {
|
||||||
|
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getblock\", \"method\": "
|
||||||
|
"\"getblock\", \"params\": [\"" +
|
||||||
|
block_hash + "\", " + std::to_string(verbosity) + "] }");
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
std::stringstream ss;
|
||||||
|
boost::property_tree::json_parser::write_json(ss, json.get_child("result"));
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed with reply '${msg}'", ("function", __FUNCTION__)("msg", ss.str()));
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitcoin_rpc_client::importaddress(const std::string &address_or_script) {
|
||||||
|
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"importaddress\", "
|
||||||
|
"\"method\": \"importaddress\", \"params\": [") +
|
||||||
|
std::string("\"") + address_or_script + std::string("\"") + std::string("] }");
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
idump((address_or_script)(ss.str()));
|
||||||
|
return;
|
||||||
|
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
wlog("Failed to import address [${addr}]! Reply: ${msg}", ("addr", address_or_script)("msg", ss.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<btc_txout> bitcoin_rpc_client::listunspent() {
|
||||||
|
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": "
|
||||||
|
"\"listunspent\", \"params\": [] }");
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
std::vector<btc_txout> result;
|
||||||
|
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
if (json.count("result")) {
|
||||||
|
for (auto &entry : json.get_child("result")) {
|
||||||
|
btc_txout txo;
|
||||||
|
txo.txid_ = entry.second.get_child("txid").get_value<std::string>();
|
||||||
|
txo.out_num_ = entry.second.get_child("vout").get_value<unsigned int>();
|
||||||
|
txo.amount_ = entry.second.get_child("amount").get_value<double>();
|
||||||
|
result.push_back(txo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
wlog("Failed to list unspent txo! Reply: ${msg}", ("msg", ss.str()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<btc_txout> bitcoin_rpc_client::listunspent_by_address_and_amount(const std::string &address, double minimum_amount) {
|
||||||
|
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": "
|
||||||
|
"\"listunspent\", \"params\": [");
|
||||||
|
body += std::string("1,999999,[\"");
|
||||||
|
body += address;
|
||||||
|
body += std::string("\"],true,{\"minimumAmount\":");
|
||||||
|
body += std::to_string(minimum_amount);
|
||||||
|
body += std::string("}] }");
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
std::vector<btc_txout> result;
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
if (json.count("result")) {
|
||||||
|
for (auto &entry : json.get_child("result")) {
|
||||||
|
btc_txout txo;
|
||||||
|
txo.txid_ = entry.second.get_child("txid").get_value<std::string>();
|
||||||
|
txo.out_num_ = entry.second.get_child("vout").get_value<unsigned int>();
|
||||||
|
txo.amount_ = entry.second.get_child("amount").get_value<double>();
|
||||||
|
result.push_back(txo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
wlog("Failed to list unspent txo! Reply: ${msg}", ("msg", ss.str()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) {
|
||||||
|
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"sendrawtransaction\", "
|
||||||
|
"\"method\": \"sendrawtransaction\", \"params\": [") +
|
||||||
|
std::string("\"") + tx_hex + std::string("\"") + std::string("] }");
|
||||||
|
|
||||||
|
ilog(body);
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
return;
|
||||||
|
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
const auto error_code = json.get_child("error").get_child("code").get_value<int>();
|
||||||
|
if (error_code == -27) // transaction already in block chain
|
||||||
|
return;
|
||||||
|
|
||||||
|
wlog("BTC tx is not sent! Reply: ${msg}", ("msg", ss.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bitcoin_rpc_client::signrawtransactionwithkey(const std::string &tx_hash, const std::string &private_key) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) {
|
||||||
|
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"signrawtransactionwithwallet\", "
|
||||||
|
"\"method\": \"signrawtransactionwithwallet\", \"params\": [");
|
||||||
|
std::string params = "\"" + tx_hash + "\"";
|
||||||
|
body = body + params + std::string("]}");
|
||||||
|
|
||||||
|
ilog(body);
|
||||||
|
|
||||||
|
const auto reply = send_post_request(body);
|
||||||
|
|
||||||
|
if (reply.body.empty()) {
|
||||||
|
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
if (reply.status == 200) {
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.count("error") && !json.get_child("error").empty()) {
|
||||||
|
wlog("BTC sign_raw_transaction_with_wallet failed! Reply: ${msg}", ("msg", ss.str()));
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
fc::http::reply bitcoin_rpc_client::send_post_request( std::string body )
|
fc::http::reply bitcoin_rpc_client::send_post_request( std::string body )
|
||||||
{
|
{
|
||||||
fc::http::connection conn;
|
fc::http::connection conn;
|
||||||
|
|
@ -499,12 +418,12 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::recreate_primary_wallet() {
|
void sidechain_net_handler_bitcoin::recreate_primary_wallet() {
|
||||||
const auto& idx_swi = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
const auto& swi = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||||
auto obj = idx_swi.rbegin();
|
const auto &active_sw = swi.rbegin();
|
||||||
if (obj != idx_swi.rend()) {
|
if (active_sw != swi.rend()) {
|
||||||
|
|
||||||
if ((obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) ||
|
if ((active_sw->addresses.find(sidechain_type::bitcoin) == active_sw->addresses.end()) ||
|
||||||
(obj->addresses.at(sidechain_type::bitcoin).empty())) {
|
(active_sw->addresses.at(sidechain_type::bitcoin).empty())) {
|
||||||
|
|
||||||
const chain::global_property_object& gpo = database.get_global_properties();
|
const chain::global_property_object& gpo = database.get_global_properties();
|
||||||
|
|
||||||
|
|
@ -517,35 +436,46 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() {
|
||||||
|
|
||||||
ilog(reply_str);
|
ilog(reply_str);
|
||||||
|
|
||||||
std::stringstream ss(reply_str);
|
std::stringstream active_pw_ss(reply_str);
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree active_pw_pt;
|
||||||
boost::property_tree::read_json( ss, pt );
|
boost::property_tree::read_json( active_pw_ss, active_pw_pt );
|
||||||
if( pt.count( "error" ) && pt.get_child( "error" ).empty() ) {
|
if( active_pw_pt.count( "error" ) && active_pw_pt.get_child( "error" ).empty() ) {
|
||||||
|
|
||||||
std::stringstream res;
|
std::stringstream res;
|
||||||
boost::property_tree::json_parser::write_json(res, pt.get_child("result"));
|
boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result"));
|
||||||
|
|
||||||
son_wallet_update_operation op;
|
son_wallet_update_operation op;
|
||||||
op.payer = GRAPHENE_SON_ACCOUNT;
|
op.payer = GRAPHENE_SON_ACCOUNT;
|
||||||
op.son_wallet_id = (*obj).id;
|
op.son_wallet_id = (*active_sw).id;
|
||||||
op.sidechain = sidechain_type::bitcoin;
|
op.sidechain = sidechain_type::bitcoin;
|
||||||
op.address = res.str();
|
op.address = res.str();
|
||||||
|
|
||||||
for (son_id_type son_id : plugin.get_sons()) {
|
proposal_create_operation proposal_op;
|
||||||
proposal_create_operation proposal_op;
|
proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account;
|
||||||
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_wrapper( op ) );
|
uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3;
|
||||||
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 );
|
||||||
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(son_id), proposal_op);
|
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||||
try {
|
try {
|
||||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||||
if(plugin.app().p2p_node())
|
if(plugin.app().p2p_node())
|
||||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||||
} catch(fc::exception e){
|
} catch(fc::exception e){
|
||||||
ilog("sidechain_net_handler: sending proposal for son wallet update operation failed with exception ${e}",("e", e.what()));
|
ilog("sidechain_net_handler: sending proposal for son wallet update operation failed with exception ${e}",("e", e.what()));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &prev_sw = std::next(active_sw);
|
||||||
|
if (prev_sw != swi.rend()) {
|
||||||
|
std::stringstream prev_sw_ss(prev_sw->addresses.at(sidechain_type::bitcoin));
|
||||||
|
boost::property_tree::ptree prev_sw_pt;
|
||||||
|
boost::property_tree::read_json( prev_sw_ss, prev_sw_pt );
|
||||||
|
|
||||||
|
std::string active_pw_address = active_pw_pt.get_child("result").get<std::string>("address");
|
||||||
|
std::string prev_pw_address = prev_sw_pt.get<std::string>("address");
|
||||||
|
|
||||||
|
transfer_all_btc(prev_pw_address, active_pw_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -556,18 +486,22 @@ void sidechain_net_handler_bitcoin::process_deposits() {
|
||||||
sidechain_net_handler::process_deposits();
|
sidechain_net_handler::process_deposits();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_object& swdo) {
|
void sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||||
|
ilog(__FUNCTION__);
|
||||||
|
transfer_deposit_to_primary_wallet(swdo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::process_withdrawals() {
|
void sidechain_net_handler_bitcoin::process_withdrawals() {
|
||||||
sidechain_net_handler::process_withdrawals();
|
sidechain_net_handler::process_withdrawals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw_object& swwo) {
|
void sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||||
|
ilog(__FUNCTION__);
|
||||||
|
transfer_withdrawal_from_primary_wallet(swwo);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::create_multisignature_wallet( const std::vector<std::string> public_keys ) {
|
std::string sidechain_net_handler_bitcoin::create_multisignature_wallet( const std::vector<std::string> public_keys ) {
|
||||||
return bitcoin_client->add_multisig_address(public_keys);
|
return bitcoin_client->addmultisigaddress(public_keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::transfer( const std::string& from, const std::string& to, const uint64_t amount ) {
|
std::string sidechain_net_handler_bitcoin::transfer( const std::string& from, const std::string& to, const uint64_t amount ) {
|
||||||
|
|
@ -598,7 +532,7 @@ std::string sidechain_net_handler_bitcoin::sign_and_send_transaction_with_wallet
|
||||||
|
|
||||||
std::string unsigned_tx_hex = pt.get<std::string>("result");
|
std::string unsigned_tx_hex = pt.get<std::string>("result");
|
||||||
|
|
||||||
reply_str = bitcoin_client->sign_raw_transaction_with_wallet(unsigned_tx_hex);
|
reply_str = bitcoin_client->signrawtransactionwithwallet(unsigned_tx_hex);
|
||||||
ilog(reply_str);
|
ilog(reply_str);
|
||||||
std::stringstream ss_stx(reply_str);
|
std::stringstream ss_stx(reply_str);
|
||||||
boost::property_tree::ptree stx_json;
|
boost::property_tree::ptree stx_json;
|
||||||
|
|
@ -610,20 +544,20 @@ std::string sidechain_net_handler_bitcoin::sign_and_send_transaction_with_wallet
|
||||||
|
|
||||||
std::string signed_tx_hex = stx_json.get<std::string>("result.hex");
|
std::string signed_tx_hex = stx_json.get<std::string>("result.hex");
|
||||||
|
|
||||||
bitcoin_client->send_btc_tx(signed_tx_hex);
|
bitcoin_client->sendrawtransaction(signed_tx_hex);
|
||||||
|
|
||||||
return reply_str;
|
return reply_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::transfer_all_btc(const std::string& from_address, const std::string& to_address)
|
std::string sidechain_net_handler_bitcoin::transfer_all_btc(const std::string& from_address, const std::string& to_address)
|
||||||
{
|
{
|
||||||
uint64_t fee_rate = bitcoin_client->receive_estimated_fee();
|
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||||
uint64_t min_fee_rate = 1000;
|
uint64_t min_fee_rate = 1000;
|
||||||
fee_rate = std::max(fee_rate, min_fee_rate);
|
fee_rate = std::max(fee_rate, min_fee_rate);
|
||||||
|
|
||||||
double min_amount = ((double)fee_rate/100000000.0); // Account only for relay fee for now
|
double min_amount = ((double)fee_rate/100000000.0); // Account only for relay fee for now
|
||||||
double total_amount = 0.0;
|
double total_amount = 0.0;
|
||||||
std::vector<btc_txout> unspent_utxo= bitcoin_client->list_unspent_by_address_and_amount(from_address, 0);
|
std::vector<btc_txout> unspent_utxo = bitcoin_client->listunspent_by_address_and_amount(from_address, 0);
|
||||||
|
|
||||||
if(unspent_utxo.size() == 0)
|
if(unspent_utxo.size() == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -647,16 +581,16 @@ std::string sidechain_net_handler_bitcoin::transfer_all_btc(const std::string& f
|
||||||
fc::flat_map<std::string, double> outs;
|
fc::flat_map<std::string, double> outs;
|
||||||
outs[to_address] = total_amount - min_amount;
|
outs[to_address] = total_amount - min_amount;
|
||||||
|
|
||||||
std::string reply_str = bitcoin_client->prepare_tx(unspent_utxo, outs);
|
std::string reply_str = bitcoin_client->createrawtransaction(unspent_utxo, outs);
|
||||||
return sign_and_send_transaction_with_wallet(reply_str);
|
return sign_and_send_transaction_with_wallet(reply_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet ( const sidechain_event_data& sed )
|
std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet (const son_wallet_deposit_object &swdo)
|
||||||
{
|
{
|
||||||
const auto& idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
const auto& idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||||
auto obj = idx.rbegin();
|
auto obj = idx.rbegin();
|
||||||
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
|
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
|
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
|
||||||
|
|
@ -667,11 +601,11 @@ std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet (
|
||||||
|
|
||||||
std::string pw_address = json.get<std::string>("address");
|
std::string pw_address = json.get<std::string>("address");
|
||||||
|
|
||||||
std::string txid = sed.sidechain_transaction_id;
|
std::string txid = swdo.sidechain_transaction_id;
|
||||||
std::string suid = sed.sidechain_uid;
|
std::string suid = swdo.sidechain_uid;
|
||||||
std::string nvout = suid.substr(suid.find_last_of("-")+1);
|
std::string nvout = suid.substr(suid.find_last_of("-")+1);
|
||||||
uint64_t deposit_amount = sed.sidechain_amount.value;
|
uint64_t deposit_amount = swdo.sidechain_amount.value;
|
||||||
uint64_t fee_rate = bitcoin_client->receive_estimated_fee();
|
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||||
uint64_t min_fee_rate = 1000;
|
uint64_t min_fee_rate = 1000;
|
||||||
fee_rate = std::max(fee_rate, min_fee_rate);
|
fee_rate = std::max(fee_rate, min_fee_rate);
|
||||||
deposit_amount -= fee_rate; // Deduct minimum relay fee
|
deposit_amount -= fee_rate; // Deduct minimum relay fee
|
||||||
|
|
@ -688,16 +622,16 @@ std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet (
|
||||||
|
|
||||||
outs[pw_address] = transfer_amount;
|
outs[pw_address] = transfer_amount;
|
||||||
|
|
||||||
std::string reply_str = bitcoin_client->prepare_tx(ins, outs);
|
std::string reply_str = bitcoin_client->createrawtransaction(ins, outs);
|
||||||
return sign_and_send_transaction_with_wallet(reply_str);
|
return sign_and_send_transaction_with_wallet(reply_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wallet(const std::string& user_address, double sidechain_amount) {
|
std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wallet(const son_wallet_withdraw_object &swwo) {
|
||||||
const auto& idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
const auto& idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||||
auto obj = idx.rbegin();
|
auto obj = idx.rbegin();
|
||||||
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end())
|
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end())
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
|
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
|
||||||
|
|
@ -708,13 +642,13 @@ std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wall
|
||||||
|
|
||||||
std::string pw_address = json.get<std::string>("address");
|
std::string pw_address = json.get<std::string>("address");
|
||||||
|
|
||||||
uint64_t fee_rate = bitcoin_client->receive_estimated_fee();
|
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||||
uint64_t min_fee_rate = 1000;
|
uint64_t min_fee_rate = 1000;
|
||||||
fee_rate = std::max(fee_rate, min_fee_rate);
|
fee_rate = std::max(fee_rate, min_fee_rate);
|
||||||
|
|
||||||
double min_amount = sidechain_amount + ((double)fee_rate/100000000.0); // Account only for relay fee for now
|
double min_amount = ((double)(swwo.withdraw_amount.value + fee_rate) / 100000000.0); // Account only for relay fee for now
|
||||||
double total_amount = 0.0;
|
double total_amount = 0.0;
|
||||||
std::vector<btc_txout> unspent_utxo= bitcoin_client->list_unspent_by_address_and_amount(pw_address, 0);
|
std::vector<btc_txout> unspent_utxo = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0);
|
||||||
|
|
||||||
if(unspent_utxo.size() == 0)
|
if(unspent_utxo.size() == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -731,23 +665,23 @@ std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wall
|
||||||
if(min_amount > total_amount)
|
if(min_amount > total_amount)
|
||||||
{
|
{
|
||||||
wlog("Failed not enough BTC to spend for ${pw}",("pw", pw_address));
|
wlog("Failed not enough BTC to spend for ${pw}",("pw", pw_address));
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fc::flat_map<std::string, double> outs;
|
fc::flat_map<std::string, double> outs;
|
||||||
outs[user_address] = sidechain_amount;
|
outs[swwo.withdraw_address] = swwo.withdraw_amount.value / 100000000.0;
|
||||||
if((total_amount - min_amount) > 0.0)
|
if((total_amount - min_amount) > 0.0)
|
||||||
{
|
{
|
||||||
outs[pw_address] = total_amount - min_amount;
|
outs[pw_address] = total_amount - min_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string reply_str = bitcoin_client->prepare_tx(unspent_utxo, outs);
|
std::string reply_str = bitcoin_client->createrawtransaction(unspent_utxo, outs);
|
||||||
return sign_and_send_transaction_with_wallet(reply_str);
|
return sign_and_send_transaction_with_wallet(reply_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::handle_event( const std::string& event_data ) {
|
void sidechain_net_handler_bitcoin::handle_event( const std::string& event_data ) {
|
||||||
std::string block = bitcoin_client->receive_full_block( event_data );
|
std::string block = bitcoin_client->getblock(event_data);
|
||||||
if( block != "" ) {
|
if( block != "" ) {
|
||||||
const auto& vins = extract_info_from_block( block );
|
const auto& vins = extract_info_from_block( block );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,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_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin& _plugin, const boost::program_options::variables_map& options) :
|
||||||
sidechain_net_handler(_plugin, options) {
|
sidechain_net_handler(_plugin, options) {
|
||||||
sidechain = sidechain_type::peerplays;
|
sidechain = sidechain_type::peerplays;
|
||||||
plugin.database().applied_block.connect( [&] (const signed_block& b) { on_block_applied(b); } );
|
plugin.database().applied_block.connect( [&] (const signed_block& b) { on_applied_block(b); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() {
|
sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() {
|
||||||
|
|
@ -61,7 +61,7 @@ std::string sidechain_net_handler_peerplays::send_transaction( const std::string
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_peerplays::on_block_applied(const signed_block& b) {
|
void sidechain_net_handler_peerplays::on_applied_block(const signed_block& b) {
|
||||||
for (const auto& trx: b.transactions) {
|
for (const auto& trx: b.transactions) {
|
||||||
size_t operation_index = -1;
|
size_t operation_index = -1;
|
||||||
for (auto op: trx.operations) {
|
for (auto op: trx.operations) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue