mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 05:55:51 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -91,6 +91,13 @@
|
|||||||
# [currencies]:
|
# [currencies]:
|
||||||
# This section allows a site to declare currencies it currently issues.
|
# This section allows a site to declare currencies it currently issues.
|
||||||
#
|
#
|
||||||
|
# [ledger_history]:
|
||||||
|
# To serve clients, servers need historical ledger data. This sets the number of
|
||||||
|
# past ledgers to acquire on server startup and the minimum to maintain while
|
||||||
|
# running. Servers that don't need to serve clients can set this to "none" or "off".
|
||||||
|
# Servers that want complete history can set this to "full" or "on".
|
||||||
|
# The default is 256 ledgers.
|
||||||
|
|
||||||
|
|
||||||
[validation_public_key]
|
[validation_public_key]
|
||||||
n9MZTnHe5D5Q2cgE8oV2usFwRqhUvEA8MwP5Mu1XVD6TxmssPRev
|
n9MZTnHe5D5Q2cgE8oV2usFwRqhUvEA8MwP5Mu1XVD6TxmssPRev
|
||||||
|
|||||||
@@ -71,8 +71,24 @@ static void InitDB(DatabaseCon** dbCon, const char *fileName, const char *dbInit
|
|||||||
*dbCon = new DatabaseCon(fileName, dbInit, dbCount);
|
*dbCon = new DatabaseCon(fileName, dbInit, dbCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile bool doShutdown = false;
|
||||||
|
|
||||||
|
#ifdef SIGINT
|
||||||
|
void sigIntHandler(int)
|
||||||
|
{
|
||||||
|
doShutdown = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Application::run()
|
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);
|
assert(mTxnDB == NULL);
|
||||||
if (!theConfig.DEBUG_LOGFILE.empty())
|
if (!theConfig.DEBUG_LOGFILE.empty())
|
||||||
{ // Let DEBUG messages go to the file but only WARNING or higher to regular output (unless verbose)
|
{ // 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
|
else
|
||||||
startNewLedger();
|
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.
|
// Begin validation and ip maintenance.
|
||||||
// - Wallet maintains local information: including identity and network connection persistence information.
|
// - Wallet maintains local information: including identity and network connection persistence information.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
#define SECTION_FEE_NICKNAME_CREATE "fee_nickname_create"
|
#define SECTION_FEE_NICKNAME_CREATE "fee_nickname_create"
|
||||||
#define SECTION_FEE_OFFER "fee_offer"
|
#define SECTION_FEE_OFFER "fee_offer"
|
||||||
#define SECTION_FEE_OPERATION "fee_operation"
|
#define SECTION_FEE_OPERATION "fee_operation"
|
||||||
#define SECTION_FULL_HISTORY "full_history"
|
#define SECTION_LEDGER_HISTORY "ledger_history"
|
||||||
#define SECTION_IPS "ips"
|
#define SECTION_IPS "ips"
|
||||||
#define SECTION_NETWORK_QUORUM "network_quorum"
|
#define SECTION_NETWORK_QUORUM "network_quorum"
|
||||||
#define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water"
|
#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_DEFAULT = DEFAULT_FEE_DEFAULT;
|
||||||
FEE_CONTRACT_OPERATION = DEFAULT_FEE_OPERATION;
|
FEE_CONTRACT_OPERATION = DEFAULT_FEE_OPERATION;
|
||||||
|
|
||||||
FULL_HISTORY = false;
|
LEDGER_HISTORY = 256;
|
||||||
|
|
||||||
ACCOUNT_PROBE_MAX = 10;
|
ACCOUNT_PROBE_MAX = 10;
|
||||||
|
|
||||||
@@ -292,8 +293,16 @@ void Config::load()
|
|||||||
if (sectionSingleB(secConfig, SECTION_FEE_OPERATION, strTemp))
|
if (sectionSingleB(secConfig, SECTION_FEE_OPERATION, strTemp))
|
||||||
FEE_CONTRACT_OPERATION = boost::lexical_cast<int>(strTemp);
|
FEE_CONTRACT_OPERATION = boost::lexical_cast<int>(strTemp);
|
||||||
|
|
||||||
if (sectionSingleB(secConfig, SECTION_FULL_HISTORY, strTemp))
|
if (sectionSingleB(secConfig, SECTION_LEDGER_HISTORY, strTemp))
|
||||||
FULL_HISTORY = boost::lexical_cast<bool>(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))
|
if (sectionSingleB(secConfig, SECTION_ACCOUNT_PROBE_MAX, strTemp))
|
||||||
ACCOUNT_PROBE_MAX = boost::lexical_cast<int>(strTemp);
|
ACCOUNT_PROBE_MAX = boost::lexical_cast<int>(strTemp);
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public:
|
|||||||
int FEE_CONTRACT_OPERATION; // fee for each contract operation
|
int FEE_CONTRACT_OPERATION; // fee for each contract operation
|
||||||
|
|
||||||
// Node storage configuration
|
// Node storage configuration
|
||||||
bool FULL_HISTORY;
|
uint32 LEDGER_HISTORY;
|
||||||
|
|
||||||
// Client behavior
|
// Client behavior
|
||||||
int ACCOUNT_PROBE_MAX; // How far to scan for accounts.
|
int ACCOUNT_PROBE_MAX; // How far to scan for accounts.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ SETUP_LOG();
|
|||||||
DECLARE_INSTANCE(HashedObject);
|
DECLARE_INSTANCE(HashedObject);
|
||||||
|
|
||||||
HashedObjectStore::HashedObjectStore(int cacheSize, int cacheAge) :
|
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);
|
mWriteSet.reserve(128);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,6 +299,29 @@ SerializedTransaction::pointer Ledger::getSTransaction(SHAMapItem::ref item, SHA
|
|||||||
return SerializedTransaction::pointer();
|
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)
|
bool Ledger::getTransaction(const uint256& txID, Transaction::pointer& txn, TransactionMetaSet::pointer& meta)
|
||||||
{
|
{
|
||||||
SHAMapTreeNode::TNType type;
|
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 deleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %d;");
|
||||||
static boost::format AcctTransExists("SELECT LedgerSeq FROM AccountTransactions WHERE TransId = '%s';");
|
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 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 "
|
static boost::format addLedger("INSERT INTO Ledgers "
|
||||||
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
|
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
|
||||||
"AccountSetHash,TransSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');");
|
"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;
|
for (SHAMapItem::pointer item = txSet.peekFirstItem(type); !!item;
|
||||||
item = txSet.peekNextItem(item->getTag(), type))
|
item = txSet.peekNextItem(item->getTag(), type))
|
||||||
{
|
{
|
||||||
SerializedTransaction::pointer txn = getSTransaction(item, type);
|
assert(type == SHAMapTreeNode::tnTRANSACTION_MD);
|
||||||
assert(txn);
|
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.
|
// Make sure transaction is in AccountTransactions.
|
||||||
if (!SQL_EXISTS(db, boost::str(AcctTransExists % item->getTag().GetHex())))
|
if (!SQL_EXISTS(db, boost::str(AcctTransExists % item->getTag().GetHex())))
|
||||||
{
|
{
|
||||||
// Transaction not in AccountTransactions
|
// 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 ";
|
std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES ";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@@ -394,7 +424,7 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
|||||||
sql += "('";
|
sql += "('";
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
sql += txn->getTransactionID().GetHex();
|
sql += txn.getTransactionID().GetHex();
|
||||||
sql += "','";
|
sql += "','";
|
||||||
sql += it->humanAccountID();
|
sql += it->humanAccountID();
|
||||||
sql += "',";
|
sql += "',";
|
||||||
@@ -406,19 +436,20 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
|||||||
db->executeSQL(sql); // may already be in there
|
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
|
db->executeSQL(boost::str(updateTx
|
||||||
% getLedgerSeq()
|
% getLedgerSeq()
|
||||||
% TXN_SQL_VALIDATED
|
% TXN_SQL_VALIDATED
|
||||||
% txn->getTransactionID().GetHex()));
|
% escMeta
|
||||||
|
% txn.getTransactionID().GetHex()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Not in Transactions, insert the whole thing..
|
// Not in Transactions, insert the whole thing..
|
||||||
db->executeSQL(
|
db->executeSQL(
|
||||||
txn->getSQLInsertHeader() + txn->getSQL(getLedgerSeq(), TXN_SQL_VALIDATED) + ";");
|
txn.getMetaSQLInsertHeader() + txn.getMetaSQL(getLedgerSeq(), escMeta) + ";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db->executeSQL("COMMIT TRANSACTION;");
|
db->executeSQL("COMMIT TRANSACTION;");
|
||||||
|
|||||||
@@ -161,7 +161,10 @@ public:
|
|||||||
bool hasTransaction(const uint256& TransID) const { return mTransactionMap->hasItem(TransID); }
|
bool hasTransaction(const uint256& TransID) const { return mTransactionMap->hasItem(TransID); }
|
||||||
Transaction::pointer getTransaction(const uint256& transID) const;
|
Transaction::pointer getTransaction(const uint256& transID) const;
|
||||||
bool getTransaction(const uint256& transID, Transaction::pointer& txn, TransactionMetaSet::pointer& txMeta);
|
bool getTransaction(const uint256& transID, Transaction::pointer& txn, TransactionMetaSet::pointer& txMeta);
|
||||||
|
|
||||||
static SerializedTransaction::pointer getSTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType);
|
static SerializedTransaction::pointer getSTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType);
|
||||||
|
SerializedTransaction::pointer getSMTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType,
|
||||||
|
TransactionMetaSet::pointer& txMeta);
|
||||||
|
|
||||||
// high-level functions
|
// high-level functions
|
||||||
AccountState::pointer getAccountState(const RippleAddress& acctID);
|
AccountState::pointer getAccountState(const RippleAddress& acctID);
|
||||||
|
|||||||
@@ -644,8 +644,16 @@ void LedgerConsensus::stateAccepted()
|
|||||||
endConsensus();
|
endConsensus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern volatile bool doShutdown;
|
||||||
|
|
||||||
void LedgerConsensus::timerEntry()
|
void LedgerConsensus::timerEntry()
|
||||||
{
|
{
|
||||||
|
if (doShutdown)
|
||||||
|
{
|
||||||
|
cLog(lsFATAL) << "Shutdown requested";
|
||||||
|
theApp->stop();
|
||||||
|
}
|
||||||
|
|
||||||
if ((mState != lcsFINISHED) && (mState != lcsACCEPTED))
|
if ((mState != lcsFINISHED) && (mState != lcsACCEPTED))
|
||||||
checkLCL();
|
checkLCL();
|
||||||
|
|
||||||
|
|||||||
@@ -117,6 +117,12 @@ TER LedgerMaster::doTransaction(const SerializedTransaction& txn, TransactionEng
|
|||||||
return result;
|
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)
|
void LedgerMaster::acquireMissingLedger(const uint256& ledgerHash, uint32 ledgerSeq)
|
||||||
{
|
{
|
||||||
mMissingLedger = theApp->getMasterLedgerAcquire().findCreate(ledgerHash);
|
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);
|
boost::recursive_mutex::scoped_lock ml(mLock);
|
||||||
|
|
||||||
mCompleteLedgers.setValue(ledger->getLedgerSeq());
|
mCompleteLedgers.setValue(ledger->getLedgerSeq());
|
||||||
@@ -161,7 +178,12 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
|||||||
if ((ledger->getLedgerSeq() != 0) && mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
if ((ledger->getLedgerSeq() != 0) && mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
||||||
{ // we think we have the previous ledger, double check
|
{ // we think we have the previous ledger, double check
|
||||||
Ledger::pointer prevLedger = getLedgerBySeq(ledger->getLedgerSeq() - 1);
|
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";
|
cLog(lsWARNING) << "Ledger " << ledger->getLedgerSeq() << " invalidates prior ledger";
|
||||||
mCompleteLedgers.clearValue(prevLedger->getLedgerSeq());
|
mCompleteLedgers.clearValue(prevLedger->getLedgerSeq());
|
||||||
@@ -171,7 +193,7 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
|||||||
if (mMissingLedger && mMissingLedger->isComplete())
|
if (mMissingLedger && mMissingLedger->isComplete())
|
||||||
mMissingLedger.reset();
|
mMissingLedger.reset();
|
||||||
|
|
||||||
if (mMissingLedger || !theConfig.FULL_HISTORY)
|
if (mMissingLedger || !theConfig.LEDGER_HISTORY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Ledger::getPendingSaves() > 3)
|
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
|
// see if there's a ledger gap we need to fill
|
||||||
if (!mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
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";
|
cLog(lsINFO) << "We need the ledger before the ledger we just accepted";
|
||||||
acquireMissingLedger(ledger->getParentHash(), ledger->getLedgerSeq() - 1);
|
acquireMissingLedger(ledger->getParentHash(), ledger->getLedgerSeq() - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32 prevMissing = mCompleteLedgers.prevMissing(ledger->getLedgerSeq());
|
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";
|
cLog(lsINFO) << "Ledger " << prevMissing << " is missing";
|
||||||
assert(!mCompleteLedgers.hasValue(prevMissing));
|
assert(!mCompleteLedgers.hasValue(prevMissing));
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ public:
|
|||||||
|
|
||||||
void addHeldTransaction(const Transaction::pointer& trans);
|
void addHeldTransaction(const Transaction::pointer& trans);
|
||||||
|
|
||||||
|
bool haveLedgerRange(uint32 from, uint32 to);
|
||||||
|
|
||||||
void sweep(void) { mLedgerHistory.sweep(); }
|
void sweep(void) { mLedgerHistory.sweep(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ uint32 NetworkOPs::getCurrentLedgerID()
|
|||||||
return mLedgerMaster->getCurrentLedger()->getLedgerSeq();
|
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)
|
void NetworkOPs::submitTransaction(Job&, SerializedTransaction::pointer iTrans, stCallback callback)
|
||||||
{ // this is an asynchronous interface
|
{ // this is an asynchronous interface
|
||||||
Serializer s;
|
Serializer s;
|
||||||
@@ -876,14 +881,15 @@ void NetworkOPs::setMode(OperatingMode om)
|
|||||||
mMode = 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 =
|
std::string sql =
|
||||||
str(boost::format("SELECT LedgerSeq,TransID FROM AccountTransactions INDEXED BY AcctTxIndex "
|
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' ORDER BY LedgerSeq LIMIT 1000;")
|
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 1000) ORDER BY LedgerSeq;")
|
||||||
% account.humanAccountID() % maxLedger % minLedger);
|
% account.humanAccountID() % maxLedger % minLedger);
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -892,11 +898,24 @@ std::vector< std::pair<uint32, uint256> >
|
|||||||
|
|
||||||
SQL_FOREACH(db, sql)
|
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>
|
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)
|
void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta)
|
||||||
{
|
{
|
||||||
Json::Value jvObj = transJson(stTxn, terResult, true, lpCurrent, "transaction");
|
Json::Value jvObj = transJson(stTxn, terResult, true, lpCurrent, "transaction");
|
||||||
|
if(meta) jvObj["meta"]=meta->getJson(0);
|
||||||
|
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
|
boost::recursive_mutex::scoped_lock sl(mMonitorLock);
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ public:
|
|||||||
|
|
||||||
uint256 getClosedLedgerHash() { return mLedgerMaster->getClosedLedger()->getHash(); }
|
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; }
|
SerializedValidation::ref getLastValidation() { return mLastValidation; }
|
||||||
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
||||||
|
|
||||||
@@ -230,8 +233,8 @@ public:
|
|||||||
uint256 getConsensusLCL();
|
uint256 getConsensusLCL();
|
||||||
|
|
||||||
// client information retrieval functions
|
// client information retrieval functions
|
||||||
std::vector< std::pair<uint32, uint256> >
|
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||||
getAffectedAccounts(const RippleAddress& account, uint32 minLedger, uint32 maxLedger);
|
getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger);
|
||||||
std::vector<RippleAddress> getLedgerAffectedAccounts(uint32 ledgerSeq);
|
std::vector<RippleAddress> getLedgerAffectedAccounts(uint32 ledgerSeq);
|
||||||
std::vector<SerializedTransaction> getLedgerTransactions(uint32 ledgerSeq);
|
std::vector<SerializedTransaction> getLedgerTransactions(uint32 ledgerSeq);
|
||||||
|
|
||||||
|
|||||||
@@ -1303,25 +1303,18 @@ Json::Value RPCHandler::doAccountTransactions(const Json::Value& params)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#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);
|
Json::Value ret(Json::objectValue);
|
||||||
ret["account"] = account.humanAccountID();
|
ret["account"] = account.humanAccountID();
|
||||||
Json::Value ledgers(Json::arrayValue);
|
Json::Value ledgers(Json::arrayValue);
|
||||||
|
|
||||||
// uint32 currentLedger = 0;
|
// 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);
|
Json::Value obj(Json::objectValue);
|
||||||
if (!txn)
|
if(it->first) obj["tx"]=it->first->getJson(1);
|
||||||
{
|
if(it->second) obj["meta"]=it->second->getJson(0);
|
||||||
ret["transactions"].append(it->second.GetHex());
|
ret["transactions"].append(obj);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
txn->setLedger(it->first);
|
|
||||||
ret["transactions"].append(txn->getJson(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
|
|||||||
@@ -183,11 +183,21 @@ std::string SerializedTransaction::getSQLValueHeader()
|
|||||||
return "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn)";
|
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()
|
std::string SerializedTransaction::getSQLInsertHeader()
|
||||||
{
|
{
|
||||||
return "INSERT INTO Transactions " + getSQLValueHeader() + " VALUES ";
|
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
|
std::string SerializedTransaction::getSQL(uint32 inLedger, char status) const
|
||||||
{
|
{
|
||||||
Serializer s;
|
Serializer s;
|
||||||
@@ -195,16 +205,36 @@ std::string SerializedTransaction::getSQL(uint32 inLedger, char status) const
|
|||||||
return getSQL(s, inLedger, status);
|
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
|
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;
|
std::string rTxn;
|
||||||
theApp->getTxnDB()->getDB()->escape(
|
theApp->getTxnDB()->getDB()->escape(
|
||||||
reinterpret_cast<const unsigned char *>(rawTxn.getDataPtr()), rawTxn.getLength(), rTxn);
|
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()
|
% getTransactionID().GetHex() % getTransactionType() % getSourceAccount().humanAccountID()
|
||||||
% getSequence() % inLedger % status % rTxn);
|
% 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)
|
BOOST_AUTO_TEST_SUITE(SerializedTransactionTS)
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,12 @@ public:
|
|||||||
std::string getSQL(uint32 inLedger, char status) const;
|
std::string getSQL(uint32 inLedger, char status) const;
|
||||||
std::string getSQL(Serializer rawTxn, 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
|
#endif
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
|||||||
return tr;
|
return tr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Transaction::pointer Transaction::load(const uint256& id)
|
Transaction::pointer Transaction::load(const uint256& id)
|
||||||
{
|
{
|
||||||
std::string sql = "SELECT LedgerSeq,Status,RawTxn FROM Transactions WHERE TransID='";
|
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));
|
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>
|
template<class Iterator>
|
||||||
bool isZero(Iterator first, int iSize)
|
bool isZero(Iterator first, int iSize)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user