diff --git a/libraries/chain/include/graphene/chain/transaction.hpp b/libraries/chain/include/graphene/chain/transaction.hpp index 0739fa70..bc3504f1 100644 --- a/libraries/chain/include/graphene/chain/transaction.hpp +++ b/libraries/chain/include/graphene/chain/transaction.hpp @@ -148,6 +148,7 @@ namespace graphene { namespace chain { : transaction(trx){} void sign( key_id_type id, const private_key_type& key ); + void sign( const address& addr, const private_key_type& key ); flat_map signatures; diff --git a/libraries/chain/transaction.cpp b/libraries/chain/transaction.cpp index 631470d1..f47b8e55 100644 --- a/libraries/chain/transaction.cpp +++ b/libraries/chain/transaction.cpp @@ -71,5 +71,16 @@ void graphene::chain::signed_transaction::sign( key_id_type id, const private_ke signatures[id] = key.sign_compact( digest() ); } } +void graphene::chain::signed_transaction::sign( const address& addr, const private_key_type& key ) +{ + if( relative_expiration != 0 ) + { + if( !block_id_cache.valid() ) edump((*this)); + assert(block_id_cache.valid()); + extra_signatures[addr] = key.sign_compact( digest(*block_id_cache) ); + } else { + extra_signatures[addr] = key.sign_compact( digest() ); + } +} } } // graphene::chain diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index eaa50b63..67b4130d 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -46,6 +46,7 @@ object* create_object( const variant& v ); struct plain_keys { map keys; + map extra_keys; fc::sha512 checksum; }; @@ -80,6 +81,9 @@ struct wallet_data /** encrypted keys */ vector cipher_keys; + /** map an account to a set of extra keys that have been imported for that account */ + map > extra_keys; + // map of account_name -> base58_private_key for // incomplete account regs map pending_account_registrations; @@ -409,6 +413,12 @@ class wallet_api */ bool import_key(string account_name_or_id, string wif_key); + /** + * This call will construct a transaction that will claim all balances controled + * by wif_keys and deposit them into the given account. + */ + signed_transaction import_balance( string account_name_or_id, const vector& wif_keys, bool broadcast ); + /** Transforms a brain key to reduce the chance of errors when re-entering the key from memory. * * This takes a user-supplied brain key and normalizes it into the form used @@ -903,11 +913,12 @@ class wallet_api } } -FC_REFLECT( graphene::wallet::plain_keys, (keys)(checksum) ) +FC_REFLECT( graphene::wallet::plain_keys, (keys)(extra_keys)(checksum) ) FC_REFLECT( graphene::wallet::wallet_data, (my_accounts) (cipher_keys) + (extra_keys) (pending_account_registrations) (ws_server) (ws_user) @@ -935,6 +946,7 @@ FC_API( graphene::wallet::wallet_api, (list_account_balances) (list_assets) (import_key) + (import_balance) (suggest_brain_key) (register_account) (upgrade_account) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index b31c9ee9..1643df1c 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2121,6 +2121,62 @@ void wallet_api::set_password( string password ) lock(); } +signed_transaction wallet_api::import_balance( string name_or_id, const vector& wif_keys, bool broadcast ) +{ try { + FC_ASSERT(!is_locked()); + account_object claimer = get_account( name_or_id ); + + vector
addrs; + map keys; + for( auto wif_key : wif_keys ) + { + auto priv_key = wif_to_key(wif_key); + FC_ASSERT( priv_key, "Invalid Private Key", ("key",wif_key) ); + addrs.push_back( priv_key->get_public_key() ); + keys[addrs.back()] = *priv_key; + } + + auto balances = my->_remote_db->get_balance_objects( addrs ); + wdump((balances)); + addrs.clear(); + + set bal_types; + for( auto b : balances ) bal_types.insert( b.balance.asset_id ); + + set
required_addrs; + signed_transaction trx; + for( auto a : bal_types ) + { + balance_claim_operation op; + op.total_claimed = asset( 0, a ); + for( auto b : balances ) + { + if( b.balance.asset_id == a ) + { + op.total_claimed += b.balance; + op.owners.insert( b.owner ); + op.deposit_to_account = claimer.id; + required_addrs.insert( b.owner ); + } + } + trx.operations.push_back(op); + } + + trx.visit( operation_set_fee( my->_remote_db->get_global_properties().parameters.current_fees ) ); + trx.validate(); + + auto tx = sign_transaction( trx, false ); + + for( auto a : required_addrs ) + tx.sign( a, keys[a] ); + + if( broadcast ) + my->_remote_net->broadcast_transaction(tx); + + return tx; + +} FC_CAPTURE_AND_RETHROW( (name_or_id) ) } + map wallet_api::dump_private_keys() { FC_ASSERT(!is_locked());