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

This commit is contained in:
jed
2012-10-24 09:47:22 -07:00
45 changed files with 1012 additions and 204 deletions

View File

@@ -166,8 +166,6 @@ STAmount::STAmount(SField::ref n, const Json::Value& v)
}
else
throw std::runtime_error("invalid amount type");
cLog(lsTRACE) << "Parsed: " << this->getJson(0);
}
std::string STAmount::createHumanCurrency(const uint160& uCurrency)

View File

@@ -70,8 +70,9 @@ void Application::run()
{
assert(mTxnDB == NULL);
if (!theConfig.DEBUG_LOGFILE.empty())
{
{ // Let DEBUG messages go to the file but only WARNING or higher to regular output
Log::setLogFile(theConfig.DEBUG_LOGFILE);
Log::setMinSeverity(lsWARNING);
LogPartition::setSeverity(lsDEBUG);
}
@@ -112,6 +113,13 @@ void Application::run()
else
startNewLedger();
if (theConfig.FULL_HISTORY && (theConfig.START_UP != Config::LOAD))
{
Ledger::pointer ledger = Ledger::getLastFullLedger();
if (ledger)
mMasterLedger.setLastFullLedger(ledger);
}
//
// Begin validation and ip maintenance.
// - Wallet maintains local information: including identity and network connection persistence information.
@@ -214,7 +222,7 @@ void Application::loadOldLedger()
{
try
{
Ledger::pointer lastLedger = Ledger::getSQL("SELECT * from Ledgers order by LedgerSeq desc limit 1;");
Ledger::pointer lastLedger = Ledger::getLastFullLedger();
if (!lastLedger)
{
@@ -243,6 +251,7 @@ void Application::loadOldLedger()
cLog(lsFATAL) << "Ledger is not sane.";
exit(-1);
}
mMasterLedger.setLastFullLedger(lastLedger);
Ledger::pointer openLedger = boost::make_shared<Ledger>(false, boost::ref(*lastLedger));
mMasterLedger.switchLedgers(lastLedger, openLedger);

View File

@@ -37,7 +37,7 @@ bool CanonicalTXKey::operator>=(const CanonicalTXKey& key)const
return mTXid >= key.mTXid;
}
void CanonicalTXSet::push_back(const SerializedTransaction::pointer& txn)
void CanonicalTXSet::push_back(SerializedTransaction::ref txn)
{
uint256 effectiveAccount = mSetHash;
effectiveAccount ^= txn->getSourceAccount().getAccountID().to256();

View File

@@ -38,7 +38,7 @@ protected:
public:
CanonicalTXSet(const uint256& lclHash) : mSetHash(lclHash) { ; }
void push_back(const SerializedTransaction::pointer& txn);
void push_back(SerializedTransaction::ref txn);
iterator erase(const iterator& it);
iterator begin() { return mMap.begin(); }

View File

@@ -14,6 +14,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_IPS "ips"
#define SECTION_NETWORK_QUORUM "network_quorum"
#define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water"
@@ -150,6 +151,8 @@ void Config::setup(const std::string& strConf)
FEE_DEFAULT = DEFAULT_FEE_DEFAULT;
FEE_CONTRACT_OPERATION = DEFAULT_FEE_OPERATION;
FULL_HISTORY = false;
ACCOUNT_PROBE_MAX = 10;
VALIDATORS_SITE = DEFAULT_VALIDATORS_SITE;
@@ -266,6 +269,9 @@ 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_ACCOUNT_PROBE_MAX, strTemp))
ACCOUNT_PROBE_MAX = boost::lexical_cast<int>(strTemp);

View File

@@ -102,6 +102,9 @@ public:
uint64 FEE_OFFER; // Rate per day.
int FEE_CONTRACT_OPERATION; // fee for each contract operation
// Node storage configuration
bool FULL_HISTORY;
// Client behavior
int ACCOUNT_PROBE_MAX; // How far to scan for accounts.

View File

@@ -9,7 +9,10 @@
// Functions to add CKey support for deterministic EC keys
#include <boost/test/unit_test.hpp>
#include "Serializer.h"
#include "Log.h"
// <-- seed
uint128 CKey::PassPhraseToKey(const std::string& passPhrase)
@@ -304,4 +307,34 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey(const NewcoinAddress& pubGen, cons
return pkey;
}
BOOST_AUTO_TEST_SUITE(DeterministicKeys_test)
BOOST_AUTO_TEST_CASE(DeterminsticKeys_test1)
{
Log(lsDEBUG) << "Beginning deterministic key test";
uint128 seed1, seed2;
seed1.SetHex("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex("CF0C3BE4485961858C4198515AE5B965");
CKey root1(seed1), root2(seed2);
uint256 priv1, priv2;
root1.GetPrivateKeyU(priv1);
root2.GetPrivateKeyU(priv2);
if (priv1.GetHex() != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
BOOST_FAIL("Incorrect private key for generator");
if (priv2.GetHex() != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
BOOST_FAIL("Incorrect private key for generator");
NewcoinAddress nSeed;
nSeed.setSeed(seed1);
if (nSeed.humanSeed() != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
BOOST_FAIL("Incorrect human seed");
if (nSeed.humanSeed1751() != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
BOOST_FAIL("Incorrect 1751 seed");
}
BOOST_AUTO_TEST_SUITE_END();
// vim:ts=4

View File

@@ -337,7 +337,7 @@ uint256 Ledger::getHash()
return mHash;
}
void Ledger::saveAcceptedLedger()
void Ledger::saveAcceptedLedger(bool fromConsensus)
{ // can be called in a different thread
static boost::format ledgerExists("SELECT LedgerSeq FROM Ledgers where LedgerSeq = %d;");
static boost::format deleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %d;");
@@ -428,7 +428,16 @@ void Ledger::saveAcceptedLedger()
mAccountHash.GetHex() % mTransHash.GetHex()));
}
if (!fromConsensus)
return;
theApp->getOPs().pubLedger(shared_from_this());
if(theConfig.FULL_HISTORY)
{
// WRITEME: check for seamless ledger history
}
}
Ledger::pointer Ledger::getSQL(const std::string& sql)
@@ -498,6 +507,11 @@ Ledger::pointer Ledger::loadByHash(const uint256& ledgerHash)
return getSQL(sql);
}
Ledger::pointer Ledger::getLastFullLedger()
{
return getSQL("SELECT * from Ledgers order by LedgerSeq desc limit 1;");
}
void Ledger::addJson(Json::Value& ret, int options)
{
ret["ledger"] = getJson(options);

View File

@@ -100,6 +100,7 @@ public:
Ledger(Ledger& target, bool isMutable); // snapshot
static Ledger::pointer getSQL(const std::string& sqlStatement);
static Ledger::pointer getLastFullLedger();
void updateHash();
void setClosed() { mClosed = true; }
@@ -156,7 +157,7 @@ public:
SLE::pointer getAccountRoot(const NewcoinAddress& naAccountID);
// database functions
void saveAcceptedLedger();
void saveAcceptedLedger(bool fromConsensus);
static Ledger::pointer loadByIndex(uint32 ledgerIndex);
static Ledger::pointer loadByHash(const uint256& ledgerHash);

View File

@@ -10,6 +10,8 @@
#include "SHAMapSync.h"
#include "HashPrefixes.h"
SETUP_LOG();
// #define LA_DEBUG
#define LEDGER_ACQUIRE_TIMEOUT 750
#define TRUST_NETWORK
@@ -72,7 +74,7 @@ void PeerSet::invokeOnTimer()
if (!mProgress)
{
++mTimeouts;
Log(lsWARNING) << "Timeout " << mTimeouts << " acquiring " << mHash;
cLog(lsWARNING) << "Timeout " << mTimeouts << " acquiring " << mHash;
}
else
mProgress = false;
@@ -89,10 +91,10 @@ void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::err
}
LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE_TIMEOUT),
mHaveBase(false), mHaveState(false), mHaveTransactions(false), mAborted(false), mSignaled(false)
mHaveBase(false), mHaveState(false), mHaveTransactions(false), mAborted(false), mSignaled(false), mAccept(false)
{
#ifdef LA_DEBUG
Log(lsTRACE) << "Acquiring ledger " << mHash;
cLog(lsTRACE) << "Acquiring ledger " << mHash;
#endif
}
@@ -156,7 +158,7 @@ void LedgerAcquire::done()
return;
mSignaled = true;
#ifdef LA_DEBUG
Log(lsTRACE) << "Done acquiring ledger " << mHash;
cLog(lsTRACE) << "Done acquiring ledger " << mHash;
#endif
std::vector< boost::function<void (LedgerAcquire::pointer)> > triggers;
@@ -167,7 +169,11 @@ void LedgerAcquire::done()
mLock.unlock();
if (mLedger)
{
if (mAccept)
mLedger->setAccepted();
theApp->getMasterLedger().storeLedger(mLedger);
}
for (unsigned int i = 0; i < triggers.size(); ++i)
triggers[i](shared_from_this());
@@ -185,12 +191,12 @@ void LedgerAcquire::trigger(Peer::ref peer, bool timer)
if (mAborted || mComplete || mFailed)
return;
#ifdef LA_DEBUG
if (peer) Log(lsTRACE) << "Trigger acquiring ledger " << mHash << " from " << peer->getIP();
else Log(lsTRACE) << "Trigger acquiring ledger " << mHash;
if (peer) cLog(lsTRACE) << "Trigger acquiring ledger " << mHash << " from " << peer->getIP();
else cLog(lsTRACE) << "Trigger acquiring ledger " << mHash;
if (mComplete || mFailed)
Log(lsTRACE) << "complete=" << mComplete << " failed=" << mFailed;
cLog(lsTRACE) << "complete=" << mComplete << " failed=" << mFailed;
else
Log(lsTRACE) << "base=" << mHaveBase << " tx=" << mHaveTransactions << " as=" << mHaveState;
cLog(lsTRACE) << "base=" << mHaveBase << " tx=" << mHaveTransactions << " as=" << mHaveState;
#endif
if (!mHaveBase)
{
@@ -204,7 +210,7 @@ void LedgerAcquire::trigger(Peer::ref peer, bool timer)
if (mHaveBase && !mHaveTransactions)
{
#ifdef LA_DEBUG
Log(lsTRACE) << "need tx";
cLog(lsTRACE) << "need tx";
#endif
assert(mLedger);
if (mLedger->peekTransactionMap()->getHash().isZero())
@@ -248,7 +254,7 @@ void LedgerAcquire::trigger(Peer::ref peer, bool timer)
if (mHaveBase && !mHaveState)
{
#ifdef LA_DEBUG
Log(lsTRACE) << "need as";
cLog(lsTRACE) << "need as";
#endif
assert(mLedger);
if (mLedger->peekAccountStateMap()->getHash().isZero())
@@ -326,18 +332,41 @@ void PeerSet::sendRequest(const ripple::TMGetLedger& tmGL)
}
}
int PeerSet::takePeerSetFrom(const PeerSet& s)
{
int ret = 0;
mPeers.clear();
mPeers.reserve(s.mPeers.size());
BOOST_FOREACH(const boost::weak_ptr<Peer>& p, s.mPeers)
if (p.lock())
{
mPeers.push_back(p);
++ret;
}
return ret;
}
int PeerSet::getPeerCount() const
{
int ret = 0;
BOOST_FOREACH(const boost::weak_ptr<Peer>& p, mPeers)
if (p.lock())
++ret;
return ret;
}
bool LedgerAcquire::takeBase(const std::string& data)
{ // Return value: true=normal, false=bad data
#ifdef LA_DEBUG
Log(lsTRACE) << "got base acquiring ledger " << mHash;
cLog(lsTRACE) << "got base acquiring ledger " << mHash;
#endif
boost::recursive_mutex::scoped_lock sl(mLock);
if (mHaveBase) return true;
mLedger = boost::make_shared<Ledger>(data);
if (mLedger->getHash() != mHash)
{
Log(lsWARNING) << "Acquire hash mismatch";
Log(lsWARNING) << mLedger->getHash() << "!=" << mHash;
cLog(lsWARNING) << "Acquire hash mismatch";
cLog(lsWARNING) << mLedger->getHash() << "!=" << mHash;
mLedger = Ledger::pointer();
#ifdef TRUST_NETWORK
assert(false);
@@ -396,7 +425,7 @@ bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
const std::list< std::vector<unsigned char> >& data)
{
#ifdef LA_DEBUG
Log(lsTRACE) << "got ASdata acquiring ledger " << mHash;
cLog(lsTRACE) << "got ASdata acquiring ledger " << mHash;
#endif
if (!mHaveBase) return false;
std::list<SHAMapNode>::const_iterator nodeIDit = nodeIDs.begin();
@@ -479,7 +508,7 @@ void LedgerAcquireMaster::dropLedger(const uint256& hash)
bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref peer)
{
#ifdef LA_DEBUG
Log(lsTRACE) << "got data for acquiring ledger ";
cLog(lsTRACE) << "got data for acquiring ledger ";
#endif
uint256 hash;
if (packet.ledgerhash().size() != 32)
@@ -489,7 +518,7 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
}
memcpy(hash.begin(), packet.ledgerhash().data(), 32);
#ifdef LA_DEBUG
Log(lsTRACE) << hash;
cLog(lsTRACE) << hash;
#endif
LedgerAcquire::pointer ledger = find(hash);
@@ -509,7 +538,7 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
}
if (!ledger->takeAsRootNode(strCopy(packet.nodes(1).nodedata())))
{
Log(lsWARNING) << "Included ASbase invalid";
cLog(lsWARNING) << "Included ASbase invalid";
}
if (packet.nodes().size() == 2)
{
@@ -517,7 +546,9 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
return true;
}
if (!ledger->takeTxRootNode(strCopy(packet.nodes(2).nodedata())))
Log(lsWARNING) << "Invcluded TXbase invalid";
{
cLog(lsWARNING) << "Invcluded TXbase invalid";
}
ledger->trigger(peer, false);
return true;
}
@@ -548,4 +579,108 @@ bool LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer::ref
return false;
}
LedgerAcquireSet::LedgerAcquireSet(Ledger::ref targetLedger, Ledger::ref currentLedger) :
mTargetLedger(targetLedger), mCheckComplete(true)
{
updateCurrentLedger(currentLedger);
}
void LedgerAcquireSet::updateCurrentLedger(Ledger::pointer currentLedger)
{ // We have 'currentLedger', what do we need to acquire next
while (1)
{
if ((currentLedger->getHash() == mTargetLedger->getHash()) ||
(currentLedger->getParentHash() == mTargetLedger->getHash()))
{ // We have completed acquiring the set
done();
return;
}
while (mTargetLedger->getLedgerSeq() >= currentLedger->getLedgerSeq())
{ // We need to back up our target
mTargetLedger = theApp->getMasterLedger().getLedgerByHash(mTargetLedger->getParentHash());
if (!mTargetLedger)
{
cLog(lsWARNING) << "LedgerAcquireSet encountered a non-present target ledger";
done();
return;
}
}
Ledger::pointer nextLedger =
theApp->getMasterLedger().getLedgerByHash(currentLedger->getParentHash());
if (nextLedger && mCheckComplete && !nextLedger->walkLedger())
{
cLog(lsINFO) << "Acquire set has encountered a ledger that is missing nodes";
nextLedger = Ledger::pointer();
}
if (!nextLedger)
{ // the next ledger we need is missing or missing nodes
LedgerAcquire::pointer nextAcquire =
theApp->getMasterLedgerAcquire().findCreate(currentLedger->getParentHash());
nextAcquire->setAccept();
if (mCurrentLedger)
nextAcquire->takePeerSetFrom(*mCurrentLedger);
mCurrentLedger = nextAcquire;
if (!mCurrentLedger->getPeerCount())
addPeers();
mCurrentLedger->addOnComplete(boost::bind(
&LedgerAcquireSet::onComplete, boost::weak_ptr<LedgerAcquireSet>(shared_from_this()), _1));
return;
}
currentLedger = nextLedger;
}
}
void LedgerAcquireSet::onComplete(boost::weak_ptr<LedgerAcquireSet> set, LedgerAcquire::pointer acquired)
{
LedgerAcquireSet::pointer lSet = set.lock();
if (!lSet)
return;
if (acquired->isComplete())
{
Ledger::pointer ledger = acquired->getLedger();
ledger->setAccepted();
lSet->updateCurrentLedger(ledger);
}
else
{
cLog(lsWARNING) << "Bailing on LedgerAcquireSet due to failure to acquire a ledger";
lSet->done();
}
}
void LedgerAcquireSet::done()
{
theApp->getMasterLedgerAcquire().killSet(*this);
}
void LedgerAcquireSet::addPeers()
{
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
const uint256& hash = mCurrentLedger->getHash();
bool found = false;
BOOST_FOREACH(Peer::ref peer, peerList)
{
if (peer->hasLedger(hash))
{
found = true;
mCurrentLedger->peerHas(peer);
}
}
if (!found)
{
BOOST_FOREACH(Peer::ref peer, peerList)
mCurrentLedger->peerHas(peer);
}
}
// vim:ts=4

View File

@@ -45,6 +45,9 @@ public:
void badPeer(Peer::ref);
void resetTimer();
int takePeerSetFrom(const PeerSet& s);
int getPeerCount() const;
protected:
virtual void newPeer(Peer::ref) = 0;
virtual void onTimer(void) = 0;
@@ -65,7 +68,7 @@ public:
protected:
Ledger::pointer mLedger;
bool mHaveBase, mHaveState, mHaveTransactions, mAborted, mSignaled;
bool mHaveBase, mHaveState, mHaveTransactions, mAborted, mSignaled, mAccept;
std::vector< boost::function<void (LedgerAcquire::pointer)> > mOnComplete;
@@ -85,6 +88,7 @@ public:
bool isTransComplete() const { return mHaveTransactions; }
Ledger::pointer getLedger() { return mLedger; }
void abort() { mAborted = true; }
void setAccept() { mAccept = true; }
void addOnComplete(boost::function<void (LedgerAcquire::pointer)>);
@@ -97,11 +101,32 @@ public:
bool tryLocal();
};
class LedgerAcquireSet : public boost::enable_shared_from_this<LedgerAcquireSet>
{ // a sequence of ledgers we are retreiving
public:
typedef boost::shared_ptr<LedgerAcquireSet> pointer;
protected:
Ledger::pointer mTargetLedger; // ledger we have and want to get back to
LedgerAcquire::pointer mCurrentLedger; // ledger we are acquiring
bool mCheckComplete; // should we check to make sure we have all nodes
void updateCurrentLedger(Ledger::pointer currentLedger);
void done();
void addPeers();
static void onComplete(boost::weak_ptr<LedgerAcquireSet>, LedgerAcquire::pointer);
public:
LedgerAcquireSet(Ledger::ref targetLedger, Ledger::ref currentLedger);
};
class LedgerAcquireMaster
{
protected:
boost::mutex mLock;
std::map<uint256, LedgerAcquire::pointer> mLedgers;
LedgerAcquireSet::pointer mAcquireSet;
public:
LedgerAcquireMaster() { ; }
@@ -111,6 +136,11 @@ public:
bool hasLedger(const uint256& ledgerHash);
void dropLedger(const uint256& ledgerHash);
bool gotLedgerData(ripple::TMLedgerData& packet, Peer::ref);
void killSet(const LedgerAcquireSet&)
{ mAcquireSet = LedgerAcquireSet::pointer(); }
void makeSet(Ledger::ref target, Ledger::ref current)
{ mAcquireSet = boost::make_shared<LedgerAcquireSet>(boost::ref(target), boost::ref(current)); }
};
#endif

View File

@@ -993,7 +993,7 @@ void LedgerConsensus::playbackProposals()
}
}
void LedgerConsensus::applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn,
void LedgerConsensus::applyTransaction(TransactionEngine& engine, SerializedTransaction::ref txn,
Ledger::ref ledger, CanonicalTXSet& failedTransactions, bool openLedger)
{
TransactionEngineParams parms = openLedger ? tapOPEN_LEDGER : tapNONE;

View File

@@ -134,7 +134,7 @@ protected:
void sendHaveTxSet(const uint256& set, bool direct);
void applyTransactions(SHAMap::ref transactionSet, Ledger::ref targetLedger,
Ledger::ref checkLedger, CanonicalTXSet& failedTransactions, bool openLgr);
void applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn,
void applyTransaction(TransactionEngine& engine, SerializedTransaction::ref txn,
Ledger::ref targetLedger, CanonicalTXSet& failedTransactions, bool openLgr);
uint32 roundCloseTime(uint32 closeTime);

View File

@@ -65,8 +65,8 @@ public:
void init(Ledger::ref ledger, const uint256& transactionID, uint32 ledgerID);
void clear();
Ledger::pointer& getLedger() { return mLedger; }
const Ledger::pointer& getLedgerRef() const { return mLedger; }
Ledger::pointer& getLedger() { return mLedger; }
Ledger::ref getLedgerRef() const { return mLedger; }
// basic entry functions
SLE::pointer getEntry(const uint256& index, LedgerEntryAction&);

View File

@@ -26,7 +26,7 @@ void LedgerHistory::addLedger(Ledger::pointer ledger)
mLedgersByHash.canonicalize(ledger->getHash(), ledger, true);
}
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger, bool fromConsensus)
{
assert(ledger && ledger->isAccepted());
uint256 h(ledger->getHash());
@@ -37,7 +37,7 @@ void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
assert(ledger->isImmutable());
mLedgersByIndex.insert(std::make_pair(ledger->getLedgerSeq(), ledger));
boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, ledger));
boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, ledger, fromConsensus));
thread.detach();
}

View File

@@ -13,7 +13,7 @@ public:
LedgerHistory();
void addLedger(Ledger::pointer ledger);
void addAcceptedLedger(Ledger::pointer ledger);
void addAcceptedLedger(Ledger::pointer ledger, bool fromConsensus);
Ledger::pointer getLedgerBySeq(uint32 index);
Ledger::pointer getLedgerByHash(const uint256& hash);

View File

@@ -32,6 +32,8 @@ void LedgerMaster::pushLedger(Ledger::ref newLedger)
mFinalizedLedger = mCurrentLedger;
mCurrentLedger = newLedger;
mEngine.setLedger(newLedger);
if (mLastFullLedger && (newLedger->getParentHash() == mLastFullLedger->getHash()))
mLastFullLedger = newLedger;
}
void LedgerMaster::pushLedger(Ledger::ref newLCL, Ledger::ref newOL)
@@ -43,7 +45,9 @@ void LedgerMaster::pushLedger(Ledger::ref newLCL, Ledger::ref newOL)
{
assert(newLCL->isClosed());
assert(newLCL->isImmutable());
mLedgerHistory.addAcceptedLedger(newLCL);
mLedgerHistory.addAcceptedLedger(newLCL, false);
if (mLastFullLedger && (newLCL->getParentHash() == mLastFullLedger->getHash()))
mLastFullLedger = newLCL;
Log(lsINFO) << "StashAccepted: " << newLCL->getHash();
}
@@ -68,6 +72,8 @@ void LedgerMaster::switchLedgers(Ledger::ref lastClosed, Ledger::ref current)
void LedgerMaster::storeLedger(Ledger::ref ledger)
{
mLedgerHistory.addLedger(ledger);
if (ledger->isAccepted())
mLedgerHistory.addAcceptedLedger(ledger, false);
}

View File

@@ -20,6 +20,7 @@ class LedgerMaster
Ledger::pointer mCurrentLedger; // The ledger we are currently processiong
Ledger::pointer mFinalizedLedger; // The ledger that most recently closed
Ledger::pointer mLastFullLedger; // We have history to this point
LedgerHistory mLedgerHistory;
@@ -49,6 +50,11 @@ public:
void pushLedger(Ledger::ref newLCL, Ledger::ref newOL);
void storeLedger(Ledger::ref);
void setLastFullLedger(Ledger::ref ledger)
{
mLastFullLedger = ledger;
}
void switchLedgers(Ledger::ref lastClosed, Ledger::ref newCurrent);
Ledger::pointer closeLedger();

View File

@@ -496,7 +496,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
ValidationCount& ourVC = ledgers[closedLedger];
if ((theConfig.LEDGER_CREATOR) && (mMode >= omTRACKING))
if (mMode >= omTRACKING)
{
++ourVC.nodesUsing;
uint160 ourAddress = theApp->getWallet().getNodePublic().getNodeID();
@@ -638,7 +638,7 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger, bool duringCo
theApp->getConnectionPool().relayMessage(NULL, packet);
}
int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger)
int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::ref closingLedger)
{
cLog(lsINFO) << "Consensus time for ledger " << closingLedger->getLedgerSeq();
cLog(lsINFO) << " LCL is " << closingLedger->getParentHash();
@@ -864,7 +864,7 @@ std::vector<NewcoinAddress>
bool NetworkOPs::recvValidation(const SerializedValidation::pointer& val)
{
cLog(lsINFO) << "recvValidation " << val->getLedgerHash();
cLog(lsDEBUG) << "recvValidation " << val->getLedgerHash();
return theApp->getValidations().addValidation(val);
}

View File

@@ -181,7 +181,7 @@ public:
void checkState(const boost::system::error_code& result);
void switchLastClosedLedger(Ledger::pointer newLedger, bool duringConsensus); // Used for the "jump" case
bool checkLastClosedLedger(const std::vector<Peer::pointer>&, uint256& networkClosed);
int beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger);
int beginConsensus(const uint256& networkClosed, Ledger::ref closingLedger);
void endConsensus(bool correctLCL);
void setStandAlone() { setMode(omFULL); }
void setStateTimer();

View File

@@ -1053,25 +1053,22 @@ void Peer::recvGetLedger(ripple::TMGetLedger& packet)
ledger->addRaw(nData);
reply.add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength());
if (packet.nodeids().size() != 0)
{ // new-style root request
cLog(lsINFO) << "Ledger root w/map roots request";
SHAMap::pointer map = ledger->peekAccountStateMap();
if (map && map->getHash().isNonZero())
{ // return account state root node if possible
Serializer rootNode(768);
if (map->getRootNode(rootNode, snfWIRE))
cLog(lsINFO) << "Ledger root w/map roots request";
SHAMap::pointer map = ledger->peekAccountStateMap();
if (map && map->getHash().isNonZero())
{ // return account state root node if possible
Serializer rootNode(768);
if (map->getRootNode(rootNode, snfWIRE))
{
reply.add_nodes()->set_nodedata(rootNode.getDataPtr(), rootNode.getLength());
if (ledger->getTransHash().isNonZero())
{
reply.add_nodes()->set_nodedata(rootNode.getDataPtr(), rootNode.getLength());
if (ledger->getTransHash().isNonZero())
map = ledger->peekTransactionMap();
if (map && map->getHash().isNonZero())
{
map = ledger->peekTransactionMap();
if (map && map->getHash().isNonZero())
{
rootNode.resize(0);
if (map->getRootNode(rootNode, snfWIRE))
reply.add_nodes()->set_nodedata(rootNode.getDataPtr(), rootNode.getLength());
}
rootNode.resize(0);
if (map->getRootNode(rootNode, snfWIRE))
reply.add_nodes()->set_nodedata(rootNode.getDataPtr(), rootNode.getLength());
}
}
}

View File

@@ -27,7 +27,7 @@ std::size_t hash_value(const aciSource& asValue)
// <-- uOfferIndex : 0=end of list.
TER RippleCalc::calcNodeAdvance(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality,
const bool bReverse)
{
@@ -267,7 +267,7 @@ TER RippleCalc::calcNodeAdvance(
// Continue process till request is satisified while we the rate does not increase past the initial rate.
TER RippleCalc::calcNodeDeliverRev(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality,
const uint160& uOutAccountID, // --> Output owner's account.
const STAmount& saOutReq, // --> Funds wanted.
@@ -459,7 +459,7 @@ TER RippleCalc::calcNodeDeliverRev(
// Goal: Make progress consuming the offer.
TER RippleCalc::calcNodeDeliverFwd(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality,
const uint160& uInAccountID, // --> Input owner's account.
const STAmount& saInFunds, // --> Funds available for delivery and fees.
@@ -610,7 +610,7 @@ TER RippleCalc::calcNodeDeliverFwd(
// Called to drive from the last offer node in a chain.
TER RippleCalc::calcNodeOfferRev(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality)
{
TER terResult;
@@ -650,7 +650,7 @@ TER RippleCalc::calcNodeOfferRev(
// - Deliver is set without transfer fees.
TER RippleCalc::calcNodeOfferFwd(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality
)
{
@@ -789,7 +789,7 @@ void RippleCalc::calcNodeRipple(
// Calculate saPrvRedeemReq, saPrvIssueReq, saPrvDeliver from saCur...
// <-- tesSUCCESS or tepPATH_DRY
TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality)
{
TER terResult = tesSUCCESS;
const unsigned int uLast = pspCur->vpnNodes.size() - 1;
@@ -1100,7 +1100,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
// - Output to next node is computed as input minus quality or transfer fee.
TER RippleCalc::calcNodeAccountFwd(
const unsigned int uIndex, // 0 <= uIndex <= uLast
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality)
{
TER terResult = tesSUCCESS;
@@ -1362,7 +1362,7 @@ TER RippleCalc::calcNodeAccountFwd(
}
// Return true, iff lhs has less priority than rhs.
bool PathState::lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs)
bool PathState::lessPriority(PathState::ref lhs, PathState::ref rhs)
{
if (lhs->uQuality != rhs->uQuality)
return lhs->uQuality > rhs->uQuality; // Bigger is worse.
@@ -1713,7 +1713,7 @@ Json::Value PathState::getJson() const
return jvPathState;
}
TER RippleCalc::calcNodeFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
TER RippleCalc::calcNodeFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality)
{
const PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
@@ -1743,7 +1743,7 @@ TER RippleCalc::calcNodeFwd(const unsigned int uIndex, const PathState::pointer&
// --> [all]saWanted.mCurrency
// --> [all]saAccount
// <-> [0]saWanted.mAmount : --> limit, <-- actual
TER RippleCalc::calcNodeRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
TER RippleCalc::calcNodeRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality)
{
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
@@ -1785,7 +1785,7 @@ TER RippleCalc::calcNodeRev(const unsigned int uIndex, const PathState::pointer&
// Calculate the next increment of a path.
// The increment is what can satisfy a portion or all of the requested output at the best quality.
// <-- pspCur->uQuality
void RippleCalc::pathNext(const PathState::pointer& pspCur, const int iPaths, const LedgerEntrySet& lesCheckpoint, LedgerEntrySet& lesCurrent)
void RippleCalc::pathNext(PathState::ref pspCur, const int iPaths, const LedgerEntrySet& lesCheckpoint, LedgerEntrySet& lesCurrent)
{
// The next state is what is available in preference order.
// This is calculated when referenced accounts changed.

View File

@@ -65,13 +65,14 @@ extern std::size_t hash_value(const aciSource& asValue);
class PathState
{
protected:
const Ledger::pointer& mLedger;
Ledger::ref mLedger;
TER pushNode(const int iType, const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID);
TER pushImply(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID);
public:
typedef boost::shared_ptr<PathState> pointer;
typedef boost::shared_ptr<PathState> pointer;
typedef const boost::shared_ptr<PathState>& ref;
TER terStatus;
std::vector<PaymentNode> vpnNodes;
@@ -123,7 +124,7 @@ public:
return boost::make_shared<PathState>(iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax);
}
static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs);
static bool lessPriority(PathState::ref lhs, PathState::ref rhs);
};
class RippleCalc
@@ -139,18 +140,18 @@ public:
boost::unordered_set<uint256> musUnfundedFound; // Offers that were found unfunded.
PathState::pointer pathCreate(const STPath& spPath);
void pathNext(const PathState::pointer& pspCur, const int iPaths, const LedgerEntrySet& lesCheckpoint, LedgerEntrySet& lesCurrent);
TER calcNode(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeOfferRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeOfferFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeAccountRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeAccountFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeAdvance(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality, const bool bReverse);
void pathNext(PathState::ref pspCur, const int iPaths, const LedgerEntrySet& lesCheckpoint, LedgerEntrySet& lesCurrent);
TER calcNode(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeOfferRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeOfferFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeAccountRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeAccountFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
TER calcNodeAdvance(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality, const bool bReverse);
TER calcNodeDeliverRev(
const unsigned int uIndex,
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality,
const uint160& uOutAccountID,
const STAmount& saOutReq,
@@ -158,7 +159,7 @@ public:
TER calcNodeDeliverFwd(
const unsigned int uIndex,
const PathState::pointer& pspCur,
PathState::ref pspCur,
const bool bMultiQuality,
const uint160& uInAccountID,
const STAmount& saInFunds,

View File

@@ -7,9 +7,9 @@
SETUP_LOG();
RippleLines::RippleLines(const uint160& accountID, Ledger::pointer ledger)
RippleLines::RippleLines(const uint160& accountID, Ledger::ref ledger)
{
fillLines(accountID,ledger);
fillLines(accountID, ledger);
}
void RippleLines::printRippleLines()
@@ -25,7 +25,7 @@ RippleLines::RippleLines(const uint160& accountID )
fillLines(accountID,theApp->getMasterLedger().getCurrentLedger());
}
void RippleLines::fillLines(const uint160& accountID, Ledger::pointer ledger)
void RippleLines::fillLines(const uint160& accountID, Ledger::ref ledger)
{
uint256 rootIndex = Ledger::getOwnerDirIndex(accountID);
uint256 currentIndex = rootIndex;

View File

@@ -9,12 +9,12 @@ It provides a vector so you to easily iterate through them
class RippleLines
{
std::vector<RippleState::pointer> mLines;
void fillLines(const uint160& accountID, Ledger::pointer ledger);
void fillLines(const uint160& accountID, Ledger::ref ledger);
public:
RippleLines(const uint160& accountID, Ledger::pointer ledger);
RippleLines(const uint160& accountID, Ledger::ref ledger);
RippleLines(const uint160& accountID ); // looks in the current ledger
std::vector<RippleState::pointer>& getLines(){ return(mLines); }
std::vector<RippleState::pointer>& getLines() { return(mLines); }
void printRippleLines();
};

View File

@@ -208,7 +208,7 @@ public:
bool hasItem() const { return !!mItem; }
SHAMapItem::ref peekItem() { return mItem; }
SHAMapItem::pointer getItem() const;
bool setItem(const SHAMapItem::pointer& i, TNType type);
bool setItem(SHAMapItem::ref i, TNType type);
const uint256& getTag() const { return mItem->getTag(); }
const std::vector<unsigned char>& peekData() { return mItem->peekData(); }
std::vector<unsigned char> getData() const { return mItem->getData(); }

View File

@@ -185,7 +185,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapN
memcpy(mHashes, node.mHashes, sizeof(mHashes));
}
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, const SHAMapItem::pointer& item, TNType type, uint32 seq) :
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::ref item, TNType type, uint32 seq) :
SHAMapNode(node), mItem(item), mSeq(seq), mType(type), mFullBelow(true)
{
assert(item->peekData().size() >= 12);
@@ -465,7 +465,7 @@ void SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format)
assert(false);
}
bool SHAMapTreeNode::setItem(const SHAMapItem::pointer& i, TNType type)
bool SHAMapTreeNode::setItem(SHAMapItem::ref i, TNType type)
{
uint256 hash = getNodeHash();
mType = type;

View File

@@ -164,7 +164,8 @@ bool STObject::setType(const std::vector<SOElement::ptr> &type)
{
if (elem->flags != SOE_OPTIONAL)
{
cLog(lsWARNING) << "setType !valid missing " << elem->e_field.fieldName;
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid missing "
<< elem->e_field.fieldName;
valid = false;
}
newData.push_back(makeNonPresentObject(elem->e_field));
@@ -178,7 +179,8 @@ bool STObject::setType(const std::vector<SOElement::ptr> &type)
{
if (!t.getFName().isDiscardable())
{
cLog(lsWARNING) << "setType !valid leftover: " << t.getFName().getName();
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid leftover "
<< t.getFName().getName();
valid = false;
}
}
@@ -792,6 +794,42 @@ Json::Value STObject::getJson(int options) const
return ret;
}
bool STObject::operator==(const STObject& obj) const
{ // This is not particularly efficient, and only compares data elements with binary representations
int matches = 0;
BOOST_FOREACH(const SerializedType& t, mData)
if ((t.getSType() != STI_NOTPRESENT) && t.getFName().isBinary())
{ // each present field must have a matching field
bool match = false;
BOOST_FOREACH(const SerializedType& t2, obj.mData)
if (t.getFName() == t2.getFName())
{
if (t2 != t)
return false;
match = true;
++matches;
break;
}
if (!match)
{
Log(lsTRACE) << "STObject::operator==: no match for " << t.getFName().getName();
return false;
}
}
int fields = 0;
BOOST_FOREACH(const SerializedType& t2, obj.mData)
if ((t2.getSType() != STI_NOTPRESENT) && t2.getFName().isBinary())
++fields;
if (fields != matches)
{
Log(lsTRACE) << "STObject::operator==: " << fields << " fields, " << matches << " matches";
return false;
}
return true;
}
Json::Value STVector256::getJson(int options) const
{
Json::Value ret(Json::arrayValue);
@@ -1246,7 +1284,6 @@ BOOST_AUTO_TEST_CASE( FieldManipulation_test )
if (object1.getFieldVL(sfTestVL) != j) BOOST_FAIL("STObject error");
if (object3.getFieldVL(sfTestVL) != j) BOOST_FAIL("STObject error");
}
}
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -148,6 +148,9 @@ public:
{ return makeDefaultObject(STI_NOTPRESENT, name); }
static std::auto_ptr<SerializedType> makeDefaultObject(SField::ref name)
{ return makeDefaultObject(name.fieldType, name); }
bool operator==(const STObject& o) const;
bool operator!=(const STObject& o) const { return ! (*this == o); }
};
class STArray : public SerializedType

View File

@@ -25,7 +25,6 @@ SerializedTransaction::SerializedTransaction(const STObject& object) : STObject(
throw std::runtime_error("invalid transaction type");
if (!setType(mFormat->elements))
{
assert(false);
throw std::runtime_error("transaction not valid");
}
}
@@ -203,8 +202,8 @@ BOOST_AUTO_TEST_CASE( STrans_test )
NewcoinAddress seed;
seed.setSeedRandom();
NewcoinAddress generator = NewcoinAddress::createGeneratorPublic(seed);
NewcoinAddress publicAcct = NewcoinAddress::createAccountPublic(generator, 1);
NewcoinAddress privateAcct = NewcoinAddress::createAccountPrivate(generator, seed, 1);
NewcoinAddress publicAcct = NewcoinAddress::createAccountPublic(generator, 1);
NewcoinAddress privateAcct = NewcoinAddress::createAccountPrivate(generator, seed, 1);
SerializedTransaction j(ttCLAIM);
j.setSourceAccount(publicAcct);
@@ -224,10 +223,15 @@ BOOST_AUTO_TEST_CASE( STrans_test )
Log(lsFATAL) << copy.getJson(0);
BOOST_FAIL("Transaction fails serialize/deserialize test");
}
Log(lsINFO) << "ORIG: " << j.getJson(0);
std::auto_ptr<STObject> new_obj = STObject::parseJson(j.getJson(0), sfGeneric);
if (new_obj.get() == NULL) BOOST_FAIL("Unable to build object from json");
Log(lsINFO) << "BUILT " << new_obj->getJson(0);
if (STObject(j) != *new_obj)
{
Log(lsINFO) << "ORIG: " << j.getJson(0);
Log(lsINFO) << "BUILT " << new_obj->getJson(0);
BOOST_FAIL("Built a different transaction");
}
}
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -20,7 +20,8 @@
class SerializedTransaction : public STObject
{
public:
typedef boost::shared_ptr<SerializedTransaction> pointer;
typedef boost::shared_ptr<SerializedTransaction> pointer;
typedef const boost::shared_ptr<SerializedTransaction>& ref;
protected:
TransactionType mType;

View File

@@ -13,7 +13,7 @@
#include "SerializedTransaction.h"
#include "Log.h"
Transaction::Transaction(const SerializedTransaction::pointer& sit, bool bValidate)
Transaction::Transaction(SerializedTransaction::ref sit, bool bValidate)
: mInLedger(0), mStatus(INVALID), mResult(temUNCERTAIN), mTransaction(sit)
{
try
@@ -709,8 +709,8 @@ bool Transaction::convertToTransactions(uint32 firstLedgerSeq, uint32 secondLedg
for(it = inMap.begin(); it != inMap.end(); ++it)
{
const uint256& id = it->first;
const SHAMapItem::pointer& first = it->second.first;
const SHAMapItem::pointer& second = it->second.second;
SHAMapItem::ref first = it->second.first;
SHAMapItem::ref second = it->second.second;
Transaction::pointer firstTrans, secondTrans;
if (!!first)

View File

@@ -1,6 +1,11 @@
#ifndef __TRANSACTION__
#define __TRANSACTION__
//
// Notes: this code contains legacy constructored sharedXYZ and setXYZ. The intent is for these functions to go away. Transactions
// should now be constructed in JSON with. Use STObject::parseJson to obtain a binary version.
//
#include <vector>
#include <boost/shared_ptr.hpp>
@@ -129,7 +134,7 @@ private:
const std::vector<unsigned char>& vucSignature);
public:
Transaction(const SerializedTransaction::pointer& st, bool bValidate);
Transaction(SerializedTransaction::ref st, bool bValidate);
static Transaction::pointer sharedTransaction(const std::vector<unsigned char>&vucTransaction, bool bValidate);
static Transaction::pointer transactionFromSQL(Database* db, bool bValidate);

View File

@@ -31,7 +31,7 @@ Transaction::pointer TransactionMaster::fetch(const uint256& txnID, bool checkDi
return txn;
}
SerializedTransaction::pointer TransactionMaster::fetch(const SHAMapItem::pointer& item, bool checkDisk, uint32 uCommitLedger)
SerializedTransaction::pointer TransactionMaster::fetch(SHAMapItem::ref item, bool checkDisk, uint32 uCommitLedger)
{
SerializedTransaction::pointer txn;
Transaction::pointer iTx = theApp->getMasterTransaction().fetch(item->getTag(), false);

View File

@@ -16,7 +16,7 @@ public:
TransactionMaster();
Transaction::pointer fetch(const uint256&, bool checkDisk);
SerializedTransaction::pointer fetch(const SHAMapItem::pointer& item, bool checkDisk, uint32 uCommitLedger);
SerializedTransaction::pointer fetch(SHAMapItem::ref item, bool checkDisk, uint32 uCommitLedger);
// return value: true = we had the transaction already
bool canonicalize(Transaction::pointer& txn, bool maybeNew);

View File

@@ -1017,7 +1017,18 @@ void WSConnection::doSubmit(Json::Value& jvResult, const Json::Value& jvRequest)
sopTrans->setFieldVL(sfSigningPubKey, naAccountPublic.getAccountPublic());
SerializedTransaction::pointer stpTrans = boost::make_shared<SerializedTransaction>(*sopTrans);
SerializedTransaction::pointer stpTrans;
try
{
stpTrans = boost::make_shared<SerializedTransaction>(*sopTrans);
}
catch (std::exception& e)
{
jvResult["error"] = "invalidTransaction";
jvResult["error_exception"] = e.what();
return;
}
stpTrans->sign(naAccountPrivate);

View File

@@ -245,15 +245,20 @@ message TMGetLedger {
optional uint32 requestCookie = 6;
}
enum TMReplyError {
reNO_LEDGER = 1; // We don't have the ledger you are asking about
reNO_NODE = 2; // We don't have any of the nodes you are asking for
}
message TMLedgerData {
required bytes ledgerHash = 1;
required uint32 ledgerSeq = 2;
required TMLedgerInfoType type = 3;
repeated TMLedgerNode nodes = 4;
optional uint32 requestCookie = 5;
optional TMReplyError error = 6;
}
message TMPing {
enum pingType {
PING = 0; // we want a reply