From 84fd629d36d52e364517ec56948375290809d776 Mon Sep 17 00:00:00 2001 From: James Calfee Date: Fri, 29 Jan 2016 15:12:55 -0600 Subject: [PATCH 1/5] Add crypto API call to derive a public key child. #536 --- libraries/app/api.cpp | 5 +++++ libraries/app/include/graphene/app/api.hpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index f262cca7..0d07ef2c 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -464,6 +464,11 @@ namespace graphene { namespace app { { return fc::ecc::range_proof_sign( min_value, commit, commit_blind, nonce, base10_exp, min_bits, actual_value ); } + + fc::ecc::public_key crypto_api::child(fc::ecc::public_key public_key, fc::sha256 child) + { + return public_key_type( public_key.child( child ) ); + } verify_range_proof_rewind_result crypto_api::verify_range_proof_rewind( const blind_factor_type& nonce, const commitment_type& commit, diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index a6ffe0e9..ebca000f 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -222,6 +222,7 @@ namespace graphene { namespace app { uint8_t min_bits, uint64_t actual_value ); + fc::ecc::public_key child(fc::ecc::public_key public_key, fc::sha256 child); verify_range_proof_rewind_result verify_range_proof_rewind( const blind_factor_type& nonce, const fc::ecc::commitment_type& commit, @@ -313,6 +314,7 @@ FC_API(graphene::app::crypto_api, (verify_sum) (verify_range) (range_proof_sign) + (child) (verify_range_proof_rewind) (range_get_info) ) From da598c82aa80e3836c012297fcc5a370b46bc1ca Mon Sep 17 00:00:00 2001 From: James Calfee Date: Tue, 2 Feb 2016 13:11:54 -0600 Subject: [PATCH 2/5] Revert "Add crypto API call to derive a public key child. #536" This reverts commit 84fd629d36d52e364517ec56948375290809d776. --- libraries/app/api.cpp | 5 ----- libraries/app/include/graphene/app/api.hpp | 2 -- 2 files changed, 7 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 0d07ef2c..f262cca7 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -464,11 +464,6 @@ namespace graphene { namespace app { { return fc::ecc::range_proof_sign( min_value, commit, commit_blind, nonce, base10_exp, min_bits, actual_value ); } - - fc::ecc::public_key crypto_api::child(fc::ecc::public_key public_key, fc::sha256 child) - { - return public_key_type( public_key.child( child ) ); - } verify_range_proof_rewind_result crypto_api::verify_range_proof_rewind( const blind_factor_type& nonce, const commitment_type& commit, diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index ebca000f..a6ffe0e9 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -222,7 +222,6 @@ namespace graphene { namespace app { uint8_t min_bits, uint64_t actual_value ); - fc::ecc::public_key child(fc::ecc::public_key public_key, fc::sha256 child); verify_range_proof_rewind_result verify_range_proof_rewind( const blind_factor_type& nonce, const fc::ecc::commitment_type& commit, @@ -314,7 +313,6 @@ FC_API(graphene::app::crypto_api, (verify_sum) (verify_range) (range_proof_sign) - (child) (verify_range_proof_rewind) (range_get_info) ) From f1be8574410662e5dee1c762d1aff953cbe9cb7d Mon Sep 17 00:00:00 2001 From: James Calfee Date: Tue, 9 Feb 2016 07:22:36 -0600 Subject: [PATCH 3/5] Updated fc submodule version (fixes compile) #500 --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index ad7ecbf0..d74eee81 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit ad7ecbf061ae74c944c81da993a020c05d53c7b6 +Subproject commit d74eee811018f5f0b562b12af3a5afaa59cf60cb From fa439e97323cdddd28c604bb89d5748343d94772 Mon Sep 17 00:00:00 2001 From: James Calfee Date: Tue, 9 Feb 2016 12:37:54 -0600 Subject: [PATCH 4/5] Saves change address in the wallet when transfering from blind to an account (close #564) --- .../wallet/include/graphene/wallet/wallet.hpp | 3 +- libraries/wallet/wallet.cpp | 39 ++++++++++++++++--- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 02582de4..76bada67 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -765,9 +765,10 @@ class wallet_api * who sent it. * * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from + * @param owner - optional, when owner is emtpy (owner == authority()) this receipt must be on the blockchain. Transfers may save their confirmation prior to broadcast. * @param confirmation_receipt - a base58 encoded stealth confirmation */ - blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); + blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo, optional owner ); /** * Transfers a public balance from @from to one or more blinded balances using a diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index ed93724a..163a7899 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -3676,7 +3676,7 @@ blind_confirmation wallet_api::transfer_from_blind( string from_blind_account_ke auto conf = blind_transfer_help( from_blind_account_key_or_label, from_blind_account_key_or_label, - blind_in, symbol, false, true ); + blind_in, symbol, false, true/*to_temp*/ ); FC_ASSERT( conf.outputs.size() > 0 ); auto to_account = my->get_account( to_account_id_or_name ); @@ -3690,6 +3690,24 @@ blind_confirmation wallet_api::transfer_from_blind( string from_blind_account_ke conf.trx.operations.push_back(from_blind); ilog( "about to validate" ); conf.trx.validate(); + + if( broadcast && conf.outputs.size() == 2 ) { + + // Save the change + blind_confirmation::output conf_output; + blind_confirmation::output change_output = conf.outputs[0]; + + // The wallet must have a private key for confirmation.to, this is used to decrypt the memo + public_key_type from_key = get_public_key(from_blind_account_key_or_label); + conf_output.confirmation.to = from_key; + conf_output.confirmation.one_time_key = change_output.confirmation.one_time_key; + conf_output.confirmation.encrypted_memo = change_output.confirmation.encrypted_memo; + conf_output.confirmation_receipt = conf_output.confirmation; + //try { + receive_blind_transfer( conf_output.confirmation_receipt, from_blind_account_key_or_label, "@"+to_account.name, change_output.auth ); + //} catch ( ... ){} + } + ilog( "about to broadcast" ); conf.trx = sign_transaction( conf.trx, broadcast ); @@ -3864,7 +3882,7 @@ blind_confirmation wallet_api::blind_transfer_help( string from_key_or_label, { for( const auto& out : confirm.outputs ) { - try { receive_blind_transfer( out.confirmation_receipt, from_key_or_label, "" ); } catch ( ... ){} + try { receive_blind_transfer( out.confirmation_receipt, from_key_or_label, "", optional() ); } catch ( ... ){} } } @@ -3953,14 +3971,14 @@ blind_confirmation wallet_api::transfer_to_blind( string from_account_id_or_name { for( const auto& out : confirm.outputs ) { - try { receive_blind_transfer( out.confirmation_receipt, "@"+from_account.name, "from @"+from_account.name ); } catch ( ... ){} + try { receive_blind_transfer( out.confirmation_receipt, "@"+from_account.name, "from @"+from_account.name, optional() ); } catch ( ... ){} } } return confirm; } FC_CAPTURE_AND_RETHROW( (from_account_id_or_name)(asset_symbol)(to_amounts) ) } -blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ) +blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo, optional owner ) { FC_ASSERT( !is_locked() ); stealth_confirmation conf(confirmation_receipt); @@ -4009,8 +4027,17 @@ blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, s auto commtiment_test = fc::ecc::blind( memo.blinding_factor, memo.amount.amount.value ); FC_ASSERT( fc::ecc::verify_sum( {commtiment_test}, {memo.commitment}, 0 ) ); - auto bbal = my->_remote_db->get_blinded_balances( {memo.commitment} ); - FC_ASSERT( bbal.size(), "commitment not found in blockchain", ("memo",memo) ); + vector bbal; + if( owner.valid() ) + { + // When owner is provided, do not require the commitment to be on the blockchain yet... This allows the receipt to be saved before it is broadcasted. + blinded_balance_object b; + b.owner = *owner; + bbal.push_back(b); + } else { + bbal = my->_remote_db->get_blinded_balances( {memo.commitment} ); + FC_ASSERT( bbal.size(), "commitment not found in blockchain", ("memo",memo) ); + } blind_balance bal; bal.amount = memo.amount; From a0cc5b775d21785d0ac87acf227276e73a87be8c Mon Sep 17 00:00:00 2001 From: James Calfee Date: Tue, 9 Feb 2016 13:43:56 -0600 Subject: [PATCH 5/5] Saves change address (without changing wallet_api::receive_blind_transfer API) #564 --- .../wallet/include/graphene/wallet/wallet.hpp | 3 +- libraries/wallet/wallet.cpp | 36 ++++++------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 76bada67..02582de4 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -765,10 +765,9 @@ class wallet_api * who sent it. * * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from - * @param owner - optional, when owner is emtpy (owner == authority()) this receipt must be on the blockchain. Transfers may save their confirmation prior to broadcast. * @param confirmation_receipt - a base58 encoded stealth confirmation */ - blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo, optional owner ); + blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); /** * Transfers a public balance from @from to one or more blinded balances using a diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 163a7899..0e93f668 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -3704,7 +3704,7 @@ blind_confirmation wallet_api::transfer_from_blind( string from_blind_account_ke conf_output.confirmation.encrypted_memo = change_output.confirmation.encrypted_memo; conf_output.confirmation_receipt = conf_output.confirmation; //try { - receive_blind_transfer( conf_output.confirmation_receipt, from_blind_account_key_or_label, "@"+to_account.name, change_output.auth ); + receive_blind_transfer( conf_output.confirmation_receipt, from_blind_account_key_or_label, "@"+to_account.name ); //} catch ( ... ){} } @@ -3882,7 +3882,7 @@ blind_confirmation wallet_api::blind_transfer_help( string from_key_or_label, { for( const auto& out : confirm.outputs ) { - try { receive_blind_transfer( out.confirmation_receipt, from_key_or_label, "", optional() ); } catch ( ... ){} + try { receive_blind_transfer( out.confirmation_receipt, from_key_or_label, "" ); } catch ( ... ){} } } @@ -3971,14 +3971,14 @@ blind_confirmation wallet_api::transfer_to_blind( string from_account_id_or_name { for( const auto& out : confirm.outputs ) { - try { receive_blind_transfer( out.confirmation_receipt, "@"+from_account.name, "from @"+from_account.name, optional() ); } catch ( ... ){} + try { receive_blind_transfer( out.confirmation_receipt, "@"+from_account.name, "from @"+from_account.name ); } catch ( ... ){} } } return confirm; } FC_CAPTURE_AND_RETHROW( (from_account_id_or_name)(asset_symbol)(to_amounts) ) } -blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo, optional owner ) +blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ) { FC_ASSERT( !is_locked() ); stealth_confirmation conf(confirmation_receipt); @@ -4003,7 +4003,6 @@ blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, s auto plain_memo = fc::aes_decrypt( secret, conf.encrypted_memo ); auto memo = fc::raw::unpack( plain_memo ); - result.to_key = *conf.to; result.to_label = get_key_label( result.to_key ); if( memo.from ) @@ -4027,18 +4026,6 @@ blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, s auto commtiment_test = fc::ecc::blind( memo.blinding_factor, memo.amount.amount.value ); FC_ASSERT( fc::ecc::verify_sum( {commtiment_test}, {memo.commitment}, 0 ) ); - vector bbal; - if( owner.valid() ) - { - // When owner is provided, do not require the commitment to be on the blockchain yet... This allows the receipt to be saved before it is broadcasted. - blinded_balance_object b; - b.owner = *owner; - bbal.push_back(b); - } else { - bbal = my->_remote_db->get_blinded_balances( {memo.commitment} ); - FC_ASSERT( bbal.size(), "commitment not found in blockchain", ("memo",memo) ); - } - blind_balance bal; bal.amount = memo.amount; bal.to = *conf.to; @@ -4048,21 +4035,20 @@ blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, s bal.commitment = memo.commitment; bal.used = false; - result.control_authority = bbal.front().owner; + auto child_pubkey = child_priv_key.get_public_key(); + auto owner = authority(1, public_key_type(child_pubkey), 1); + result.control_authority = owner; result.data = memo; - - auto child_key_itr = bbal.front().owner.key_auths.find( child_priv_key.get_public_key() ); - - if( child_key_itr != bbal.front().owner.key_auths.end() ) + auto child_key_itr = owner.key_auths.find( child_pubkey ); + if( child_key_itr != owner.key_auths.end() ) my->_keys[child_key_itr->first] = key_to_wif( child_priv_key ); - - + // my->_wallet.blinded_balances[memo.amount.asset_id][bal.to].push_back( bal ); result.date = fc::time_point::now(); my->_wallet.blind_receipts.insert( result ); - my->_keys[child_priv_key.get_public_key()] = key_to_wif( child_priv_key ); + my->_keys[child_pubkey] = key_to_wif( child_priv_key ); save_wallet_file();