Move LCT code to the right file.

Be smarter in the consensus set filter code.
This commit is contained in:
JoelKatz
2013-03-20 09:22:30 -07:00
parent d8a384467a
commit 371d52cc9e
3 changed files with 147 additions and 117 deletions

View File

@@ -9,10 +9,10 @@
#include "Application.h"
#include "NetworkOPs.h"
#include "LedgerTiming.h"
#include "SerializedValidation.h"
#include "Log.h"
#include "SHAMapSync.h"
#include "HashPrefixes.h"
#define TX_ACQUIRE_TIMEOUT 250
@@ -174,127 +174,46 @@ SMAddNode TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
}
}
void LCTransaction::setVote(const uint160& peer, bool votesYes)
{ // Track a peer's yes/no vote on a particular disputed transaction
std::pair<boost::unordered_map<const uint160, bool>::iterator, bool> res =
mVotes.insert(std::pair<const uint160, bool>(peer, votesYes));
if (res.second)
{ // new vote
if (votesYes)
{
cLog(lsDEBUG) << "Peer " << peer << " votes YES on " << mTransactionID;
++mYays;
}
else
{
cLog(lsDEBUG) << "Peer " << peer << " votes NO on " << mTransactionID;
++mNays;
}
}
else if (votesYes && !res.first->second)
{ // changes vote to yes
cLog(lsDEBUG) << "Peer " << peer << " now votes YES on " << mTransactionID;
--mNays;
++mYays;
res.first->second = true;
}
else if (!votesYes && res.first->second)
{ // changes vote to no
cLog(lsDEBUG) << "Peer " << peer << " now votes NO on " << mTransactionID;
++mNays;
--mYays;
res.first->second = false;
}
}
void LCTransaction::unVote(const uint160& peer)
{ // Remove a peer's vote on this disputed transasction
boost::unordered_map<uint160, bool>::iterator it = mVotes.find(peer);
if (it != mVotes.end())
{
if (it->second)
--mYays;
else
--mNays;
mVotes.erase(it);
}
}
bool LCTransaction::updateVote(int percentTime, bool proposing)
{
if (mOurVote && (mNays == 0))
return false;
if (!mOurVote && (mYays == 0))
return false;
bool newPosition;
int weight;
if (proposing) // give ourselves full weight
{
// This is basically the percentage of nodes voting 'yes' (including us)
weight = (mYays * 100 + (mOurVote ? 100 : 0)) / (mNays + mYays + 1);
// To prevent avalanche stalls, we increase the needed weight slightly over time
if (percentTime < AV_MID_CONSENSUS_TIME)
newPosition = weight > AV_INIT_CONSENSUS_PCT;
else if (percentTime < AV_LATE_CONSENSUS_TIME)
newPosition = weight > AV_MID_CONSENSUS_PCT;
else if (percentTime < AV_STUCK_CONSENSUS_TIME)
newPosition = weight > AV_LATE_CONSENSUS_PCT;
else
newPosition = weight > AV_STUCK_CONSENSUS_PCT;
}
else // don't let us outweigh a proposing node, just recognize consensus
{
weight = -1;
newPosition = mYays > mNays;
}
if (newPosition == mOurVote)
{
cLog(lsINFO) <<
"No change (" << (mOurVote ? "YES" : "NO") << ") : weight " << weight << ", percent " << percentTime;
cLog(lsDEBUG) << getJson();
return false;
}
mOurVote = newPosition;
cLog(lsDEBUG) << "We now vote " << (mOurVote ? "YES" : "NO") << " on " << mTransactionID;
cLog(lsDEBUG) << getJson();
return true;
}
Json::Value LCTransaction::getJson()
{
Json::Value ret(Json::objectValue);
ret["yays"] = mYays;
ret["nays"] = mNays;
ret["our_vote"] = mOurVote;
if (!mVotes.empty())
{
Json::Value votesj(Json::objectValue);
typedef boost::unordered_map<uint160, bool>::value_type vt;
BOOST_FOREACH(vt& vote, mVotes)
{
votesj[vote.first.GetHex()] = vote.second;
}
ret["votes"] = votesj;
}
return ret;
}
void ConsensusTransSetSF::gotNode(const SHAMapNode& id, const uint256& nodeHash,
const std::vector<unsigned char>& nodeData, SHAMapTreeNode::TNType)
const std::vector<unsigned char>& nodeData, SHAMapTreeNode::TNType type)
{
// WRITEME: If 'isLeaf' is true, this is a transaction
theApp->getTempNodeCache().store(nodeHash, nodeData);
if ((type == SHAMapTreeNode::tnTRANSACTION_NM) && (nodeData.size() > 16))
{ // this is a transaction, and we didn't have it
cLog(lsDEBUG) << "Node on our acquiring TX set is TXN we don't have";
try
{
Serializer s(nodeData.begin() + 4, nodeData.end()); // skip prefix
SerializerIterator sit(s);
SerializedTransaction::pointer stx = boost::make_shared<SerializedTransaction>(boost::ref(sit));
assert(stx->getTransactionID() == nodeHash);
theApp->getJobQueue().addJob(jtTRANSACTION, "TXS->TXN",
BIND_TYPE(&NetworkOPs::submitTransaction, &theApp->getOPs(), P_1, stx, NetworkOPs::stCallback()));
}
catch (...)
{
cLog(lsWARNING) << "Fetched invalid transaction in proposed set";
}
}
}
bool ConsensusTransSetSF::haveNode(const SHAMapNode& id, const uint256& nodeHash,
std::vector<unsigned char>& nodeData)
{
// WRITEME: We could check our own map, we could check transaction tables
return theApp->getTempNodeCache().retrieve(nodeHash, nodeData);
if (theApp->getTempNodeCache().retrieve(nodeHash, nodeData))
return true;
Transaction::pointer txn = Transaction::load(nodeHash);
if (txn)
{ // this is a transaction, and we have it
cLog(lsDEBUG) << "Node in our acquiring TX set is TXN we have";
Serializer s;
s.add32(sHP_TransactionID);
txn->getSTransaction()->add(s, true);
assert(s.getSHA512Half() == nodeHash);
nodeData = s.peekData();
return true;
}
return false;
}