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:
@@ -10,6 +10,9 @@
|
||||
if ((_db)->executeSQL(_strQuery)) \
|
||||
for (bool _bMore = (_db)->startIterRows(); _bMore; _bMore = (_db)->getNextRow())
|
||||
|
||||
#define SQL_EXISTS(_db, _strQuery) \
|
||||
((_db)->executeSQL(_strQuery) && (_db)->startIterRows())
|
||||
|
||||
/*
|
||||
this maintains the connection to the database
|
||||
*/
|
||||
|
||||
@@ -228,7 +228,7 @@ int WalletDBCount = sizeof(WalletDBInit) / sizeof(const char *);
|
||||
|
||||
// Hash node database holds nodes indexed by hash
|
||||
const char *HashNodeDBInit[] = {
|
||||
"CREATE TABLE CommittedObjects \
|
||||
"CREATE TABLE CommittedObjects ( \
|
||||
Hash CHARACTER(64) PRIMARY KEY, \
|
||||
ObjType CHAR(1) NOT NULL, \
|
||||
LedgerIndex BIGINT UNSIGNED, \
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
#include "HashedObject.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "HashedObject.h"
|
||||
#include "Serializer.h"
|
||||
#include "Application.h"
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
|
||||
bool HashedObject::checkHash() const
|
||||
@@ -26,16 +27,6 @@ void HashedObject::setHash()
|
||||
mHash = Serializer::getSHA512Half(mData);
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE TABLE CommittedObjects ( -- used to synch nodes
|
||||
Hash BLOB PRIMARY KEY,
|
||||
ObjType CHAR(1) NOT NULL, -- (L)edger, (T)ransaction, (A)ccount node, transaction (N)ode
|
||||
LedgerIndex BIGINT UNSIGNED, -- 0 if none
|
||||
Object BLOB
|
||||
);
|
||||
CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
||||
*/
|
||||
|
||||
// FIXME: Stores should be added to a queue that's services by an auxilliary thread or from an
|
||||
// auxilliary thread pool. These should be tied into a cache, since you need one to handle
|
||||
// an immedate read back (before the write completes)
|
||||
@@ -117,6 +108,9 @@ HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
||||
case 'T': htype = TRANSACTION; break;
|
||||
case 'A': htype = ACCOUNT_NODE; break;
|
||||
case 'N': htype = TRANSACTION_NODE; break;
|
||||
default:
|
||||
Log(lsERROR) << "Invalid hashed object";
|
||||
return HashedObject::pointer();
|
||||
}
|
||||
|
||||
HashedObject::pointer obj = boost::make_shared<HashedObject>(htype, index, data);
|
||||
|
||||
@@ -236,6 +236,7 @@ uint256 Ledger::getHash()
|
||||
|
||||
void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
||||
{
|
||||
|
||||
std::string sql="INSERT INTO Ledgers "
|
||||
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,AccountSetHash,TransSetHash) VALUES ('";
|
||||
sql.append(ledger->getHash().GetHex());
|
||||
@@ -254,6 +255,13 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
||||
sql.append("');");
|
||||
|
||||
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
|
||||
if (SQL_EXISTS(theApp->getLedgerDB()->getDB(),
|
||||
boost::str(boost::format("SELECT LedgerSeq FROM Ledgers where LedgerSeq = '%d';") % ledger->mLedgerSeq)
|
||||
))
|
||||
{
|
||||
theApp->getLedgerDB()->getDB()->executeSQL(
|
||||
boost::str(boost::format("DELETE FROM Ledgers WHERE LedgerSeq = '%d';") % ledger->mLedgerSeq));
|
||||
}
|
||||
theApp->getLedgerDB()->getDB()->executeSQL(sql);
|
||||
|
||||
// write out dirty nodes
|
||||
@@ -270,36 +278,46 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
||||
{
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedTransaction txn(sit);
|
||||
std::vector<NewcoinAddress> accts = txn.getAffectedAccounts();
|
||||
|
||||
std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES ";
|
||||
bool first = true;
|
||||
for (std::vector<NewcoinAddress>::iterator it = accts.begin(), end = accts.end(); it != end; ++it)
|
||||
if (!SQL_EXISTS(db,
|
||||
boost::str(boost::format("SELECT LedgerSeq FROM AccountTransactions WHERE TransId = '%s';")
|
||||
% item->getTag().GetHex())))
|
||||
{
|
||||
if (!first)
|
||||
sql += ", ('";
|
||||
else
|
||||
std::vector<NewcoinAddress> accts = txn.getAffectedAccounts();
|
||||
|
||||
std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES ";
|
||||
bool first = true;
|
||||
for (std::vector<NewcoinAddress>::iterator it = accts.begin(), end = accts.end(); it != end; ++it)
|
||||
{
|
||||
sql += "('";
|
||||
first = false;
|
||||
if (!first)
|
||||
sql += ", ('";
|
||||
else
|
||||
{
|
||||
sql += "('";
|
||||
first = false;
|
||||
}
|
||||
sql += txn.getTransactionID().GetHex();
|
||||
sql += "','";
|
||||
sql += it->humanAccountID();
|
||||
sql += "',";
|
||||
sql += boost::lexical_cast<std::string>(ledger->getLedgerSeq());
|
||||
sql += ")";
|
||||
}
|
||||
sql += txn.getTransactionID().GetHex();
|
||||
sql += "','";
|
||||
sql += it->humanAccountID();
|
||||
sql += "',";
|
||||
sql += boost::lexical_cast<std::string>(ledger->getLedgerSeq());
|
||||
sql += ")";
|
||||
sql += ";";
|
||||
Log(lsTRACE) << "ActTx: " << sql;
|
||||
db->executeSQL(sql); // may already be in there
|
||||
}
|
||||
sql += ";";
|
||||
Log(lsTRACE) << "ActTx: " << sql;
|
||||
db->executeSQL(sql);
|
||||
if (!db->executeSQL(
|
||||
txn.getSQLInsertHeader() + txn.getSQL(ledger->getLedgerSeq(), TXN_SQL_VALIDATED) + ";"), true)
|
||||
{ // transaction already in DB, update
|
||||
db->executeSQL(boost::str(boost::format(
|
||||
"UPDATE Transactions SET LedgerSeq = '%d', Status = '%c' WHERE TransID = '%s';") %
|
||||
if (SQL_EXISTS(db, boost::str(boost::format("SELECT Status from Transactions where TransID = '%s';") %
|
||||
txn.getTransactionID().GetHex())))
|
||||
{
|
||||
db->executeSQL(boost::str(
|
||||
boost::format("UPDATE Transactions SET LedgerSeq = '%d', Status = '%c' WHERE TransID = '%s';") %
|
||||
ledger->getLedgerSeq() % TXN_SQL_VALIDATED % txn.getTransactionID().GetHex()));
|
||||
}
|
||||
else
|
||||
{
|
||||
db->executeSQL(
|
||||
txn.getSQLInsertHeader() + txn.getSQL(ledger->getLedgerSeq(), TXN_SQL_VALIDATED) + ";");
|
||||
}
|
||||
}
|
||||
db->executeSQL("COMMIT TRANSACTION;");
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ void LedgerAcquire::addOnComplete(boost::function<void (LedgerAcquire::pointer)>
|
||||
|
||||
void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "Trigger acquiring ledger " << mHash.GetHex() << std::endl;
|
||||
std::cerr << "complete=" << mComplete << " failed=" << mFailed << std::endl;
|
||||
std::cerr << "base=" << mHaveBase << " tx=" << mHaveTransactions << " as=" << mHaveState << std::endl;
|
||||
@@ -114,7 +114,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
return;
|
||||
if (!mHaveBase)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "need base" << std::endl;
|
||||
#endif
|
||||
newcoin::TMGetLedger tmGL;
|
||||
@@ -130,7 +130,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
|
||||
if (mHaveBase && !mHaveTransactions)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "need tx" << std::endl;
|
||||
#endif
|
||||
assert(mLedger);
|
||||
@@ -182,7 +182,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
|
||||
if (mHaveBase && !mHaveState)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "need as" << std::endl;
|
||||
#endif
|
||||
assert(mLedger);
|
||||
@@ -267,7 +267,7 @@ void PeerSet::sendRequest(const newcoin::TMGetLedger& tmGL)
|
||||
|
||||
bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer)
|
||||
{ // Return value: true=normal, false=bad data
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "got base acquiring ledger " << mHash.GetHex() << std::endl;
|
||||
#endif
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
@@ -275,10 +275,8 @@ bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer)
|
||||
mLedger = boost::make_shared<Ledger>(data);
|
||||
if (mLedger->getHash() != mHash)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "Acquire hash mismatch" << std::endl;
|
||||
std::cerr << mLedger->getHash().GetHex() << "!=" << mHash.GetHex() << std::endl;
|
||||
#endif
|
||||
mLedger = Ledger::pointer();
|
||||
return false;
|
||||
}
|
||||
@@ -320,7 +318,7 @@ bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
|
||||
bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
|
||||
const std::list< std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "got ASdata acquiring ledger " << mHash.GetHex() << std::endl;
|
||||
#endif
|
||||
if (!mHaveBase) return false;
|
||||
@@ -380,19 +378,17 @@ bool LedgerAcquireMaster::dropLedger(const uint256& hash)
|
||||
|
||||
bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer peer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << "got data for acquiring ledger ";
|
||||
#endif
|
||||
uint256 hash;
|
||||
if (packet.ledgerhash().size() != 32)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "error" << std::endl;
|
||||
#endif
|
||||
std::cerr << "Acquire error" << std::endl;
|
||||
return false;
|
||||
}
|
||||
memcpy(hash.begin(), packet.ledgerhash().data(), 32);
|
||||
#ifdef DEBUG
|
||||
#ifdef LA_DEBUG
|
||||
std::cerr << hash.GetHex() << std::endl;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include "../json/writer.h"
|
||||
|
||||
@@ -13,6 +14,8 @@
|
||||
|
||||
#define TRUST_NETWORK
|
||||
|
||||
// #define LC_DEBUG
|
||||
|
||||
TransactionAcquire::TransactionAcquire(const uint256& hash)
|
||||
: PeerSet(hash, 1), mFilter(&theApp->getNodeCache()), mHaveRoot(false)
|
||||
{
|
||||
@@ -39,7 +42,6 @@ void TransactionAcquire::trigger(Peer::pointer peer)
|
||||
return;
|
||||
if (!mHaveRoot)
|
||||
{
|
||||
Log(lsTRACE) << "Don't have root";
|
||||
newcoin::TMGetLedger tmGL;
|
||||
tmGL.set_ledgerhash(mHash.begin(), mHash.size());
|
||||
tmGL.set_itype(newcoin::liTS_CANDIDATE);
|
||||
@@ -48,7 +50,6 @@ void TransactionAcquire::trigger(Peer::pointer peer)
|
||||
}
|
||||
if (mHaveRoot)
|
||||
{
|
||||
Log(lsTRACE) << "Have root";
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::vector<uint256> nodeHashes;
|
||||
mMap->getMissingNodes(nodeIDs, nodeHashes, 256, &mFilter);
|
||||
@@ -126,18 +127,26 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes)
|
||||
if (res.second)
|
||||
{ // new vote
|
||||
if (votesYes)
|
||||
{
|
||||
Log(lsTRACE) << "Peer " << peer.GetHex() << " votes YES on " << mTransactionID.GetHex();
|
||||
++mYays;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsTRACE) << "Peer " << peer.GetHex() << " votes NO on " << mTransactionID.GetHex();
|
||||
++mNays;
|
||||
}
|
||||
}
|
||||
else if (votesYes && !res.first->second)
|
||||
{ // changes vote to yes
|
||||
Log(lsTRACE) << "Peer " << peer.GetHex() << " now votes YES on " << mTransactionID.GetHex();
|
||||
--mNays;
|
||||
++mYays;
|
||||
res.first->second = true;
|
||||
}
|
||||
else if(!votesYes && !res.first->second)
|
||||
else if(!votesYes && res.first->second)
|
||||
{ // changes vote to no
|
||||
Log(lsTRACE) << "Peer " << peer.GetHex() << " now votes NO on " << mTransactionID.GetHex();
|
||||
++mNays;
|
||||
--mYays;
|
||||
res.first->second = false;
|
||||
@@ -146,21 +155,30 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes)
|
||||
|
||||
bool LCTransaction::updatePosition(int seconds)
|
||||
{ // this many seconds after close, should our position change
|
||||
|
||||
if (mOurPosition && (mNays == 0)) return false;
|
||||
if (!mOurPosition && (mYays == 0)) return false;
|
||||
if (mOurPosition && (mNays == 0))
|
||||
return false;
|
||||
if (!mOurPosition && (mYays == 0))
|
||||
return false;
|
||||
|
||||
// This is basically the percentage of nodes voting 'yes' (including us)
|
||||
int weight = (mYays * 100 + (mOurPosition ? 100 : 0)) / (mNays + mYays + 1);
|
||||
|
||||
// To prevent avalanche stalls, we increase the needed weight slightly over time
|
||||
bool newPosition;
|
||||
if (seconds <= LEDGER_CONVERGE) newPosition = weight > AV_MIN_CONSENSUS;
|
||||
else if (seconds >= LEDGER_FORCE_CONVERGE) newPosition = weight > AV_MAX_CONSENSUS;
|
||||
else newPosition = weight > AV_AVG_CONSENSUS;
|
||||
if (seconds <= LEDGER_ACCEL_CONVERGE) newPosition = weight > AV_MIN_CONSENSUS;
|
||||
else if (seconds >= LEDGER_CONVERGE) newPosition = weight > AV_AVG_CONSENSUS;
|
||||
else newPosition = weight > AV_MAX_CONSENSUS;
|
||||
|
||||
if (newPosition == mOurPosition) return false;
|
||||
if (newPosition == mOurPosition)
|
||||
{
|
||||
#ifdef LC_DEBUG
|
||||
Log(lsTRACE) << "No change (" << (mOurPosition ? "YES" : "NO") << ") : weight "
|
||||
<< weight << ", seconds " << seconds;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
mOurPosition = newPosition;
|
||||
Log(lsTRACE) << "We now vote " << (mOurPosition ? "YES" : "NO") << " on " << mTransactionID.GetHex();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -175,24 +193,55 @@ LedgerConsensus::LedgerConsensus(Ledger::pointer previousLedger, uint32 closeTim
|
||||
{
|
||||
Log(lsDEBUG) << "Creating consensus object";
|
||||
Log(lsTRACE) << "LCL:" << previousLedger->getHash().GetHex() <<", ct=" << closeTime;
|
||||
|
||||
// we always have an empty map
|
||||
mComplete[uint256()] = boost::make_shared<SHAMap>();
|
||||
}
|
||||
|
||||
void LedgerConsensus::takeInitialPosition(Ledger::pointer initialLedger)
|
||||
{
|
||||
// XXX Don't even start if no VALIDATION_SEED.
|
||||
|
||||
SHAMap::pointer initialSet = initialLedger->peekTransactionMap()->snapShot(false);
|
||||
uint256 txSet = initialSet->getHash();
|
||||
assert (initialLedger->getParentHash() == mPreviousLedger->getHash());
|
||||
|
||||
mOurPosition = boost::make_shared<LedgerProposal>(theConfig.VALIDATION_SEED, initialLedger->getParentHash(), txSet);
|
||||
// if any peers have taken a contrary position, process disputes
|
||||
boost::unordered_set<uint256> found;
|
||||
for(boost::unordered_map<uint160, LedgerProposal::pointer>::iterator it = mPeerPositions.begin(),
|
||||
end = mPeerPositions.end(); it != end; ++it)
|
||||
{
|
||||
uint256 set = it->second->getCurrentHash();
|
||||
if (found.insert(set).second)
|
||||
{
|
||||
boost::unordered_map<uint256, SHAMap::pointer>::iterator it = mComplete.find(set);
|
||||
if (it != mComplete.end())
|
||||
createDisputes(initialSet, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
mOurPosition = boost::make_shared<LedgerProposal>
|
||||
(theConfig.VALIDATION_SEED, initialLedger->getParentHash(), txSet);
|
||||
mapComplete(txSet, initialSet);
|
||||
propose(std::vector<uint256>(), std::vector<uint256>());
|
||||
}
|
||||
|
||||
void LedgerConsensus::createDisputes(SHAMap::pointer m1, SHAMap::pointer m2)
|
||||
{
|
||||
SHAMap::SHAMapDiff differences;
|
||||
m1->compare(m2, differences, 16384);
|
||||
for(SHAMap::SHAMapDiff::iterator pos = differences.begin(), end = differences.end(); pos != end; ++pos)
|
||||
{ // create disputed transactions (from the ledger that has them)
|
||||
Log(lsTRACE) << "Transaction now in dispute: " << pos->first.GetHex();
|
||||
if (pos->second.first)
|
||||
{
|
||||
assert(!pos->second.second);
|
||||
addDisputedTransaction(pos->first, pos->second.first->peekData());
|
||||
}
|
||||
else if(pos->second.second)
|
||||
{
|
||||
assert(!pos->second.first);
|
||||
addDisputedTransaction(pos->first, pos->second.second->peekData());
|
||||
}
|
||||
else assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map)
|
||||
{
|
||||
Log(lsINFO) << "We have acquired TXS " << hash.GetHex();
|
||||
@@ -201,32 +250,23 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map)
|
||||
if (!map)
|
||||
{ // this is an invalid/corrupt map
|
||||
mComplete[hash] = map;
|
||||
Log(lsWARNING) << "A trusted node directed us to acquire an invalid TXN map";
|
||||
return;
|
||||
}
|
||||
|
||||
mAcquiring.erase(hash);
|
||||
|
||||
if (mComplete.find(hash) != mComplete.end())
|
||||
{
|
||||
Log(lsERROR) << "Which we already had";
|
||||
return; // we already have this map
|
||||
}
|
||||
|
||||
if (mOurPosition && (map->getHash() != mOurPosition->getCurrentHash()))
|
||||
{ // this could create disputed transactions
|
||||
boost::unordered_map<uint256, SHAMap::pointer>::iterator it2 = mComplete.find(mOurPosition->getCurrentHash());
|
||||
if (it2 != mComplete.end())
|
||||
{
|
||||
assert((it2->first == mOurPosition->getCurrentHash()) && it2->second);
|
||||
SHAMap::SHAMapDiff differences;
|
||||
it2->second->compare(map, differences, 16384);
|
||||
for(SHAMap::SHAMapDiff::iterator pos = differences.begin(), end = differences.end(); pos != end; ++pos)
|
||||
{ // create disputed transactions (from the ledger that has them)
|
||||
if (pos->second.first)
|
||||
addDisputedTransaction(pos->first, pos->second.first->peekData());
|
||||
else if(pos->second.second)
|
||||
addDisputedTransaction(pos->first, pos->second.second->peekData());
|
||||
else assert(false);
|
||||
}
|
||||
createDisputes(it2->second, map);
|
||||
}
|
||||
else assert(false); // We don't have our own position?!
|
||||
}
|
||||
@@ -242,6 +282,8 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::pointer map)
|
||||
}
|
||||
if (!peers.empty())
|
||||
adjustCount(map, peers);
|
||||
else
|
||||
Log(lsWARNING) << "By the time we got the map, no peers were proposing it";
|
||||
|
||||
sendHaveTxSet(hash, true);
|
||||
}
|
||||
@@ -319,7 +361,7 @@ int LedgerConsensus::statePostClose(int secondsSinceClose)
|
||||
int LedgerConsensus::stateEstablish(int secondsSinceClose)
|
||||
{ // we are establishing consensus
|
||||
updateOurPositions(secondsSinceClose);
|
||||
if (secondsSinceClose > LEDGER_CONVERGE)
|
||||
if (secondsSinceClose > LEDGER_MAX_CONVERGE)
|
||||
{
|
||||
Log(lsINFO) << "Converge cutoff";
|
||||
mState = lcsCUTOFF;
|
||||
@@ -330,7 +372,7 @@ int LedgerConsensus::stateEstablish(int secondsSinceClose)
|
||||
int LedgerConsensus::stateCutoff(int secondsSinceClose)
|
||||
{ // we are making sure everyone else agrees
|
||||
bool haveConsensus = updateOurPositions(secondsSinceClose);
|
||||
if (haveConsensus || (secondsSinceClose > LEDGER_FORCE_CONVERGE))
|
||||
if (haveConsensus || (secondsSinceClose > LEDGER_CONVERGE))
|
||||
{
|
||||
Log(lsINFO) << "Consensus complete (" << haveConsensus << ")";
|
||||
mState = lcsFINISHED;
|
||||
@@ -404,11 +446,11 @@ bool LedgerConsensus::updateOurPositions(int sinceClose)
|
||||
|
||||
if (changes)
|
||||
{
|
||||
Log(lsINFO) << "We change our position";
|
||||
uint256 newHash = ourPosition->getHash();
|
||||
mOurPosition->changePosition(newHash);
|
||||
propose(addedTx, removedTx);
|
||||
sendHaveTxSet(newHash, true);
|
||||
mapComplete(newHash, ourPosition);
|
||||
Log(lsINFO) << "We change our position to " << newHash.GetHex();
|
||||
}
|
||||
|
||||
return stable;
|
||||
@@ -424,6 +466,12 @@ SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool do
|
||||
TransactionAcquire::pointer& acquiring = mAcquiring[hash];
|
||||
if (!acquiring)
|
||||
{
|
||||
if (!hash)
|
||||
{
|
||||
SHAMap::pointer empty = boost::make_shared<SHAMap>();
|
||||
mapComplete(hash, empty);
|
||||
return empty;
|
||||
}
|
||||
acquiring = boost::make_shared<TransactionAcquire>(hash);
|
||||
startAcquiring(acquiring);
|
||||
}
|
||||
@@ -473,6 +521,7 @@ void LedgerConsensus::propose(const std::vector<uint256>& added, const std::vect
|
||||
|
||||
void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vector<unsigned char>& tx)
|
||||
{
|
||||
Log(lsTRACE) << "Transacstion " << txID.GetHex() << " is disputed";
|
||||
boost::unordered_map<uint256, LCTransaction::pointer>::iterator it = mDisputes.find(txID);
|
||||
if (it != mDisputes.end()) return;
|
||||
|
||||
@@ -516,16 +565,18 @@ bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Log(lsINFO) << "Peer position " << newPosition->getProposeSeq() << "/"
|
||||
Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/"
|
||||
<< newPosition->getCurrentHash().GetHex();
|
||||
currentPosition = newPosition;
|
||||
SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true);
|
||||
if (set)
|
||||
{
|
||||
Log(lsTRACE) << "Have that set";
|
||||
for (boost::unordered_map<uint256, LCTransaction::pointer>::iterator it = mDisputes.begin(),
|
||||
end = mDisputes.end(); it != end; ++it)
|
||||
it->second->setVote(newPosition->getPeerID(), set->hasItem(it->first));
|
||||
}
|
||||
else Log(lsTRACE) << "Don't have that set";
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -575,9 +626,44 @@ void LedgerConsensus::Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::p
|
||||
This->accept(txSet);
|
||||
}
|
||||
|
||||
void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger,
|
||||
CanonicalTXSet& failedTransactions)
|
||||
void LedgerConsensus::applyTransaction(TransactionEngine& engine, SerializedTransaction::pointer txn,
|
||||
Ledger::pointer ledger, CanonicalTXSet& failedTransactions, bool final)
|
||||
{
|
||||
TransactionEngineParams parms = final ? (tepNO_CHECK_FEE | tepUPDATE_TOTAL) : tepNONE;
|
||||
#ifndef TRUST_NETWORK
|
||||
try
|
||||
{
|
||||
#endif
|
||||
TransactionEngineResult result = engine.applyTransaction(*txn, parms, 0);
|
||||
if (result > 0)
|
||||
{
|
||||
Log(lsINFO) << " retry";
|
||||
// assert(!ledger->hasTransaction(txn->getTransactionID())); FIXME: We get these (doPasswordSet)
|
||||
failedTransactions.push_back(txn);
|
||||
}
|
||||
else if (result == 0)
|
||||
{
|
||||
Log(lsDEBUG) << " success";
|
||||
assert(ledger->hasTransaction(txn->getTransactionID()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << " hard fail";
|
||||
assert(!ledger->hasTransaction(txn->getTransactionID()));
|
||||
}
|
||||
#ifndef TRUST_NETWORK
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger,
|
||||
CanonicalTXSet& failedTransactions, bool final)
|
||||
{
|
||||
TransactionEngineParams parms = final ? (tepNO_CHECK_FEE | tepUPDATE_TOTAL) : tepNONE;
|
||||
TransactionEngine engine(ledger);
|
||||
|
||||
for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag()))
|
||||
@@ -589,23 +675,7 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led
|
||||
#endif
|
||||
SerializerIterator sit(item->peekSerializer());
|
||||
SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
TransactionEngineResult result = engine.applyTransaction(*txn, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0);
|
||||
if (result > 0)
|
||||
{
|
||||
Log(lsINFO) << " retry";
|
||||
assert(!ledger->hasTransaction(item->getTag()));
|
||||
failedTransactions.push_back(txn);
|
||||
}
|
||||
else if (result == 0)
|
||||
{
|
||||
Log(lsDEBUG) << " success";
|
||||
assert(ledger->hasTransaction(item->getTag()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << " hard fail";
|
||||
assert(!ledger->hasTransaction(item->getTag()));
|
||||
}
|
||||
applyTransaction(engine, txn, ledger, failedTransactions, final);
|
||||
#ifndef TRUST_NETWORK
|
||||
}
|
||||
catch (...)
|
||||
@@ -624,8 +694,7 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led
|
||||
{
|
||||
try
|
||||
{
|
||||
TransactionEngineResult result =
|
||||
engine.applyTransaction(*it->second, tepNO_CHECK_FEE | tepUPDATE_TOTAL, 0);
|
||||
TransactionEngineResult result = engine.applyTransaction(*it->second, parms, 0);
|
||||
if (result <= 0)
|
||||
{
|
||||
if (result == 0) ++successes;
|
||||
@@ -666,11 +735,12 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
#endif
|
||||
|
||||
CanonicalTXSet failedTransactions(set->getHash());
|
||||
applyTransactions(set, newLCL, failedTransactions);
|
||||
applyTransactions(set, newLCL, failedTransactions, true);
|
||||
newLCL->setClosed();
|
||||
newLCL->setAccepted();
|
||||
newLCL->updateHash();
|
||||
uint256 newLCLHash = newLCL->getHash();
|
||||
Log(lsTRACE) << "newLCL " << newLCLHash.GetHex();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (1)
|
||||
@@ -702,7 +772,29 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
#endif
|
||||
|
||||
ScopedLock sl = theApp->getMasterLedger().getLock();
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, failedTransactions);
|
||||
|
||||
// Apply disputed transactions that didn't get in
|
||||
TransactionEngine engine(newOL);
|
||||
for (boost::unordered_map<uint256, LCTransaction::pointer>::iterator it = mDisputes.begin(),
|
||||
end = mDisputes.end(); it != end; ++it)
|
||||
{
|
||||
if (!it->second->getOurPosition())
|
||||
{ // we voted NO
|
||||
try
|
||||
{
|
||||
SerializerIterator sit(it->second->peekTransaction());
|
||||
SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
applyTransaction(engine, txn, newOL, failedTransactions, false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsINFO) << "Failed to apply transaction we voted NO on";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL,
|
||||
failedTransactions, false);
|
||||
theApp->getMasterLedger().pushLedger(newLCL, newOL);
|
||||
mState = lcsACCEPTED;
|
||||
sl.unlock();
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "LedgerProposal.h"
|
||||
#include "Peer.h"
|
||||
#include "CanonicalTXSet.h"
|
||||
#include "TransactionEngine.h"
|
||||
|
||||
class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this<TransactionAcquire>
|
||||
{ // A transaction set we are trying to acquire
|
||||
@@ -47,7 +48,7 @@ protected:
|
||||
uint256 mTransactionID;
|
||||
int mYays, mNays;
|
||||
bool mOurPosition;
|
||||
std::vector<unsigned char> transaction;
|
||||
Serializer transaction;
|
||||
boost::unordered_map<uint160, bool> mVotes;
|
||||
|
||||
public:
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
|
||||
const uint256& getTransactionID() const { return mTransactionID; }
|
||||
bool getOurPosition() const { return mOurPosition; }
|
||||
const std::vector<unsigned char>& peekTransaction() { return transaction; }
|
||||
Serializer& peekTransaction() { return transaction; }
|
||||
|
||||
void setVote(const uint160& peer, bool votesYes);
|
||||
|
||||
@@ -106,6 +107,7 @@ protected:
|
||||
void startAcquiring(TransactionAcquire::pointer);
|
||||
SHAMap::pointer find(const uint256& hash);
|
||||
|
||||
void createDisputes(SHAMap::pointer, SHAMap::pointer);
|
||||
void addDisputedTransaction(const uint256&, const std::vector<unsigned char>& transaction);
|
||||
void adjustCount(SHAMap::pointer map, const std::vector<uint160>& peers);
|
||||
void propose(const std::vector<uint256>& addedTx, const std::vector<uint256>& removedTx);
|
||||
@@ -114,7 +116,9 @@ protected:
|
||||
void removePosition(LedgerProposal&, bool ours);
|
||||
void sendHaveTxSet(const uint256& set, bool direct);
|
||||
void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger,
|
||||
CanonicalTXSet& failedTransactions);
|
||||
CanonicalTXSet& failedTransactions, bool final);
|
||||
void applyTransaction(TransactionEngine& engine, SerializedTransaction::pointer txn, Ledger::pointer targetLedger,
|
||||
CanonicalTXSet& failedTransactions, bool final);
|
||||
|
||||
// manipulating our own position
|
||||
void takeInitialPosition(Ledger::pointer initialLedger);
|
||||
|
||||
@@ -12,11 +12,15 @@
|
||||
// Time before we take a position
|
||||
# define LEDGER_WOBBLE_TIME 1
|
||||
|
||||
// Time we expect avalanche to finish
|
||||
// Time we acceleratet avalanche
|
||||
# define LEDGER_ACCEL_CONVERGE 10
|
||||
|
||||
// Time we permit avalanche to finish
|
||||
# define LEDGER_CONVERGE 14
|
||||
|
||||
// Time we forcibly abort avalanche
|
||||
# define LEDGER_FORCE_CONVERGE 18
|
||||
// Maximum converge time
|
||||
# define LEDGER_MAX_CONVERGE 22
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,9 +28,10 @@
|
||||
|
||||
# define LEDGER_INTERVAL 1800
|
||||
|
||||
# define LEDGER_CONVERGE 180
|
||||
# define LEDGER_FORCE_CONVERGE 180
|
||||
|
||||
# define LEDGER_CONVERGE 240
|
||||
|
||||
# define LEDGER_FORCE_CONVERGE 240
|
||||
|
||||
// Time a transaction must be unconflicted before we consider it protected
|
||||
# define LEDGER_PROTECT 90
|
||||
|
||||
@@ -392,7 +392,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
// check if the ledger is good enough to go to omFULL
|
||||
// Note: Do not go to omFULL if we don't have the previous ledger
|
||||
// check if the ledger is bad enough to go to omCONNECTED -- TODO
|
||||
if (!switchLedgers) setMode(omFULL);
|
||||
if ((!switchLedgers) && theConfig.VALIDATION_SEED.isValid()) setMode(omFULL);
|
||||
}
|
||||
|
||||
if (mMode == omFULL)
|
||||
@@ -489,7 +489,11 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash,
|
||||
// Is this node on our UNL?
|
||||
// XXX Is this right?
|
||||
if (!theApp->getUNL().nodeInUNL(naPeerPublic))
|
||||
{
|
||||
Log(lsINFO) << "Relay, but no process peer proposal " << proposal->getProposeSeq() << "/"
|
||||
<< proposal->getCurrentHash().GetHex();
|
||||
return true;
|
||||
}
|
||||
|
||||
return consensus->peerPosition(proposal);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,6 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip
|
||||
{
|
||||
std::cerr << "Connect peer: success." << std::endl;
|
||||
|
||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||
|
||||
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::client,
|
||||
@@ -224,7 +223,6 @@ void Peer::connected(const boost::system::error_code& error)
|
||||
mIpPort = make_pair(strIp, iPort);
|
||||
assert(!mIpPort.first.empty());
|
||||
|
||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||
|
||||
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::server,
|
||||
@@ -828,7 +826,6 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
return;
|
||||
}
|
||||
memcpy(ledgerhash.begin(), packet.ledgerhash().data(), 32);
|
||||
Log(lsINFO) << "Query by hash: " << ledgerhash.GetHex();
|
||||
ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash);
|
||||
}
|
||||
else if (packet.has_ledgerseq())
|
||||
@@ -913,7 +910,6 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
}
|
||||
if (packet.has_requestcookie()) reply.set_requestcookie(packet.requestcookie());
|
||||
PackedMessage::pointer oPacket = boost::make_shared<PackedMessage>(reply, newcoin::mtLEDGER_DATA);
|
||||
Log(lsTRACE) << "sending reply";
|
||||
sendPacket(oPacket);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +92,6 @@ Json::Value RPCServer::RPCError(int iError)
|
||||
|
||||
void RPCServer::connected()
|
||||
{
|
||||
|
||||
//BOOST_LOG_TRIVIAL(info) << "RPC request";
|
||||
//std::cout << "RPC request" << std::endl;
|
||||
|
||||
mSocket.async_read_some(boost::asio::buffer(mReadBuffer),
|
||||
|
||||
@@ -228,6 +228,10 @@ SHAMapItem::SHAMapItem(const uint256& tag, const std::vector<unsigned char>& dat
|
||||
: mTag(tag), mData(data)
|
||||
{ ; }
|
||||
|
||||
SHAMapItem::SHAMapItem(const uint256& tag, const Serializer& data)
|
||||
: mTag(tag), mData(data.peekData())
|
||||
{ ; }
|
||||
|
||||
SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode* node)
|
||||
{
|
||||
// Return the first item below this node
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
|
||||
SHAMapItem(const uint256& tag) : mTag(tag) { ; }
|
||||
SHAMapItem(const uint256& tag, const std::vector<unsigned char>& data);
|
||||
SHAMapItem(const uint256& tag, const Serializer& s);
|
||||
SHAMapItem(const std::vector<unsigned char>& data); // tag by hash
|
||||
|
||||
const uint256& getTag() const { return mTag; }
|
||||
|
||||
@@ -60,7 +60,7 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsTRACE) << "Got sync node from cache";
|
||||
Log(lsTRACE) << "Got sync node from cache: " << d->getString();
|
||||
mTNByID[*d] = d;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,9 +523,14 @@ bool Transaction::save()
|
||||
default: status = TXN_SQL_UNKNOWN;
|
||||
}
|
||||
|
||||
std::string exists = boost::str(boost::format("SELECT Status FROM Transactions WHERE TransID = '%s';")
|
||||
% mTransaction->getTransactionID().GetHex());
|
||||
|
||||
Database *db = theApp->getTxnDB()->getDB();
|
||||
ScopedLock dbLock = theApp->getTxnDB()->getDBLock();
|
||||
return db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";");
|
||||
if (!SQL_EXISTS(db, exists)) return false;
|
||||
return
|
||||
db->executeSQL(mTransaction->getSQLInsertHeader() + mTransaction->getSQL(getLedger(), status) + ";");
|
||||
}
|
||||
|
||||
Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
||||
|
||||
Reference in New Issue
Block a user