diff --git a/src/AccountState.cpp b/src/AccountState.cpp index 5e56bd9965..1f84c9dce9 100644 --- a/src/AccountState.cpp +++ b/src/AccountState.cpp @@ -10,12 +10,12 @@ #include "Ledger.h" #include "Serializer.h" -AccountState::AccountState(const NewcoinAddress& id) : mAccountID(id), mValid(false) +AccountState::AccountState(const NewcoinAddress& id) : mValid(false) { if (!id.isValid()) return; mLedgerEntry = boost::make_shared(ltACCOUNT_ROOT); mLedgerEntry->setIndex(Ledger::getAccountRootIndex(id)); - mLedgerEntry->setIFieldAccount(sfAccount, id); + mValid = true; } @@ -23,9 +23,8 @@ AccountState::AccountState(SerializedLedgerEntry::pointer ledgerEntry) : mLedger { if (!mLedgerEntry) return; if (mLedgerEntry->getType() != ltACCOUNT_ROOT) return; - mAccountID = mLedgerEntry->getIValueFieldAccount(sfAccount); - if (mAccountID.isValid()) - mValid = true; + + mValid = true; } std::string AccountState::createGravatarUrl(uint128 uEmailHash) diff --git a/src/AccountState.h b/src/AccountState.h index d51898e5dd..b2e5a0c95a 100644 --- a/src/AccountState.h +++ b/src/AccountState.h @@ -21,7 +21,6 @@ public: typedef boost::shared_ptr pointer; private: - NewcoinAddress mAccountID; NewcoinAddress mAuthorizedKey; SerializedLedgerEntry::pointer mLedgerEntry; @@ -41,7 +40,6 @@ public: return mLedgerEntry->getIValueFieldAccount(sfAuthorizedKey); } - const NewcoinAddress& getAccountID() const { return mAccountID; } STAmount getBalance() const { return mLedgerEntry->getIValueFieldAmount(sfBalance); } uint32 getSeq() const { return mLedgerEntry->getIFieldU32(sfSequence); } diff --git a/src/Application.cpp b/src/Application.cpp index af3b17f9a0..2fe18c161f 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -95,13 +95,14 @@ void Application::run() // // Set up UNL. // - getUNL().nodeBootstrap(); + if (!theConfig.RUN_STANDALONE) + getUNL().nodeBootstrap(); // // Allow peer connections. // - if (!theConfig.PEER_IP.empty() && theConfig.PEER_PORT) + if (!theConfig.RUN_STANDALONE && !theConfig.PEER_IP.empty() && theConfig.PEER_PORT) { mPeerDoor = new PeerDoor(mIOService); } @@ -127,7 +128,8 @@ void Application::run() // // Begin connecting to network. // - mConnectionPool.start(); + if (!theConfig.RUN_STANDALONE) + mConnectionPool.start(); // New stuff. NewcoinAddress rootSeedMaster = NewcoinAddress::createSeedGeneric("masterpassphrase"); @@ -155,7 +157,14 @@ void Application::run() } - mNetOps.setStateTimer(); + if (theConfig.RUN_STANDALONE) + { + Log(lsWARNING) << "Running in standalone mode"; + mNetOps.setStandAlone(); + mMasterLedger.runStandAlone(); + } + else + mNetOps.setStateTimer(); mIOService.run(); // This blocks diff --git a/src/Config.cpp b/src/Config.cpp index cf9c135bfe..4e36f39a1b 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -150,6 +150,8 @@ void Config::setup(const std::string& strConf) VALIDATORS_SITE = DEFAULT_VALIDATORS_SITE; + RUN_STANDALONE = false; + load(); } diff --git a/src/Config.h b/src/Config.h index 585980b92b..89fb60b3de 100644 --- a/src/Config.h +++ b/src/Config.h @@ -63,6 +63,7 @@ public: int LEDGER_PROPOSAL_DELAY_SECONDS; int LEDGER_AVALANCHE_SECONDS; bool LEDGER_CREATOR; // should be false unless we are starting a new ledger + bool RUN_STANDALONE; // Note: The following parameters do not relate to the UNL or trust at all unsigned int NETWORK_QUORUM; // Minimum number of nodes to consider the network present diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp index 2a7f38bb7e..3d79fbc2ad 100644 --- a/src/ConnectionPool.cpp +++ b/src/ConnectionPool.cpp @@ -42,6 +42,9 @@ ConnectionPool::ConnectionPool(boost::asio::io_service& io_service) : void ConnectionPool::start() { + if (theConfig.RUN_STANDALONE) + return; + // Start running policy. policyEnforce(); @@ -243,6 +246,8 @@ void ConnectionPool::relayMessage(Peer* fromPeer, PackedMessage::pointer msg) // Requires sane IP and port. void ConnectionPool::connectTo(const std::string& strIp, int iPort) { + if (theConfig.RUN_STANDALONE) + return; { Database* db = theApp->getWalletDB()->getDB(); ScopedLock sl(theApp->getWalletDB()->getDBLock()); diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index 6e13a883c8..d2189e693f 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -11,14 +11,16 @@ #include "HashPrefixes.h" // #define LA_DEBUG -#define LEDGER_ACQUIRE_TIMEOUT 1 +#define LEDGER_ACQUIRE_TIMEOUT 750 #define TRUST_NETWORK PeerSet::PeerSet(const uint256& hash, int interval) : mHash(hash), mTimerInterval(interval), mTimeouts(0), mComplete(false), mFailed(false), mProgress(true), mTimer(theApp->getIOService()) -{ ; } +{ + assert((mTimerInterval > 10) && (mTimerInterval < 30000)); +} -void PeerSet::peerHas(Peer::pointer ptr) +void PeerSet::peerHas(const Peer::pointer& ptr) { boost::recursive_mutex::scoped_lock sl(mLock); std::vector< boost::weak_ptr >::iterator it = mPeers.begin(); @@ -38,7 +40,7 @@ void PeerSet::peerHas(Peer::pointer ptr) newPeer(ptr); } -void PeerSet::badPeer(Peer::pointer ptr) +void PeerSet::badPeer(const Peer::pointer& ptr) { boost::recursive_mutex::scoped_lock sl(mLock); std::vector< boost::weak_ptr >::iterator it = mPeers.begin(); @@ -61,7 +63,7 @@ void PeerSet::badPeer(Peer::pointer ptr) void PeerSet::resetTimer() { - mTimer.expires_from_now(boost::posix_time::seconds(mTimerInterval)); + mTimer.expires_from_now(boost::posix_time::milliseconds(mTimerInterval)); mTimer.async_wait(boost::bind(&PeerSet::TimerEntry, pmDowncast(), boost::asio::placeholders::error)); } @@ -140,7 +142,7 @@ void LedgerAcquire::addOnComplete(boost::function mLock.unlock(); } -void LedgerAcquire::trigger(Peer::pointer peer, bool timer) +void LedgerAcquire::trigger(const Peer::pointer& peer, bool timer) { if (mAborted || mComplete || mFailed) return; @@ -433,7 +435,7 @@ void LedgerAcquireMaster::dropLedger(const uint256& hash) mLedgers.erase(hash); } -bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer peer) +bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, const Peer::pointer& peer) { #ifdef LA_DEBUG Log(lsTRACE) << "got data for acquiring ledger "; diff --git a/src/LedgerAcquire.h b/src/LedgerAcquire.h index 1497ca41ad..3ea334bd10 100644 --- a/src/LedgerAcquire.h +++ b/src/LedgerAcquire.h @@ -41,12 +41,12 @@ public: void progress() { mProgress = true; } - void peerHas(Peer::pointer); - void badPeer(Peer::pointer); + void peerHas(const Peer::pointer&); + void badPeer(const Peer::pointer&); void resetTimer(); protected: - virtual void newPeer(Peer::pointer) = 0; + virtual void newPeer(const Peer::pointer&) = 0; virtual void onTimer(void) = 0; virtual boost::weak_ptr pmDowncast() = 0; @@ -72,7 +72,7 @@ protected: void done(); void onTimer(); - void newPeer(Peer::pointer peer) { trigger(peer, false); } + void newPeer(const Peer::pointer& peer) { trigger(peer, false); } boost::weak_ptr pmDowncast(); @@ -92,7 +92,7 @@ public: bool takeTxRootNode(const std::vector& data); bool takeAsNode(const std::list& IDs, const std::list >& data); bool takeAsRootNode(const std::vector& data); - void trigger(Peer::pointer, bool timer); + void trigger(const Peer::pointer&, bool timer); }; class LedgerAcquireMaster @@ -108,7 +108,7 @@ public: LedgerAcquire::pointer find(const uint256& hash); bool hasLedger(const uint256& ledgerHash); void dropLedger(const uint256& ledgerHash); - bool gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer); + bool gotLedgerData(newcoin::TMLedgerData& packet, const Peer::pointer&); }; #endif diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index aba77ea75f..2b45f3b8c4 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -13,11 +13,13 @@ #include "Log.h" #include "SHAMapSync.h" +#define TX_ACQUIRE_TIMEOUT 250 + #define TRUST_NETWORK // #define LC_DEBUG -TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mHaveRoot(false) +TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, TX_ACQUIRE_TIMEOUT), mHaveRoot(false) { mMap = boost::make_shared(); mMap->setSynching(); @@ -39,7 +41,7 @@ boost::weak_ptr TransactionAcquire::pmDowncast() return boost::shared_polymorphic_downcast(shared_from_this()); } -void TransactionAcquire::trigger(Peer::pointer peer, bool timer) +void TransactionAcquire::trigger(const Peer::pointer& peer, bool timer) { if (mComplete || mFailed) return; @@ -664,6 +666,7 @@ void LedgerConsensus::startAcquiring(TransactionAcquire::pointer acquire) } } } + acquire->resetTimer(); } void LedgerConsensus::propose(const std::vector& added, const std::vector& removed) diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 7e104a43b7..cadfb23acd 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -27,11 +27,11 @@ protected: SHAMap::pointer mMap; bool mHaveRoot; - void onTimer() { trigger(Peer::pointer(), true); } - void newPeer(Peer::pointer peer) { trigger(peer, false); } + void onTimer() { trigger(Peer::pointer(), true); } + void newPeer(const Peer::pointer& peer) { trigger(peer, false); } void done(); - void trigger(Peer::pointer, bool timer); + void trigger(const Peer::pointer&, bool timer); boost::weak_ptr pmDowncast(); public: diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index a43ea72bf3..390cec2301 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -20,7 +20,7 @@ LedgerEntrySet LedgerEntrySet::duplicate() const return LedgerEntrySet(mEntries, mSet, mSeq + 1); } -void LedgerEntrySet::setTo(LedgerEntrySet& e) +void LedgerEntrySet::setTo(const LedgerEntrySet& e) { mEntries = e.mEntries; mSet = e.mSet; @@ -61,7 +61,7 @@ LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const return it->second.mAction; } -void LedgerEntrySet::entryCache(SLE::pointer& sle) +void LedgerEntrySet::entryCache(const SLE::pointer& sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -82,7 +82,7 @@ void LedgerEntrySet::entryCache(SLE::pointer& sle) } } -void LedgerEntrySet::entryCreate(SLE::pointer& sle) +void LedgerEntrySet::entryCreate(const SLE::pointer& sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -112,7 +112,7 @@ void LedgerEntrySet::entryCreate(SLE::pointer& sle) } } -void LedgerEntrySet::entryModify(SLE::pointer& sle) +void LedgerEntrySet::entryModify(const SLE::pointer& sle) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) @@ -147,7 +147,7 @@ void LedgerEntrySet::entryModify(SLE::pointer& sle) } } -void LedgerEntrySet::entryDelete(SLE::pointer& sle, bool unfunded) +void LedgerEntrySet::entryDelete(const SLE::pointer& sle, bool unfunded) { boost::unordered_map::iterator it = mEntries.find(sle->getIndex()); if (it == mEntries.end()) diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index a6784d946d..0980d094b3 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -23,7 +23,7 @@ public: LedgerEntryAction mAction; int mSeq; - LedgerEntrySetEntry(SLE::pointer e, LedgerEntryAction a, int s) : mEntry(e), mAction(a), mSeq(s) { ; } + LedgerEntrySetEntry(const SLE::pointer& e, LedgerEntryAction a, int s) : mEntry(e), mAction(a), mSeq(s) { ; } }; @@ -42,7 +42,7 @@ public: // set functions LedgerEntrySet duplicate() const; // Make a duplicate of this set - void setTo(LedgerEntrySet&); // Set this set to have the same contents as another + void setTo(const LedgerEntrySet&); // Set this set to have the same contents as another void swapWith(LedgerEntrySet&); // Swap the contents of two sets int getSeq() const { return mSeq; } @@ -53,10 +53,10 @@ public: // basic entry functions SLE::pointer getEntry(const uint256& index, LedgerEntryAction&); LedgerEntryAction hasEntry(const uint256& index) const; - void entryCache(SLE::pointer&); // Add this entry to the cache - void entryCreate(SLE::pointer&); // This entry will be created - void entryDelete(SLE::pointer&, bool unfunded); - void entryModify(SLE::pointer&); // This entry will be modified + void entryCache(const SLE::pointer&); // Add this entry to the cache + void entryCreate(const SLE::pointer&); // This entry will be created + void entryDelete(const SLE::pointer&, bool unfunded); + void entryModify(const SLE::pointer&); // This entry will be modified Json::Value getJson(int) const; void addRawMeta(Serializer&); diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index 8cc358b58c..5b031ffc99 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -7,7 +7,6 @@ LedgerEntryFormat LedgerFormats[]= { { "AccountRoot", ltACCOUNT_ROOT, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, { S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 }, { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, { S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 }, diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index 9f9603f1bc..187aaeec13 100644 --- a/src/LedgerMaster.h +++ b/src/LedgerMaster.h @@ -43,6 +43,8 @@ public: // The finalized ledger is the last closed/accepted ledger Ledger::pointer getClosedLedger() { return mFinalizedLedger; } + void runStandAlone() { mFinalizedLedger = mCurrentLedger; } + TransactionEngineResult doTransaction(const SerializedTransaction& txn, uint32 targetLedger, TransactionEngineParams params); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index c09d427e55..35ae4c4063 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -324,7 +324,7 @@ public: void NetworkOPs::checkState(const boost::system::error_code& result) { // Network state machine - if (result == boost::asio::error::operation_aborted) + if ((result == boost::asio::error::operation_aborted) || theConfig.RUN_STANDALONE) return; setStateTimer(); @@ -669,15 +669,15 @@ void NetworkOPs::setMode(OperatingMode om) if (mMode == om) return; if ((om >= omCONNECTED) && (mMode == omDISCONNECTED)) mConnectTime = boost::posix_time::second_clock::universal_time(); - Log l((om < mMode) ? lsWARNING : lsINFO); + Log lg((om < mMode) ? lsWARNING : lsINFO); if (om == omDISCONNECTED) - l << "STATE->Disonnected"; + lg << "STATE->Disconnected"; else if (om == omCONNECTED) - l << "STATE->Connected"; + lg << "STATE->Connected"; else if (om == omTRACKING) - l << "STATE->Tracking"; + lg << "STATE->Tracking"; else - l << "STATE->Full"; + lg << "STATE->Full"; mMode = om; } diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index e631685bc0..52e1329f8d 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -174,6 +174,7 @@ public: bool checkLastClosedLedger(const std::vector&, uint256& networkClosed); int beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger); void endConsensus(bool correctLCL); + void setStandAlone() { setMode(omFULL); } void setStateTimer(); void newLCL(int proposers, int convergeTime, const uint256& ledgerHash); int getPreviousProposers() { return mLastCloseProposers; } diff --git a/src/Peer.cpp b/src/Peer.cpp index 9b88610265..7ef797a98a 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -260,7 +260,7 @@ void Peer::connected(const boost::system::error_code& error) } } -void Peer::sendPacketForce(PackedMessage::pointer packet) +void Peer::sendPacketForce(const PackedMessage::pointer& packet) { if (!mDetaching) { @@ -273,7 +273,7 @@ void Peer::sendPacketForce(PackedMessage::pointer packet) } } -void Peer::sendPacket(PackedMessage::pointer packet) +void Peer::sendPacket(const PackedMessage::pointer& packet) { if (packet) { diff --git a/src/Peer.h b/src/Peer.h index 13cf6b79bc..01c5863714 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -30,7 +30,7 @@ public: static const int psbNoLedgers = 4, psbNoTransactions = 5, psbDownLevel = 6; void handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it); - static void sHandleConnect(Peer::pointer ptr, const boost::system::error_code& error, + static void sHandleConnect(const Peer::pointer& ptr, const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it) { ptr->handleConnect(error, it); } @@ -52,11 +52,11 @@ private: boost::asio::deadline_timer mVerifyTimer; void handleStart(const boost::system::error_code& ecResult); - static void sHandleStart(Peer::pointer ptr, const boost::system::error_code& ecResult) + static void sHandleStart(const Peer::pointer& ptr, const boost::system::error_code& ecResult) { ptr->handleStart(ecResult); } void handleVerifyTimer(const boost::system::error_code& ecResult); - static void sHandleVerifyTimer(Peer::pointer ptr, const boost::system::error_code& ecResult) + static void sHandleVerifyTimer(const Peer::pointer& ptr, const boost::system::error_code& ecResult) { ptr->handleVerifyTimer(ecResult); } protected: @@ -70,26 +70,26 @@ protected: Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx); void handleShutdown(const boost::system::error_code& error) { ; } - static void sHandleShutdown(Peer::pointer ptr, const boost::system::error_code& error) + static void sHandleShutdown(const Peer::pointer& ptr, const boost::system::error_code& error) { ptr->handleShutdown(error); } void handle_write(const boost::system::error_code& error, size_t bytes_transferred); - static void sHandle_write(Peer::pointer ptr, const boost::system::error_code& error, size_t bytes_transferred) + static void sHandle_write(const Peer::pointer& ptr, const boost::system::error_code& error, size_t bytes_transferred) { ptr->handle_write(error, bytes_transferred); } void handle_read_header(const boost::system::error_code& error); - static void sHandle_read_header(Peer::pointer ptr, const boost::system::error_code& error) + static void sHandle_read_header(const Peer::pointer& ptr, const boost::system::error_code& error) { ptr->handle_read_header(error); } void handle_read_body(const boost::system::error_code& error); - static void sHandle_read_body(Peer::pointer ptr, const boost::system::error_code& error) + static void sHandle_read_body(const Peer::pointer& ptr, const boost::system::error_code& error) { ptr->handle_read_body(error); } void processReadBuffer(); void start_read_header(); void start_read_body(unsigned msg_len); - void sendPacketForce(PackedMessage::pointer packet); + void sendPacketForce(const PackedMessage::pointer& packet); void sendHello(); @@ -139,12 +139,12 @@ public: void connect(const std::string strIp, int iPort); void connected(const boost::system::error_code& error); void detach(const char *); - bool samePeer(Peer::pointer p) { return samePeer(*p); } - bool samePeer(const Peer& p) { return this == &p; } + bool samePeer(const Peer::pointer& p) { return samePeer(*p); } + bool samePeer(const Peer& p) { return this == &p; } - void sendPacket(PackedMessage::pointer packet); - void sendLedgerProposal(Ledger::pointer ledger); - void sendFullLedger(Ledger::pointer ledger); + void sendPacket(const PackedMessage::pointer& packet); + void sendLedgerProposal(const Ledger::pointer& ledger); + void sendFullLedger(const Ledger::pointer& ledger); void sendGetFullLedger(uint256& hash); void sendGetPeers(); @@ -153,11 +153,6 @@ public: Json::Value getJson(); bool isConnected() const { return mHelloed && !mDetaching; } - //static PackedMessage::pointer createFullLedger(Ledger::pointer ledger); - static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger); - static PackedMessage::pointer createValidation(Ledger::pointer ledger); - static PackedMessage::pointer createGetFullLedger(uint256& hash); - uint256 getClosedLedgerHash() const { return mClosedLedgerHash; } bool hasLedger(const uint256& hash) const; NewcoinAddress getNodePublic() const { return mNodePublic; } diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index db22f72683..d2ce4c0127 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -833,6 +833,9 @@ Json::Value RPCServer::doAccountWalletSet(const Json::Value& params) { Json::Value RPCServer::doConnect(const Json::Value& params) { + if (theConfig.RUN_STANDALONE) + return "cannot connect in standalone mode"; + // connect [port] std::string strIp; int iPort = -1; diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 41bcafc33d..63977102ca 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -342,6 +342,7 @@ public: static STAmount multiply(const STAmount& v1, const STAmount& v2, const uint160& currencyOut); // Someone is offering X for Y, what is the rate? + // Rate: smaller is better, the taker wants the most out: in/out static uint64 getRate(const STAmount& offerOut, const STAmount& offerIn); static STAmount setRate(uint64 rate, const uint160& currencyOut); diff --git a/src/Transaction.cpp b/src/Transaction.cpp index d600bfefae..da778890c3 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -500,7 +500,7 @@ Transaction::pointer Transaction::setPayment( mTransaction->setITFieldAccount(sfDestination, naDstAccountID); mTransaction->setITFieldAmount(sfAmount, saAmount); - if (saAmount != saSendMax) + if (saAmount != saSendMax || saAmount.getCurrency() != saSendMax.getCurrency()) { mTransaction->setITFieldAmount(sfSendMax, saSendMax); } diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index d95b0bb198..70695407b8 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -70,7 +70,6 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std { terBAD_LEDGER, "terBAD_LEDGER", "Ledger in unexpected state." }, { terBAD_RIPPLE, "terBAD_RIPPLE", "No ripple path can be satisfied." }, { terBAD_SEQ, "terBAD_SEQ", "This sequence number should be zero for prepaid transactions." }, - { terCREATED, "terCREATED", "Can not create a previously created account." }, { terDIR_FULL, "terDIR_FULL", "Can not add entry to full dir." }, { terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." }, { terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee" }, @@ -819,7 +818,7 @@ SLE::pointer TransactionEngine::entryCache(LedgerEntryType letType, const uint25 mOrigNodes.entryCache(sleEntry); // So the metadata code can compare to the original } } - else if(action == taaDELETE) + else if (action == taaDELETE) assert(false); } @@ -3166,7 +3165,7 @@ PathState::PathState( STAmount saSendMax, bool bPartialPayment ) - : mIndex(iIndex), uQuality(0), bDirty(true) + : mIndex(iIndex), uQuality(0) { lesEntries = lesSource.duplicate(); @@ -3183,6 +3182,59 @@ PathState::PathState( pushNode(STPathElement::typeAccount, uReceiverID, saOutReq.getCurrency(), saOutReq.getIssuer()); } +Json::Value PathState::getJson() const +{ + Json::Value jvPathState(Json::arrayValue); + Json::Value jvNodes(Json::arrayValue); + + BOOST_FOREACH(const paymentNode& pnNode, vpnNodes) + { + Json::Value jvNode(Json::objectValue); + + Json::Value jvFlags(Json::objectValue); + + if (pnNode.uFlags & STPathElement::typeRedeem) + jvFlags["redeem"] = 1; + + if (pnNode.uFlags & STPathElement::typeIssue) + jvFlags["issue"] = 1; + + jvNode["flags"] = jvFlags; + + if (pnNode.uFlags & STPathElement::typeAccount) + jvNode["account"] = NewcoinAddress::createHumanAccountID(pnNode.uAccountID); + + if (!!pnNode.uCurrencyID) + jvNode["currency"] = STAmount::createHumanCurrency(pnNode.uCurrencyID); + + if (!!pnNode.uIssuerID) + jvNode["issuer"] = NewcoinAddress::createHumanAccountID(pnNode.uIssuerID); + + jvNodes.append(jvNode); + } + + jvPathState["nodes"] = jvNodes; + + jvPathState["index"] = mIndex; + + if (!!saInReq) + jvPathState["in_req"] = saInReq.getJson(0); + + if (!!saOutReq) + jvPathState["in_act"] = saInAct.getJson(0); + + if (!!saOutReq) + jvPathState["out_req"] = saOutReq.getJson(0); + + if (!!saOutAct) + jvPathState["out_act"] = saOutAct.getJson(0); + + if (uQuality) + jvPathState["uQuality"] = Json::Value::UInt(uQuality); + + return jvNodes; +} + // Calculate a node and its previous nodes. // From the destination work towards the source calculating how much must be asked for. // --> bAllowPartial: If false, fail if can't meet requirements. @@ -3222,6 +3274,8 @@ bool TransactionEngine::calcNode(unsigned int uIndex, PathState::pointer pspCur, } // 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 TransactionEngine::pathNext(PathState::pointer pspCur, int iPaths) { // The next state is what is available in preference order. @@ -3229,17 +3283,15 @@ void TransactionEngine::pathNext(PathState::pointer pspCur, int iPaths) unsigned int uLast = pspCur->vpnNodes.size() - 1; - if (!calcNode(uLast, pspCur, iPaths == 1)) - { - // Mark path as inactive. - pspCur->uQuality = 0; - pspCur->bDirty = false; - } -} + Log(lsINFO) << "Path In: " << pspCur->getJson(); -// Apply an increment of the path, then calculate the next increment. -void TransactionEngine::pathApply(PathState::pointer pspCur) -{ + bool bZero = !calcNode(uLast, pspCur, iPaths == 1); + + pspCur->uQuality = bZero + ? STAmount::getRate(pspCur->saOutAct, pspCur->saInAct) // Calculate relative quality. + : 0; // Mark path as inactive. + + Log(lsINFO) << "Path Out: " << pspCur->getJson(); } // XXX Need to audit for things like setting accountID not having memory. @@ -3280,6 +3332,14 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction return tenREDUNDANT; } + else if (bMax + && ((saMaxAmount == saDstAmount && saMaxAmount.getCurrency() == saDstAmount.getCurrency()) + || (saDstAmount.isNative() && saMaxAmount.isNative()))) + { + Log(lsINFO) << "doPayment: Invalid transaction: bad SendMax."; + + return tenINVALID; + } SLE::pointer sleDst = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID)); if (!sleDst) @@ -3302,22 +3362,14 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction // Create the account. sleDst = entryCreate(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID)); - sleDst->setIFieldAccount(sfAccount, uDstAccountID); sleDst->setIFieldU32(sfSequence, 1); } - // Destination exists. - else if (bCreate) - { - // Retryable: if account created this ledger, reordering might allow account to be made by this transaction. - Log(lsINFO) << "doPayment: Invalid transaction: Account already created."; - - return terCREATED; - } else { entryModify(sleDst); } + // XXX Should bMax be sufficient to imply ripple? bool bRipple = bPaths || bMax || !saDstAmount.isNative(); if (!bRipple) @@ -3343,9 +3395,12 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction // Ripple payment // +#if 0 +// Disabled to make sure full ripple code is correct. // Try direct ripple first. if (!bNoRippleDirect && mTxnAccountID != uDstAccountID && uSrcCurrency == uDstCurrency) { + // XXX Does not handle quality. SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uDstCurrency)); if (sleRippleState) @@ -3425,16 +3480,18 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction return terSUCCESS; } } +#endif STPathSet spsPaths = txn.getITFieldPathSet(sfPaths); - if (!spsPaths.isEmpty()) + if (bNoRippleDirect && spsPaths.isEmpty()) { - Log(lsINFO) << "doPayment: Invalid transaction: No paths."; + Log(lsINFO) << "doPayment: Invalid transaction: No paths and direct ripple not allowed."; return tenRIPPLE_EMPTY; } - else if (spsPaths.getPathCount() > RIPPLE_PATHS_MAX) + + if (spsPaths.getPathCount() > RIPPLE_PATHS_MAX) { return tenBAD_PATH_COUNT; } @@ -3442,6 +3499,21 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction // Incrementally search paths. std::vector vpsPaths; + if (!bNoRippleDirect) + { + // Direct path. + vpsPaths.push_back(PathState::createPathState( + vpsPaths.size(), + mNodes, + STPath(), + uDstAccountID, + mTxnAccountID, + saDstAmount, + saMaxAmount, + bPartialPayment + )); + } + BOOST_FOREACH(const STPath& spPath, spsPaths) { vpsPaths.push_back(PathState::createPathState( @@ -3464,48 +3536,30 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction while (tenUNKNOWN == terResult) { PathState::pointer pspBest; + LedgerEntrySet lesCheckpoint; + + mNodes.swapWith(lesCheckpoint); // Checkpoint ledger prior to path application. // Find the best path. BOOST_FOREACH(PathState::pointer pspCur, vpsPaths) { - if (pspCur->bDirty) - { - pspCur->bDirty = false; - pspCur->lesEntries = mNodes.duplicate(); + mNodes.setTo(lesCheckpoint.duplicate()); // Vary ledger from checkpoint. - // XXX Compute increment - pathNext(pspCur, vpsPaths.size()); - } + pathNext(pspCur, vpsPaths.size()); // Compute increment + + mNodes.swapWith(pspCur->lesEntries); // For the path, save ledger state. if (!pspBest || (pspCur->uQuality && PathState::lessPriority(pspBest, pspCur))) pspBest = pspCur; } - if (!pspBest) + if (pspBest) { - // - // Apply path. - // + // Apply best path. - // Install changes for path. + // Install ledger for best past. mNodes.swapWith(pspBest->lesEntries); - // Mark that path as dirty. - pspBest->bDirty = true; - - // Mark as dirty any other path that intersected. - BOOST_FOREACH(PathState::pointer& pspOther, vpsPaths) - { - // Look for intersection of best and the others. - // - Will forget the intersection applied. - // - Anything left will not interfere with it. - // - Will remember the non-intersection non-applied for future consideration. - if (!pspOther->bDirty - && pspOther->uQuality - && LedgerEntrySet::intersect(pspBest->lesEntries, pspOther->lesEntries)) - pspOther->bDirty = true; - } - // Figure out if done. if (tenUNKNOWN == terResult && saPaid == saWanted) { @@ -3521,8 +3575,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction else if (saPaid.isZero()) { // Nothing claimed. - terResult = terPATH_EMPTY; // XXX No effect except unfundeds and charge fee. - // XXX + terResult = terPATH_EMPTY; // XXX No effect except unfundeds and charge fee. } else { @@ -3581,7 +3634,6 @@ TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransacti // Create the account. sleDst = entryCreate(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID)); - sleDst->setIFieldAccount(sfAccount, uDstAccountID); sleDst->setIFieldU32(sfSequence, 1); sleDst->setIFieldAmount(sfBalance, saAmount); sleDst->setIFieldAccount(sfAuthorizedKey, uAuthKeyID); diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 832f09e5e0..7bb68509e0 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -139,7 +139,6 @@ public: STAmount saInAct; // Amount spent by sender (calc output) STAmount saOutReq; // Amount to send (calc input) STAmount saOutAct; // Amount actually sent (calc output). - bool bDirty; // Path not computed. PathState( int iIndex, @@ -152,6 +151,8 @@ public: bool bPartialPayment ); + Json::Value getJson() const; + static PathState::pointer createPathState( int iIndex, const LedgerEntrySet& lesSource, @@ -188,14 +189,6 @@ private: bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex); bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex); -#ifdef WORK_IN_PROGRESS - - typedef struct { - std::vector vpnNodes; - bool bAllowPartial; - } paymentGroup; -#endif - TransactionEngineResult setAuthorized(const SerializedTransaction& txn, bool bMustSetGenerator); TransactionEngineResult takeOffers( @@ -240,7 +233,6 @@ protected: STAmount accountFunds(const uint160& uAccountID, const STAmount& saDefault); PathState::pointer pathCreate(const STPath& spPath); - void pathApply(PathState::pointer pspCur); void pathNext(PathState::pointer pspCur, int iPaths); bool calcNode(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality); bool calcNodeOfferRev(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality); diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index 1502e4b52d..1bb971c576 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -7,7 +7,7 @@ // #define VC_DEBUG -bool ValidationCollection::addValidation(SerializedValidation::pointer& val) +bool ValidationCollection::addValidation(const SerializedValidation::pointer& val) { NewcoinAddress signer = val->getSignerPublic(); bool isCurrent = false; diff --git a/src/ValidationCollection.h b/src/ValidationCollection.h index 1ed522dc54..bdd224a040 100644 --- a/src/ValidationCollection.h +++ b/src/ValidationCollection.h @@ -17,7 +17,7 @@ class ValidationPair public: SerializedValidation::pointer oldest, newest; - ValidationPair(SerializedValidation::pointer v) : newest(v) { ; } + ValidationPair(const SerializedValidation::pointer& v) : newest(v) { ; } }; class ValidationCollection @@ -38,7 +38,7 @@ protected: public: ValidationCollection() : mWriting(false) { ; } - bool addValidation(SerializedValidation::pointer&); + bool addValidation(const SerializedValidation::pointer&); ValidationSet getValidations(const uint256& ledger); void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted); diff --git a/src/main.cpp b/src/main.cpp index 155408170a..444231ba3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -93,6 +93,7 @@ int main(int argc, char* argv[]) ("help,h", "Display this message.") ("conf", po::value(), "Specify the configuration file.") ("rpc", "Perform rpc command (default).") + ("standalone,a", "Run with no peers.") ("test,t", "Perform unit tests.") ("parameters", po::value< vector >(), "Specify comma separated parameters.") ("verbose,v", "Increase log level") @@ -145,6 +146,11 @@ int main(int argc, char* argv[]) if (!iResult) { theConfig.setup(vm.count("conf") ? vm["conf"].as() : ""); + + if (vm.count("standalone")) + { + theConfig.RUN_STANDALONE = true; + } } if (iResult)