mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 05:55:51 +00:00
Fix 'getAffectedAccount' -- logic was totally wrong.
You can't get this from the transaction because which accounts a transaction affects depends on things like which offers it winds up taking. And you can't build it with the metadata because you don't always build the metadata locally -- consider fetching a ledger after a network split. The only rational way to do this is to build the affected account vector from the metadata.
This commit is contained in:
@@ -403,17 +403,19 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
||||
assert(type == SHAMapTreeNode::tnTRANSACTION_MD);
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
Serializer rawTxn(sit.getVL());
|
||||
std::string escMeta(sqlEscape(sit.getVL()));
|
||||
Serializer rawMeta(sit.getVL());
|
||||
std::string escMeta(sqlEscape(rawMeta.peekData()));
|
||||
|
||||
SerializerIterator txnIt(rawTxn);
|
||||
SerializedTransaction txn(txnIt);
|
||||
assert(txn.getTransactionID() == item->getTag());
|
||||
TransactionMetaSet meta(item->getTag(), mLedgerSeq, rawMeta.peekData());
|
||||
|
||||
// Make sure transaction is in AccountTransactions.
|
||||
if (!SQL_EXISTS(db, boost::str(AcctTransExists % item->getTag().GetHex())))
|
||||
{
|
||||
// Transaction not in AccountTransactions
|
||||
std::vector<RippleAddress> accts = txn.getAffectedAccounts();
|
||||
std::vector<RippleAddress> accts = meta.getAffectedAccounts();
|
||||
|
||||
std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES ";
|
||||
bool first = true;
|
||||
@@ -620,10 +622,13 @@ Json::Value Ledger::getJson(int options)
|
||||
{
|
||||
Json::Value ledger(Json::objectValue);
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
ledger["parentHash"] = mParentHash.GetHex();
|
||||
|
||||
bool full = (options & LEDGER_JSON_FULL) != 0;
|
||||
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
ledger["parentHash"] = mParentHash.GetHex();
|
||||
ledger["seqNum"] = boost::lexical_cast<std::string>(mLedgerSeq);
|
||||
|
||||
if(mClosed || full)
|
||||
{
|
||||
if (mClosed)
|
||||
@@ -646,6 +651,7 @@ Json::Value Ledger::getJson(int options)
|
||||
}
|
||||
else
|
||||
ledger["closed"] = false;
|
||||
|
||||
if (mTransactionMap && (full || ((options & LEDGER_JSON_DUMP_TXRP) != 0)))
|
||||
{
|
||||
Json::Value txns(Json::arrayValue);
|
||||
@@ -685,6 +691,7 @@ Json::Value Ledger::getJson(int options)
|
||||
}
|
||||
ledger["transactions"] = txns;
|
||||
}
|
||||
|
||||
if (mAccountStateMap && (full || ((options & LEDGER_JSON_DUMP_STATE) != 0)))
|
||||
{
|
||||
Json::Value state(Json::arrayValue);
|
||||
@@ -702,7 +709,6 @@ Json::Value Ledger::getJson(int options)
|
||||
}
|
||||
ledger["accountState"] = state;
|
||||
}
|
||||
ledger["seqNum"] = boost::lexical_cast<std::string>(mLedgerSeq);
|
||||
return ledger;
|
||||
}
|
||||
|
||||
|
||||
@@ -717,7 +717,7 @@ SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const ui
|
||||
try
|
||||
{
|
||||
SHAMapTreeNode::pointer ret =
|
||||
boost::make_shared<SHAMapTreeNode>(id, obj->getData(), mSeq - 1, snfPREFIX, hash);
|
||||
boost::make_shared<SHAMapTreeNode>(id, obj->getData(), mSeq, snfPREFIX, hash);
|
||||
if (id != *ret)
|
||||
{
|
||||
cLog(lsFATAL) << "id:" << id << ", got:" << *ret;
|
||||
|
||||
@@ -78,8 +78,8 @@ std::string SerializedTransaction::getText() const
|
||||
return STObject::getText();
|
||||
}
|
||||
|
||||
std::vector<RippleAddress> SerializedTransaction::getAffectedAccounts() const
|
||||
{ // FIXME: This needs to be thought out better
|
||||
std::vector<RippleAddress> SerializedTransaction::getMentionedAccounts() const
|
||||
{
|
||||
std::vector<RippleAddress> accounts;
|
||||
|
||||
BOOST_FOREACH(const SerializedType& it, peekData())
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
uint32 getSequence() const { return getFieldU32(sfSequence); }
|
||||
void setSequence(uint32 seq) { return setFieldU32(sfSequence, seq); }
|
||||
|
||||
std::vector<RippleAddress> getAffectedAccounts() const;
|
||||
std::vector<RippleAddress> getMentionedAccounts() const;
|
||||
|
||||
uint256 getTransactionID() const;
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "Log.h"
|
||||
#include "SerializedObject.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
TransactionMetaSet::TransactionMetaSet(const uint256& txid, uint32 ledger, const std::vector<unsigned char>& vec) :
|
||||
mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
|
||||
@@ -52,33 +55,58 @@ void TransactionMetaSet::setAffectedNode(const uint256& node, SField::ref type,
|
||||
obj.setFieldU16(sfLedgerEntryType, nodeType);
|
||||
}
|
||||
|
||||
/*
|
||||
static void addIfUnique(std::vector<RippleAddress>& vector, const RippleAddress& address)
|
||||
{
|
||||
BOOST_FOREACH(const RippleAddress& a, vector)
|
||||
if (a == address)
|
||||
return;
|
||||
vector.push_back(address);
|
||||
}
|
||||
|
||||
std::vector<RippleAddress> TransactionMetaSet::getAffectedAccounts()
|
||||
{
|
||||
std::vector<RippleAddress> accounts;
|
||||
accounts.reserve(10);
|
||||
|
||||
BOOST_FOREACH(STObject& object, mNodes.getValue() )
|
||||
BOOST_FOREACH(const STObject& it, mNodes)
|
||||
{
|
||||
const STAccount* sa = dynamic_cast<const STAccount*>(&it);
|
||||
if (sa != NULL)
|
||||
int index = it.getFieldIndex((it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
|
||||
if (index != -1)
|
||||
{
|
||||
bool found = false;
|
||||
RippleAddress na = sa->getValueNCA();
|
||||
BOOST_FOREACH(const RippleAddress& it, accounts)
|
||||
const STObject *inner = dynamic_cast<const STObject*>(&it.peekAtIndex(index));
|
||||
if (inner)
|
||||
{
|
||||
if (it == na)
|
||||
BOOST_FOREACH(const SerializedType& field, inner->peekData())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
const STAccount* sa = dynamic_cast<const STAccount*>(&it);
|
||||
if (sa)
|
||||
addIfUnique(accounts, sa->getValueNCA());
|
||||
else if ((field.getFName() == sfLowLimit) || (field.getFName() == sfHighLimit))
|
||||
{
|
||||
const STAmount* lim = dynamic_cast<const STAmount*>(&field);
|
||||
if (lim != NULL)
|
||||
{
|
||||
uint160 issuer = lim->getIssuer();
|
||||
if (issuer.isNonZero())
|
||||
{
|
||||
RippleAddress na;
|
||||
na.setAccountID(issuer);
|
||||
addIfUnique(accounts, na);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsFATAL) << "limit is not amount " << field.getJson(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
accounts.push_back(na);
|
||||
else assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
*/
|
||||
|
||||
STObject& TransactionMetaSet::getAffectedNode(SLE::ref node, SField::ref type)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
STObject& getAffectedNode(SLE::ref node, SField::ref type); // create if needed
|
||||
STObject& getAffectedNode(const uint256&);
|
||||
const STObject& peekAffectedNode(const uint256&) const;
|
||||
//std::vector<RippleAddress> getAffectedAccounts();
|
||||
std::vector<RippleAddress> getAffectedAccounts();
|
||||
|
||||
|
||||
Json::Value getJson(int p) const { return getAsObject().getJson(p); }
|
||||
|
||||
Reference in New Issue
Block a user