//------------------------------------------------------------------------------ /* Copyright (c) 2011-2013, OpenCoin, Inc. */ //============================================================================== // VFALCO TODO rename class to TransactionMeta SETUP_LOG (TransactionMetaSet) TransactionMetaSet::TransactionMetaSet (uint256 const& txid, uint32 ledger, Blob const& vec) : mTransactionID (txid), mLedger (ledger), mNodes (sfAffectedNodes, 32) { Serializer s (vec); SerializerIterator sit (s); UPTR_T pobj = STObject::deserialize (sit, sfAffectedNodes); STObject* obj = static_cast (pobj.get ()); if (!obj) throw std::runtime_error ("bad metadata"); mResult = obj->getFieldU8 (sfTransactionResult); mIndex = obj->getFieldU32 (sfTransactionIndex); mNodes = * dynamic_cast (&obj->getField (sfAffectedNodes)); } bool TransactionMetaSet::isNodeAffected (uint256 const& node) const { BOOST_FOREACH (const STObject & it, mNodes) if (it.getFieldH256 (sfLedgerIndex) == node) return true; return false; } void TransactionMetaSet::setAffectedNode (uint256 const& node, SField::ref type, uint16 nodeType) { // make sure the node exists and force its type BOOST_FOREACH (STObject & it, mNodes) { if (it.getFieldH256 (sfLedgerIndex) == node) { it.setFName (type); it.setFieldU16 (sfLedgerEntryType, nodeType); return; } } mNodes.push_back (STObject (type)); STObject& obj = mNodes.back (); assert (obj.getFName () == type); obj.setFieldH256 (sfLedgerIndex, node); obj.setFieldU16 (sfLedgerEntryType, nodeType); } static void addIfUnique (std::vector& vector, const RippleAddress& address) { BOOST_FOREACH (const RippleAddress & a, vector) if (a == address) return; vector.push_back (address); } std::vector TransactionMetaSet::getAffectedAccounts () { std::vector accounts; accounts.reserve (10); // This code should match the behavior of the JS method: // Meta#getAffectedAccounts BOOST_FOREACH (const STObject & it, mNodes) { int index = it.getFieldIndex ((it.getFName () == sfCreatedNode) ? sfNewFields : sfFinalFields); if (index != -1) { const STObject* inner = dynamic_cast (&it.peekAtIndex (index)); if (inner) { BOOST_FOREACH (const SerializedType & field, inner->peekData ()) { const STAccount* sa = dynamic_cast (&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 (&field); if (lim != NULL) { uint160 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; } STObject& TransactionMetaSet::getAffectedNode (SLE::ref node, SField::ref type) { assert (&type); uint256 index = node->getIndex (); BOOST_FOREACH (STObject & it, mNodes) { if (it.getFieldH256 (sfLedgerIndex) == index) return it; } mNodes.push_back (STObject (type)); STObject& obj = mNodes.back (); assert (obj.getFName () == type); obj.setFieldH256 (sfLedgerIndex, index); obj.setFieldU16 (sfLedgerEntryType, node->getFieldU16 (sfLedgerEntryType)); return obj; } STObject& TransactionMetaSet::getAffectedNode (uint256 const& node) { BOOST_FOREACH (STObject & it, mNodes) { if (it.getFieldH256 (sfLedgerIndex) == node) return it; } assert (false); throw std::runtime_error ("Affected node not found"); } const STObject& TransactionMetaSet::peekAffectedNode (uint256 const& node) const { BOOST_FOREACH (const STObject & it, mNodes) if (it.getFieldH256 (sfLedgerIndex) == node) return it; throw std::runtime_error ("Affected node not found"); } void TransactionMetaSet::init (uint256 const& id, uint32 ledger) { mTransactionID = id; mLedger = ledger; mNodes = STArray (sfAffectedNodes, 32); } void TransactionMetaSet::swap (TransactionMetaSet& s) { assert ((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger)); mNodes.swap (s.mNodes); } bool TransactionMetaSet::thread (STObject& node, uint256 const& prevTxID, uint32 prevLgrID) { if (node.getFieldIndex (sfPreviousTxnID) == -1) { assert (node.getFieldIndex (sfPreviousTxnLgrSeq) == -1); node.setFieldH256 (sfPreviousTxnID, prevTxID); node.setFieldU32 (sfPreviousTxnLgrSeq, prevLgrID); return true; } assert (node.getFieldH256 (sfPreviousTxnID) == prevTxID); assert (node.getFieldU32 (sfPreviousTxnLgrSeq) == prevLgrID); return false; } static bool compare (const STObject& o1, const STObject& o2) { return o1.getFieldH256 (sfLedgerIndex) < o2.getFieldH256 (sfLedgerIndex); } STObject TransactionMetaSet::getAsObject () const { STObject metaData (sfTransactionMetaData); assert (mResult != 255); metaData.setFieldU8 (sfTransactionResult, mResult); metaData.setFieldU32 (sfTransactionIndex, mIndex); metaData.addObject (mNodes); return metaData; } void TransactionMetaSet::addRaw (Serializer& s, TER result, uint32 index) { mResult = static_cast (result); mIndex = index; assert ((mResult == 0) || ((mResult > 100) && (mResult <= 255))); mNodes.sort (compare); getAsObject ().add (s); } // vim:ts=4