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

This commit is contained in:
jed
2012-06-21 06:36:46 -07:00
12 changed files with 241 additions and 111 deletions

View File

@@ -83,7 +83,15 @@ bool ConnectionPool::savePeer(const std::string& strIp, int iPort, char code)
{
db->executeSQL(str(boost::format("INSERT INTO PeerIps (IpPort,Score,Source) values (%s,0,'%c');") % ipPort % code));
bNew = true;
}// else we already had this peer
}
else
{
// We already had this peer.
// We will eventually verify its address if it is possible.
// YYY If it is vsInbound, then we might make verification immediate so we can connect back sooner if the connection
// is lost.
nothing();
}
}
else
{
@@ -442,8 +450,8 @@ bool ConnectionPool::peerScanSet(const std::string& strIp, int iPort)
boost::posix_time::ptime tpNow = boost::posix_time::second_clock::universal_time();
boost::posix_time::ptime tpNext = tpNow + boost::posix_time::seconds(iInterval);
Log(lsINFO) << str(boost::format("Pool: Scan: schedule create: %s %s (next %s, delay=%s)")
% mScanIp % mScanPort % tpNext % iInterval);
Log(lsINFO) << str(boost::format("Pool: Scan: schedule create: %s %s (next %s, delay=%d)")
% mScanIp % mScanPort % tpNext % (tpNext-tpNow).total_seconds());
db->executeSQL(str(boost::format("UPDATE PeerIps SET ScanNext=%d,ScanInterval=%d WHERE IpPort=%s;")
% iToSeconds(tpNext)
@@ -457,10 +465,9 @@ bool ConnectionPool::peerScanSet(const std::string& strIp, int iPort)
// Scan connection terminated, already scheduled for retry.
boost::posix_time::ptime tpNow = boost::posix_time::second_clock::universal_time();
boost::posix_time::ptime tpNext = ptFromSeconds(db->getInt("ScanNext"));
int iInterval = (tpNext-tpNow).seconds();
Log(lsINFO) << str(boost::format("Pool: Scan: schedule exists: %s %s (next %s, delay=%s)")
% mScanIp % mScanPort % tpNext % iInterval);
Log(lsINFO) << str(boost::format("Pool: Scan: schedule exists: %s %s (next %s, delay=%d)")
% mScanIp % mScanPort % tpNext % (tpNext-tpNow).total_seconds());
}
}
else
@@ -531,15 +538,23 @@ void ConnectionPool::peerVerified(Peer::pointer peer)
{
if (mScanning && mScanning == peer)
{
// Scan completed successfully.
std::string strIp = peer->getIP();
int iPort = peer->getPort();
std::string strIpPort = str(boost::format("%s %d") % strIp % iPort);
Log(lsINFO) << str(boost::format("Pool: Scan: connected: %s %s %s (scan off)") % ADDRESS_SHARED(peer) % strIp % iPort);
Log(lsINFO) << str(boost::format("Pool: Scan: connected: %s %s %s (scanned)") % ADDRESS_SHARED(peer) % strIp % iPort);
// Scan completed successfully.
if (peer->getNodePublic() == theApp->getWallet().getNodePublic())
{
// Talking to ourself. We will just back off. This lets us maybe advertise our outside address.
nothing(); // Do nothing, leave scheduled scanning.
}
else
{
// Talking with a different peer.
ScopedLock sl(theApp->getWalletDB()->getDBLock());
Database *db=theApp->getWalletDB()->getDB();
@@ -628,10 +643,10 @@ void ConnectionPool::scanRefresh()
tpNext = tpNow + boost::posix_time::seconds(iInterval);
iInterval *= 2;
Log(lsINFO) << str(boost::format("Pool: Scan: Now: %s %s (next %s, delay=%d)")
% mScanIp % mScanPort % tpNext % (tpNext-tpNow).total_seconds());
Log(lsINFO) << str(boost::format("Pool: Scan: Now: %s %s (next %s, delay=%s)")
% mScanIp % mScanPort % tpNext % iInterval);
iInterval *= 2;
{
ScopedLock sl(theApp->getWalletDB()->getDBLock());
@@ -653,8 +668,8 @@ void ConnectionPool::scanRefresh()
}
else
{
Log(lsINFO) << str(boost::format("Pool: Scan: Next: %s (next %s, delay=%s)")
% strIpPort % tpNext % (tpNext-tpNow).seconds());
Log(lsINFO) << str(boost::format("Pool: Scan: Next: %s (next %s, delay=%d)")
% strIpPort % tpNext % (tpNext-tpNow).total_seconds());
mScanTimer.expires_at(tpNext);
mScanTimer.async_wait(boost::bind(&ConnectionPool::scanHandler, this, _1));

View File

@@ -323,7 +323,10 @@ void LedgerConsensus::statusChange(newcoin::NodeEvent event, Ledger::pointer led
{ // Send a node status change message to our peers
newcoin::TMStatusChange s;
if (!mHaveCorrectLCL)
{
Log(lsTRACE) << "Telling peers we have lost sync";
s.set_newevent(newcoin::neLOST_SYNC);
}
else
{
s.set_newevent(event);

View File

@@ -261,10 +261,10 @@ void NetworkOPs::setStateTimer(int sec)
class ValidationCount
{
public:
int trustedValidations, untrustedValidations, nodesUsing;
int trustedValidations, nodesUsing;
NewcoinAddress highNode;
ValidationCount() : trustedValidations(0), untrustedValidations(0), nodesUsing(0) { ; }
ValidationCount() : trustedValidations(0), nodesUsing(0) { ; }
bool operator>(const ValidationCount& v)
{
if (trustedValidations > v.trustedValidations) return true;
@@ -362,44 +362,40 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
// node is using. THis is kind of fundamental.
boost::unordered_map<uint256, ValidationCount> ledgers;
{
boost::unordered_map<uint256, int> current = theApp->getValidations().getCurrentValidations();
for (boost::unordered_map<uint256, int>::iterator it = current.begin(), end = current.end(); it != end; ++it)
ledgers[it->first].trustedValidations += it->second;
}
Ledger::pointer currentClosed = mLedgerMaster->getClosedLedger();
uint256 closedLedger = currentClosed->getHash();
ValidationCount& ourVC = ledgers[closedLedger];
++ourVC.nodesUsing;
ourVC.highNode = theApp->getWallet().getNodePublic();
for (std::vector<Peer::pointer>::const_iterator it = peerList.begin(), end = peerList.end(); it != end; ++it)
{
if (!*it)
{
Log(lsDEBUG) << "NOP::CS Dead pointer in peer list";
}
else
else if ((*it)->isConnected())
{
uint256 peerLedger = (*it)->getClosedLedgerHash();
if (!!peerLedger)
{
// FIXME: If we have this ledger, don't count it if it's too far past its close time
ValidationCount& vc = ledgers[peerLedger];
if (vc.nodesUsing == 0)
{
theApp->getValidations().getValidationCount(peerLedger, true,
vc.trustedValidations, vc.untrustedValidations);
Log(lsTRACE) << peerLedger.GetHex() << " has " << vc.trustedValidations <<
" trusted validations and " << vc.untrustedValidations << " untrusted";
}
if ((vc.nodesUsing == 0) || ((*it)->getNodePublic() > vc.highNode))
vc.highNode = (*it)->getNodePublic();
++vc.nodesUsing;
}
else Log(lsTRACE) << "Connected peer announces no LCL";
}
}
Ledger::pointer currentClosed = mLedgerMaster->getClosedLedger();
uint256 closedLedger = currentClosed->getHash();
ValidationCount& ourVC = ledgers[closedLedger];
if (ourVC.nodesUsing == 0)
{
ourVC.highNode = theApp->getWallet().getNodePublic();
theApp->getValidations().getValidationCount(closedLedger, true,
ourVC.trustedValidations, ourVC.untrustedValidations);
}
++ourVC.nodesUsing;
ValidationCount bestVC = ourVC;
ValidationCount bestVC = ledgers[closedLedger];
// 3) Is there a network ledger we'd like to switch to? If so, do we have it?
bool switchLedgers = false;
@@ -407,8 +403,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
it != end; ++it)
{
Log(lsTRACE) << "L: " << it->first.GetHex() <<
" t=" << it->second.trustedValidations << ", u=" << it->second.untrustedValidations <<
", n=" << it->second.nodesUsing;
" t=" << it->second.trustedValidations << ", n=" << it->second.nodesUsing;
if (it->second > bestVC)
{
bestVC = it->second;
@@ -580,7 +575,10 @@ void NetworkOPs::endConsensus()
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
for (std::vector<Peer::pointer>::const_iterator it = peerList.begin(), end = peerList.end(); it != end; ++it)
if (*it && ((*it)->getClosedLedgerHash() == deadLedger))
{
Log(lsTRACE) << "Killing obsolete peer status";
(*it)->cycleStatus();
}
mConsensus = boost::shared_ptr<LedgerConsensus>();
}

View File

@@ -23,7 +23,7 @@
#define NODE_VERIFY_SECONDS 15
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx) :
mConnected(false),
mHelloed(false),
mDetaching(false),
mSocketSsl(io_service, ctx),
mVerifyTimer(io_service)
@@ -40,19 +40,22 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra
mSendingPacket = PackedMessage::pointer();
if (error)
if (mDetaching)
{
if (!mDetaching)
{
Log(lsINFO) << "Peer: Write: Error: " << ADDRESS(this) << ": bytes=" << bytes_transferred << ": " << error.category().name() << ": " << error.message() << ": " << error;
// Ignore write requests when detatching.
nothing();
}
else if (error)
{
Log(lsINFO) << "Peer: Write: Error: " << ADDRESS(this) << ": bytes=" << bytes_transferred << ": " << error.category().name() << ": " << error.message() << ": " << error;
detach("hw");
}
} else if (!mSendQ.empty())
detach("hw");
}
else if (!mSendQ.empty())
{
PackedMessage::pointer packet = mSendQ.front();
if(packet)
if (packet)
{
sendPacketForce(packet);
mSendQ.pop_front();
@@ -71,7 +74,6 @@ void Peer::setIpPort(const std::string& strIP, int iPort)
void Peer::detach(const char *rsn)
{
if (!mDetaching)
{
mDetaching = true; // Race is ok.
@@ -81,17 +83,10 @@ void Peer::detach(const char *rsn)
<< rsn << ": "
<< (mNodePublic.isValid() ? mNodePublic.humanNodePublic() : "-") << " " << getIP() << " " << getPort();
boost::system::error_code ecCancel;
(void) mVerifyTimer.cancel();
mSendQ.clear();
// We may close more than once.
boost::system::error_code ecShutdown;
getSocket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ecShutdown);
getSocket().close();
(void) mVerifyTimer.cancel();
mSocketSsl.async_shutdown(boost::bind(&Peer::handleShutdown, shared_from_this(), boost::asio::placeholders::error));
if (mNodePublic.isValid())
{
@@ -264,11 +259,15 @@ void Peer::connected(const boost::system::error_code& error)
void Peer::sendPacketForce(PackedMessage::pointer packet)
{
mSendingPacket = packet;
boost::asio::async_write(mSocketSsl, boost::asio::buffer(packet->getBuffer()),
boost::bind(&Peer::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
if (!mDetaching)
{
mSendingPacket = packet;
boost::asio::async_write(mSocketSsl, boost::asio::buffer(packet->getBuffer()),
boost::bind(&Peer::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
void Peer::sendPacket(PackedMessage::pointer packet)
@@ -288,10 +287,14 @@ void Peer::sendPacket(PackedMessage::pointer packet)
void Peer::start_read_header()
{
mReadbuf.clear();
mReadbuf.resize(HEADER_SIZE);
boost::asio::async_read(mSocketSsl, boost::asio::buffer(mReadbuf),
boost::bind(&Peer::handle_read_header, shared_from_this(), boost::asio::placeholders::error));
if (!mDetaching)
{
mReadbuf.clear();
mReadbuf.resize(HEADER_SIZE);
boost::asio::async_read(mSocketSsl, boost::asio::buffer(mReadbuf),
boost::bind(&Peer::handle_read_header, shared_from_this(), boost::asio::placeholders::error));
}
}
void Peer::start_read_body(unsigned msg_len)
@@ -299,15 +302,24 @@ void Peer::start_read_body(unsigned msg_len)
// m_readbuf already contains the header in its first HEADER_SIZE
// bytes. Expand it to fit in the body as well, and start async
// read into the body.
//
mReadbuf.resize(HEADER_SIZE + msg_len);
boost::asio::async_read(mSocketSsl, boost::asio::buffer(&mReadbuf[HEADER_SIZE], msg_len),
boost::bind(&Peer::handle_read_body, shared_from_this(), boost::asio::placeholders::error));
if (!mDetaching)
{
mReadbuf.resize(HEADER_SIZE + msg_len);
boost::asio::async_read(mSocketSsl, boost::asio::buffer(&mReadbuf[HEADER_SIZE], msg_len),
boost::bind(&Peer::handle_read_body, shared_from_this(), boost::asio::placeholders::error));
}
}
void Peer::handle_read_header(const boost::system::error_code& error)
{
if (!error)
if (mDetaching)
{
// Drop data or error if detaching.
nothing();
}
else if (!error)
{
unsigned msg_len = PackedMessage::getLength(mReadbuf);
// WRITEME: Compare to maximum message length, abort if too large
@@ -318,7 +330,7 @@ void Peer::handle_read_header(const boost::system::error_code& error)
}
start_read_body(msg_len);
}
else if (!mDetaching)
else
{
Log(lsINFO) << "Peer: Header: Error: " << ADDRESS(this) << ": " << error.category().name() << ": " << error.message() << ": " << error;
detach("hrh2");
@@ -327,12 +339,17 @@ void Peer::handle_read_header(const boost::system::error_code& error)
void Peer::handle_read_body(const boost::system::error_code& error)
{
if (!error)
if (mDetaching)
{
// Drop data or error if detaching.
nothing();
}
else if (!error)
{
processReadBuffer();
start_read_header();
}
else if (!mDetaching)
else
{
Log(lsINFO) << "Peer: Body: Error: " << ADDRESS(this) << ": " << error.category().name() << ": " << error.message() << ": " << error;
detach("hrb");
@@ -349,7 +366,7 @@ void Peer::processReadBuffer()
// std::cerr << "Peer::processReadBuffer: " << mIpPort.first << " " << mIpPort.second << std::endl;
// If connected and get a mtHELLO or if not connected and get a non-mtHELLO, wrong message was sent.
if (mConnected == (type == newcoin::mtHELLO))
if (mHelloed == (type == newcoin::mtHELLO))
{
Log(lsWARNING) << "Wrong message type: " << type;
detach("prb1");
@@ -593,7 +610,7 @@ void Peer::recvHello(newcoin::TMHello& packet)
}
// Consider us connected. No longer accepting mtHELLO.
mConnected = true;
mHelloed = true;
// XXX Set timer: connection is in grace period to be useful.
// XXX Set timer: connection idle (idle may vary depending on connection type.)
@@ -840,8 +857,10 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet)
if (packet.newevent() == newcoin::neLOST_SYNC)
{
Log(lsTRACE) << "peer has lost sync";
mPreviousLedgerHash.zero();
mClosedLedgerHash.zero();
return;
}
if (packet.has_ledgerhash() && (packet.ledgerhash().size() == (256 / 8)))
{ // a peer has changed ledgers
@@ -849,7 +868,12 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet)
mClosedLedgerTime = ptFromSeconds(packet.networktime());
Log(lsTRACE) << "peer LCL is " << mClosedLedgerHash.GetHex();
}
else mClosedLedgerHash.zero();
else
{
Log(lsTRACE) << "peer has no ledger hash";
mClosedLedgerHash.zero();
}
if (packet.has_previousledgerhash() && packet.previousledgerhash().size() == (256 / 8))
{
memcpy(mPreviousLedgerHash.begin(), packet.previousledgerhash().data(), 256 / 8);

View File

@@ -31,7 +31,7 @@ public:
private:
bool mClientConnect; // In process of connecting as client.
bool mConnected; // True, if hello accepted.
bool mHelloed; // True, if hello accepted.
bool mDetaching; // True, if detaching.
NewcoinAddress mNodePublic; // Node public key of peer.
ipPort mIpPort;
@@ -58,6 +58,8 @@ protected:
Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx);
void handleShutdown(const boost::system::error_code& error) { ; }
void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
void handle_read_header(const boost::system::error_code& error);
void handle_read_body(const boost::system::error_code& error);
@@ -128,7 +130,7 @@ public:
void punishPeer(PeerPunish pp);
Json::Value getJson();
bool isConnected() const { return mConnected; }
bool isConnected() const { return mHelloed && !mDetaching; }
//static PackedMessage::pointer createFullLedger(Ledger::pointer ledger);
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);

View File

@@ -485,6 +485,17 @@ STAmount STObject::getValueFieldAmount(SOE_Field field) const
return *cf;
}
STPathSet STObject::getValueFieldPathSet(SOE_Field field) const
{
const SerializedType* rf = peekAtPField(field);
if (!rf) throw std::runtime_error("Field not found");
SerializedTypeID id = rf->getSType();
if (id == STI_NOTPRESENT) return STPathSet(); // optional field not present
const STPathSet *cf = dynamic_cast<const STPathSet *>(rf);
if (!cf) throw std::runtime_error("Wrong field type");
return *cf;
}
STVector256 STObject::getValueFieldV256(SOE_Field field) const
{
const SerializedType* rf = peekAtPField(field);

View File

@@ -167,6 +167,7 @@ public:
std::vector<unsigned char> getValueFieldVL(SOE_Field field) const;
std::vector<TaggedListItem> getValueFieldTL(SOE_Field field) const;
STAmount getValueFieldAmount(SOE_Field field) const;
STPathSet getValueFieldPathSet(SOE_Field field) const;
STVector256 getValueFieldV256(SOE_Field field) const;
void setValueFieldU8(SOE_Field field, unsigned char);

View File

@@ -89,6 +89,7 @@ public:
std::vector<unsigned char> getITFieldVL(SOE_Field field) const { return mInnerTxn.getValueFieldVL(field); }
std::vector<TaggedListItem> getITFieldTL(SOE_Field field) const { return mInnerTxn.getValueFieldTL(field); }
STAmount getITFieldAmount(SOE_Field field) const { return mInnerTxn.getValueFieldAmount(field); }
STPathSet getITFieldPathSet(SOE_Field field) const { return mInnerTxn.getValueFieldPathSet(field); }
void setITFieldU8(SOE_Field field, unsigned char v) { return mInnerTxn.setValueFieldU8(field, v); }
void setITFieldU16(SOE_Field field, uint16 v) { return mInnerTxn.setValueFieldU16(field, v); }

View File

@@ -1,6 +1,11 @@
//
// XXX Should make sure all fields and are recognized on a transactions.
// XXX Make sure fee is claimed for failed transactions.
//
#include "TransactionEngine.h"
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include "../json/writer.h"
@@ -1008,10 +1013,15 @@ TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransac
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts,
const uint160& srcAccountID)
const uint160& uSrcAccountID)
{
uint32 txFlags = txn.getFlags();
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
uint32 txFlags = txn.getFlags();
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
// XXX Could also be ripple if direct credit lines.
bool bRipple = txn.getITFieldPresent(sfPaths);
bool bCreate = !!(txFlags & tfCreateAccount);
STAmount saAmount = txn.getITFieldAmount(sfAmount);
STAmount saSrcBalance = accounts[0].second->getIValueFieldAmount(sfBalance);
if (!uDstAccountID)
{
@@ -1019,38 +1029,30 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
return tenINVALID;
}
// XXX Only bad if no currency conversion in between through other people's offer.
else if (srcAccountID == uDstAccountID)
else if (uSrcAccountID == uDstAccountID)
{
std::cerr << "doPayment: Invalid transaction: Source account is the same as destination." << std::endl;
return tenINVALID;
}
bool bCreate = !!(txFlags & tfCreateAccount);
uint160 uCurrency;
if (txn.getITFieldPresent(sfCurrency))
{
uCurrency = txn.getITFieldH160(sfCurrency);
if (!uCurrency)
{
std::cerr << "doPayment: Invalid transaction: " SYSTEM_CURRENCY_CODE " explicitly specified." << std::endl;
return tenEXPLICITXNC;
}
}
// XXX Allow ripple to create.
LedgerStateParms qry = lepNONE;
SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID);
if (!sleDst)
{
// Destination account does not exist.
if (bCreate && !!uCurrency)
// XXX Also make sure non-ripple dest if creating.
if (bCreate && !saAmount.isNative())
{
std::cerr << "doPayment: Invalid transaction: Create account may only fund XBC." << std::endl;
return tenCREATEXNC;
std::cerr << "doPayment: Invalid transaction: Create account may only fund XNS." << std::endl;
return tenCREATEXNS;
}
else if (!bCreate)
{
std::cerr << "doPayment: Delay transaction: Destination account does not exist." << std::endl;
return terNO_DST;
}
@@ -1067,6 +1069,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
else if (bCreate)
{
std::cerr << "doPayment: Invalid transaction: Account already created." << std::endl;
return terCREATED;
}
else
@@ -1074,28 +1077,68 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
accounts.push_back(std::make_pair(taaMODIFY, sleDst));
}
STAmount saAmount = txn.getITFieldAmount(sfAmount);
if (!uCurrency)
if (!bRipple)
{
STAmount saSrcBalance = accounts[0].second->getIValueFieldAmount(sfBalance);
// Direct XNS payment.
if (!saAmount.isNative())
{
std::cerr << "doPayment: Invalid transaction: direct " SYSTEM_CURRENCY_CODE " required." << std::endl;
return tenDIRECT_XNS_ONLY;
}
if (saSrcBalance < saAmount)
{
std::cerr << "doPayment: Delay transaction: Insufficent funds." << std::endl;
return terUNFUNDED;
}
accounts[0].second->setIFieldAmount(sfBalance, saSrcBalance - saAmount);
accounts[1].second->setIFieldAmount(sfBalance, accounts[1].second->getIValueFieldAmount(sfBalance) + saAmount);
}
else
{
// WRITEME: Handle non-native currencies, paths
return tenUNKNOWN;
return terSUCCESS;
}
return terSUCCESS;
//
// Try direct ripple first.
//
uint160 uDstCurrency = saAmount.getCurrency();
qry = lepNONE;
SLE::pointer sleRippleState = mLedger->getRippleState(qry, uSrcAccountID, uDstAccountID, uDstCurrency);
if (sleRippleState)
{
// There is a direct relationship.
}
STPathSet spsPaths = txn.getITFieldPathSet(sfPaths);
// XXX If we are parsing for determing forwarding check maximum path count.
if (!spsPaths.getPathCount())
{
std::cerr << "doPayment: Invalid transaction: No paths." << std::endl;
return tenRIPPLE_EMPTY;
}
#if 0
std::vector<STPath> spPath;
BOOST_FOREACH(std::vector<STPath>& spPath, spsPaths)
{
std::cerr << "doPayment: Implementation error: Not implemented." << std::endl;
return tenUNKNOWN;
}
#endif
std::cerr << "doPayment: Delay transaction: No ripple paths could be satisfied." << std::endl;
return terBAD_RIPPLE;
}
TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction& st, std::vector<AffectedAccount>&)

View File

@@ -14,20 +14,23 @@ enum TransactionEngineResult
// Malformed: Fee claimed
tenGEN_IN_USE = -300, // Generator already in use.
tenCREATEXNC, // Can not specify non XNC for Create.
tenEXPLICITXNC, // XNC is used by default, don't specify it.
tenCREATEXNS, // Can not specify non XNS for Create.
tenEXPLICITXNS, // XNS is used by default, don't specify it.
tenDST_NEEDED, // Destination not specified.
tenDST_IS_SRC, // Destination may not be source.
tenBAD_GEN_AUTH, // Not authorized to claim generator.
tenBAD_ADD_AUTH, // Not authorized to add account.
tenBAD_CLAIM_ID, // Malformed.
tenBAD_SET_ID, // Malformed.
tenDIRECT_XNS_ONLY, // Direct payments are non-ripple XNS only.
tenRIPPLE_EMPTY, // PathSet with no paths.
// Invalid: Ledger won't allow.
tenCLAIMED = -200, // Can not claim a previously claimed account.
tenCREATED, // Can't add an already created account.
tenMSG_SET, // Can't change a message key.
tenBAD_AUTH_MASTER, // Auth for unclaimed account needs correct master key.
tenBAD_RIPPLE, // Ledger prevents ripple from succeeding.
// Other
tenFAILED = -100, // Something broke horribly
@@ -61,6 +64,7 @@ enum TransactionEngineResult
terFUNDS_SPENT, // Can't set password, password set funds already spent.
terUNCLAIMED, // Can not use an unclaimed account.
terBAD_AUTH, // Transaction's public key is not authorized.
terBAD_RIPPLE, // No ripple path can be satisfied.
};
enum TransactionEngineParams

View File

@@ -13,7 +13,7 @@ bool ValidationCollection::addValidation(SerializedValidation::pointer val)
val->setTrusted();
uint64 now = theApp->getOPs().getNetworkTimeNC();
uint64 valClose = val->getCloseTime();
if ((now > valClose) && (now < (valClose + 2 * LEDGER_INTERVAL)))
if ((now > valClose) && (now < (valClose + LEDGER_INTERVAL)))
isCurrent = true;
else
Log(lsWARNING) << "Received stale validation now=" << now << ", close=" << valClose;
@@ -74,3 +74,30 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
}
}
}
boost::unordered_map<uint256, int> ValidationCollection::getCurrentValidations()
{
uint64 now = theApp->getOPs().getNetworkTimeNC();
boost::unordered_map<uint256, int> ret;
{
boost::mutex::scoped_lock sl(mValidationLock);
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
while (it != mCurrentValidations.end())
{
if (now > (it->second->getCloseTime() + LEDGER_INTERVAL))
{
Log(lsTRACE) << "Erasing validation for " << it->second->getLedgerHash().GetHex();
it = mCurrentValidations.erase(it);
}
else
{
Log(lsTRACE) << "Counting validation for " << it->second->getLedgerHash().GetHex();
++ret[it->second->getLedgerHash()];
++it;
}
}
}
return ret;
}

View File

@@ -24,6 +24,7 @@ public:
bool addValidation(SerializedValidation::pointer);
ValidationSet getValidations(const uint256& ledger);
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
boost::unordered_map<uint256, int> getCurrentValidations();
};
#endif