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:
JoelKatz
2013-01-17 10:46:12 -08:00
parent a87768ead5
commit 8da284705f
6 changed files with 58 additions and 24 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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())

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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); }