From 639ba9dfcbf6cbfffa0d5c12493b25e629950c0b Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 15 Dec 2011 01:19:50 -0800 Subject: [PATCH] NetworkOPs layer Begin coding the 'NetworkOPs' layer. This will provide most of the functions 'client' code will want to call such as functions to lookup transactions, check on their status, get balances, and so on. Much of the RPC layer will be a thin wrapper over these functions. The purpose of this layer is to permit the node to support these functions regardless of its operating mode or available data, as long as it's connected to the network. If synchronized and tracking the current ledger, it can do most functions locally. If not, it can ask for help from other nodes. If hopeless, it can return an error code. --- Application.h | 12 ++++-- LedgerMaster.cpp | 6 ++- LedgerMaster.h | 3 +- Makefile | 2 +- NetworkOPs.cpp | 101 +++++++++++++++++++++++++++++++++++++++++++++++ NetworkOPs.h | 49 +++++++++++++++++++++++ 6 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 NetworkOPs.cpp create mode 100644 NetworkOPs.h diff --git a/Application.h b/Application.h index c6dd5b0f8d..5a14abe5d5 100644 --- a/Application.h +++ b/Application.h @@ -10,6 +10,7 @@ #include "LedgerMaster.h" #include "Wallet.h" #include "Peer.h" +#include "NetworkOPs.h" #include "database/database.h" #include @@ -19,10 +20,12 @@ class PeerDoor; class Application { + NetworkOPs mNetOps; + Wallet mWallet; + TimingService mTimingService; UniqueNodeList mUNL; KnownNodeList mKnownNodes; - Wallet mWallet; PubKeyCache mPKCache; LedgerMaster mMasterLedger; Database* mDatabase; @@ -41,11 +44,12 @@ class Application public: Application(); - ConnectionPool& getConnectionPool() { return(mConnectionPool); } + ConnectionPool& getConnectionPool() { return mConnectionPool; } - UniqueNodeList& getUNL() { return(mUNL); } + UniqueNodeList& getUNL() { return mUNL; } - Wallet& getWallet() { return(mWallet); } + Wallet& getWallet() { return mWallet ; } + NetworkOPs& getOPs() { return mNetOps; } PubKeyCache& getPubKeyCache() { return mPKCache; } diff --git a/LedgerMaster.cpp b/LedgerMaster.cpp index 85b65984c8..e22bef6e29 100644 --- a/LedgerMaster.cpp +++ b/LedgerMaster.cpp @@ -24,9 +24,11 @@ uint64 LedgerMaster::getBalance(std::string& addr) return mCurrentLedger->getBalance(humanTo160(addr)); } -bool LedgerMaster::addTransaction(Transaction::pointer transaction) +bool LedgerMaster::addHeldTransaction(Transaction::pointer transaction) { - return mCurrentLedger->applyTransaction(transaction)==Ledger::TR_SUCCESS; + boost::recursive_mutex::scoped_lock ml(mLock); + if(!mHeldTransactionsByID[transaction->getID()]) + mHeldTransactionsByID[transaction->getID()]=transaction; } void LedgerMaster::pushLedger(Ledger::pointer newLedger) diff --git a/LedgerMaster.h b/LedgerMaster.h index 2f2a554618..4988fbf8fa 100644 --- a/LedgerMaster.h +++ b/LedgerMaster.h @@ -22,7 +22,6 @@ class LedgerMaster LedgerHistory mLedgerHistory; std::map mHeldTransactionsByID; - std::map mHeldTransactionsByLedger; void applyFutureTransactions(uint32 ledgerIndex); bool isValidTransaction(Transaction::pointer trans); @@ -60,7 +59,7 @@ public: AccountState::pointer getAccountState(const uint160& addr) { return mCurrentLedger->getAccountState(addr); } - bool addTransaction(Transaction::pointer trans); + bool addHeldTransaction(Transaction::pointer trans); }; #endif diff --git a/Makefile b/Makefile index 9d0ff21cf7..912e844d10 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ SRCS= keystore.cpp BitcoinUtil.cpp \ Application.cpp TimingService.cpp KnownNodeList.cpp ConnectionPool.cpp Peer.cpp \ PeerDoor.cpp RPCDoor.cpp RPCServer.cpp rpc.cpp Conversion.cpp RequestParser.cpp HashedObject.cpp \ UniqueNodeList.cpp PubKeyCache.cpp SHAMapDiff.cpp DeterministicKeys.cpp LedgerMaster.cpp \ - LedgerHistory.cpp + LedgerHistory.cpp NetworkOPs.cpp DBSRCS= SqliteDatabase.cpp database.cpp diff --git a/NetworkOPs.cpp b/NetworkOPs.cpp new file mode 100644 index 0000000000..864ad6494c --- /dev/null +++ b/NetworkOPs.cpp @@ -0,0 +1,101 @@ + +#include "Application.h" +#include "NetworkOPs.h" +#include "Transaction.h" + +// This is the primary interface into the "client" portion of the program. +// Code that wants to do normal operations on the network such as +// creating and monitoring accounts, creating transactions, and so on +// should use this interface. The RPC code will primarily be a light wrapper +// over this code. + +// Eventually, it will check the node's operating mode (synched, unsynched, +// etectera) and defer to the correct means of processing. The current +// code assumes this node is synched (and will continue to do so until +// there's a functional network. + +uint64 NetworkOPs::getNetworkTime() +{ + return time(NULL); +} + +uint32 NetworkOPs::getCurrentLedgerID() +{ + return theApp->getMasterLedger().getCurrentLedger()->getLedgerSeq(); +} + +Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans) +{ + Transaction::pointer dbtx=Transaction::load(trans->getID()); + if(dbtx) return dbtx; + + if(!trans->checkSign()) + { + trans->setStatus(INVALID); + return trans; + } + + Ledger::TransResult r=theApp->getMasterLedger().getCurrentLedger()->applyTransaction(trans); + if(r==Ledger::TR_ERROR) throw Fault(IO_ERROR); + + if((r==Ledger::TR_PREASEQ) || (r==Ledger::TR_BADLSEQ)) + { // transaction should be held + trans->setStatus(HELD); + trans->save(); + theApp->getMasterLedger().addHeldTransaction(trans); + return trans; + } + if( (r==Ledger::TR_PASTASEQ) || (r==Ledger::TR_ALREADY) ) + { // duplicate or conflict + trans->setStatus(OBSOLETE); + return trans; + } + + if(r==Ledger::TR_SUCCESS) + { + // WRITEME: send to others + trans->setStatus(INCLUDED); + return trans; + } + + trans->setStatus(INVALID); + return trans; +} + +Transaction::pointer NetworkOPs::findTransactionByID(const uint256& transactionID) +{ + return Transaction::load(transactionID); +} + +int NetworkOPs::findTransactionsBySource(std::list& txns, + const uint160& sourceAccount, uint32 minSeq, uint32 maxSeq) +{ + AccountState::pointer state=getAccountState(sourceAccount); + if(!state) return 0; + if(minSeq>state->getSeq()) return 0; + if(maxSeq>state->getSeq()) maxSeq=state->getSeq(); + if(maxSeq>minSeq) return 0; + + int count=0; + for(int i=minSeq; i<=maxSeq; i++) + { + Transaction::pointer txn=Transaction::findFrom(sourceAccount, i); + if(txn) + { + txns.push_back(txn); + count++; + } + } + return count; +} + +int NetworkOPs::findTransactionsByDestination(std::list& txns, + const uint160& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions) +{ + // WRITEME +} + +AccountState::pointer NetworkOPs::getAccountState(const uint160& accountID) +{ + return theApp->getMasterLedger().getCurrentLedger()->getAccountState(accountID); +} diff --git a/NetworkOPs.h b/NetworkOPs.h new file mode 100644 index 0000000000..29044aeb9b --- /dev/null +++ b/NetworkOPs.h @@ -0,0 +1,49 @@ +#ifndef __NETWORK_OPS__ +#define __NETWORK_OPS__ + +#include "Transaction.h" +#include "AccountState.h" + +// Operations that clients may wish to perform against the network + +class NetworkOPs +{ + enum Fault + { + IO_ERROR=1, + NO_NETWORK=2, + }; + +public: + + // network information + uint64 getNetworkTime(); + uint32 getCurrentLedgerID(); + + // transaction operations + Transaction::pointer processTransaction(Transaction::pointer transaction); + Transaction::pointer findTransactionByID(const uint256& transactionID); + int findTransactionsBySource(std::list&, const uint160& sourceAccount, + uint32 minSeq, uint32 maxSeq); + int findTransactionsByDestination(std::list&, const uint160& destinationAccount, + uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions); + + // account operations + AccountState::pointer getAccountState(const uint160& accountID); + + // contact block operations + + // raw object operations + bool findRawLedger(const uint256& ledgerHash, std::vector& rawLedger); + bool findRawTransaction(const uint256& transactionHash, std::vector& rawTransaction); + bool findAccountNode(const uint256& nodeHash, std::vector& rawAccountNode); + bool findTransactionNode(const uint256& nodeHash, std::vector& rawTransactionNode); + + // tree synchronzation operations + bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID, + const std::vector& myNode, std::list >& newNodes); + bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId, + const std::vector& myNode, std::list >& newNodes); +}; + +#endif