mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
|
||||
104
src/Peer.cpp
104
src/Peer.cpp
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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>&)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user