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

This commit is contained in:
jed
2012-06-18 13:08:05 -07:00
15 changed files with 243 additions and 123 deletions

View File

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

View File

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

View File

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

View File

@@ -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;");
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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