mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
.
This commit is contained in:
@@ -34,6 +34,7 @@ Config::Config()
|
|||||||
|
|
||||||
TRANSACTION_FEE=1000;
|
TRANSACTION_FEE=1000;
|
||||||
ACCOUNT_FEE=1000;
|
ACCOUNT_FEE=1000;
|
||||||
|
MIN_VOTES_FOR_CONSENSUS=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::load()
|
void Config::load()
|
||||||
|
|||||||
2
Config.h
2
Config.h
@@ -24,6 +24,8 @@ public:
|
|||||||
|
|
||||||
std::string HISTORY_DIR;
|
std::string HISTORY_DIR;
|
||||||
|
|
||||||
|
int MIN_VOTES_FOR_CONSENSUS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Config();
|
Config();
|
||||||
|
|||||||
136
Ledger.cpp
136
Ledger.cpp
@@ -221,7 +221,7 @@ bool Ledger::addTransaction(TransactionPtr trans,bool checkDuplicate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't check the amounts. We will do this at the end.
|
// Don't check the amounts. We will do this at the end.
|
||||||
void Ledger::addTransactionRecalculate(TransactionPtr trans)
|
void Ledger::addTransactionAllowNeg(TransactionPtr trans)
|
||||||
{
|
{
|
||||||
uint160 fromAddress=NewcoinAddress::protobufToInternal(trans->from());
|
uint160 fromAddress=NewcoinAddress::protobufToInternal(trans->from());
|
||||||
|
|
||||||
@@ -268,47 +268,7 @@ void Ledger::addTransactionRecalculate(TransactionPtr trans)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must look for transactions to discard to make this account positive
|
|
||||||
// When we chuck transactions it might cause other accounts to need correcting
|
|
||||||
void Ledger::correctAccount(uint160& address)
|
|
||||||
{
|
|
||||||
list<uint160> effected;
|
|
||||||
|
|
||||||
// do this in reverse so we take of the higher seqnum first
|
|
||||||
for( list<TransactionPtr>::reverse_iterator iter=mTransactions.rbegin(); iter != mTransactions.rend(); )
|
|
||||||
{
|
|
||||||
TransactionPtr trans= *iter;
|
|
||||||
if(NewcoinAddress::protobufToInternal(trans->from()) == address)
|
|
||||||
{
|
|
||||||
Account fromAccount=mAccounts[address];
|
|
||||||
assert(fromAccount.second==trans->seqnum()+1);
|
|
||||||
if(fromAccount.first<0)
|
|
||||||
{
|
|
||||||
fromAccount.first += trans->amount();
|
|
||||||
fromAccount.second --;
|
|
||||||
|
|
||||||
mAccounts[address]=fromAccount;
|
|
||||||
|
|
||||||
uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest());
|
|
||||||
Account destAccount=mAccounts[destAddress];
|
|
||||||
destAccount.first -= trans->amount();
|
|
||||||
mAccounts[destAddress]=destAccount;
|
|
||||||
if(destAccount.first<0) effected.push_back(destAddress);
|
|
||||||
|
|
||||||
list<TransactionPtr>::iterator temp=mTransactions.erase( --iter.base() );
|
|
||||||
if(fromAccount.first>=0) break;
|
|
||||||
|
|
||||||
iter=list<TransactionPtr>::reverse_iterator(temp);
|
|
||||||
}else break;
|
|
||||||
}else iter--;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(uint160& address,effected)
|
|
||||||
{
|
|
||||||
correctAccount(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// start from your parent and go through every transaction
|
// start from your parent and go through every transaction
|
||||||
// calls this on its child if recursive is set
|
// calls this on its child if recursive is set
|
||||||
@@ -333,22 +293,15 @@ void Ledger::recalculate(bool recursive)
|
|||||||
// don't check balances until the end
|
// don't check balances until the end
|
||||||
BOOST_FOREACH(TransactionPtr trans,firstTransactions)
|
BOOST_FOREACH(TransactionPtr trans,firstTransactions)
|
||||||
{
|
{
|
||||||
addTransactionRecalculate(trans);
|
addTransactionAllowNeg(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(TransactionPtr trans,secondTransactions)
|
BOOST_FOREACH(TransactionPtr trans,secondTransactions)
|
||||||
{
|
{
|
||||||
addTransactionRecalculate(trans);
|
addTransactionAllowNeg(trans);
|
||||||
}
|
}
|
||||||
|
correctAccounts();
|
||||||
|
|
||||||
pair<uint160, Account >& fullAccount=pair<uint160, Account >();
|
|
||||||
BOOST_FOREACH(fullAccount,mAccounts)
|
|
||||||
{
|
|
||||||
if(fullAccount.second.first <0 )
|
|
||||||
{
|
|
||||||
correctAccount(fullAccount.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(mChild && recursive) mChild->recalculate();
|
if(mChild && recursive) mChild->recalculate();
|
||||||
@@ -422,3 +375,84 @@ bool Ledger::hasTransaction(TransactionPtr needle)
|
|||||||
|
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ledgers are compatible if both sets of transactions merged together would lead to the same ending balance
|
||||||
|
bool Ledger::isCompatible(Ledger::pointer other)
|
||||||
|
{
|
||||||
|
Ledger::pointer l1=Ledger::pointer(new Ledger(*this));
|
||||||
|
Ledger::pointer l2=Ledger::pointer(new Ledger(*other));
|
||||||
|
|
||||||
|
l1->mergeIn(l2);
|
||||||
|
l2->mergeIn(l1);
|
||||||
|
|
||||||
|
map<uint160, Account > a1=l1->getAccounts();
|
||||||
|
map<uint160, Account > a2=l2->getAccounts();
|
||||||
|
|
||||||
|
return(a1==a2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ledger::mergeIn(Ledger::pointer other)
|
||||||
|
{
|
||||||
|
list<TransactionPtr>& otherTransactions=other->getTransactions();
|
||||||
|
BOOST_FOREACH(TransactionPtr trans,otherTransactions)
|
||||||
|
{
|
||||||
|
addTransactionAllowNeg(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
correctAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ledger::correctAccounts()
|
||||||
|
{
|
||||||
|
pair<uint160, Account >& fullAccount=pair<uint160, Account >();
|
||||||
|
BOOST_FOREACH(fullAccount,mAccounts)
|
||||||
|
{
|
||||||
|
if(fullAccount.second.first <0 )
|
||||||
|
{
|
||||||
|
correctAccount(fullAccount.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must look for transactions to discard to make this account positive
|
||||||
|
// When we chuck transactions it might cause other accounts to need correcting
|
||||||
|
void Ledger::correctAccount(uint160& address)
|
||||||
|
{
|
||||||
|
list<uint160> effected;
|
||||||
|
|
||||||
|
// do this in reverse so we take of the higher seqnum first
|
||||||
|
for( list<TransactionPtr>::reverse_iterator iter=mTransactions.rbegin(); iter != mTransactions.rend(); )
|
||||||
|
{
|
||||||
|
TransactionPtr trans= *iter;
|
||||||
|
if(NewcoinAddress::protobufToInternal(trans->from()) == address)
|
||||||
|
{
|
||||||
|
Account fromAccount=mAccounts[address];
|
||||||
|
assert(fromAccount.second==trans->seqnum()+1);
|
||||||
|
if(fromAccount.first<0)
|
||||||
|
{
|
||||||
|
fromAccount.first += trans->amount();
|
||||||
|
fromAccount.second --;
|
||||||
|
|
||||||
|
mAccounts[address]=fromAccount;
|
||||||
|
|
||||||
|
uint160 destAddress=NewcoinAddress::protobufToInternal(trans->dest());
|
||||||
|
Account destAccount=mAccounts[destAddress];
|
||||||
|
destAccount.first -= trans->amount();
|
||||||
|
mAccounts[destAddress]=destAccount;
|
||||||
|
if(destAccount.first<0) effected.push_back(destAddress);
|
||||||
|
|
||||||
|
list<TransactionPtr>::iterator temp=mTransactions.erase( --iter.base() );
|
||||||
|
if(fromAccount.first>=0) break;
|
||||||
|
|
||||||
|
iter=list<TransactionPtr>::reverse_iterator(temp);
|
||||||
|
}else break;
|
||||||
|
}else iter--;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(uint160& address,effected)
|
||||||
|
{
|
||||||
|
correctAccount(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
8
Ledger.h
8
Ledger.h
@@ -44,7 +44,8 @@ private:
|
|||||||
|
|
||||||
void sign();
|
void sign();
|
||||||
void hash();
|
void hash();
|
||||||
void addTransactionRecalculate(TransactionPtr trans);
|
void addTransactionAllowNeg(TransactionPtr trans);
|
||||||
|
void correctAccounts();
|
||||||
void correctAccount(uint160& address);
|
void correctAccount(uint160& address);
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<Ledger> pointer;
|
typedef boost::shared_ptr<Ledger> pointer;
|
||||||
@@ -52,6 +53,7 @@ public:
|
|||||||
Ledger(newcoin::FullLedger& ledger);
|
Ledger(newcoin::FullLedger& ledger);
|
||||||
|
|
||||||
void setTo(newcoin::FullLedger& ledger);
|
void setTo(newcoin::FullLedger& ledger);
|
||||||
|
void mergeIn(Ledger::pointer other);
|
||||||
|
|
||||||
void save(std::string dir);
|
void save(std::string dir);
|
||||||
bool load(std::string dir);
|
bool load(std::string dir);
|
||||||
@@ -74,11 +76,13 @@ public:
|
|||||||
uint256& getSignature();
|
uint256& getSignature();
|
||||||
uint32 getValidSeqNum(){ return(mValidationSeqNum); }
|
uint32 getValidSeqNum(){ return(mValidationSeqNum); }
|
||||||
unsigned int getNumTransactions(){ return(mTransactions.size()); }
|
unsigned int getNumTransactions(){ return(mTransactions.size()); }
|
||||||
std::map<uint160, std::pair<int64,uint32> >& getAccounts(){ return(mAccounts); }
|
std::map<uint160, Account >& getAccounts(){ return(mAccounts); }
|
||||||
Account* getAccount(uint160& address);
|
Account* getAccount(uint160& address);
|
||||||
newcoin::FullLedger* createFullLedger();
|
newcoin::FullLedger* createFullLedger();
|
||||||
|
|
||||||
Ledger::pointer getParent();
|
Ledger::pointer getParent();
|
||||||
|
Ledger::pointer getChild();
|
||||||
|
bool isCompatible(Ledger::pointer other);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -239,3 +239,39 @@ void LedgerMaster::checkLedgerProposal(Peer::pointer peer, newcoin::ProposeLedge
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: optimize. this is expensive so limit the amount it is run
|
||||||
|
void LedgerMaster::checkConsensus(uint32 ledgerIndex)
|
||||||
|
{
|
||||||
|
Ledger::pointer ourAcceptedLedger=mLedgerHistory.getAcceptedLedger(ledgerIndex);
|
||||||
|
if(ourAcceptedLedger)
|
||||||
|
{
|
||||||
|
uint256* consensusHash=theApp->getValidationCollection().getConsensusLedgerHash(ledgerIndex);
|
||||||
|
if( consensusHash &&
|
||||||
|
(ourAcceptedLedger->getHash()!= *consensusHash))
|
||||||
|
{
|
||||||
|
Ledger::pointer consensusLedger=mLedgerHistory.getLedger(*consensusHash);
|
||||||
|
if(consensusLedger)
|
||||||
|
{ // see if these are compatible
|
||||||
|
if(ourAcceptedLedger->isCompatible(consensusLedger))
|
||||||
|
{ // try to merge any transactions from the consensus one into ours
|
||||||
|
ourAcceptedLedger->mergeIn(consensusLedger);
|
||||||
|
// Ledger::pointer child=ourAcceptedLedger->getChild();
|
||||||
|
Ledger::pointer child=mLedgerHistory.getAcceptedLedger(ledgerIndex+1);
|
||||||
|
if(child) child->recalculate();
|
||||||
|
}else
|
||||||
|
{ // switch to this ledger. Re-validate
|
||||||
|
mLedgerHistory.addAcceptedLedger(consensusLedger);
|
||||||
|
consensusLedger->publishValidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
}else
|
||||||
|
{ // we don't know the consensus one. Ask peers for it
|
||||||
|
PackedMessage::pointer msg=Peer::createGetFullLedger(*consensusHash);
|
||||||
|
theApp->getConnectionPool().relayMessage(NULL,msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public:
|
|||||||
void sendProposal();
|
void sendProposal();
|
||||||
void endFinalization();
|
void endFinalization();
|
||||||
void checkLedgerProposal(Peer::pointer peer,newcoin::ProposeLedger& packet);
|
void checkLedgerProposal(Peer::pointer peer,newcoin::ProposeLedger& packet);
|
||||||
|
void checkConsensus(uint32 ledgerIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
1
Peer.h
1
Peer.h
@@ -84,6 +84,7 @@ public:
|
|||||||
//static PackedMessage::pointer createFullLedger(Ledger::pointer ledger);
|
//static PackedMessage::pointer createFullLedger(Ledger::pointer ledger);
|
||||||
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);
|
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);
|
||||||
static PackedMessage::pointer createValidation(Ledger::pointer ledger);
|
static PackedMessage::pointer createValidation(Ledger::pointer ledger);
|
||||||
|
static PackedMessage::pointer createGetFullLedger(uint256& hash);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,28 +1,37 @@
|
|||||||
#include "ValidationCollection.h"
|
#include "ValidationCollection.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "NewcoinAddress.h"
|
#include "NewcoinAddress.h"
|
||||||
#include <boost/foreach.hpp>
|
#include "Config.h"
|
||||||
|
|
||||||
bool ValidationCollection::hasValidation(uint256& ledgerHash,uint160& hanko)
|
#include <boost/foreach.hpp>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
bool ValidationCollection::hasValidation(uint256& ledgerHash,uint160& hanko,uint32 seqnum)
|
||||||
{
|
{
|
||||||
if(mValidations.count(ledgerHash))
|
if(mValidations.count(ledgerHash))
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(newcoin::Validation& valid,mValidations[ledgerHash])
|
BOOST_FOREACH(newcoin::Validation& valid,mValidations[ledgerHash])
|
||||||
{
|
{
|
||||||
if(NewcoinAddress::protobufToInternal(valid.hanko()) == hanko) return(true);
|
if( valid.seqnum()==seqnum &&
|
||||||
|
NewcoinAddress::protobufToInternal(valid.hanko()) == hanko) return(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mIgnoredValidations.count(ledgerHash))
|
if(mIgnoredValidations.count(ledgerHash))
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(newcoin::Validation& valid,mIgnoredValidations[ledgerHash])
|
BOOST_FOREACH(newcoin::Validation& valid,mIgnoredValidations[ledgerHash])
|
||||||
{
|
{
|
||||||
if(NewcoinAddress::protobufToInternal(valid.hanko()) == hanko) return(true);
|
if( valid.seqnum()==seqnum &&
|
||||||
|
NewcoinAddress::protobufToInternal(valid.hanko()) == hanko) return(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: we are adding our own validation
|
||||||
// TODO: when do we check if we are with the consensus?
|
// TODO: when do we check if we are with the consensus?
|
||||||
|
// TODO: throw out lower seqnums
|
||||||
void ValidationCollection::addValidation(newcoin::Validation& valid)
|
void ValidationCollection::addValidation(newcoin::Validation& valid)
|
||||||
{
|
{
|
||||||
// TODO: make sure the validation is valid
|
// TODO: make sure the validation is valid
|
||||||
@@ -31,25 +40,135 @@ void ValidationCollection::addValidation(newcoin::Validation& valid)
|
|||||||
uint160 hanko=NewcoinAddress::protobufToInternal(valid.hanko());
|
uint160 hanko=NewcoinAddress::protobufToInternal(valid.hanko());
|
||||||
|
|
||||||
// make sure we don't already have this validation
|
// make sure we don't already have this validation
|
||||||
if(hasValidation(hash,hanko)) return;
|
if(hasValidation(hash,hanko,valid.seqnum())) return;
|
||||||
|
|
||||||
// check if we care about this hanko
|
// check if we care about this hanko
|
||||||
if( theApp->getUNL().findHanko(valid.hanko()) )
|
if( theApp->getUNL().findHanko(valid.hanko()) )
|
||||||
{
|
{
|
||||||
mValidations[hash].push_back(valid);
|
mValidations[hash].push_back(valid);
|
||||||
|
|
||||||
|
theApp->getLedgerMaster().checkConsensus(valid.ledgerindex());
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
mIgnoredValidations[hash].push_back(valid);
|
mIgnoredValidations[hash].push_back(valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
mMapIndexToValid[valid.ledgerindex()].push_back(valid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<newcoin::Validation>* ValidationCollection::getValidations(uint32 ledgerIndex)
|
|
||||||
|
// TODO: optimize. We can at least cache what ledgers are compatible
|
||||||
|
// a validation can be in multiple groups since compatibility isn't transitive
|
||||||
|
// Sometimes things are just complex
|
||||||
|
void ValidationCollection::addToGroup(newcoin::Validation& newValid)
|
||||||
{
|
{
|
||||||
if(mMapIndexToValid.count(ledgerIndex))
|
if(mGroupValidations.count(newValid.ledgerindex()))
|
||||||
{
|
{
|
||||||
return(&(mMapIndexToValid[ledgerIndex]));
|
bool canReturn=false;
|
||||||
|
// see if this hash is already on the list. If so add it there.
|
||||||
|
vector< vector<newcoin::Validation> >& groups=mGroupValidations[newValid.ledgerindex()];
|
||||||
|
vector<newcoin::Validation>& groupList=vector<newcoin::Validation>();
|
||||||
|
BOOST_FOREACH(groupList,groups)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(newcoin::Validation& valid,groupList)
|
||||||
|
{
|
||||||
|
if(valid.hash()==newValid.hash())
|
||||||
|
{
|
||||||
|
groupList.push_back(newValid);
|
||||||
|
canReturn=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canReturn) return;
|
||||||
|
// this is a validation of a new ledger hash
|
||||||
|
|
||||||
|
uint256 newHash=Transaction::protobufToInternalHash(newValid.hash());
|
||||||
|
Ledger::pointer newLedger=theApp->getLedgerMaster().getLedger(newHash);
|
||||||
|
if(newLedger)
|
||||||
|
{ // see if this ledger is compatible with any groups
|
||||||
|
BOOST_FOREACH(groupList,groups)
|
||||||
|
{
|
||||||
|
bool compatible=true;
|
||||||
|
BOOST_FOREACH(newcoin::Validation& valid,groupList)
|
||||||
|
{
|
||||||
|
uint256 hash=Transaction::protobufToInternalHash(valid.hash());
|
||||||
|
Ledger::pointer ledger=theApp->getLedgerMaster().getLedger(hash);
|
||||||
|
if(ledger)
|
||||||
|
{
|
||||||
|
if(!ledger->isCompatible(newLedger))
|
||||||
|
{ // not compatible with this group
|
||||||
|
compatible=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
{ // we can't tell if it is compatible
|
||||||
|
compatible=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(compatible) groupList.push_back(newValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// also add to its own group in case
|
||||||
|
groupList.push_back(newValid);
|
||||||
|
groups.push_back(groupList);
|
||||||
|
|
||||||
|
}else
|
||||||
|
{ // this is the first validation of this ledgerindex
|
||||||
|
mGroupValidations[newValid.ledgerindex()][0].push_back(newValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<newcoin::Validation>* ValidationCollection::getValidations(uint32 ledgerIndex)
|
||||||
|
{
|
||||||
|
if(mGroupValidations.count(ledgerIndex))
|
||||||
|
{
|
||||||
|
return(&(mGroupValidations[ledgerIndex]));
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// look through all the validated hashes at that index
|
||||||
|
// put the ledgers into compatible groups
|
||||||
|
// Pick the group with the most votes
|
||||||
|
bool ValidationCollection::getConsensusLedgers(uint32 ledgerIndex, list<uint256>& retHashs)
|
||||||
|
{
|
||||||
|
vector<newcoin::Validation>* valids=getValidations(ledgerIndex);
|
||||||
|
if(valids)
|
||||||
|
{
|
||||||
|
vector< pair<int, list<uint256> > > compatibleGroups;
|
||||||
|
|
||||||
|
map<uint256, int> voteCounts;
|
||||||
|
BOOST_FOREACH(newcoin::Validation valid,*valids)
|
||||||
|
{
|
||||||
|
uint256 hash=Transaction::protobufToInternalHash(valid.hash());
|
||||||
|
Ledger::pointer testLedger=theApp->getLedgerMaster().getLedger(hash);
|
||||||
|
if(testLedger)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
voteCounts[ ] += 1;
|
||||||
|
}
|
||||||
|
bool ret=false;
|
||||||
|
int maxVotes=theConfig.MIN_VOTES_FOR_CONSENSUS;
|
||||||
|
pair<uint256, int>& vote=pair<uint256, int>();
|
||||||
|
BOOST_FOREACH(vote,voteCounts)
|
||||||
|
{
|
||||||
|
if(vote.second>maxVotes)
|
||||||
|
{
|
||||||
|
maxVotes=vote.second;
|
||||||
|
retHash=vote.first;
|
||||||
|
ret=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
@@ -7,18 +7,32 @@
|
|||||||
|
|
||||||
class ValidationCollection
|
class ValidationCollection
|
||||||
{
|
{
|
||||||
|
|
||||||
// from ledger hash to the validation
|
// from ledger hash to the validation
|
||||||
std::map<uint256, std::vector<newcoin::Validation> > mValidations;
|
std::map<uint256, std::vector<newcoin::Validation> > mValidations;
|
||||||
std::map<uint256, std::vector<newcoin::Validation> > mIgnoredValidations;
|
std::map<uint256, std::vector<newcoin::Validation> > mIgnoredValidations;
|
||||||
std::map<uint32, std::vector<newcoin::Validation> > mMapIndexToValid;
|
|
||||||
|
|
||||||
bool hasValidation(uint256& ledgerHash,uint160& hanko);
|
// this maps ledgerIndex to an array of groups. Each group is a list of validations.
|
||||||
|
// a validation can be in multiple groups since compatibility isn't transitive
|
||||||
|
//
|
||||||
|
std::map<uint32, std::vector< std::vector<newcoin::Validation> > > mGroupValidations;
|
||||||
|
|
||||||
|
bool hasValidation(uint256& ledgerHash,uint160& hanko,uint32 seqnum);
|
||||||
|
void addToGroup(newcoin::Validation& valid);
|
||||||
public:
|
public:
|
||||||
ValidationCollection();
|
ValidationCollection();
|
||||||
|
|
||||||
void addValidation(newcoin::Validation& valid);
|
void addValidation(newcoin::Validation& valid);
|
||||||
|
|
||||||
std::vector<newcoin::Validation>* getValidations(uint32 ledgerIndex);
|
std::vector<newcoin::Validation>* getValidations(uint32 ledgerIndex);
|
||||||
|
|
||||||
|
|
||||||
|
// It can miss some compatible ledgers of course if you don't know them
|
||||||
|
// gets a list of all the compatible ledgers that were voted for the most
|
||||||
|
// returns false if there isn't a consensus yet
|
||||||
|
bool getConsensusLedgers(uint32 ledgerIndex, std::list<uint256>& retHashs);
|
||||||
|
|
||||||
|
int getSeqNum(uint32 ledgerIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user