Partial Wallet support for Blind Transfers

public->blind
blind->blind
TODO: blind->public
This commit is contained in:
Daniel Larimer 2015-07-24 11:37:37 -04:00
parent c740d2b3c8
commit e4ff106cd4
4 changed files with 38 additions and 16 deletions

View file

@ -38,6 +38,7 @@ digest_type transaction::digest()const
} }
void transaction::validate() const void transaction::validate() const
{ {
FC_ASSERT( operations.size() > 0, "A transaction must have at least one operation", ("trx",*this) );
for( const auto& op : operations ) for( const auto& op : operations )
operation_validate(op); operation_validate(op);
} }

@ -1 +1 @@
Subproject commit d76a15ec896dddb021ef8aeb9f77bba34dadd27b Subproject commit d79855b49107e7ca488db3dfe0a7d4872bf208f1

View file

@ -1135,7 +1135,7 @@ class wallet_api
} } } }
FC_REFLECT( graphene::wallet::key_label, (label)(key) ) FC_REFLECT( graphene::wallet::key_label, (label)(key) )
FC_REFLECT( graphene::wallet::blind_balance, (amount)(from)(to)(one_time_key)(commitment)(used) ) FC_REFLECT( graphene::wallet::blind_balance, (amount)(from)(to)(one_time_key)(blinding_factor)(commitment)(used) )
FC_REFLECT( graphene::wallet::blind_confirmation::output, (label)(pub_key)(decrypted_memo)(confirmation)(confirmation_receipt) ) FC_REFLECT( graphene::wallet::blind_confirmation::output, (label)(pub_key)(decrypted_memo)(confirmation)(confirmation_receipt) )
FC_REFLECT( graphene::wallet::blind_confirmation, (trx)(outputs) ) FC_REFLECT( graphene::wallet::blind_confirmation, (trx)(outputs) )
@ -1244,5 +1244,6 @@ FC_API( graphene::wallet::wallet_api,
(get_blind_balances) (get_blind_balances)
(create_blind_account) (create_blind_account)
(transfer_to_blind) (transfer_to_blind)
(blind_transfer)
(receive_blind_transfer) (receive_blind_transfer)
) )

View file

@ -2690,9 +2690,11 @@ blind_confirmation wallet_api::blind_transfer( string from_key_or_label,
string amount_in, string amount_in,
string symbol, string symbol,
bool broadcast ) bool broadcast )
{ try { {
blind_confirmation confirm;
try {
FC_ASSERT( !is_locked() ); FC_ASSERT( !is_locked() );
blind_confirmation conf;
public_key_type from_key = get_public_key(from_key_or_label); public_key_type from_key = get_public_key(from_key_or_label);
public_key_type to_key = get_public_key(to_key_or_label); public_key_type to_key = get_public_key(to_key_or_label);
@ -2740,6 +2742,7 @@ blind_confirmation wallet_api::blind_transfer( string from_key_or_label,
} }
} }
} }
wdump( ("input")(blinding_factors) );
FC_ASSERT( total_amount >= amount+blind_tr.fee, "Insufficent Balance", ("available",total_amount)("amount",amount)("fee",blind_tr.fee) ); FC_ASSERT( total_amount >= amount+blind_tr.fee, "Insufficent Balance", ("available",total_amount)("amount",amount)("fee",blind_tr.fee) );
@ -2758,32 +2761,34 @@ blind_confirmation wallet_api::blind_transfer( string from_key_or_label,
fc::sha256 to_blind_factor; fc::sha256 to_blind_factor;
if( change.amount > 0 ) if( change.amount > 0 )
{ {
idump(("to_blind_factor")(blind_factor) );
blinding_factors.push_back( blind_factor ); blinding_factors.push_back( blind_factor );
change_blind_factor = fc::ecc::blind_sum( blinding_factors, blinding_factors.size() - 1 ); change_blind_factor = fc::ecc::blind_sum( blinding_factors, blinding_factors.size() - 1 );
wdump(("change_blind_factor")(change_blind_factor) );
} }
else // change == 0 else // change == 0
{ {
blind_tr.outputs.resize(1); blind_tr.outputs.resize(1);
blind_factor = fc::ecc::blind_sum( blinding_factors, blinding_factors.size() ); blind_factor = fc::ecc::blind_sum( blinding_factors, blinding_factors.size() );
blinding_factors.push_back( blind_factor ); blinding_factors.push_back( blind_factor );
idump(("nochange to_blind_factor")(blind_factor) );
} }
fc::ecc::public_key from_pub_key = from_key; fc::ecc::public_key from_pub_key = from_key;
fc::ecc::public_key to_pub_key = to_key; fc::ecc::public_key to_pub_key = to_key;
blind_output out; blind_output to_out;
out.owner = authority( 1, public_key_type( from_pub_key.child( from_child ) ), 1 ); to_out.owner = authority( 1, public_key_type( to_pub_key.child( child ) ), 1 );
out.commitment = fc::ecc::blind( change_blind_factor, amount.amount.value ); to_out.commitment = fc::ecc::blind( blind_factor, amount.amount.value );
blind_confirmation confirm;
if( blind_tr.outputs.size() > 1 ) if( blind_tr.outputs.size() > 1 )
{ {
out.range_proof = fc::ecc::range_proof_sign( 0, out.commitment, blind_factor, nonce, 0, 0, amount.amount.value ); to_out.range_proof = fc::ecc::range_proof_sign( 0, to_out.commitment, blind_factor, nonce, 0, 0, amount.amount.value );
blind_output change_out; blind_output change_out;
change_out.owner = authority( 1, public_key_type( to_pub_key.child( child ) ), 1 ); change_out.owner = authority( 1, public_key_type( from_pub_key.child( from_child ) ), 1 );
change_out.commitment = fc::ecc::blind( change_blind_factor, change.amount.value ); change_out.commitment = fc::ecc::blind( change_blind_factor, change.amount.value );
change_out.range_proof = fc::ecc::range_proof_sign( 0, out.commitment, change_blind_factor, from_nonce, 0, 0, change.amount.value ); change_out.range_proof = fc::ecc::range_proof_sign( 0, change_out.commitment, change_blind_factor, from_nonce, 0, 0, change.amount.value );
blind_tr.outputs[1] = change_out; blind_tr.outputs[1] = change_out;
@ -2797,12 +2802,12 @@ blind_confirmation wallet_api::blind_transfer( string from_key_or_label,
conf_output.decrypted_memo.check = from_secret._hash[0]; conf_output.decrypted_memo.check = from_secret._hash[0];
conf_output.confirmation.one_time_key = one_time_key.get_public_key(); conf_output.confirmation.one_time_key = one_time_key.get_public_key();
conf_output.confirmation.to = from_key; conf_output.confirmation.to = from_key;
conf_output.confirmation.encrypted_memo = fc::aes_encrypt( secret, fc::raw::pack( conf_output.decrypted_memo ) ); conf_output.confirmation.encrypted_memo = fc::aes_encrypt( from_secret, fc::raw::pack( conf_output.decrypted_memo ) );
conf_output.confirmation_receipt = conf_output.confirmation; conf_output.confirmation_receipt = conf_output.confirmation;
confirm.outputs.push_back( conf_output ); confirm.outputs.push_back( conf_output );
} }
blind_tr.outputs[0] = out; blind_tr.outputs[0] = to_out;
blind_confirmation::output conf_output; blind_confirmation::output conf_output;
conf_output.label = to_key_or_label; conf_output.label = to_key_or_label;
@ -2810,7 +2815,7 @@ blind_confirmation wallet_api::blind_transfer( string from_key_or_label,
conf_output.decrypted_memo.from = from_key; conf_output.decrypted_memo.from = from_key;
conf_output.decrypted_memo.amount = amount; conf_output.decrypted_memo.amount = amount;
conf_output.decrypted_memo.blinding_factor = blind_factor; conf_output.decrypted_memo.blinding_factor = blind_factor;
conf_output.decrypted_memo.commitment = out.commitment; conf_output.decrypted_memo.commitment = to_out.commitment;
conf_output.decrypted_memo.check = secret._hash[0]; conf_output.decrypted_memo.check = secret._hash[0];
conf_output.confirmation.one_time_key = one_time_key.get_public_key(); conf_output.confirmation.one_time_key = one_time_key.get_public_key();
conf_output.confirmation.to = to_key; conf_output.confirmation.to = to_key;
@ -2823,11 +2828,16 @@ blind_confirmation wallet_api::blind_transfer( string from_key_or_label,
std::sort( blind_tr.outputs.begin(), blind_tr.outputs.end(), std::sort( blind_tr.outputs.begin(), blind_tr.outputs.end(),
[&]( const blind_output& a, const blind_output& b ){ return a.commitment < b.commitment; } ); [&]( const blind_output& a, const blind_output& b ){ return a.commitment < b.commitment; } );
confirm.trx.operations.emplace_back( std::move(blind_tr) );
ilog( "validate before" );
confirm.trx.validate(); confirm.trx.validate();
confirm.trx = sign_transaction(confirm.trx, broadcast); confirm.trx = sign_transaction(confirm.trx, broadcast);
ilog( "validate after signing" );
confirm.trx.validate();
return conf; return confirm;
} FC_CAPTURE_AND_RETHROW( (from_key_or_label)(to_key_or_label)(amount_in)(symbol)(broadcast) ) } } FC_CAPTURE_AND_RETHROW( (from_key_or_label)(to_key_or_label)(amount_in)(symbol)(broadcast)(confirm) ) }
@ -2922,6 +2932,8 @@ stealth_confirmation::memo_data wallet_api::receive_blind_transfer( string confi
auto secret = to_priv_key->get_shared_secret( conf.one_time_key ); auto secret = to_priv_key->get_shared_secret( conf.one_time_key );
auto child = fc::sha256::hash( secret ); auto child = fc::sha256::hash( secret );
auto child_priv_key = to_priv_key->child( child );
//auto blind_factor = fc::sha256::hash( child ); //auto blind_factor = fc::sha256::hash( child );
auto plain_memo = fc::aes_decrypt( secret, conf.encrypted_memo ); auto plain_memo = fc::aes_decrypt( secret, conf.encrypted_memo );
@ -2939,11 +2951,19 @@ stealth_confirmation::memo_data wallet_api::receive_blind_transfer( string confi
bal.commitment = memo.commitment; bal.commitment = memo.commitment;
bal.used = false; bal.used = false;
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() )
my->_keys[child_key_itr->first] = key_to_wif( child_priv_key );
// TODO: confirm the amount matches the commitment (verify the blinding factor // TODO: confirm the amount matches the commitment (verify the blinding factor
// TODO: make sure the same blind balance isn't included twice // TODO: make sure the same blind balance isn't included twice
my->_wallet.blinded_balances[memo.amount.asset_id][bal.to].push_back( bal ); my->_wallet.blinded_balances[memo.amount.asset_id][bal.to].push_back( bal );
my->_keys[child_priv_key.get_public_key()] = key_to_wif( child_priv_key );
save_wallet_file();
return memo; return memo;
} }