mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-24 21:15:58 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -71,8 +71,24 @@ static void InitDB(DatabaseCon** dbCon, const char *fileName, const char *dbInit
|
||||
*dbCon = new DatabaseCon(fileName, dbInit, dbCount);
|
||||
}
|
||||
|
||||
volatile bool doShutdown = false;
|
||||
|
||||
#ifdef SIGINT
|
||||
void sigIntHandler(int)
|
||||
{
|
||||
doShutdown = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::run()
|
||||
{
|
||||
#ifdef SIGINT
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = sigIntHandler;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
#endif
|
||||
|
||||
assert(mTxnDB == NULL);
|
||||
if (!theConfig.DEBUG_LOGFILE.empty())
|
||||
{ // Let DEBUG messages go to the file but only WARNING or higher to regular output (unless verbose)
|
||||
@@ -118,13 +134,6 @@ void Application::run()
|
||||
else
|
||||
startNewLedger();
|
||||
|
||||
if (theConfig.FULL_HISTORY && (theConfig.START_UP != Config::LOAD))
|
||||
{
|
||||
Ledger::pointer ledger = Ledger::getLastFullLedger();
|
||||
if (ledger)
|
||||
mLedgerMaster.setLedgerRangePresent(0, ledger->getLedgerSeq());
|
||||
}
|
||||
|
||||
//
|
||||
// Begin validation and ip maintenance.
|
||||
// - Wallet maintains local information: including identity and network connection persistence information.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
@@ -14,7 +15,7 @@
|
||||
#define SECTION_FEE_NICKNAME_CREATE "fee_nickname_create"
|
||||
#define SECTION_FEE_OFFER "fee_offer"
|
||||
#define SECTION_FEE_OPERATION "fee_operation"
|
||||
#define SECTION_FULL_HISTORY "full_history"
|
||||
#define SECTION_LEDGER_HISTORY "ledger_history"
|
||||
#define SECTION_IPS "ips"
|
||||
#define SECTION_NETWORK_QUORUM "network_quorum"
|
||||
#define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water"
|
||||
@@ -157,7 +158,7 @@ void Config::setup(const std::string& strConf)
|
||||
FEE_DEFAULT = DEFAULT_FEE_DEFAULT;
|
||||
FEE_CONTRACT_OPERATION = DEFAULT_FEE_OPERATION;
|
||||
|
||||
FULL_HISTORY = false;
|
||||
LEDGER_HISTORY = 256;
|
||||
|
||||
ACCOUNT_PROBE_MAX = 10;
|
||||
|
||||
@@ -292,8 +293,16 @@ void Config::load()
|
||||
if (sectionSingleB(secConfig, SECTION_FEE_OPERATION, strTemp))
|
||||
FEE_CONTRACT_OPERATION = boost::lexical_cast<int>(strTemp);
|
||||
|
||||
if (sectionSingleB(secConfig, SECTION_FULL_HISTORY, strTemp))
|
||||
FULL_HISTORY = boost::lexical_cast<bool>(strTemp);
|
||||
if (sectionSingleB(secConfig, SECTION_LEDGER_HISTORY, strTemp))
|
||||
{
|
||||
boost::to_lower(strTemp);
|
||||
if ((strTemp == "no") || (strTemp == "none") || (strTemp == "off") || (strTemp == "false"))
|
||||
LEDGER_HISTORY = 0;
|
||||
else if ((strTemp == "yes") || (strTemp == "full") || (strTemp == "on") || (strTemp == "-1"))
|
||||
LEDGER_HISTORY = 1000000000u;
|
||||
else
|
||||
LEDGER_HISTORY = boost::lexical_cast<uint32>(strTemp);
|
||||
}
|
||||
|
||||
if (sectionSingleB(secConfig, SECTION_ACCOUNT_PROBE_MAX, strTemp))
|
||||
ACCOUNT_PROBE_MAX = boost::lexical_cast<int>(strTemp);
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
int FEE_CONTRACT_OPERATION; // fee for each contract operation
|
||||
|
||||
// Node storage configuration
|
||||
bool FULL_HISTORY;
|
||||
uint32 LEDGER_HISTORY;
|
||||
|
||||
// Client behavior
|
||||
int ACCOUNT_PROBE_MAX; // How far to scan for accounts.
|
||||
|
||||
@@ -12,7 +12,7 @@ SETUP_LOG();
|
||||
DECLARE_INSTANCE(HashedObject);
|
||||
|
||||
HashedObjectStore::HashedObjectStore(int cacheSize, int cacheAge) :
|
||||
mCache("HashedObjectStore", cacheSize, cacheAge), mWritePending(false), mWriteGeneration(0)
|
||||
mCache("HashedObjectStore", cacheSize, cacheAge), mWriteGeneration(0), mWritePending(false)
|
||||
{
|
||||
mWriteSet.reserve(128);
|
||||
}
|
||||
|
||||
@@ -299,6 +299,29 @@ SerializedTransaction::pointer Ledger::getSTransaction(SHAMapItem::ref item, SHA
|
||||
return SerializedTransaction::pointer();
|
||||
}
|
||||
|
||||
SerializedTransaction::pointer Ledger::getSMTransaction(SHAMapItem::ref item, SHAMapTreeNode::TNType type,
|
||||
TransactionMetaSet::pointer& txMeta)
|
||||
{
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
|
||||
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
|
||||
{
|
||||
txMeta.reset();
|
||||
return boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
}
|
||||
else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
|
||||
{
|
||||
Serializer sTxn(sit.getVL());
|
||||
SerializerIterator tSit(sTxn);
|
||||
|
||||
txMeta = boost::make_shared<TransactionMetaSet>(item->getTag(), mLedgerSeq, sit.getVL());
|
||||
return boost::make_shared<SerializedTransaction>(boost::ref(tSit));
|
||||
}
|
||||
|
||||
txMeta.reset();
|
||||
return SerializedTransaction::pointer();
|
||||
}
|
||||
|
||||
bool Ledger::getTransaction(const uint256& txID, Transaction::pointer& txn, TransactionMetaSet::pointer& meta)
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
@@ -346,7 +369,8 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
||||
static boost::format deleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %d;");
|
||||
static boost::format AcctTransExists("SELECT LedgerSeq FROM AccountTransactions WHERE TransId = '%s';");
|
||||
static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';");
|
||||
static boost::format updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c' WHERE TransID = '%s';");
|
||||
static boost::format
|
||||
updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c', TxnMeta = %s WHERE TransID = '%s';");
|
||||
static boost::format addLedger("INSERT INTO Ledgers "
|
||||
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
|
||||
"AccountSetHash,TransSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');");
|
||||
@@ -374,14 +398,20 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
||||
for (SHAMapItem::pointer item = txSet.peekFirstItem(type); !!item;
|
||||
item = txSet.peekNextItem(item->getTag(), type))
|
||||
{
|
||||
SerializedTransaction::pointer txn = getSTransaction(item, type);
|
||||
assert(txn);
|
||||
assert(type == SHAMapTreeNode::tnTRANSACTION_MD);
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
Serializer rawTxn(sit.getVL());
|
||||
std::string escMeta(sqlEscape(sit.getVL()));
|
||||
|
||||
SerializerIterator txnIt(rawTxn);
|
||||
SerializedTransaction txn(txnIt);
|
||||
assert(txn.getTransactionID() == item->getTag());
|
||||
|
||||
// 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 = txn.getAffectedAccounts();
|
||||
|
||||
std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES ";
|
||||
bool first = true;
|
||||
@@ -394,7 +424,7 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
||||
sql += "('";
|
||||
first = false;
|
||||
}
|
||||
sql += txn->getTransactionID().GetHex();
|
||||
sql += txn.getTransactionID().GetHex();
|
||||
sql += "','";
|
||||
sql += it->humanAccountID();
|
||||
sql += "',";
|
||||
@@ -406,19 +436,20 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
||||
db->executeSQL(sql); // may already be in there
|
||||
}
|
||||
|
||||
if (SQL_EXISTS(db, boost::str(transExists % txn->getTransactionID().GetHex())))
|
||||
if (SQL_EXISTS(db, boost::str(transExists % txn.getTransactionID().GetHex())))
|
||||
{
|
||||
// In Transactions, update LedgerSeq and Status.
|
||||
// In Transactions, update LedgerSeq, metadata and Status.
|
||||
db->executeSQL(boost::str(updateTx
|
||||
% getLedgerSeq()
|
||||
% TXN_SQL_VALIDATED
|
||||
% txn->getTransactionID().GetHex()));
|
||||
% escMeta
|
||||
% txn.getTransactionID().GetHex()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not in Transactions, insert the whole thing..
|
||||
db->executeSQL(
|
||||
txn->getSQLInsertHeader() + txn->getSQL(getLedgerSeq(), TXN_SQL_VALIDATED) + ";");
|
||||
txn.getMetaSQLInsertHeader() + txn.getMetaSQL(getLedgerSeq(), escMeta) + ";");
|
||||
}
|
||||
}
|
||||
db->executeSQL("COMMIT TRANSACTION;");
|
||||
|
||||
@@ -161,7 +161,10 @@ public:
|
||||
bool hasTransaction(const uint256& TransID) const { return mTransactionMap->hasItem(TransID); }
|
||||
Transaction::pointer getTransaction(const uint256& transID) const;
|
||||
bool getTransaction(const uint256& transID, Transaction::pointer& txn, TransactionMetaSet::pointer& txMeta);
|
||||
|
||||
static SerializedTransaction::pointer getSTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType);
|
||||
SerializedTransaction::pointer getSMTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType,
|
||||
TransactionMetaSet::pointer& txMeta);
|
||||
|
||||
// high-level functions
|
||||
AccountState::pointer getAccountState(const RippleAddress& acctID);
|
||||
|
||||
@@ -644,8 +644,16 @@ void LedgerConsensus::stateAccepted()
|
||||
endConsensus();
|
||||
}
|
||||
|
||||
extern volatile bool doShutdown;
|
||||
|
||||
void LedgerConsensus::timerEntry()
|
||||
{
|
||||
if (doShutdown)
|
||||
{
|
||||
cLog(lsFATAL) << "Shutdown requested";
|
||||
theApp->stop();
|
||||
}
|
||||
|
||||
if ((mState != lcsFINISHED) && (mState != lcsACCEPTED))
|
||||
checkLCL();
|
||||
|
||||
|
||||
@@ -117,6 +117,12 @@ TER LedgerMaster::doTransaction(const SerializedTransaction& txn, TransactionEng
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LedgerMaster::haveLedgerRange(uint32 from, uint32 to)
|
||||
{
|
||||
uint32 prevMissing = mCompleteLedgers.prevMissing(to + 1);
|
||||
return (prevMissing == RangeSet::RangeSetAbsent) || (prevMissing < from);
|
||||
}
|
||||
|
||||
void LedgerMaster::acquireMissingLedger(const uint256& ledgerHash, uint32 ledgerSeq)
|
||||
{
|
||||
mMissingLedger = theApp->getMasterLedgerAcquire().findCreate(ledgerHash);
|
||||
@@ -152,8 +158,19 @@ void LedgerMaster::missingAcquireComplete(LedgerAcquire::pointer acq)
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
||||
static bool shouldAcquire(uint32 currentLedger, uint32 ledgerHistory, uint32 candidateLedger)
|
||||
{
|
||||
bool ret;
|
||||
if (candidateLedger >= currentLedger)
|
||||
ret = true;
|
||||
else ret = (currentLedger - candidateLedger) <= ledgerHistory;
|
||||
cLog(lsDEBUG) << "Missing ledger " << candidateLedger << (ret ? "will" : "will NOT") << " be acquired";
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
||||
{ // A new ledger has been accepted as part of the trusted chain
|
||||
|
||||
boost::recursive_mutex::scoped_lock ml(mLock);
|
||||
|
||||
mCompleteLedgers.setValue(ledger->getLedgerSeq());
|
||||
@@ -161,7 +178,12 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
||||
if ((ledger->getLedgerSeq() != 0) && mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
||||
{ // we think we have the previous ledger, double check
|
||||
Ledger::pointer prevLedger = getLedgerBySeq(ledger->getLedgerSeq() - 1);
|
||||
if (prevLedger && (prevLedger->getHash() != ledger->getParentHash()))
|
||||
if (!prevLedger)
|
||||
{
|
||||
cLog(lsWARNING) << "Ledger " << ledger->getLedgerSeq() - 1 << " missing";
|
||||
mCompleteLedgers.clearValue(ledger->getLedgerSeq() - 1);
|
||||
}
|
||||
else if (prevLedger->getHash() != ledger->getParentHash())
|
||||
{
|
||||
cLog(lsWARNING) << "Ledger " << ledger->getLedgerSeq() << " invalidates prior ledger";
|
||||
mCompleteLedgers.clearValue(prevLedger->getLedgerSeq());
|
||||
@@ -171,7 +193,7 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
||||
if (mMissingLedger && mMissingLedger->isComplete())
|
||||
mMissingLedger.reset();
|
||||
|
||||
if (mMissingLedger || !theConfig.FULL_HISTORY)
|
||||
if (mMissingLedger || !theConfig.LEDGER_HISTORY)
|
||||
return;
|
||||
|
||||
if (Ledger::getPendingSaves() > 3)
|
||||
@@ -183,13 +205,17 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
||||
// see if there's a ledger gap we need to fill
|
||||
if (!mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
||||
{
|
||||
if (!shouldAcquire(mCurrentLedger->getLedgerSeq(), theConfig.LEDGER_HISTORY, ledger->getLedgerSeq() - 1))
|
||||
return;
|
||||
cLog(lsINFO) << "We need the ledger before the ledger we just accepted";
|
||||
acquireMissingLedger(ledger->getParentHash(), ledger->getLedgerSeq() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 prevMissing = mCompleteLedgers.prevMissing(ledger->getLedgerSeq());
|
||||
if (prevMissing != RangeSet::RangeSetAbsent)
|
||||
if (prevMissing == RangeSet::RangeSetAbsent)
|
||||
return;
|
||||
if (shouldAcquire(mCurrentLedger->getLedgerSeq(), theConfig.LEDGER_HISTORY, prevMissing))
|
||||
{
|
||||
cLog(lsINFO) << "Ledger " << prevMissing << " is missing";
|
||||
assert(!mCompleteLedgers.hasValue(prevMissing));
|
||||
|
||||
@@ -93,6 +93,8 @@ public:
|
||||
|
||||
void addHeldTransaction(const Transaction::pointer& trans);
|
||||
|
||||
bool haveLedgerRange(uint32 from, uint32 to);
|
||||
|
||||
void sweep(void) { mLedgerHistory.sweep(); }
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,11 @@ uint32 NetworkOPs::getCurrentLedgerID()
|
||||
return mLedgerMaster->getCurrentLedger()->getLedgerSeq();
|
||||
}
|
||||
|
||||
bool NetworkOPs::haveLedgerRange(uint32 from, uint32 to)
|
||||
{
|
||||
return mLedgerMaster->haveLedgerRange(from, to);
|
||||
}
|
||||
|
||||
void NetworkOPs::submitTransaction(Job&, SerializedTransaction::pointer iTrans, stCallback callback)
|
||||
{ // this is an asynchronous interface
|
||||
Serializer s;
|
||||
@@ -876,14 +881,15 @@ void NetworkOPs::setMode(OperatingMode om)
|
||||
mMode = om;
|
||||
}
|
||||
|
||||
std::vector< std::pair<uint32, uint256> >
|
||||
NetworkOPs::getAffectedAccounts(const RippleAddress& account, uint32 minLedger, uint32 maxLedger)
|
||||
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||
NetworkOPs::getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger)
|
||||
{
|
||||
std::vector< std::pair<uint32, uint256> > affectedAccounts;
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > ret;
|
||||
|
||||
std::string sql =
|
||||
str(boost::format("SELECT LedgerSeq,TransID FROM AccountTransactions INDEXED BY AcctTxIndex "
|
||||
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ORDER BY LedgerSeq LIMIT 1000;")
|
||||
str(boost::format("SELECT LedgerSeq,Status,RawTxn,TxnMeta FROM Transactions where TransID in (SELECT TransID from AccountTransactions "
|
||||
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 1000) ORDER BY LedgerSeq;")
|
||||
% account.humanAccountID() % maxLedger % minLedger);
|
||||
|
||||
{
|
||||
@@ -892,11 +898,24 @@ std::vector< std::pair<uint32, uint256> >
|
||||
|
||||
SQL_FOREACH(db, sql)
|
||||
{
|
||||
affectedAccounts.push_back(std::make_pair<uint32, uint256>(db->getInt("LedgerSeq"), uint256(db->getStrBinary("TransID"))));
|
||||
Transaction::pointer txn=Transaction::transactionFromSQL(db,false);
|
||||
|
||||
Serializer rawMeta;
|
||||
int metaSize = 2048;
|
||||
rawMeta.resize(metaSize);
|
||||
metaSize = db->getBinary("RawTxn", &*rawMeta.begin(), rawMeta.getLength());
|
||||
if (metaSize > rawMeta.getLength())
|
||||
{
|
||||
rawMeta.resize(metaSize);
|
||||
db->getBinary("RawTxn", &*rawMeta.begin(), rawMeta.getLength());
|
||||
}else rawMeta.resize(metaSize);
|
||||
|
||||
TransactionMetaSet::pointer meta= boost::make_shared<TransactionMetaSet>(txn->getID(), txn->getLedger(), rawMeta.getData());
|
||||
ret.push_back(std::make_pair<Transaction::pointer, TransactionMetaSet::pointer>(txn,meta));
|
||||
}
|
||||
}
|
||||
|
||||
return affectedAccounts;
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<RippleAddress>
|
||||
@@ -1076,6 +1095,7 @@ Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TER terRes
|
||||
void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta)
|
||||
{
|
||||
Json::Value jvObj = transJson(stTxn, terResult, true, lpCurrent, "transaction");
|
||||
if(meta) jvObj["meta"]=meta->getJson(0);
|
||||
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
|
||||
|
||||
@@ -134,6 +134,9 @@ public:
|
||||
|
||||
uint256 getClosedLedgerHash() { return mLedgerMaster->getClosedLedger()->getHash(); }
|
||||
|
||||
// Do we have this inclusive range of ledgers in our database
|
||||
bool haveLedgerRange(uint32 from, uint32 to);
|
||||
|
||||
SerializedValidation::ref getLastValidation() { return mLastValidation; }
|
||||
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
||||
|
||||
@@ -230,8 +233,8 @@ public:
|
||||
uint256 getConsensusLCL();
|
||||
|
||||
// client information retrieval functions
|
||||
std::vector< std::pair<uint32, uint256> >
|
||||
getAffectedAccounts(const RippleAddress& account, uint32 minLedger, uint32 maxLedger);
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||
getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger);
|
||||
std::vector<RippleAddress> getLedgerAffectedAccounts(uint32 ledgerSeq);
|
||||
std::vector<SerializedTransaction> getLedgerTransactions(uint32 ledgerSeq);
|
||||
|
||||
|
||||
@@ -1303,25 +1303,18 @@ Json::Value RPCHandler::doAccountTransactions(const Json::Value& params)
|
||||
try
|
||||
{
|
||||
#endif
|
||||
std::vector< std::pair<uint32, uint256> > txns = mNetOps->getAffectedAccounts(account, minLedger, maxLedger);
|
||||
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns = mNetOps->getAccountTxs(account, minLedger, maxLedger);
|
||||
Json::Value ret(Json::objectValue);
|
||||
ret["account"] = account.humanAccountID();
|
||||
Json::Value ledgers(Json::arrayValue);
|
||||
|
||||
// uint32 currentLedger = 0;
|
||||
for (std::vector< std::pair<uint32, uint256> >::iterator it = txns.begin(), end = txns.end(); it != end; ++it)
|
||||
for (std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >::iterator it = txns.begin(), end = txns.end(); it != end; ++it)
|
||||
{
|
||||
Transaction::pointer txn = theApp->getMasterTransaction().fetch(it->second, true);
|
||||
if (!txn)
|
||||
{
|
||||
ret["transactions"].append(it->second.GetHex());
|
||||
}
|
||||
else
|
||||
{
|
||||
txn->setLedger(it->first);
|
||||
ret["transactions"].append(txn->getJson(1));
|
||||
}
|
||||
|
||||
Json::Value obj(Json::objectValue);
|
||||
if(it->first) obj["tx"]=it->first->getJson(1);
|
||||
if(it->second) obj["meta"]=it->second->getJson(0);
|
||||
ret["transactions"].append(obj);
|
||||
}
|
||||
return ret;
|
||||
#ifndef DEBUG
|
||||
|
||||
@@ -183,11 +183,21 @@ std::string SerializedTransaction::getSQLValueHeader()
|
||||
return "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn)";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQLValueHeader()
|
||||
{
|
||||
return "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn, TxnMeta)";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getSQLInsertHeader()
|
||||
{
|
||||
return "INSERT INTO Transactions " + getSQLValueHeader() + " VALUES ";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQLInsertHeader()
|
||||
{
|
||||
return "INSERT INTO Transactions " + getMetaSQLValueHeader() + " VALUES ";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getSQL(uint32 inLedger, char status) const
|
||||
{
|
||||
Serializer s;
|
||||
@@ -195,16 +205,36 @@ std::string SerializedTransaction::getSQL(uint32 inLedger, char status) const
|
||||
return getSQL(s, inLedger, status);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQL(uint32 inLedger, const std::string& escapedMetaData) const
|
||||
{
|
||||
Serializer s;
|
||||
add(s);
|
||||
return getMetaSQL(s, inLedger, TXN_SQL_VALIDATED, escapedMetaData);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getSQL(Serializer rawTxn, uint32 inLedger, char status) const
|
||||
{
|
||||
static boost::format bfTrans("('%s', '%s', '%s', '%d', '%d', '%c', %s)");
|
||||
std::string rTxn;
|
||||
theApp->getTxnDB()->getDB()->escape(
|
||||
reinterpret_cast<const unsigned char *>(rawTxn.getDataPtr()), rawTxn.getLength(), rTxn);
|
||||
return str(boost::format("('%s', '%s', '%s', '%d', '%d', '%c', %s)")
|
||||
return str(bfTrans
|
||||
% getTransactionID().GetHex() % getTransactionType() % getSourceAccount().humanAccountID()
|
||||
% getSequence() % inLedger % status % rTxn);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQL(Serializer rawTxn, uint32 inLedger, char status,
|
||||
const std::string& escapedMetaData) const
|
||||
{
|
||||
static boost::format bfTrans("('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)");
|
||||
std::string rTxn;
|
||||
theApp->getTxnDB()->getDB()->escape(
|
||||
reinterpret_cast<const unsigned char *>(rawTxn.getDataPtr()), rawTxn.getLength(), rTxn);
|
||||
return str(bfTrans
|
||||
% getTransactionID().GetHex() % getTransactionType() % getSourceAccount().humanAccountID()
|
||||
% getSequence() % inLedger % status % rTxn % escapedMetaData);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(SerializedTransactionTS)
|
||||
|
||||
|
||||
@@ -77,6 +77,12 @@ public:
|
||||
std::string getSQL(uint32 inLedger, char status) const;
|
||||
std::string getSQL(Serializer rawTxn, uint32 inLedger, char status) const;
|
||||
|
||||
// SQL Functions with metadata
|
||||
static std::string getMetaSQLValueHeader();
|
||||
static std::string getMetaSQLInsertHeader();
|
||||
std::string getMetaSQL(uint32 inLedger, const std::string& escapedMetaData) const;
|
||||
std::string getMetaSQL(Serializer rawTxn, uint32 inLedger, char status, const std::string& escapedMetaData) const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -246,6 +246,7 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
||||
return tr;
|
||||
}
|
||||
|
||||
|
||||
Transaction::pointer Transaction::load(const uint256& id)
|
||||
{
|
||||
std::string sql = "SELECT LedgerSeq,Status,RawTxn FROM Transactions WHERE TransID='";
|
||||
|
||||
@@ -158,6 +158,12 @@ inline static std::string sqlEscape(const std::string& strSrc)
|
||||
return str(f % strHex(strSrc));
|
||||
}
|
||||
|
||||
inline static std::string sqlEscape(const std::vector<unsigned char>& vecSrc)
|
||||
{
|
||||
static boost::format f("X'%s'");
|
||||
return str(f % strHex(vecSrc));
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
bool isZero(Iterator first, int iSize)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user