set<public_key_type> signed_transaction::get_required_signatures( const chain_id_type& chain_id, const flat_set<public_key_type>& available_keys, const std::function<const authority*(account_id_type)>& get_active, const std::function<const authority*(account_id_type)>& get_owner, uint32_t max_recursion_depth )const { flat_set<account_id_type> required_active; flat_set<account_id_type> required_owner; vector<authority> other; get_required_authorities( required_active, required_owner, other ); sign_state s(get_signature_keys( chain_id ),get_active,available_keys); s.max_recursion = max_recursion_depth; for( const auto& auth : other ) s.check_authority(&auth); for( auto& owner : required_owner ) s.check_authority( get_owner( owner ) ); for( auto& active : required_active ) s.check_authority( active ); s.remove_unused_signatures(); set<public_key_type> result; for( auto& provided_sig : s.provided_signatures ) if( available_keys.find( provided_sig.first ) != available_keys.end() ) result.insert( provided_sig.first ); return result; }
void get_required_active_authorities( flat_set<account_id_type>& a )const { // registrar should be required anyway as it is the fee_payer(), but we insert it here just to be sure a.insert( registrar ); if( extensions.value.buyback_options.valid() ) a.insert( extensions.value.buyback_options->asset_to_buy_issuer ); }
bool RoseDedupeAuxImpl::hasSafeMultiReports( const flat_set<ReportID> &reports) const { if (reports.size() <= 1) { return true; } /* We have more than one ReportID corresponding to the external ID that is * presented to the user. These may differ in offset adjustment, bounds * checks, etc. */ /* TODO: work out if these differences will actually cause problems */ /* One common case where we know we don't have a problem is if there are * precisely two reports, one for the main Rose path and one for the * "small block matcher" path. */ if (reports.size() == 2) { ReportID id1 = *reports.begin(); ReportID id2 = *reports.rbegin(); bool has_verts_1 = contains(vert_map, id1); bool has_verts_2 = contains(vert_map, id2); bool has_sb_verts_1 = contains(sb_vert_map, id1); bool has_sb_verts_2 = contains(sb_vert_map, id2); if (has_verts_1 != has_verts_2 && has_sb_verts_1 != has_sb_verts_2) { DEBUG_PRINTF("two reports, one full and one small block: ok\n"); return true; } } DEBUG_PRINTF("more than one report\n"); return false; }
authority_checker( PermissionToAuthorityFunc permission_to_authority, uint16_t recursion_depth_limit, const flat_set<public_key_type>& signing_keys, flat_set<account_name> provided_auths = flat_set<account_name>() ) : permission_to_authority(permission_to_authority), recursion_depth_limit(recursion_depth_limit), signing_keys(signing_keys.begin(), signing_keys.end()), _provided_auths(provided_auths.begin(), provided_auths.end()), _used_keys(signing_keys.size(), false) {}
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs, const std::function<const authority*(account_id_type)>& get_active, const std::function<const authority*(account_id_type)>& get_owner, uint32_t max_recursion_depth, bool allow_committe, const flat_set<account_id_type>& active_aprovals, const flat_set<account_id_type>& owner_approvals ) { try { flat_set<account_id_type> required_active; flat_set<account_id_type> required_owner; vector<authority> other; for( const auto& op : ops ) operation_get_required_authorities( op, required_active, required_owner, other ); if( !allow_committe ) GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(), invalid_committee_approval, "Committee account may only propose transactions" ); sign_state s(sigs,get_active); s.max_recursion = max_recursion_depth; for( auto& id : active_aprovals ) s.approved_by.insert( id ); for( auto& id : owner_approvals ) s.approved_by.insert( id ); for( const auto& auth : other ) { GRAPHENE_ASSERT( s.check_authority(&auth), tx_missing_other_auth, "Missing Authority", ("auth",auth)("sigs",sigs) ); } // fetch all of the top level authorities for( auto id : required_active ) { GRAPHENE_ASSERT( s.check_authority(id) || s.check_authority(get_owner(id)), tx_missing_active_auth, "Missing Active Authority ${id}", ("id",id)("auth",*get_active(id))("owner",*get_owner(id)) ); } for( auto id : required_owner ) { GRAPHENE_ASSERT( owner_approvals.find(id) != owner_approvals.end() || s.check_authority(get_owner(id)), tx_missing_owner_auth, "Missing Owner Authority ${id}", ("id",id)("auth",*get_owner(id)) ); } GRAPHENE_ASSERT( !s.remove_unused_signatures(), tx_irrelevant_sig, "Unnecessary signature(s) detected" ); } FC_CAPTURE_AND_RETHROW( (ops)(sigs) ) }
void required_approval_index::insert_or_remove_delta( proposal_id_type p, const flat_set<account_id_type>& before, const flat_set<account_id_type>& after ) { auto b = before.begin(); auto a = after.begin(); while( b != before.end() || a != after.end() ) { if( a == after.end() || (b != before.end() && *b < *a) ) { remove( *b, p ); ++b; } else if( b == before.end() || (a != after.end() && *a < *b) ) { _account_to_proposals[*a].insert( p ); ++a; } else // *a == *b { ++a; ++b; } } }
void account_history_plugin_impl::update_account_histories( const signed_block& b ) { graphene::chain::database& db = database(); const vector<operation_history_object>& hist = db.get_applied_operations(); for( auto op : hist ) { // add to the operation history index const auto& oho = db.create<operation_history_object>( [&]( operation_history_object& h ){ h = op; }); // get the set of accounts this operation applies to flat_set<account_id_type> impacted; vector<authority> other; operation_get_required_authorities( op.op, impacted, impacted, other ); op.op.visit( operation_get_impacted_accounts( oho, _self, impacted ) ); for( auto& a : other ) for( auto& item : a.account_auths ) impacted.insert( item.first ); // for each operation this account applies to that is in the config link it into the history if( _tracked_accounts.size() == 0 ) { for( auto& account_id : impacted ) { // we don't do index_account_keys here anymore, because // that indexing now happens in observers' post_evaluate() // add history const auto& stats_obj = account_id(db).statistics(db); const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){ obj.operation_id = oho.id; obj.next = stats_obj.most_recent_op; }); db.modify( stats_obj, [&]( account_statistics_object& obj ){ obj.most_recent_op = ath.id; }); } } else { for( auto account_id : _tracked_accounts ) { if( impacted.find( account_id ) != impacted.end() ) { // add history const auto& stats_obj = account_id(db).statistics(db); const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){ obj.operation_id = oho.id; obj.next = stats_obj.most_recent_op; }); db.modify( stats_obj, [&]( account_statistics_object& obj ){ obj.most_recent_op = ath.id; }); } } } } }
vector<asset> database_api::get_account_balances(account_id_type acnt, const flat_set<asset_id_type>& assets)const { vector<asset> result; if (assets.empty()) { // if the caller passes in an empty list of assets, return balances for all assets the account owns const account_balance_index& balance_index = _db.get_index_type<account_balance_index>(); auto range = balance_index.indices().get<by_account>().equal_range(acnt); for (const account_balance_object& balance : boost::make_iterator_range(range.first, range.second)) result.push_back(asset(balance.get_balance())); } else { result.reserve(assets.size()); std::transform(assets.begin(), assets.end(), std::back_inserter(result), [this, acnt](asset_id_type id) { return _db.get_balance(acnt, id); }); } return result; }
void get_required_active_authorities( flat_set<string>& a )const{ a.insert(owner); }
void proposal_update_operation::get_required_active_authorities( flat_set<account_id_type>& a )const { for( const auto& i : active_approvals_to_add ) a.insert(i); for( const auto& i : active_approvals_to_remove ) a.insert(i); }
bool has_permission( account_name n )const { return _provided_auths.find(n) != _provided_auths.end(); }
void get_required_posting_authorities( flat_set< account_name_type >& a )const { a.insert( required_posting.begin(), required_posting.end() ); }
void get_impacted_accounts( flat_set<account_id_type>& i)const { i.insert( authorized_account ); }
static void add_authority_accounts( flat_set<account_id_type>& i, const authority& a ) { for( auto& item : a.account_auths ) i.insert( item.first ); }
static void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts ) { if( obj->id.space() == protocol_ids ) { switch( (object_type)obj->id.type() ) { case null_object_type: case base_object_type: case OBJECT_TYPE_COUNT: return; case account_object_type:{ accounts.insert( obj->id ); break; } case asset_object_type:{ const auto& aobj = dynamic_cast<const asset_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->issuer ); break; } case force_settlement_object_type:{ const auto& aobj = dynamic_cast<const force_settlement_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->owner ); break; } case committee_member_object_type:{ const auto& aobj = dynamic_cast<const committee_member_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->committee_member_account ); break; } case witness_object_type:{ const auto& aobj = dynamic_cast<const witness_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->witness_account ); break; } case limit_order_object_type:{ const auto& aobj = dynamic_cast<const limit_order_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->seller ); break; } case call_order_object_type:{ const auto& aobj = dynamic_cast<const call_order_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->borrower ); break; } case custom_object_type:{ break; } case proposal_object_type:{ const auto& aobj = dynamic_cast<const proposal_object*>(obj); FC_ASSERT( aobj != nullptr ); transaction_get_impacted_accounts( aobj->proposed_transaction, accounts ); break; } case operation_history_object_type:{ const auto& aobj = dynamic_cast<const operation_history_object*>(obj); FC_ASSERT( aobj != nullptr ); operation_get_impacted_accounts( aobj->op, accounts ); break; } case withdraw_permission_object_type:{ const auto& aobj = dynamic_cast<const withdraw_permission_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->withdraw_from_account ); accounts.insert( aobj->authorized_account ); break; } case vesting_balance_object_type:{ const auto& aobj = dynamic_cast<const vesting_balance_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->owner ); break; } case worker_object_type:{ const auto& aobj = dynamic_cast<const worker_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->worker_account ); break; } case balance_object_type:{ /** these are free from any accounts */ break; } } } else if( obj->id.space() == implementation_ids ) { switch( (impl_object_type)obj->id.type() ) { case impl_global_property_object_type: break; case impl_dynamic_global_property_object_type: break; case impl_reserved0_object_type: break; case impl_asset_dynamic_data_type: break; case impl_asset_bitasset_data_type: break; case impl_account_balance_object_type:{ const auto& aobj = dynamic_cast<const account_balance_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->owner ); break; } case impl_account_statistics_object_type:{ const auto& aobj = dynamic_cast<const account_statistics_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->owner ); break; } case impl_transaction_object_type:{ const auto& aobj = dynamic_cast<const transaction_object*>(obj); FC_ASSERT( aobj != nullptr ); transaction_get_impacted_accounts( aobj->trx, accounts ); break; } case impl_blinded_balance_object_type:{ const auto& aobj = dynamic_cast<const blinded_balance_object*>(obj); FC_ASSERT( aobj != nullptr ); for( const auto& a : aobj->owner.account_auths ) accounts.insert( a.first ); break; } case impl_block_summary_object_type: break; case impl_account_transaction_history_object_type: { const auto& aobj = dynamic_cast<const account_transaction_history_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->account ); break; } case impl_chain_property_object_type: break; case impl_witness_schedule_object_type: break; case impl_budget_record_object_type: break; case impl_special_authority_object_type: break; case impl_buyback_object_type: break; case impl_fba_accumulator_object_type: break; case impl_collateral_bid_object_type:{ const auto& aobj = dynamic_cast<const collateral_bid_object*>(obj); FC_ASSERT( aobj != nullptr ); accounts.insert( aobj->bidder ); break; } } } } // end get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )
void get_required_posting_authorities( flat_set<string>& a )const{ a.insert(voter); }
void get_impacted_accounts( flat_set<account_id_type>& i )const { i.insert(owner); }
void get_required_owner_authorities(flat_set<account_name_type> &a) const { if (require_owner) { a.insert(challenged); } }
void get_impacted_accounts( flat_set<account_id_type>& i)const { i.insert( withdraw_from_account ); }
void get_required_owner_authorities(flat_set<account_name_type> &a) const { if (amount.symbol == VESTS_SYMBOL) { a.insert(from); } }
void get_required_active_authorities( flat_set< account_name_type >& a )const { a.insert( required_active.begin(), required_active.end() ); }
void get_required_posting_authorities(flat_set<account_name_type> &a) const { for (const auto &i : required_posting_auths) { a.insert(i); } }
void get_required_active_authorities( flat_set<account_name_type>& a )const{ a.insert(account); }
void get_required_posting_authorities(flat_set<account_name_type> &a) const { if (!current_reset_account.size()) { a.insert(account); } }
void get_required_active_authorities( flat_set<account_id_type>& a )const { if( !is_owner_update() ) a.insert( account ); }
void get_required_owner_authorities(flat_set<account_name_type> &a) const { a.insert(account_to_recover); }
void get_required_posting_authorities(flat_set<account_name_type> &a) const { a.insert(author); }
/// Whether this account is voting inline bool is_voting() const { return ( voting_account != GRAPHENE_PROXY_TO_SELF_ACCOUNT || !votes.empty() ); }
void get_required_owner_authorities( flat_set<account_id_type>& a )const { if( owner ) a.insert( account ); }
void get_required_active_authorities( flat_set<string>& a )const { if( !owner /*&& active*/) a.insert( account ); }