Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2013-03-04 15:14:28 -08:00
14 changed files with 152 additions and 77 deletions

View File

@@ -1,13 +1,59 @@
#include "AcceptedLedger.h"
#include <boost/foreach.hpp>
TaggedCache<uint256, AcceptedLedger> AcceptedLedger::ALCache("AcceptedLedger", 4, 60);
ALTransaction::ALTransaction(uint32 seq, SerializerIterator& sit)
{
Serializer txnSer(sit.getVL());
SerializerIterator txnIt(txnSer);
mTxn = boost::make_shared<SerializedTransaction>(boost::ref(txnIt));
mMeta = boost::make_shared<TransactionMetaSet>(mTxn->getTransactionID(), seq, sit.getVL());
mRawMeta= sit.getVL();
mMeta = boost::make_shared<TransactionMetaSet>(mTxn->getTransactionID(), seq, mRawMeta);
mAffected = mMeta->getAffectedAccounts();
mResult = mMeta->getResultTER();
}
ALTransaction::ALTransaction(SerializedTransaction::ref txn, TransactionMetaSet::ref met) :
mTxn(txn), mMeta(met), mAffected(met->getAffectedAccounts())
{
mResult = mMeta->getResultTER();
}
ALTransaction::ALTransaction(SerializedTransaction::ref txn, TER result) :
mTxn(txn), mResult(result), mAffected(txn->getMentionedAccounts())
{ ; }
std::string ALTransaction::getEscMeta() const
{
assert(!mRawMeta.empty());
return sqlEscape(mRawMeta);
}
Json::Value ALTransaction::getJson(int j) const
{
Json::Value ret(Json::objectValue);
ret["transaction"] = mTxn->getJson(j);
if (mMeta)
{
ret["meta"] = mMeta->getJson(j);
ret["raw_meta"] = strHex(mRawMeta);
}
ret["result"] = transHuman(mResult);
if (!mAffected.empty())
{
Json::Value affected(Json::arrayValue);
BOOST_FOREACH(const RippleAddress& ra, mAffected)
{
affected.append(ra.humanAccountID());
}
ret["affected"] = affected;
}
return ret;
}
AcceptedLedger::AcceptedLedger(Ledger::ref ledger) : mLedger(ledger)
@@ -20,6 +66,16 @@ AcceptedLedger::AcceptedLedger(Ledger::ref ledger) : mLedger(ledger)
}
}
AcceptedLedger::pointer AcceptedLedger::makeAcceptedLedger(Ledger::ref ledger)
{
AcceptedLedger::pointer ret = ALCache.fetch(ledger->getHash());
if (ret)
return ret;
ret = AcceptedLedger::pointer(new AcceptedLedger(ledger));
ALCache.canonicalize(ledger->getHash(), ret);
return ret;
}
void AcceptedLedger::insert(const ALTransaction& at)
{
assert(mMap.find(at.getIndex()) == mMap.end());
@@ -32,4 +88,4 @@ const ALTransaction* AcceptedLedger::getTxn(int i) const
if (it == mMap.end())
return NULL;
return &it->second;
}
}

View File

@@ -11,25 +11,38 @@ class ALTransaction
protected:
SerializedTransaction::pointer mTxn;
TransactionMetaSet::pointer mMeta;
TER mResult;
std::vector<RippleAddress> mAffected;
std::vector<unsigned char> mRawMeta;
public:
ALTransaction(uint32 ledgerSeq, SerializerIterator& sit);
ALTransaction(SerializedTransaction::ref, TransactionMetaSet::ref);
ALTransaction(SerializedTransaction::ref, TER result);
SerializedTransaction::ref getTxn() const { return mTxn; }
TransactionMetaSet::ref getMeta() const { return mMeta; }
const std::vector<RippleAddress>& getAffected() const { return mAffected; }
int getIndex() const { return mMeta->getIndex(); }
TER getResult() const { return mMeta->getResultTER(); }
uint256 getTransactionID() const { return mTxn->getTransactionID(); }
TransactionType getTxnType() const { return mTxn->getTxnType(); }
TER getResult() const { return mResult; }
bool isApplied() const { return !!mMeta; }
int getIndex() const { return mMeta ? mMeta->getIndex() : 0; }
std::string getEscMeta() const;
Json::Value getJson(int) const;
};
class AcceptedLedger
{
public:
typedef std::map<int, ALTransaction> map_t;
typedef map_t::value_type value_type;
typedef map_t::const_iterator const_iterator;
typedef boost::shared_ptr<AcceptedLedger> pointer;
typedef const pointer& ret;
typedef std::map<int, ALTransaction> map_t;
typedef map_t::value_type value_type;
typedef map_t::const_iterator const_iterator;
protected:
Ledger::pointer mLedger;
@@ -37,9 +50,14 @@ protected:
void insert(const ALTransaction&);
public:
static TaggedCache<uint256, AcceptedLedger> ALCache;
AcceptedLedger(Ledger::ref ledger);
public:
static pointer makeAcceptedLedger(Ledger::ref ledger);
static void sweep() { ALCache.sweep(); }
Ledger::ref getLedger() const { return mLedger; }
const map_t& getMap() const { return mMap; }

View File

@@ -1,5 +1,6 @@
#include "Application.h"
#include "AcceptedLedger.h"
#include "Config.h"
#include "PeerDoor.h"
#include "RPCDoor.h"
@@ -303,6 +304,7 @@ void Application::sweep()
mValidations.sweep();
getMasterLedgerAcquire().sweep();
mSLECache.sweep();
AcceptedLedger::sweep();
mSweepTimer.expires_from_now(boost::posix_time::seconds(theConfig.getSize(siSweepInterval)));
mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
}

View File

@@ -428,6 +428,8 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
addRaw(s);
theApp->getHashedObjectStore().store(hotLEDGER, mLedgerSeq, s.peekData(), mHash);
AcceptedLedger::pointer aLedger = AcceptedLedger::makeAcceptedLedger(shared_from_this());
{
{
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
@@ -435,33 +437,22 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
theApp->getLedgerDB()->getDB()->executeSQL(boost::str(deleteLedger % mLedgerSeq));
}
SHAMap& txSet = *peekTransactionMap();
Database *db = theApp->getTxnDB()->getDB();
{
ScopedLock dbLock(theApp->getTxnDB()->getDBLock());
db->executeSQL("BEGIN TRANSACTION;");
SHAMapTreeNode::TNType type;
for (SHAMapItem::pointer item = txSet.peekFirstItem(type); !!item;
item = txSet.peekNextItem(item->getTag(), type))
BOOST_FOREACH(const AcceptedLedger::value_type& vt, aLedger->getMap())
{
assert(type == SHAMapTreeNode::tnTRANSACTION_MD);
SerializerIterator sit(item->peekSerializer());
Serializer rawTxn(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());
theApp->getMasterTransaction().inLedger(item->getTag(), mLedgerSeq);
cLog(lsTRACE) << "Saving: " << vt.second.getJson(0);
uint256 txID = vt.second.getTransactionID();
theApp->getMasterTransaction().inLedger(txID, mLedgerSeq);
// Make sure transaction is in AccountTransactions.
if (!SQL_EXISTS(db, boost::str(AcctTransExists % item->getTag().GetHex())))
if (!SQL_EXISTS(db, boost::str(AcctTransExists % txID.GetHex())))
{
// Transaction not in AccountTransactions
const std::vector<RippleAddress> accts = meta.getAffectedAccounts();
const std::vector<RippleAddress>& accts = vt.second.getAffected();
if (!accts.empty())
{
@@ -476,7 +467,7 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
sql += "('";
first = false;
}
sql += txn.getTransactionID().GetHex();
sql += txID.GetHex();
sql += "','";
sql += it->humanAccountID();
sql += "',";
@@ -491,20 +482,21 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
cLog(lsWARNING) << "Transaction in ledger " << mLedgerSeq << " affects no accounts";
}
if (SQL_EXISTS(db, boost::str(transExists % txn.getTransactionID().GetHex())))
if (SQL_EXISTS(db, boost::str(transExists % txID.GetHex())))
{
// In Transactions, update LedgerSeq, metadata and Status.
db->executeSQL(boost::str(updateTx
% getLedgerSeq()
% TXN_SQL_VALIDATED
% escMeta
% txn.getTransactionID().GetHex()));
% vt.second.getEscMeta()
% txID.GetHex()));
}
else
{
// Not in Transactions, insert the whole thing..
db->executeSQL(
txn.getMetaSQLInsertHeader() + txn.getMetaSQL(getLedgerSeq(), escMeta) + ";");
SerializedTransaction::getMetaSQLInsertHeader() +
vt.second.getTxn()->getMetaSQL(getLedgerSeq(), vt.second.getEscMeta()) + ";");
}
}
db->executeSQL("COMMIT TRANSACTION;");

View File

@@ -119,11 +119,11 @@ Ledger::pointer LedgerMaster::closeLedger(bool recover)
return closingLedger;
}
TER LedgerMaster::doTransaction(const SerializedTransaction& txn, TransactionEngineParams params, bool& didApply)
TER LedgerMaster::doTransaction(SerializedTransaction::ref txn, TransactionEngineParams params, bool& didApply)
{
TER result = mEngine.applyTransaction(txn, params, didApply);
// CHECKME: Should we call this even on gross failures?
theApp->getOPs().pubProposedTransaction(mEngine.getLedger(), txn, result);
TER result = mEngine.applyTransaction(*txn, params, didApply);
// if (didApply)
theApp->getOPs().pubProposedTransaction(mEngine.getLedger(), txn, result);
return result;
}

View File

@@ -75,7 +75,7 @@ public:
// The published ledger is the last fully validated ledger
Ledger::ref getValidatedLedger() { return mPubLedger; }
TER doTransaction(const SerializedTransaction& txn, TransactionEngineParams params, bool& didApply);
TER doTransaction(SerializedTransaction::ref txn, TransactionEngineParams params, bool& didApply);
void pushLedger(Ledger::ref newLedger);
void pushLedger(Ledger::ref newLCL, Ledger::ref newOL, bool fromConsensus);

View File

@@ -267,7 +267,7 @@ void NetworkOPs::runTransactionQueue()
assert(dbtx);
bool didApply;
TER r = mLedgerMaster->doTransaction(*dbtx->getSTransaction(),
TER r = mLedgerMaster->doTransaction(dbtx->getSTransaction(),
tapOPEN_LEDGER | tapNO_CHECK_SIGN, didApply);
dbtx->setResult(r);
@@ -352,7 +352,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock());
Transaction::pointer dbtx = theApp->getMasterTransaction().fetch(trans->getID(), true);
bool didApply;
TER r = mLedgerMaster->doTransaction(*trans->getSTransaction(), tapOPEN_LEDGER | tapNO_CHECK_SIGN, didApply);
TER r = mLedgerMaster->doTransaction(trans->getSTransaction(), tapOPEN_LEDGER | tapNO_CHECK_SIGN, didApply);
trans->setResult(r);
if (isTemMalformed(r)) // malformed, cache bad
@@ -1289,9 +1289,9 @@ Json::Value NetworkOPs::pubBootstrapAccountInfo(Ledger::ref lpAccepted, const Ri
return jvObj;
}
void NetworkOPs::pubProposedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult)
void NetworkOPs::pubProposedTransaction(Ledger::ref lpCurrent, SerializedTransaction::ref stTxn, TER terResult)
{
Json::Value jvObj = transJson(stTxn, terResult, false, lpCurrent, "transaction");
Json::Value jvObj = transJson(*stTxn, terResult, false, lpCurrent, "transaction");
{
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
@@ -1308,15 +1308,19 @@ void NetworkOPs::pubProposedTransaction(Ledger::ref lpCurrent, const SerializedT
it = mSubRTTransactions.erase(it);
}
}
TransactionMetaSet::pointer ret;
pubAccountTransaction(lpCurrent,stTxn,terResult,false,ret);
ALTransaction alt(stTxn, terResult);
cLog(lsTRACE) << "pubProposed: " << alt.getJson(0);
pubAccountTransaction(lpCurrent, ALTransaction(stTxn, terResult));
}
void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
void NetworkOPs::pubLedger(Ledger::ref accepted)
{
// Ledgers are published only when they acquire sufficient validations
// Holes are filled across connection loss or other catastrophe
AcceptedLedger::pointer alpAccepted = AcceptedLedger::makeAcceptedLedger(accepted);
Ledger::ref lpAccepted = alpAccepted->getLedger();
{
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
@@ -1334,6 +1338,8 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
jvObj["reserve_base"] = Json::UInt(lpAccepted->getReserve(0));
jvObj["reserve_inc"] = Json::UInt(lpAccepted->getReserveInc());
jvObj["txn_count"] = Json::UInt(alpAccepted->getTxnCount());
NetworkOPs::subMapType::const_iterator it = mSubLedger.begin();
while (it != mSubLedger.end())
{
@@ -1352,21 +1358,10 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
// Don't lock since pubAcceptedTransaction is locking.
if (!mSubTransactions.empty() || !mSubRTTransactions.empty() || !mSubAccount.empty() || !mSubRTAccount.empty())
{
SHAMap& txSet = *lpAccepted->peekTransactionMap();
for (SHAMapItem::pointer item = txSet.peekFirstItem(); !!item; item = txSet.peekNextItem(item->getTag()))
BOOST_FOREACH(const AcceptedLedger::value_type& vt, alpAccepted->getMap())
{
SerializerIterator it(item->peekSerializer());
// OPTIMIZEME: Could get transaction from txn master, but still must call getVL
Serializer txnSer(it.getVL());
SerializerIterator txnIt(txnSer);
SerializedTransaction stTxn(txnIt);
TransactionMetaSet::pointer meta = boost::make_shared<TransactionMetaSet>(
stTxn.getTransactionID(), lpAccepted->getLedgerSeq(), it.getVL());
pubAcceptedTransaction(lpAccepted, stTxn, meta->getResultTER(), meta);
cLog(lsTRACE) << "pubAccepted: " << vt.second.getJson(0);
pubAcceptedTransaction(lpAccepted, vt.second);
}
}
}
@@ -1407,11 +1402,10 @@ Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TER terRes
return jvObj;
}
void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta)
void NetworkOPs::pubAcceptedTransaction(Ledger::ref alAccepted, const ALTransaction& alTx)
{
Json::Value jvObj = transJson(stTxn, terResult, true, lpCurrent, "transaction");
if (meta) jvObj["meta"] = meta->getJson(0);
Json::Value jvObj = transJson(*alTx.getTxn(), alTx.getResult(), true, alAccepted, "transaction");
jvObj["meta"] = alTx.getMeta()->getJson(0);
{
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
@@ -1442,14 +1436,14 @@ void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedT
it = mSubRTTransactions.erase(it);
}
}
theApp->getOrderBookDB().processTxn(stTxn, terResult, meta, jvObj);
pubAccountTransaction(lpCurrent, stTxn, terResult, true, meta);
theApp->getOrderBookDB().processTxn(alAccepted, alTx, jvObj);
pubAccountTransaction(alAccepted, alTx);
}
void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted, TransactionMetaSet::pointer& meta)
void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const ALTransaction& alTx)
{
boost::unordered_set<InfoSub::pointer> notify;
bool bAccepted = alTx.isApplied();
int iProposed = 0;
int iAccepted = 0;
@@ -1460,8 +1454,7 @@ void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTr
if (!mSubAccount.empty() || (!mSubRTAccount.empty()) )
{
std::vector<RippleAddress> accounts = meta ? meta->getAffectedAccounts() : stTxn.getMentionedAccounts();
BOOST_FOREACH(const RippleAddress& affectedAccount, accounts)
BOOST_FOREACH(const RippleAddress& affectedAccount, alTx.getAffected())
{
subInfoMapIterator simiIt = mSubRTAccount.find(affectedAccount.getAccountID());
@@ -1510,9 +1503,10 @@ void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTr
if (!notify.empty())
{
Json::Value jvObj = transJson(stTxn, terResult, bAccepted, lpCurrent, "account");
Json::Value jvObj = transJson(*alTx.getTxn(), alTx.getResult(), bAccepted, lpCurrent, "account");
if (meta) jvObj["meta"] = meta->getJson(0);
if (alTx.isApplied())
jvObj["meta"] = alTx.getMeta()->getJson(0);
BOOST_FOREACH(InfoSub::ref isrListener, notify)
{

View File

@@ -14,6 +14,7 @@
#include "LedgerAcquire.h"
#include "LedgerProposal.h"
#include "JobQueue.h"
#include "AcceptedLedger.h"
// Operations that clients may wish to perform against the network
// Master operational handler, server sequencer, network tracker
@@ -140,8 +141,8 @@ protected:
Json::Value pubBootstrapAccountInfo(Ledger::ref lpAccepted, const RippleAddress& naAccountID);
void pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta);
void pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult,bool accepted,TransactionMetaSet::pointer& meta);
void pubAcceptedTransaction(Ledger::ref alAccepted, const ALTransaction& alTransaction);
void pubAccountTransaction(Ledger::ref lpCurrent, const ALTransaction& alTransaction);
void pubServer();
@@ -306,7 +307,7 @@ public:
// Monitoring: publisher side
//
void pubLedger(Ledger::ref lpAccepted);
void pubProposedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult);
void pubProposedTransaction(Ledger::ref lpCurrent, SerializedTransaction::ref stTxn, TER terResult);
//

View File

@@ -187,15 +187,14 @@ BookListeners::pointer OrderBookDB::getBookListeners(const uint160& currencyIn,
*/
// Based on the meta, send the meta to the streams that are listening
// We need to determine which streams a given meta effects
void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult,
TransactionMetaSet::pointer& meta, Json::Value& jvObj)
void OrderBookDB::processTxn(Ledger::ref ledger, const ALTransaction& alTx, Json::Value& jvObj)
{
boost::recursive_mutex::scoped_lock sl(mLock);
if (terResult == tesSUCCESS)
if (alTx.getResult() == tesSUCCESS)
{
// check if this is an offer or an offer cancel or a payment that consumes an offer
//check to see what the meta looks like
BOOST_FOREACH(STObject& node, meta->getNodes())
BOOST_FOREACH(STObject& node, alTx.getMeta()->getNodes())
{
try
{

View File

@@ -6,6 +6,7 @@
#include <boost/unordered_map.hpp>
#include "Ledger.h"
#include "AcceptedLedger.h"
#include "OrderBook.h"
@@ -66,7 +67,7 @@ public:
const uint160& issuerIn, const uint160& issuerOut);
// see if this txn effects any orderbook
void processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj);
void processTxn(Ledger::ref ledger, const ALTransaction& alTx, Json::Value& jvObj);
};