boost::container::flat_set<AccountID> TxMeta::getAffectedAccounts() const { boost::container::flat_set<AccountID> list; list.reserve (10); // This code should match the behavior of the JS method: // Meta#getAffectedAccounts for (auto const& it : mNodes) { int index = it.getFieldIndex ((it.getFName () == sfCreatedNode) ? sfNewFields : sfFinalFields); if (index != -1) { const STObject* inner = dynamic_cast<const STObject*> (&it.peekAtIndex (index)); assert(inner); if (inner) { for (auto const& field : *inner) { STAccount const* sa = dynamic_cast<STAccount const*> (&field); if (sa) { AccountID id; assert(sa->isValueH160()); if (sa->getValueH160(id)) list.insert(id); } else if ((field.getFName () == sfLowLimit) || (field.getFName () == sfHighLimit) || (field.getFName () == sfTakerPays) || (field.getFName () == sfTakerGets)) { const STAmount* lim = dynamic_cast<const STAmount*> (&field); if (lim != nullptr) { auto issuer = lim->getIssuer (); if (issuer.isNonZero ()) list.insert(issuer); } else { JLOG (j_.fatal) << "limit is not amount " << field.getJson (0); } } } } } } return list; }
std::vector<RippleAddress> TransactionMetaSet::getAffectedAccounts () { std::vector<RippleAddress> accounts; accounts.reserve (10); // This code should match the behavior of the JS method: // Meta#getAffectedAccounts for (auto const& it : mNodes) { int index = it.getFieldIndex ((it.getFName () == sfCreatedNode) ? sfNewFields : sfFinalFields); if (index != -1) { const STObject* inner = dynamic_cast<const STObject*> (&it.peekAtIndex (index)); if (inner) { for (auto const& field : *inner) { const STAccount* sa = dynamic_cast<const STAccount*> (&field); if (sa) addIfUnique (accounts, sa->getValueNCA ()); else if ((field.getFName () == sfLowLimit) || (field.getFName () == sfHighLimit) || (field.getFName () == sfTakerPays) || (field.getFName () == sfTakerGets)) { const STAmount* lim = dynamic_cast<const STAmount*> (&field); if (lim != nullptr) { auto issuer = lim->getIssuer (); if (issuer.isNonZero ()) { RippleAddress na; na.setAccountID (issuer); addIfUnique (accounts, na); } } else { WriteLog (lsFATAL, TransactionMetaSet) << "limit is not amount " << field.getJson (0); } } } } else assert (false); } } return accounts; }
std::vector<RippleAddress> SerializedTransaction::getMentionedAccounts () const { std::vector<RippleAddress> accounts; BOOST_FOREACH (const SerializedType & it, peekData ()) { const STAccount* sa = dynamic_cast<const STAccount*> (&it); if (sa != nullptr) { bool found = false; RippleAddress na = sa->getValueNCA (); BOOST_FOREACH (const RippleAddress & it, accounts) { if (it == na) { found = true; break; } } if (!found) accounts.push_back (na); } const STAmount* sam = dynamic_cast<const STAmount*> (&it); if (sam) { auto issuer = sam->getIssuer (); if (issuer.isNonZero ()) { RippleAddress na; na.setAccountID (issuer); bool found = false; BOOST_FOREACH (const RippleAddress & it, accounts) { if (it == na) { found = true; break; } } if (!found) accounts.push_back (na); } }
// { // ledger_hash : <ledger> // ledger_index : <ledger_index> // } Json::Value doLedgerRequest (RPC::Context& context) { auto const hasHash = context.params.isMember (jss::ledger_hash); auto const hasIndex = context.params.isMember (jss::ledger_index); auto& ledgerMaster = getApp().getLedgerMaster(); LedgerHash ledgerHash; if ((hasHash && hasIndex) || !(hasHash || hasIndex)) { return RPC::make_param_error( "Exactly one of ledger_hash and ledger_index can be set."); } if (hasHash) { auto const& jsonHash = context.params[jss::ledger_hash]; if (!jsonHash.isString() || !ledgerHash.SetHex (jsonHash.asString ())) return RPC::invalid_field_message (jss::ledger_hash); } else { auto const& jsonIndex = context.params[jss::ledger_index]; if (!jsonIndex.isNumeric ()) return RPC::invalid_field_message (jss::ledger_index); // We need a validated ledger to get the hash from the sequence if (ledgerMaster.getValidatedLedgerAge() > 120) return rpcError (rpcNO_CURRENT); auto ledgerIndex = jsonIndex.asInt(); auto ledger = ledgerMaster.getValidatedLedger(); if (ledgerIndex >= ledger->getLedgerSeq()) return RPC::make_param_error("Ledger index too large"); // Try to get the hash of the desired ledger from the validated ledger ledgerHash = ledger->getLedgerHash (ledgerIndex); if (ledgerHash == zero) { // Find a ledger more likely to have the hash of the desired ledger auto refIndex = (ledgerIndex + 255) & (~255); auto refHash = ledger->getLedgerHash (refIndex); assert (refHash.isNonZero ()); ledger = ledgerMaster.getLedgerByHash (refHash); if (!ledger) { // We don't have the ledger we need to figure out which ledger // they want. Try to get it. if (auto il = getApp().getInboundLedgers().acquire ( refHash, refIndex, InboundLedger::fcGENERIC)) return getJson (LedgerFill (*il)); if (auto il = getApp().getInboundLedgers().find (refHash)) { Json::Value jvResult = il->getJson (0); jvResult[jss::error] = "ledgerNotFound"; return jvResult; } // Likely the app is shutting down return Json::Value(); } ledgerHash = ledger->getLedgerHash (ledgerIndex); assert (ledgerHash.isNonZero ()); } } auto ledger = ledgerMaster.getLedgerByHash (ledgerHash); if (ledger) { // We already have the ledger they want Json::Value jvResult; jvResult[jss::ledger_index] = ledger->getLedgerSeq(); addJson (jvResult, {*ledger, 0}); return jvResult; } else { // Try to get the desired ledger if (auto il = getApp ().getInboundLedgers ().acquire ( ledgerHash, 0, InboundLedger::fcGENERIC)) return getJson (LedgerFill (*il)); if (auto il = getApp().getInboundLedgers().find (ledgerHash)) return il->getJson (0); return RPC::make_error ( rpcNOT_READY, "findCreate failed to return an inbound ledger"); } }