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.
This commit is contained in:
JoelKatz
2011-12-15 01:19:50 -08:00
parent 0b25b9641f
commit 639ba9dfcb
6 changed files with 164 additions and 9 deletions

View File

@@ -10,6 +10,7 @@
#include "LedgerMaster.h"
#include "Wallet.h"
#include "Peer.h"
#include "NetworkOPs.h"
#include "database/database.h"
#include <boost/asio.hpp>
@@ -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; }

View File

@@ -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)

View File

@@ -22,7 +22,6 @@ class LedgerMaster
LedgerHistory mLedgerHistory;
std::map<uint256, Transaction::pointer> mHeldTransactionsByID;
std::map<uint32, Transaction::pointer> 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

View File

@@ -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

101
NetworkOPs.cpp Normal file
View File

@@ -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<Transaction::pointer>& 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<Transaction::pointer>& txns,
const uint160& destinationAccount, uint32 startLedgerSeq, uint32 endLedgerSeq, int maxTransactions)
{
// WRITEME
}
AccountState::pointer NetworkOPs::getAccountState(const uint160& accountID)
{
return theApp->getMasterLedger().getCurrentLedger()->getAccountState(accountID);
}

49
NetworkOPs.h Normal file
View File

@@ -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<Transaction::pointer>&, const uint160& sourceAccount,
uint32 minSeq, uint32 maxSeq);
int findTransactionsByDestination(std::list<Transaction::pointer>&, 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<unsigned char>& rawLedger);
bool findRawTransaction(const uint256& transactionHash, std::vector<unsigned char>& rawTransaction);
bool findAccountNode(const uint256& nodeHash, std::vector<unsigned char>& rawAccountNode);
bool findTransactionNode(const uint256& nodeHash, std::vector<unsigned char>& rawTransactionNode);
// tree synchronzation operations
bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID,
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId,
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
};
#endif