33 #include <boost/version.hpp>
34 #include <boost/lexical_cast.hpp>
35 #include <boost/algorithm/string/replace.hpp>
37 #include <boost/range/adaptor/map.hpp>
38 #include <boost/range/algorithm_ext/erase.hpp>
39 #include <boost/range/algorithm/unique.hpp>
40 #include <boost/range/algorithm/sort.hpp>
42 #include <boost/multi_index_container.hpp>
43 #include <boost/multi_index/ordered_index.hpp>
44 #include <boost/multi_index/mem_fun.hpp>
45 #include <boost/multi_index/member.hpp>
46 #include <boost/multi_index/random_access_index.hpp>
47 #include <boost/multi_index/tag.hpp>
48 #include <boost/multi_index/sequenced_index.hpp>
49 #include <boost/multi_index/hashed_index.hpp>
69 #include <graphene/chain/hardfork.hpp>
81 #define BRAIN_KEY_WORD_COUNT 16
82 #define RANGE_PROOF_MANTISSA 49 // Minimum mantissa bits to "hide" in the range proof.
87 namespace graphene {
namespace wallet {
93 to_sign <<
"memokey=" << string(
meta.
memo_key ) <<
'\n';
94 to_sign <<
"block=" <<
meta.
block <<
'\n';
95 to_sign <<
"timestamp=" <<
meta.
time;
100 uint32_t number_of_desired_keys )
103 FC_ASSERT( number_of_desired_keys >= 1,
"number_of_desired_keys should be at least 1" );
106 vector<brain_key_info> results;
107 for( uint32_t i = 0; i < number_of_desired_keys; ++i )
116 results.push_back(result);
131 entropy <<= 8 * sha_entropy1.
data_size();
133 string brain_key =
"";
153 namespace graphene {
namespace wallet {
156 : my(
std::make_unique<detail::wallet_api_impl>(*this, initial_data, rapi) )
164 return my->copy_wallet_file(destination_filename);
169 return my->_remote_db->get_block(num);
174 return my->_remote_db->get_account_count();
179 return vector<account_object>(
my->_wallet.my_accounts.begin(),
my->_wallet.my_accounts.end());
184 return my->_remote_db->lookup_accounts(lowerbound, limit, {});
189 return my->_remote_db->get_account_balances(
id, flat_set<asset_id_type>());
194 return my->_remote_db->list_assets( lowerbound, limit );
199 return my->_remote_db->get_asset_count();
203 const string& amount,
const string& asset_symbol,
const string& hash_algorithm,
204 const string& preimage_hash, uint32_t preimage_size,
205 uint32_t claim_period_seconds,
const string& memo,
bool broadcast )
const
207 return my->htlc_create(source, destination, amount, asset_symbol, hash_algorithm, preimage_hash, preimage_size,
208 claim_period_seconds, memo, broadcast);
214 if ( optional_obj.
valid() )
226 if (obj.
memo.valid())
228 class htlc_hash_to_variant_visitor
234 {
return convert(
"RIPEMD160", obj.
str()); }
236 {
return convert(
"SHA1", obj.
str()); }
238 {
return convert(
"SHA256", obj.
str()); }
240 {
return convert(
"HASH160", obj.
str()); }
242 result_type convert(
const string& type,
const string& hash)
const
245 ret_val[
"hash_algo"] = type;
246 ret_val[
"preimage_hash"] = hash;
250 static htlc_hash_to_variant_visitor hash_visitor;
257 conditions[
"htlc_lock"] = htlc_lock;
258 conditions[
"time_lock"] = time_lock;
261 result[
"conditions"] = conditions;
268 const string& preimage,
bool broadcast )
const
271 return my->htlc_redeem(htlc_id, issuer, std::vector<char>(preimage.begin(), preimage.end()), broadcast);
275 uint32_t seconds_to_add,
bool broadcast )
const
277 return my->htlc_extend(htlc_id, issuer, seconds_to_add, broadcast);
282 vector<operation_detail> result;
286 bool skip_first_row =
false;
287 operation_history_id_type start;
290 start = result.back().op.id;
291 if( start == operation_history_id_type() )
293 start = start + (-1);
294 if( start == operation_history_id_type() )
298 skip_first_row =
true;
302 uint32_t default_page_size = 100;
303 uint32_t page_limit = skip_first_row ? std::min<uint32_t>( default_page_size, limit + 1 )
304 : std::min<uint32_t>( default_page_size, limit );
306 vector<operation_history_object> current =
my->_remote_hist->get_account_history(
308 operation_history_id_type(),
311 bool first_row =
true;
312 for(
auto& o : current )
322 std::stringstream ss;
327 if( current.size() < page_limit )
330 limit -= current.size();
342 uint32_t start )
const
344 vector<operation_detail> result;
353 start = std::min<uint32_t>(start, stats.
total_ops);
355 uint32_t default_page_size = 100;
358 uint32_t page_size = std::min<uint32_t>(default_page_size, limit);
359 vector <operation_history_object> current =
my->_remote_hist->get_relative_account_history(
364 for (
auto &o : current) {
365 std::stringstream ss;
369 if (current.size() < page_size)
373 if( start == 0 )
break;
380 const flat_set<uint16_t>& operation_types,
382 uint32_t limit )
const
386 const auto& account =
my->get_account(name);
387 const auto& stats =
my->get_object(account.statistics);
390 start = start == 0 ? 1 : start;
392 if (start <= stats.removed_ops) {
393 start = stats.removed_ops;
397 uint32_t default_page_size = 100;
398 while (limit > 0 && start <= stats.total_ops) {
399 uint32_t min_limit = std::min(default_page_size, limit);
400 auto current =
my->_remote_hist->get_account_history_by_operations(name, operation_types, start, min_limit);
401 auto his_rend = current.operation_history_objs.rend();
402 for(
auto it = current.operation_history_objs.rbegin(); it != his_rend; ++it )
405 std::stringstream ss;
410 if (block.valid() && obj.trx_in_block < block->transaction_ids.size()) {
411 transaction_id = block->transaction_ids[obj.trx_in_block];
415 result.
result_count += current.operation_history_objs.size();
418 start += current.total_count > 0 ? current.total_count : min_limit;
419 limit -= current.operation_history_objs.size();
427 return my->_remote_db->get_full_accounts({name_or_id},
false)[name_or_id];
431 const string& symbol1,
432 const string& symbol2,
437 return my->_remote_hist->get_market_history( symbol1, symbol2, bucket, start, end );
441 const string& name_or_id,
445 const optional<limit_order_id_type>& ostart_id,
446 const optional<price>& ostart_price )
const
448 return my->_remote_db->get_account_limit_orders(name_or_id, base, quote, limit, ostart_id, ostart_price);
453 return my->_remote_db->get_limit_orders(a, b, limit);
458 return my->_remote_db->get_call_orders(a, limit);
463 return my->_remote_db->get_settle_orders(a, limit);
468 return my->_remote_db->get_collateral_bids(a, limit, start);
477 const string& brain_key,
478 uint32_t number_of_desired_keys )
const
485 bool is_known =
my->_remote_db->is_public_key_registered(public_key);
497 return my->_remote_db->get_objects({
id}, {});
502 return my->get_wallet_filename();
507 return my->begin_builder_transaction();
514 my->add_operation_to_builder_transaction(transaction_handle, op);
519 uint32_t operation_index,
522 my->replace_operation_in_builder_transaction(handle, operation_index, new_op);
527 return my->set_fees_on_builder_transaction(handle, fee_asset);
532 return my->preview_builder_transaction(handle);
538 return my->sign_builder_transaction(transaction_handle, broadcast);
542 const vector<public_key_type>& explicit_keys,
545 return my->sign_builder_transaction2(transaction_handle, explicit_keys, broadcast);
550 return my->broadcast_transaction(tx);
555 const time_point_sec& expiration,
556 uint32_t review_period_seconds,
557 bool broadcast )
const
559 return my->propose_builder_transaction(handle, expiration, review_period_seconds, broadcast);
564 const string& account_name_or_id,
565 const time_point_sec& expiration,
566 uint32_t review_period_seconds,
567 bool broadcast )
const
569 return my->propose_builder_transaction2(handle, account_name_or_id, expiration, review_period_seconds, broadcast);
574 return my->remove_builder_transaction(handle);
579 return my->get_account(account_name_or_id);
584 auto found_asset =
my->find_asset(asset_name_or_id);
585 FC_ASSERT( found_asset,
"Unable to find asset '${a}'", (
"a",asset_name_or_id) );
593 return my->get_object(*
asset.bitasset_data_id);
598 return my->get_account_id(account_name_or_id);
603 return my->get_asset_id(asset_symbol_or_id);
611 if (!optional_private_key)
616 if(
my->import_key(account_name_or_id, wif_key) )
630 const auto imported_keys = fc::json::from_file<exported_keys>( filename );
635 map<string, bool, std::less<>> result;
636 for(
const auto& item : imported_keys.account_keys )
638 const auto import_this_account = [ & ]() ->
bool
646 for(
const auto& public_key : item.public_keys )
648 if( std::find( owner_keys.begin(), owner_keys.end(), public_key ) != owner_keys.end() )
651 if( std::find( active_keys.begin(), active_keys.end(), public_key ) != active_keys.end() )
662 const auto should_proceed = import_this_account();
663 result[ item.account_name ] = should_proceed;
667 uint32_t import_successes = 0;
668 uint32_t import_failures = 0;
670 for(
const auto& encrypted_key : item.encrypted_private_keys )
674 const auto plain_text =
fc::aes_decrypt( password_hash, encrypted_key );
675 const auto private_key = fc::raw::unpack<private_key_type>( plain_text );
686 ilog(
"successfully imported ${n} keys for account ${name}",
687 (
"n", import_successes)(
"name", item.account_name) );
688 if( import_failures > 0 )
689 elog(
"failed to import ${n} keys for account ${name}",
690 (
"n", import_failures)(
"name", item.account_name) );
698 const string& filename,
699 const string& password,
700 const string& src_account_name,
701 const string& dest_account_name )
const
706 bool is_my_account =
false;
708 for(
const auto& account : accounts )
710 if( account.name == dest_account_name )
712 is_my_account =
true;
718 const auto imported_keys = fc::json::from_file<exported_keys>( filename );
723 bool found_account =
false;
724 for(
const auto& item : imported_keys.account_keys )
726 if( item.account_name != src_account_name )
729 found_account =
true;
731 for(
const auto& encrypted_key : item.encrypted_private_keys )
733 const auto plain_text =
fc::aes_decrypt( password_hash, encrypted_key );
734 const auto private_key = fc::raw::unpack<private_key_type>( plain_text );
769 const public_key_type& owner_pubkey,
770 const public_key_type& active_pubkey,
771 const string& registrar_account,
772 const string& referrer_account,
773 uint32_t referrer_percent,
774 bool broadcast )
const
776 return my->register_account( name, owner_pubkey, active_pubkey,
777 registrar_account, referrer_account, referrer_percent, broadcast );
780 const string& registrar_account,
const string& referrer_account,
781 bool broadcast )
const
783 return my->create_account_with_brain_key(
784 brain_key, account_name, registrar_account,
785 referrer_account, broadcast
789 const string& memo,
bool broadcast )
const
791 return my->issue_asset(to_account, amount, symbol, memo, broadcast);
795 const string& asset_symbol,
const string& memo,
796 bool broadcast )
const
798 return my->transfer(from, to, amount, asset_symbol, memo, broadcast);
801 const string& symbol,
803 const asset_options& common,
804 const optional<bitasset_options>& bitasset_opts,
805 bool broadcast )
const
807 return my->create_asset(issuer, symbol, precision, common, bitasset_opts, broadcast);
811 const optional<string>& new_issuer,
812 const asset_options& new_options,
813 bool broadcast )
const
815 return my->update_asset(symbol, new_issuer, new_options, broadcast);
819 const string& new_issuer,
820 bool broadcast )
const
822 return my->update_asset_issuer(symbol, new_issuer, broadcast);
826 const bitasset_options& new_options,
827 bool broadcast )
const
829 return my->update_bitasset(symbol, new_options, broadcast);
833 const flat_set<string>& new_feed_producers,
834 bool broadcast )
const
836 return my->update_asset_feed_producers(symbol, new_feed_producers, broadcast);
840 const string& symbol,
841 const price_feed& feed,
842 bool broadcast )
const
844 return my->publish_asset_feed(publishing_account, symbol, feed, broadcast);
848 const string& symbol,
849 const string& amount,
850 bool broadcast )
const
852 return my->fund_asset_fee_pool(from, symbol, amount, broadcast);
856 const string& amount,
857 bool broadcast )
const
859 return my->claim_asset_fee_pool(symbol, amount, broadcast);
863 const string& amount,
864 const string& symbol,
865 bool broadcast )
const
867 return my->reserve_asset(from, amount, symbol, broadcast);
871 const price& settle_price,
872 bool broadcast )
const
874 return my->global_settle_asset(symbol, settle_price, broadcast);
878 const string& amount_to_settle,
879 const string& symbol,
880 bool broadcast )
const
882 return my->settle_asset(account_to_settle, amount_to_settle, symbol, broadcast);
886 const string& debt_amount,
const string& debt_symbol,
887 const string& additional_collateral,
888 bool broadcast )
const
890 return my->bid_collateral(bidder_name, debt_amount, debt_symbol, additional_collateral, broadcast);
894 const string& account_to_list,
895 account_whitelist_operation::account_listing new_listing_status,
896 bool broadcast )
const
898 return my->whitelist_account(authorizing_account, account_to_list, new_listing_status, broadcast);
902 bool broadcast )
const
904 return my->create_committee_member(owner_account, url, broadcast);
909 return my->_remote_db->lookup_witness_accounts(lowerbound, limit);
913 const string& lowerbound, uint32_t limit )
const
915 return my->_remote_db->lookup_committee_member_accounts(lowerbound, limit);
920 return my->get_witness(owner_account);
925 return my->get_committee_member(owner_account);
930 bool broadcast )
const
932 return my->create_witness(owner_account, url, broadcast);
936 const string& owner_account,
937 const time_point_sec& work_begin_date,
938 const time_point_sec& work_end_date,
942 const variant& worker_settings,
943 bool broadcast )
const
945 return my->create_worker( owner_account, work_begin_date, work_end_date,
946 daily_pay, name, url, worker_settings, broadcast );
950 const string& owner_account,
952 bool broadcast )
const
954 return my->update_worker_votes( owner_account, delta, broadcast );
958 const string& witness_name,
960 const string& block_signing_key,
961 bool broadcast )
const
963 return my->update_witness(witness_name, url, block_signing_key, broadcast);
968 return my->get_vesting_balances( account_name );
972 const string& witness_name,
973 const string& amount,
974 const string& asset_symbol,
975 bool broadcast )
const
977 return my->withdraw_vesting( witness_name, amount, asset_symbol, broadcast );
981 const string& witness,
983 bool broadcast )
const
985 return my->vote_for_committee_member(voting_account,
witness, approve, broadcast);
989 const string& witness,
991 bool broadcast )
const
993 return my->vote_for_witness(voting_account,
witness, approve, broadcast);
997 const optional<string>& voting_account,
998 bool broadcast )
const
1000 return my->set_voting_proxy(account_to_modify, voting_account, broadcast);
1004 uint16_t desired_number_of_witnesses,
1005 uint16_t desired_number_of_committee_members,
1006 bool broadcast )
const
1008 return my->set_desired_witness_and_committee_member_count(account_to_modify, desired_number_of_witnesses,
1009 desired_number_of_committee_members, broadcast);
1014 my->_wallet_filename = wallet_filename;
1019 return my->sign_transaction( tx, broadcast);
1023 const vector<public_key_type>& signing_keys,
1024 bool broadcast )
const
1026 return my->sign_transaction2( tx, signing_keys, broadcast);
1031 return my->get_transaction_signers(tx);
1036 return my->get_key_references(keys);
1041 return my->get_prototype_operation( operation_name );
1047 my->dbg_make_uia(creator, symbol);
1053 my->dbg_make_mia(creator, symbol);
1058 my->dbg_push_blocks( src_filename, count );
1063 my->dbg_generate_blocks( debug_wif_key, count );
1068 my->dbg_stream_json_objects( filename );
1073 my->dbg_update_object( update );
1078 my->network_add_nodes( nodes );
1083 return my->network_get_connected_peers();
1089 my->flood_network(prefix, number_of_transactions);
1093 const string& proposing_account,
1099 return my->propose_parameter_change( proposing_account, expiration_time, changed_values, broadcast );
1103 const string& proposing_account,
1109 return my->propose_fee_change( proposing_account, expiration_time, changed_fees, broadcast );
1113 const string& fee_paying_account,
1114 const string& proposal_id,
1119 return my->approve_proposal( fee_paying_account, proposal_id, delta, broadcast );
1124 return my->get_global_properties();
1129 return my->get_dynamic_global_properties();
1133 bool broadcast )
const
1135 return my->add_transaction_signature( tx, broadcast );
1140 std::vector<string> method_names =
my->method_documentation.get_method_names();
1141 std::stringstream ss;
1142 for (
const string& method_name : method_names)
1146 ss <<
my->method_documentation.get_brief_description(method_name);
1148 catch (
const fc::key_not_found_exception&)
1150 ss << method_name <<
" (no help available)\n";
1159 std::stringstream ss;
1162 string doxygenHelpString =
my->method_documentation.get_detailed_description(method);
1163 if (!doxygenHelpString.empty())
1164 ss << doxygenHelpString <<
"\n";
1166 if( method ==
"import_key" )
1168 ss <<
"usage: import_key ACCOUNT_NAME_OR_ID WIF_PRIVATE_KEY\n\n";
1169 ss <<
"example: import_key \"1.3.11\" 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3\n";
1170 ss <<
"example: import_key \"usera\" 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3\n";
1172 else if( method ==
"transfer" )
1174 ss <<
"usage: transfer FROM TO AMOUNT SYMBOL \"memo\" BROADCAST\n\n";
1175 ss <<
"example: transfer \"1.3.11\" \"1.3.4\" 1000.03 CORE \"memo\" true\n";
1176 ss <<
"example: transfer \"usera\" \"userb\" 1000.123 CORE \"memo\" true\n";
1178 else if( method ==
"create_account_with_brain_key" )
1180 ss <<
"usage: create_account_with_brain_key BRAIN_KEY ACCOUNT_NAME REGISTRAR REFERRER BROADCAST\n\n";
1181 ss <<
"example: create_account_with_brain_key "
1182 <<
"\"my really long brain key\" \"newaccount\" \"1.3.11\" \"1.3.11\" true\n";
1183 ss <<
"example: create_account_with_brain_key "
1184 <<
"\"my really long brain key\" \"newaccount\" \"someaccount\" \"otheraccount\" true\n";
1186 ss <<
"This method should be used if you would like the wallet to generate new keys derived from the "
1188 ss <<
"The BRAIN_KEY will be used as the owner key, and the active key will be derived from the BRAIN_KEY. "
1190 ss <<
"register_account if you already know the keys you know the public keys that you would like to "
1194 else if( method ==
"register_account" )
1196 ss <<
"usage: register_account ACCOUNT_NAME OWNER_PUBLIC_KEY ACTIVE_PUBLIC_KEY REGISTRAR "
1197 <<
"REFERRER REFERRER_PERCENT BROADCAST\n\n";
1198 ss <<
"example: register_account \"newaccount\" \"CORE6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV\" "
1199 <<
"\"CORE6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV\" \"1.3.11\" \"1.3.11\" 50 true\n";
1201 ss <<
"Use this method to register an account for which you do not know the private keys.";
1203 else if( method ==
"create_asset" )
1205 ss <<
"usage: ISSUER SYMBOL PRECISION_DIGITS OPTIONS BITASSET_OPTIONS BROADCAST\n\n";
1206 ss <<
"PRECISION_DIGITS: the number of digits after the decimal point\n\n";
1207 ss <<
"Example value of OPTIONS: \n";
1209 ss <<
"\nExample value of BITASSET_OPTIONS: \n";
1211 ss <<
"\nBITASSET_OPTIONS may be null\n";
1213 else if (doxygenHelpString.empty())
1214 ss <<
"No help defined for method " << method <<
"\n";
1221 return my->load_wallet_file( wallet_filename );
1231 my->save_wallet_file( wallet_filename );
1237 return my->get_result_formatters();
1242 return my->is_locked();
1246 return my->_wallet.cipher_keys.size() == 0;
1258 for(
auto key :
my->_keys )
1262 my->self.lock_changed(
true);
1270 auto pk = fc::raw::unpack<plain_keys>(decrypted);
1272 my->_keys = std::move(pk.keys);
1273 my->_checksum = pk.checksum;
1274 my->self.lock_changed(
false);
1280 FC_ASSERT( !
is_locked(),
"The wallet must be unlocked before the password can be set" );
1286 const string& name_or_id,
1287 const vector<string>& wif_keys,
1288 bool broadcast )
const
1290 return my->import_balance( name_or_id, wif_keys, broadcast );
1301 return my->upgrade_account(name,broadcast);
1305 const string& amount_to_sell,
1306 const string& symbol_to_sell,
1307 const string& min_to_receive,
1308 const string& symbol_to_receive,
1309 uint32_t expiration,
1311 bool broadcast )
const
1313 return my->sell_asset(seller_account, amount_to_sell, symbol_to_sell, min_to_receive,
1314 symbol_to_receive, expiration, fill_or_kill, broadcast);
1318 const string& asset_symbol,
const string& amount_of_collateral,
1319 bool broadcast )
const
1322 return my->borrow_asset_ext( seller_name, amount_to_sell, asset_symbol, amount_of_collateral, {}, broadcast );
1326 const string& asset_symbol,
const string& amount_of_collateral,
1328 bool broadcast )
const
1331 return my->borrow_asset_ext(seller_name, amount_to_sell, asset_symbol,
1332 amount_of_collateral, extensions, broadcast);
1338 return my->cancel_order(order_id, broadcast);
1344 return my->sign_memo(from, to, memo);
1350 return my->read_memo(memo);
1356 return my->sign_message(signer,
message);
1362 return my->verify_message(
message, account, block, msg_time, sig );
1372 return my->verify_signed_message(
message );
1382 return my->verify_encapsulated_message(
message );
1388 auto key_itr =
my->_wallet.labeled_keys.get<by_key>().find(key);
1389 if( key_itr !=
my->_wallet.labeled_keys.get<by_key>().end() )
1390 return key_itr->label;
1401 try {
return fc::variant(label, 1).
as<public_key_type>( 1 ); }
catch ( ... ){}
1403 auto key_itr =
my->_wallet.labeled_keys.get<by_label>().find(label);
1404 if( key_itr !=
my->_wallet.labeled_keys.get<by_label>().end() )
1405 return key_itr->key;
1406 return public_key_type();
1411 auto result =
my->_wallet.labeled_keys.insert(
key_label{label,key} );
1412 if( result.second )
return true;
1414 auto key_itr =
my->_wallet.labeled_keys.get<by_key>().find(key);
1415 auto label_itr =
my->_wallet.labeled_keys.get<by_label>().find(label);
1416 if( label_itr ==
my->_wallet.labeled_keys.get<by_label>().end() )
1418 if( key_itr !=
my->_wallet.labeled_keys.get<by_key>().end() )
1419 return my->_wallet.labeled_keys.get<by_key>().modify( key_itr, [&](
key_label& obj ){ obj.
label = label; } );
1425 map<string, public_key_type, std::less<>> result;
1426 for(
const auto& item :
my->_wallet.labeled_keys )
1427 result[item.label] = item.key;
1433 map<string, public_key_type, std::less<>> result;
1434 for(
const auto& item :
my->_wallet.labeled_keys )
1436 if(
my->_keys.find(item.key) !=
my->_keys.end() )
1437 result[item.label] = item.key;
1446 auto label_itr =
my->_wallet.labeled_keys.get<by_label>().find(label);
1447 if( label_itr !=
my->_wallet.labeled_keys.get<by_label>().end() )
1448 FC_ASSERT( !
"Key with label already exists" );
1452 public_key_type pub_key = priv_key.get_public_key();
1464 vector<asset> result;
1465 map<asset_id_type, share_type> balances;
1467 vector<commitment_type> used;
1470 auto& to_asset_used_idx =
my->_wallet.blind_receipts.get<by_to_asset_used>();
1471 auto start = to_asset_used_idx.lower_bound( std::make_tuple(pub_key,asset_id_type(0),
false) );
1472 auto end = to_asset_used_idx.lower_bound( std::make_tuple(pub_key,asset_id_type(uint32_t(0xffffffff)),
true) );
1473 while( start != end )
1477 auto answer =
my->_remote_db->get_blinded_balances( {start->commitment()} );
1479 balances[start->amount.asset_id] += start->amount.amount;
1481 used.push_back( start->commitment() );
1485 for(
const auto& u : used )
1487 auto itr =
my->_wallet.blind_receipts.get<by_commitment>().find( u );
1490 for(
auto item : balances )
1491 result.push_back(
asset( item.second, item.first ) );
1496 const string& to_account_id_or_name,
1497 const string& amount_in,
1498 const string& symbol,
1499 bool broadcast )
const
1504 auto fees =
my->_remote_db->get_global_properties().parameters.get_current_fees();
1506 FC_ASSERT(asset_obj.
valid(),
"Could not find asset matching ${asset}", (
"asset", symbol));
1515 from_blind_account_key_or_label,
1516 blind_in, symbol,
false,
true );
1519 auto to_account =
my->get_account( to_account_id_or_name );
1520 from_blind.
to = to_account.id;
1521 from_blind.
amount = amount;
1522 from_blind.
blinding_factor = conf.outputs.back().decrypted_memo.blinding_factor;
1523 from_blind.
inputs.push_back( {conf.outputs.back().decrypted_memo.commitment,
authority() } );
1526 idump( (from_blind) );
1527 conf.trx.operations.push_back(from_blind);
1528 ilog(
"about to validate" );
1529 conf.trx.validate();
1531 ilog(
"about to broadcast" );
1534 if( broadcast && conf.outputs.size() == 2 ) {
1541 public_key_type from_key =
get_public_key(from_blind_account_key_or_label);
1548 from_blind_account_key_or_label,
1549 "@"+to_account.name );
1554 }
FC_CAPTURE_AND_RETHROW( (from_blind_account_key_or_label)(to_account_id_or_name)(amount_in)(symbol) ) }
1557 const string& to_key_or_label,
1558 const string& amount_in,
1559 const string& symbol,
1560 bool broadcast )
const
1562 return blind_transfer_help( from_key_or_label, to_key_or_label, amount_in, symbol, broadcast,
false );
1565 const string& to_key_or_label,
1566 const string& amount_in,
1567 const string& symbol,
1579 FC_ASSERT(asset_obj.
valid(),
"Could not find asset matching ${asset}", (
"asset", symbol));
1584 auto fees =
my->_remote_db->get_global_properties().parameters.get_current_fees();
1590 vector<fc::sha256> blinding_factors;
1596 vector<commitment_type> used;
1598 auto& to_asset_used_idx =
my->_wallet.blind_receipts.get<by_to_asset_used>();
1599 auto start = to_asset_used_idx.lower_bound( std::make_tuple(from_key,amount.asset_id,
false) );
1600 auto end = to_asset_used_idx.lower_bound( std::make_tuple(from_key,amount.asset_id,
true) );
1601 while( start != end )
1603 auto result =
my->_remote_db->get_blinded_balances( {start->commitment() } );
1604 if( result.size() == 0 )
1606 used.push_back( start->commitment() );
1610 blind_tr.
inputs.push_back({start->commitment(), start->control_authority});
1611 blinding_factors.push_back( start->data.blinding_factor );
1612 total_amount += start->
amount;
1614 if( total_amount >= amount + blind_tr.
fee )
1619 for(
const auto& u : used )
1621 auto itr =
my->_wallet.blind_receipts.get<by_commitment>().find( u );
1626 "Insufficient Balance",
1627 (
"available",total_amount)(
"amount",amount)(
"fee",blind_tr.
fee) );
1630 auto secret = one_time_key.get_shared_secret( to_key );
1635 auto from_secret = one_time_key.get_shared_secret( from_key );
1639 auto change = total_amount - amount - blind_tr.
fee;
1642 if( change.amount > 0 )
1644 idump((
"to_blind_factor")(blind_factor) );
1645 blinding_factors.push_back( blind_factor );
1646 change_blind_factor =
fc::ecc::blind_sum( blinding_factors, blinding_factors.size() - 1 );
1647 wdump((
"change_blind_factor")(change_blind_factor) );
1653 idump((
"to_sum_blind_factor")(blind_factor) );
1654 blinding_factors.push_back( blind_factor );
1655 idump((
"nochange to_blind_factor")(blind_factor) );
1666 if( blind_tr.
outputs.size() > 1 )
1672 change_out.
owner =
authority( 1, public_key_type( from_pub_key.
child( from_child ) ), 1 );
1676 blind_tr.
outputs[1] = change_out;
1680 conf_output.
label = from_key_or_label;
1681 conf_output.
pub_key = from_key;
1694 confirm.
outputs.push_back( conf_output );
1699 conf_output.
label = to_key_or_label;
1712 confirm.
outputs.push_back( conf_output );
1717 std::sort( blind_tr.
inputs.begin(), blind_tr.
inputs.end(),
1721 ilog(
"validate before" );
1727 for(
const auto& out : confirm.
outputs )
1734 }
FC_CAPTURE_AND_RETHROW( (from_key_or_label)(to_key_or_label)(amount_in)(symbol)(broadcast)(confirm) ) }
1743 const string& asset_symbol,
1745 const vector<pair<string, string>>& to_amounts,
1746 bool broadcast )
const
1749 idump((to_amounts));
1755 FC_ASSERT(asset_obj,
"Could not find asset matching ${asset}", (
"asset", asset_symbol));
1758 bop.
from = from_account.
id;
1760 vector<fc::sha256> blinding_factors;
1764 for(
auto item : to_amounts )
1768 auto secret = one_time_key.get_shared_secret( to_key );
1773 blinding_factors.push_back( blind_factor );
1776 total_amount += amount;
1783 if( to_amounts.size() > 1 )
1788 conf_output.
label = item.first;
1800 confirm.
outputs.push_back( conf_output );
1804 bop.
amount = total_amount;
1812 my->set_operation_fees( confirm.
trx,
my->_remote_db->get_global_properties().parameters.get_current_fees());
1818 for(
const auto& out : confirm.
outputs )
1830 const string& opt_from,
const string& opt_memo )
const
1839 auto to_priv_key_itr =
my->_keys.find( *conf.
to );
1840 FC_ASSERT( to_priv_key_itr !=
my->_keys.end(),
"No private key for receiver", (
"conf",conf) );
1843 auto to_priv_key =
wif_to_key( to_priv_key_itr->second );
1846 auto secret = to_priv_key->get_shared_secret( conf.
one_time_key );
1849 auto child_priv_key = to_priv_key->child( child );
1853 auto memo = fc::raw::unpack<stealth_confirmation::memo_data>( plain_memo );
1872 result.
memo = opt_memo;
1875 auto commtiment_test =
fc::ecc::blind( memo.blinding_factor, memo.amount.amount.value );
1881 if( memo.from ) bal.
from = *memo.from;
1887 auto child_pubkey = child_priv_key.get_public_key();
1888 auto owner =
authority(1, public_key_type(child_pubkey), 1);
1892 auto child_key_itr = owner.key_auths.find( child_pubkey );
1893 if( child_key_itr != owner.key_auths.end() )
1894 my->_keys[child_key_itr->first] =
key_to_wif( child_priv_key );
1899 my->_wallet.blind_receipts.insert( result );
1900 my->_keys[child_pubkey] =
key_to_wif( child_priv_key );
1909 vector<blind_receipt> result;
1912 if( pub_key == public_key_type() )
1913 return vector<blind_receipt>();
1915 for(
auto& r :
my->_wallet.blind_receipts )
1917 if( r.from_key == pub_key || r.to_key == pub_key )
1918 result.push_back( r );
1920 std::sort( result.begin(), result.end(),
1927 return(
my->_remote_db->get_order_book( base, quote, limit ) );
1932 const flat_map<
string, optional<string>>& key_values,
bool broadcast )
const
1934 return my->account_store_map(account, catalog, is_to_remove, key_values, broadcast);
1939 return my->_custom_operations->get_storage_info(account, catalog);
1943 : signed_block( block ),
1945 signing_key { signee() }
1947 transaction_ids.reserve( transactions.size() );
1949 transaction_ids.push_back( tx.id() );
1957 allowed_withdraw_time { now }
1966 to_variant( std::vector<account_object>(accts.begin(), accts.end()), vo, max_depth );
1971 const std::vector<account_object>& v = var.
as<std::vector<account_object>>( max_depth );