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

This commit is contained in:
jed
2012-06-23 22:54:07 -07:00
18 changed files with 179 additions and 163 deletions

View File

@@ -527,14 +527,14 @@ STAmount::operator double() const
}
STAmount operator+(const STAmount& v1, const STAmount& v2)
{ // We can check for precision loss here (value%10)!=0
// FIXME
{
if (v1.isZero()) return v2;
if (v2.isZero()) return v1;
v1.throwComparable(v2);
if (v1.mIsNative)
return STAmount(v1.name, v1.getSNValue() + v2.getSNValue());
if (v1.isZero()) return v2;
if (v2.isZero()) return v1;
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<int64>(v2.mValue);
@@ -562,14 +562,12 @@ STAmount operator+(const STAmount& v1, const STAmount& v2)
STAmount operator-(const STAmount& v1, const STAmount& v2)
{
if (v2.isZero()) return v1;
v1.throwComparable(v2);
if (v2.mIsNative)
return STAmount(v1.name, v1.getSNValue() - v2.getSNValue());
if (v2.isZero()) return v1;
if (v1.isZero() || (v2.mOffset > v1.mOffset) )
throw std::runtime_error("value underflow");
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<int64>(v2.mValue);
if (v1.mIsNegative) vv1 = -vv1;

View File

@@ -37,7 +37,7 @@ DatabaseCon::~DatabaseCon()
Application::Application() :
mUNL(mIOService),
mNetOps(mIOService, &mMasterLedger), mNodeCache(16384, 600),
mNetOps(mIOService, &mMasterLedger), mNodeCache(16384, 600), mHashedObjectStore(16384, 300),
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
{

View File

@@ -49,6 +49,7 @@ class Application
NodeCache mNodeCache;
ValidationCollection mValidations;
SuppressionTable mSuppressions;
HashedObjectStore mHashedObjectStore;
DatabaseCon *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
@@ -80,9 +81,10 @@ public:
LedgerAcquireMaster& getMasterLedgerAcquire() { return mMasterLedgerAcquire; }
TransactionMaster& getMasterTransaction() { return mMasterTransaction; }
NodeCache& getNodeCache() { return mNodeCache; }
HashedObjectStore& getHashedObjectStore() { return mHashedObjectStore; }
ValidationCollection& getValidations() { return mValidations; }
bool suppress(const uint256& s) { return mSuppressions.addSuppression(s); }
bool suppress(const uint160& s) { return mSuppressions.addSuppression(s); }
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
bool isNew(const uint160& s) { return mSuppressions.addSuppression(s); }
DatabaseCon* getTxnDB() { return mTxnDB; }
DatabaseCon* getLedgerDB() { return mLedgerDB; }

View File

@@ -7,7 +7,6 @@
#include "Application.h"
#include "Log.h"
bool HashedObject::checkHash() const
{
uint256 hash = Serializer::getSHA512Half(mData);
@@ -27,18 +26,19 @@ void HashedObject::setHash()
mHash = Serializer::getSHA512Half(mData);
}
// FIXME: Stores should be added to a queue that's services by an auxilliary thread or from an
// FIXME: Stores should be added to a queue that's serviced 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)
bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
const uint256& hash)
bool HashedObjectStore::store(HashedObjectType type, uint32 index,
const std::vector<unsigned char>& data, const uint256& hash)
{
if (!theApp->getHashNodeDB()) return true;
#ifdef DEBUG
Serializer s(data);
assert(hash == s.getSHA512Half());
#endif
HashedObject::pointer object = boost::make_shared<HashedObject>(type, index, data);
object->setHash();
if (object->getHash() != hash)
throw std::runtime_error("Object added to store doesn't have valid hash");
std::string sql = "INSERT INTO CommittedObjects (Hash,ObjType,LedgerIndex,Object) VALUES ('";
sql.append(hash.GetHex());
switch(type)
@@ -51,32 +51,32 @@ bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<
}
sql.append(boost::lexical_cast<std::string>(index));
sql.append("',");
std::string obj;
theApp->getHashNodeDB()->getDB()->escape(&(data.front()), data.size(), obj);
sql.append(obj);
sql.append(");");
std::string exists =
boost::str(boost::format("SELECT ObjType FROM CommittedObject WHERE Hash = '%s';") % hash.GetHex());
boost::str(boost::format("SELECT ObjType FROM CommittedObjects WHERE Hash = '%s';") % hash.GetHex());
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
if (mCache.canonicalize(hash, object))
return false;
Database* db = theApp->getHashNodeDB()->getDB();
if (SQL_EXISTS(db, exists))
return false;
return db->executeSQL(sql);
}
bool HashedObject::store() const
HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash)
{
#ifdef DEBUG
assert(checkHash());
#endif
return store(mType, mLedgerIndex, mData, mHash);
}
HashedObject::pointer obj;
{
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
obj = mCache.fetch(hash);
if (obj) return obj;
}
HashedObject::pointer HashedObject::retrieve(const uint256& hash)
{
if (!theApp || !theApp->getHashNodeDB()) return HashedObject::pointer();
std::string sql = "SELECT * FROM CommittedObjects WHERE Hash='";
sql.append(hash.GetHex());
@@ -102,34 +102,37 @@ HashedObject::pointer HashedObject::retrieve(const uint256& hash)
data.resize(size);
db->getBinary("Object", &(data.front()), size);
db->endIterRows();
}
HashedObjectType htype = UNKNOWN;
switch(type[0])
{
case 'L': htype = LEDGER; break;
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();
}
HashedObjectType htype = UNKNOWN;
switch(type[0])
{
case 'L': htype = LEDGER; break;
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);
obj->mHash = hash;
obj = boost::make_shared<HashedObject>(htype, index, data);
obj->mHash = hash;
mCache.canonicalize(hash, obj);
}
#ifdef DEBUG
assert(obj->checkHash());
#endif
return obj;
}
HashedObjectBulkWriter::HashedObjectBulkWriter() : sl(theApp->getHashNodeDB()->getDBLock())
ScopedLock HashedObjectStore::beginBulk()
{
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
theApp->getHashNodeDB()->getDB()->executeSQL("BEGIN TRANSACTION;");
return sl;
}
HashedObjectBulkWriter::~HashedObjectBulkWriter()
void HashedObjectStore::endBulk()
{
theApp->getHashNodeDB()->getDB()->executeSQL("END TRANSACTION;");
}

View File

@@ -6,6 +6,7 @@
#include "types.h"
#include "uint256.h"
#include "ScopedLock.h"
#include "TaggedCache.h"
enum HashedObjectType
{
@@ -34,29 +35,41 @@ public:
void setHash();
const std::vector<unsigned char>& getData() { return mData; }
const uint256& getHash() { return mHash; }
};
bool store() const;
class HashedObjectStore
{
protected:
TaggedCache<uint256, HashedObject> mCache;
static bool store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
public:
HashedObjectStore(int cacheSize, int cacheAge) : mCache(cacheSize, cacheAge) { ; }
bool store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
const uint256& hash);
static HashedObject::pointer retrieve(const uint256& hash);
HashedObject::pointer retrieve(const uint256& hash);
ScopedLock beginBulk();
void endBulk();
};
class HashedObjectBulkWriter
{
protected:
HashedObjectStore& mStore;
ScopedLock sl;
public:
HashedObjectBulkWriter(HashedObjectStore& ostore) : mStore(ostore), sl(mStore.beginBulk()) { ; }
~HashedObjectBulkWriter() { mStore.endBulk(); }
HashedObjectBulkWriter();
~HashedObjectBulkWriter();
bool store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
const uint256& hash) { return mStore.store(type, index, data, hash); }
bool store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data, const uint256& hash)
{ return HashedObject::store(type, index, data, hash); }
HashedObject::pointer retrieve(const uint256& hash)
{ return HashedObject::retrieve(hash); }
HashedObject::pointer retrieve(const uint256& hash) { return mStore.retrieve(hash); }
};
#endif

View File

@@ -11,8 +11,8 @@
#define LA_DEBUG
#define LEDGER_ACQUIRE_TIMEOUT 2
PeerSet::PeerSet(const uint256& hash, int interval) : mHash(hash), mTimerInterval(interval),
mComplete(false), mFailed(false), mTimer(theApp->getIOService())
PeerSet::PeerSet(const uint256& hash, int interval) : mHash(hash), mTimerInterval(interval), mTimeouts(0),
mComplete(false), mFailed(false), mProgress(true), mTimer(theApp->getIOService())
{ ; }
void PeerSet::peerHas(Peer::pointer ptr)
@@ -61,11 +61,24 @@ void PeerSet::resetTimer()
mTimer.async_wait(boost::bind(&PeerSet::TimerEntry, pmDowncast(), boost::asio::placeholders::error));
}
void PeerSet::invokeOnTimer()
{
if (!mProgress)
{
++mTimeouts;
Log(lsWARNING) << "Timeout " << mTimeouts << " acquiring " << mHash.GetHex();
}
else
mProgress = false;
onTimer();
}
void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::error_code& result)
{
if (result == boost::asio::error::operation_aborted) return;
boost::shared_ptr<PeerSet> ptr = wptr.lock();
if (!!ptr) ptr->onTimer();
if (!ptr) return;
ptr->invokeOnTimer();
}
LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE_TIMEOUT),
@@ -284,6 +297,7 @@ bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer)
return false;
}
mHaveBase = true;
progress();
if (!mLedger->getTransHash()) mHaveTransactions = true;
if (!mLedger->getAccountHash()) mHaveState = true;
mLedger->setAcquiring();
@@ -315,6 +329,7 @@ bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
if (mHaveState) mComplete = true;
}
trigger(peer);
progress();
return true;
}
@@ -345,6 +360,7 @@ bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
if (mHaveTransactions) mComplete = true;
}
trigger(peer);
progress();
return true;
}

View File

@@ -20,8 +20,8 @@ class PeerSet
{
protected:
uint256 mHash;
int mTimerInterval;
bool mComplete, mFailed;
int mTimerInterval, mTimeouts;
bool mComplete, mFailed, mProgress;
boost::recursive_mutex mLock;
boost::asio::deadline_timer mTimer;
@@ -37,6 +37,9 @@ public:
const uint256& getHash() const { return mHash; }
bool isComplete() const { return mComplete; }
bool isFailed() const { return mFailed; }
int getTimeouts() const { return mTimeouts; }
void progress() { mProgress = true; }
void peerHas(Peer::pointer);
void badPeer(Peer::pointer);
@@ -49,6 +52,7 @@ protected:
void setComplete() { mComplete = true; }
void setFailed() { mFailed = true; }
void invokeOnTimer();
private:
static void TimerEntry(boost::weak_ptr<PeerSet>, const boost::system::error_code& result);

View File

@@ -110,6 +110,7 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
++nodeDatait;
}
trigger(peer);
progress();
return true;
}
catch (...)
@@ -426,7 +427,6 @@ int LedgerConsensus::timerEntry()
theApp->getOPs().switchLastClosedLedger(consensus);
mPreviousLedger = consensus;
mHaveCorrectLCL = true;
// FIXME: We need some kind of idea what the consensus transaction set is
}
}
@@ -589,10 +589,7 @@ bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition)
{
assert(newPosition->getPeerID() == currentPosition->getPeerID());
if (newPosition->getProposeSeq() <= currentPosition->getProposeSeq())
{
Log(lsINFO) << "Redundant/stale positon";
return false;
}
if (newPosition->getCurrentHash() == currentPosition->getCurrentHash())
{ // we missed an intermediary change
Log(lsINFO) << "We missed an intermediary position";
@@ -672,7 +669,7 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, SerializedTran
if (result > 0)
{
Log(lsINFO) << " retry";
// assert(!ledger->hasTransaction(txn->getTransactionID())); FIXME: We get these (doPasswordSet)
assert(!ledger->hasTransaction(txn->getTransactionID()));
failedTransactions.push_back(txn);
}
else if (result == 0)
@@ -757,17 +754,6 @@ void LedgerConsensus::accept(SHAMap::pointer set)
Ledger::pointer newLCL = boost::make_shared<Ledger>(false, boost::ref(*mPreviousLedger));
newLCL->armDirty();
#ifdef DEBUG
Json::StyledStreamWriter ssw;
if (1)
{
Log(lsTRACE) << "newLCL before transactions";
Json::Value p;
newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
ssw.write(Log(lsTRACE).ref(), p);
}
#endif
CanonicalTXSet failedTransactions(set->getHash());
applyTransactions(set, newLCL, failedTransactions, true);
newLCL->setClosed();
@@ -775,27 +761,23 @@ void LedgerConsensus::accept(SHAMap::pointer set)
newLCL->updateHash();
uint256 newLCLHash = newLCL->getHash();
Log(lsTRACE) << "newLCL " << newLCLHash.GetHex();
statusChange(newcoin::neACCEPTED_LEDGER, newLCL);
if (mValidating)
{
assert (theApp->getOPs().getNetworkTimeNC() > newLCL->getCloseTimeNC());
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
(newLCLHash, newLCL->getCloseTimeNC(), mValSeed, mProposing);
v->setTrusted();
theApp->getValidations().addValidation(v);
std::vector<unsigned char> validation = v->getSigned();
newcoin::TMValidation val;
val.set_validation(&validation[0], validation.size());
theApp->getConnectionPool().relayMessage(NULL, boost::make_shared<PackedMessage>(val, newcoin::mtVALIDATION));
Log(lsINFO) << "Validation sent " << newLCLHash.GetHex();
}
else Log(lsWARNING) << "Not validating";
Ledger::pointer newOL = boost::make_shared<Ledger>(true, boost::ref(*newLCL));
#ifdef DEBUG
if (1)
{
Log(lsTRACE) << "newOL before transactions";
Json::Value p;
newOL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
ssw.write(Log(lsTRACE).ref(), p);
}
if (1)
{
Log(lsTRACE) << "current ledger";
Json::Value p;
theApp->getMasterLedger().getCurrentLedger()->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
ssw.write(Log(lsTRACE).ref(), p);
}
#endif
ScopedLock sl = theApp->getMasterLedger().getLock();
// Apply disputed transactions that didn't get in
@@ -825,35 +807,15 @@ void LedgerConsensus::accept(SHAMap::pointer set)
sl.unlock();
#ifdef DEBUG
Json::StyledStreamWriter ssw;
if (1)
{
Log(lsTRACE) << "newOL after current ledger transactions";
Log(lsTRACE) << "newLCL";
Json::Value p;
newOL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
ssw.write(Log(lsTRACE).ref(), p);
Log(lsINFO) << "newLCL after transactions";
Json::Value p2;
newLCL->addJson(p2, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
ssw.write(Log(lsTRACE).ref(), p2);
}
#endif
if (mValidating)
{
assert (theApp->getOPs().getNetworkTimeNC() > newLCL->getCloseTimeNC());
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
(newLCLHash, newLCL->getCloseTimeNC(), mOurPosition->peekSeed(), true);
v->setTrusted();
// FIXME: If not proposing, set not full
theApp->getValidations().addValidation(v);
std::vector<unsigned char> validation = v->getSigned();
newcoin::TMValidation val;
val.set_validation(&validation[0], validation.size());
theApp->getConnectionPool().relayMessage(NULL, boost::make_shared<PackedMessage>(val, newcoin::mtVALIDATION));
Log(lsINFO) << "Validation sent " << newLCLHash.GetHex();
}
else Log(lsWARNING) << "Not validating";
statusChange(newcoin::neACCEPTED_LEDGER, newLCL);
// FIXME: If necessary, change state to TRACKING/FULL
}

View File

@@ -22,7 +22,6 @@ LedgerProposal::LedgerProposal(const uint256& pLgr, uint32 seq, const uint256& t
LedgerProposal::LedgerProposal(const NewcoinAddress& naSeed, const uint256& prevLgr, const uint256& position) :
mPreviousLedger(prevLgr), mCurrentHash(position), mProposeSeq(0)
{
mSeed = naSeed;
mPublicKey = NewcoinAddress::createNodePublic(naSeed);
mPrivateKey = NewcoinAddress::createNodePrivate(naSeed);
mPeerID = mPublicKey.getNodeID();
@@ -46,9 +45,9 @@ uint256 LedgerProposal::getSigningHash() const
return s.getSHA512Half();
}
bool LedgerProposal::checkSign(const std::string& signature)
bool LedgerProposal::checkSign(const std::string& signature, const uint256& signingHash)
{
return mPublicKey.verifyNodePublic(getSigningHash(), signature);
return mPublicKey.verifyNodePublic(signingHash, signature);
}
void LedgerProposal::changePosition(const uint256& newPosition)

View File

@@ -16,9 +16,8 @@ protected:
uint32 mProposeSeq;
uint160 mPeerID;
NewcoinAddress mPublicKey; // Peer
NewcoinAddress mPrivateKey; // Our's
NewcoinAddress mSeed; // Our's
NewcoinAddress mPublicKey;
NewcoinAddress mPrivateKey; // If ours
static const uint32 sProposeMagic = 0x50525000; // PRP
@@ -27,22 +26,24 @@ public:
typedef boost::shared_ptr<LedgerProposal> pointer;
// proposal from peer
LedgerProposal(const uint256& prevLgr, uint32 proposeSeq, const uint256& propose, const NewcoinAddress& naPeerPublic);
LedgerProposal(const uint256& prevLgr, uint32 proposeSeq, const uint256& propose,
const NewcoinAddress& naPeerPublic);
// our first proposal
LedgerProposal(const NewcoinAddress& naSeed, const uint256& prevLedger, const uint256& position);
LedgerProposal(const NewcoinAddress& privKey, const uint256& prevLedger, const uint256& position);
// an unsigned proposal
LedgerProposal(const uint256& prevLedger, const uint256& position);
uint256 getSigningHash() const;
bool checkSign(const std::string& signature);
bool checkSign(const std::string& signature, const uint256& signingHash);
bool checkSign(const std::string& signature) { return checkSign(signature, getSigningHash()); }
const uint160& getPeerID() const { return mPeerID; }
const uint256& getCurrentHash() const { return mCurrentHash; }
const uint256& getPrevLedger() const { return mPreviousLedger; }
uint32 getProposeSeq() const { return mProposeSeq; }
const NewcoinAddress& peekSeed() const { return mSeed; }
const NewcoinAddress& peekPublic() const { return mPublicKey; }
std::vector<unsigned char> getPubKey() const { return mPublicKey.getNodePublic(); }
std::vector<unsigned char> sign();

View File

@@ -19,7 +19,7 @@
# define LEDGER_CONVERGE 14
// Maximum converge time
# define LEDGER_MAX_CONVERGE 22
# define LEDGER_MAX_CONVERGE 20
#endif

View File

@@ -98,7 +98,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
}
Log(lsDEBUG) << "Status other than success " << r ;
if ((mMode != omFULL) && (theApp->suppress(trans->getID())))
if ((mMode != omFULL) && (mMode != omTRACKING) && (theApp->isNew(trans->getID())))
{
newcoin::TMTransaction tx;
Serializer s;
@@ -432,26 +432,26 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
}
if (!acq->isComplete())
{ // add more peers
//JED: seems like you need to do something here so it knows in beginConsensus that it isn't on the the right ledger
// switch to an empty ledger so we won't keep going
//Ledger::pointer emptyLedger(new Ledger());
//switchLastClosedLedger(emptyLedger);
// JED: just ask everyone
int count = 0;
std::vector<Peer::pointer> peers=theApp->getConnectionPool().getPeerVector();
for(int n=0; n<peers.size(); n++)
{
if(peers[n]->isConnected()) acq->peerHas(peers[n]);
}
/* JED this wasn't adding any peers. This is also an optimization so we can do this later
// FIXME: A peer may not have a ledger just because it accepts it as the network's consensus
for (std::vector<Peer::pointer>::const_iterator it = peerList.begin(), end = peerList.end();
it != end; ++it)
{
if ((*it)->getClosedLedgerHash() == closedLedger)
{
++count;
acq->peerHas(*it);
}*/
}
}
if (!count)
{ // just ask everyone
for (std::vector<Peer::pointer>::const_iterator it = peerList.begin(), end = peerList.end();
it != end; ++it)
{
if ((*it)->isConnected())
acq->peerHas(*it);
}
}
return true;
}
consensus = acq->getLedger();
@@ -521,20 +521,28 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash,
// XXX Validate key.
// XXX Take a vuc for pubkey.
NewcoinAddress naPeerPublic = NewcoinAddress::createNodePublic(strCopy(pubKey));
if (mMode != omFULL)
// Get a preliminary hash to use to suppress duplicates
Serializer s;
s.add32(proposeSeq);
s.add32(getCurrentLedgerID());
s.addRaw(pubKey);
if (!theApp->isNew(s.getSHA512Half()))
return false;
if ((mMode != omFULL) && (mMode != omTRACKING))
{
Log(lsINFO) << "Received proposal when not full: " << mMode;
Serializer s(signature);
return theApp->suppress(s.getSHA512Half());
Log(lsINFO) << "Received proposal when not full/tracking: " << mMode;
return true;
}
if (!mConsensus)
{
Log(lsWARNING) << "Received proposal when full but not during consensus window";
return false;
}
NewcoinAddress naPeerPublic = NewcoinAddress::createNodePublic(strCopy(pubKey));
LedgerProposal::pointer proposal =
boost::make_shared<LedgerProposal>(mConsensus->getLCL(), proposeSeq, proposeHash, naPeerPublic);
if (!proposal->checkSign(signature))
@@ -545,15 +553,14 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash,
// Is this node on our UNL?
// XXX Is this right?
if (!theApp->getUNL().nodeInUNL(naPeerPublic))
if (!theApp->getUNL().nodeInUNL(proposal->peekPublic()))
{
Log(lsINFO) << "Relay, but no process peer proposal " << proposal->getProposeSeq() << "/"
<< proposal->getCurrentHash().GetHex();
Log(lsINFO) << "Untrusted proposal: " << naPeerPublic.humanNodePublic() << " " <<
proposal->getCurrentHash().GetHex();
return true;
}
return mConsensus->peerPosition(proposal);
}
SHAMap::pointer NetworkOPs::getTXMap(const uint256& hash)
@@ -640,7 +647,6 @@ std::vector< std::pair<uint32, uint256> >
bool NetworkOPs::recvValidation(SerializedValidation::pointer val)
{
Log(lsINFO) << "recvValidation " << val->getLedgerHash().GetHex();
return theApp->getValidations().addValidation(val);
}

View File

@@ -730,16 +730,23 @@ void Peer::recvValidation(newcoin::TMValidation& packet)
punishPeer(PP_UNKNOWN_REQUEST);
return;
}
try
{
Serializer s(packet.validation());
SerializerIterator sit(s);
SerializedValidation::pointer val = boost::make_shared<SerializedValidation>(boost::ref(sit));
if (!val->isValid())
SerializedValidation::pointer val = boost::make_shared<SerializedValidation>(boost::ref(sit), false);
uint256 signingHash = val->getSigningHash();
if (!theApp->isNew(signingHash))
return;
if (!val->isValid(signingHash))
{
punishPeer(PP_UNKNOWN_REQUEST);
return;
}
if (theApp->getOPs().recvValidation(val))
{
PackedMessage::pointer message = boost::make_shared<PackedMessage>(packet, newcoin::mtVALIDATION);
@@ -852,7 +859,7 @@ void Peer::recvAccount(newcoin::TMAccount& packet)
void Peer::recvStatus(newcoin::TMStatusChange& packet)
{
Log(lsTRACE) << "Received status change from peer" << getIP();
Log(lsTRACE) << "Received status change from peer " << getIP();
if (!packet.has_networktime())
packet.set_networktime(theApp->getOPs().getNetworkTimeNC());
mLastStatus = packet;

View File

@@ -623,7 +623,7 @@ void SHAMapItem::dump()
bool SHAMap::fetchNode(const uint256& hash, std::vector<unsigned char>& data)
{
HashedObject::pointer obj(HashedObject::retrieve(hash));
HashedObject::pointer obj(theApp->getHashedObjectStore().retrieve(hash));
if(!obj) return false;
data = obj->getData();
return true;
@@ -642,7 +642,7 @@ int SHAMap::flushDirty(int maxNodes, HashedObjectType t, uint32 seq)
if(mDirtyNodes)
{
HashedObjectBulkWriter bw;
HashedObjectBulkWriter bw(theApp->getHashedObjectStore());
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>& dirtyNodes = *mDirtyNodes;
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it = dirtyNodes.begin();
while (it != dirtyNodes.end())

View File

@@ -16,7 +16,7 @@ const uint32 SerializedValidation::sValidationMagic = 0x4c575200; // "LGR"
SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature)
: STObject(sValidationFormat, sit), mSignature(sit, "Signature"), mTrusted(false)
{
if (!isValid()) throw std::runtime_error("Invalid validation");
if (checkSignature && !isValid()) throw std::runtime_error("Invalid validation");
}
SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint64 closeTime,
@@ -56,12 +56,16 @@ uint64 SerializedValidation::getCloseTime() const
}
bool SerializedValidation::isValid() const
{
return isValid(getSigningHash());
}
bool SerializedValidation::isValid(const uint256& signingHash) const
{
try
{
NewcoinAddress naPublicKey = NewcoinAddress::createNodePublic(getValueFieldVL(sfSigningKey));
return naPublicKey.isValid() && naPublicKey.verifyNodePublic(getSigningHash(), mSignature.peekValue());
return naPublicKey.isValid() && naPublicKey.verifyNodePublic(signingHash, mSignature.peekValue());
}
catch (...)
{

View File

@@ -33,6 +33,7 @@ public:
bool isTrusted() const { return mTrusted; }
CKey::pointer getSigningKey() const;
uint256 getSigningHash() const;
bool isValid(const uint256&) const;
void setTrusted() { mTrusted = true; }
void addSigned(Serializer&) const;

View File

@@ -31,6 +31,7 @@ enum TransactionEngineResult
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.
terALREADY, // The exact transaction was already in this ledger
// Other
tenFAILED = -100, // Something broke horribly
@@ -43,7 +44,6 @@ enum TransactionEngineResult
// terFAILED_BUT_COULD_SUCCEED = >0
// Conflict with ledger database: Fee claimed
// Might succeed if not conflict is not caused by transaction ordering.
terALREADY, // The transaction was already in the ledger
terBAD_SEQ, // This sequence number should be zero for prepaid transactions.
terCREATED, // Can not create a previously created account.
terDIR_FULL, // Can not add entry to full dir.

View File

@@ -36,7 +36,7 @@ bool ValidationCollection::addValidation(SerializedValidation::pointer val)
Log(lsINFO) << "Val for " << hash.GetHex() << " from " << val->getSignerPublic().humanNodePublic()
<< " added " << (val->isTrusted() ? "trusted" : "UNtrusted");
return true;
return isCurrent;
}
ValidationSet ValidationCollection::getValidations(const uint256& ledger)