Skip to content

Commit

Permalink
Merge pull request #87 from peerplays-network/feature/GRPH-54
Browse files Browse the repository at this point in the history
Fix for irrelevant signature included issue
  • Loading branch information
bobinson authored Sep 5, 2019
2 parents cdc89c1 + 6dddfd5 commit 2c28d0d
Showing 1 changed file with 12 additions and 86 deletions.
98 changes: 12 additions & 86 deletions libraries/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2206,77 +2206,15 @@ class wallet_api_impl

signed_transaction sign_transaction(signed_transaction tx, bool broadcast = false)
{
flat_set<account_id_type> req_active_approvals;
flat_set<account_id_type> req_owner_approvals;
vector<authority> other_auths;

tx.get_required_authorities( req_active_approvals, req_owner_approvals, other_auths );

for( const auto& auth : other_auths )
for( const auto& a : auth.account_auths )
req_active_approvals.insert(a.first);

// std::merge lets us de-duplicate account_id's that occur in both
// sets, and dump them into a vector (as required by remote_db api)
// at the same time
vector<account_id_type> v_approving_account_ids;
std::merge(req_active_approvals.begin(), req_active_approvals.end(),
req_owner_approvals.begin() , req_owner_approvals.end(),
std::back_inserter(v_approving_account_ids));

/// TODO: fetch the accounts specified via other_auths as well.

vector< optional<account_object> > approving_account_objects =
_remote_db->get_accounts( v_approving_account_ids );

/// TODO: recursively check one layer deeper in the authority tree for keys

FC_ASSERT( approving_account_objects.size() == v_approving_account_ids.size() );

flat_map<account_id_type, account_object*> approving_account_lut;
size_t i = 0;
for( optional<account_object>& approving_acct : approving_account_objects )
{
if( !approving_acct.valid() )
{
wlog( "operation_get_required_auths said approval of non-existing account ${id} was needed",
("id", v_approving_account_ids[i]) );
i++;
continue;
}
approving_account_lut[ approving_acct->id ] = &(*approving_acct);
i++;
}

flat_set<public_key_type> approving_key_set;
for( account_id_type& acct_id : req_active_approvals )
{
const auto it = approving_account_lut.find( acct_id );
if( it == approving_account_lut.end() )
continue;
const account_object* acct = it->second;
vector<public_key_type> v_approving_keys = acct->active.get_keys();
for( const public_key_type& approving_key : v_approving_keys )
approving_key_set.insert( approving_key );
}
for( account_id_type& acct_id : req_owner_approvals )
{
const auto it = approving_account_lut.find( acct_id );
if( it == approving_account_lut.end() )
continue;
const account_object* acct = it->second;
vector<public_key_type> v_approving_keys = acct->owner.get_keys();
for( const public_key_type& approving_key : v_approving_keys )
approving_key_set.insert( approving_key );
}
for( const authority& a : other_auths )
{
for( const auto& k : a.key_auths )
approving_key_set.insert( k.first );
}
set<public_key_type> pks = _remote_db->get_potential_signatures(tx);
flat_set<public_key_type> owned_keys;
owned_keys.reserve(pks.size());
std::copy_if(pks.begin(), pks.end(), std::inserter(owned_keys, owned_keys.end()),
[this](const public_key_type &pk) { return _keys.find(pk) != _keys.end(); });
set<public_key_type> approving_key_set = _remote_db->get_required_signatures(tx, owned_keys);

auto dyn_props = get_dynamic_global_properties();
tx.set_reference_block( dyn_props.head_block_id );
tx.set_reference_block(dyn_props.head_block_id);

// first, some bookkeeping, expire old items from _recently_generated_transactions
// since transactions include the head block id, we just need the index for keeping transactions unique
Expand All @@ -2290,23 +2228,11 @@ class wallet_api_impl
uint32_t expiration_time_offset = 0;
for (;;)
{
tx.set_expiration( dyn_props.time + fc::seconds(30 + expiration_time_offset) );
tx.set_expiration(dyn_props.time + fc::seconds(30 + expiration_time_offset));
tx.signatures.clear();

for( public_key_type& key : approving_key_set )
{
auto it = _keys.find(key);
if( it != _keys.end() )
{
fc::optional<fc::ecc::private_key> privkey = wif_to_key( it->second );
FC_ASSERT( privkey.valid(), "Malformed private key in _keys" );
tx.sign( *privkey, _chain_id );
}
/// TODO: if transaction has enough signatures to be "valid" don't add any more,
/// there are cases where the wallet may have more keys than strictly necessary and
/// the transaction will be rejected if the transaction validates without requiring
/// all signatures provided
}
for (const public_key_type &key : approving_key_set)
tx.sign(get_private_key(key), _chain_id);

graphene::chain::transaction_id_type this_transaction_id = tx.id();
auto iter = _recently_generated_transactions.find(this_transaction_id);
Expand All @@ -2328,11 +2254,11 @@ class wallet_api_impl
{
try
{
_remote_net_broadcast->broadcast_transaction( tx );
_remote_net_broadcast->broadcast_transaction(tx);
}
catch (const fc::exception& e)
{
elog("Caught exception while broadcasting tx ${id}: ${e}", ("id", tx.id().str())("e", e.to_detail_string()) );
elog("Caught exception while broadcasting tx ${id}: ${e}", ("id", tx.id().str())("e", e.to_detail_string()));
throw;
}
}
Expand Down

0 comments on commit 2c28d0d

Please sign in to comment.