mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' into pay
This commit is contained in:
@@ -23,7 +23,7 @@ uint160 humanTo160(const std::string& buf)
|
||||
vector<unsigned char> retVec;
|
||||
DecodeBase58(buf,retVec);
|
||||
uint160 ret;
|
||||
memcpy(reinterpret_cast<unsigned char*>(&ret), &retVec[0], ret.GetSerializeSize());
|
||||
memcpy(ret.begin(), &retVec[0], ret.GetSerializeSize());
|
||||
|
||||
|
||||
return(ret);
|
||||
|
||||
@@ -238,19 +238,19 @@ void LedgerAcquire::trigger(Peer::pointer peer)
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL, Peer::pointer peer)
|
||||
void PeerSet::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL, Peer::pointer peer)
|
||||
{
|
||||
peer->sendPacket(boost::make_shared<PackedMessage>(tmGL, newcoin::mtGET_LEDGER));
|
||||
}
|
||||
|
||||
void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL)
|
||||
void PeerSet::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
if (mPeers.empty()) return;
|
||||
|
||||
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(tmGL, newcoin::mtGET_LEDGER);
|
||||
|
||||
std::vector<boost::weak_ptr<Peer> >::iterator it = mPeers.begin();
|
||||
std::vector< boost::weak_ptr<Peer> >::iterator it = mPeers.begin();
|
||||
while (it != mPeers.end())
|
||||
{
|
||||
if (it->expired())
|
||||
@@ -291,11 +291,11 @@ bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer)
|
||||
}
|
||||
|
||||
bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
|
||||
const std::list<std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||
const std::list< std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||
{
|
||||
if (!mHaveBase) return false;
|
||||
std::list<SHAMapNode>::const_iterator nodeIDit = nodeIDs.begin();
|
||||
std::list<std::vector<unsigned char> >::const_iterator nodeDatait = data.begin();
|
||||
std::list< std::vector<unsigned char> >::const_iterator nodeDatait = data.begin();
|
||||
while (nodeIDit != nodeIDs.end())
|
||||
{
|
||||
if (nodeIDit->isRoot())
|
||||
@@ -318,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)
|
||||
const std::list< std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "got ASdata acquiring ledger " << mHash.GetHex() << std::endl;
|
||||
@@ -391,7 +391,7 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::poi
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
memcpy(&hash, packet.ledgerhash().data(), 32);
|
||||
memcpy(hash.begin(), packet.ledgerhash().data(), 32);
|
||||
#ifdef DEBUG
|
||||
std::cerr << hash.GetHex() << std::endl;
|
||||
#endif
|
||||
@@ -409,7 +409,7 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::poi
|
||||
else if ((packet.type() == newcoin::liTX_NODE) || (packet.type() == newcoin::liAS_NODE))
|
||||
{
|
||||
std::list<SHAMapNode> nodeIDs;
|
||||
std::list<std::vector<unsigned char> > nodeData;
|
||||
std::list< std::vector<unsigned char> > nodeData;
|
||||
|
||||
if (packet.nodes().size() <= 0) return false;
|
||||
for (int i = 0; i < packet.nodes().size(); ++i)
|
||||
|
||||
@@ -29,6 +29,9 @@ protected:
|
||||
PeerSet(const uint256& hash, int interval);
|
||||
virtual ~PeerSet() { ; }
|
||||
|
||||
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message);
|
||||
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message, Peer::pointer peer);
|
||||
|
||||
public:
|
||||
const uint256& getHash() const { return mHash; }
|
||||
bool isComplete() const { return mComplete; }
|
||||
@@ -64,8 +67,6 @@ protected:
|
||||
void done();
|
||||
void onTimer() { trigger(Peer::pointer()); }
|
||||
|
||||
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message);
|
||||
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message, Peer::pointer peer);
|
||||
void newPeer(Peer::pointer peer) { trigger(peer); }
|
||||
void trigger(Peer::pointer);
|
||||
|
||||
@@ -88,29 +89,6 @@ public:
|
||||
Peer::pointer);
|
||||
};
|
||||
|
||||
class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this<TransactionAcquire>
|
||||
{ // A transaction set we are trying to acquire
|
||||
public:
|
||||
typedef boost::shared_ptr<TransactionAcquire> pointer;
|
||||
|
||||
protected:
|
||||
SHAMap::pointer mMap;
|
||||
|
||||
void onTimer() { trigger(Peer::pointer()); }
|
||||
void newPeer(Peer::pointer peer) { trigger(peer); }
|
||||
|
||||
void done();
|
||||
void trigger(Peer::pointer);
|
||||
boost::weak_ptr<PeerSet> pmDowncast();
|
||||
|
||||
public:
|
||||
TransactionAcquire(const uint256& hash);
|
||||
SHAMap::pointer getMap();
|
||||
|
||||
bool takeNode(const std::list<SHAMapNode>& IDs, const std::list<std::vector<unsigned char> >& data,
|
||||
Peer::pointer);
|
||||
};
|
||||
|
||||
class LedgerAcquireMaster
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -1,16 +1,169 @@
|
||||
|
||||
#include "LedgerConsensus.h"
|
||||
|
||||
TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mHaveRoot(false)
|
||||
{
|
||||
mMap = boost::make_shared<SHAMap>();
|
||||
mMap->setSynching();
|
||||
}
|
||||
|
||||
void TransactionAcquire::done()
|
||||
{
|
||||
// insert SHAMap in finished set (as valid or invalid), remove ourselves from current set
|
||||
// WRITEME
|
||||
}
|
||||
|
||||
boost::weak_ptr<PeerSet> TransactionAcquire::pmDowncast()
|
||||
{
|
||||
return boost::shared_polymorphic_downcast<PeerSet, TransactionAcquire>(shared_from_this());
|
||||
}
|
||||
|
||||
void TransactionAcquire::trigger(Peer::pointer peer)
|
||||
{
|
||||
if (mComplete || mFailed)
|
||||
return;
|
||||
if (!mHaveRoot)
|
||||
{
|
||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||
tmGL->set_itype(newcoin::liTS_CANDIDATE);
|
||||
*(tmGL->add_nodeids()) = SHAMapNode().getRawString();
|
||||
sendRequest(tmGL);
|
||||
}
|
||||
if (mHaveRoot)
|
||||
{
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::vector<uint256> nodeHashes;
|
||||
mMap->getMissingNodes(nodeIDs, nodeHashes, 256);
|
||||
if (nodeIDs.empty())
|
||||
{
|
||||
if (mMap->isValid())
|
||||
mComplete = true;
|
||||
else
|
||||
mFailed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||
tmGL->set_itype(newcoin::liTS_CANDIDATE);
|
||||
for (std::vector<SHAMapNode>::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it)
|
||||
*(tmGL->add_nodeids()) = it->getRawString();
|
||||
if (peer)
|
||||
sendRequest(tmGL, peer);
|
||||
else
|
||||
sendRequest(tmGL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mComplete || mFailed)
|
||||
done();
|
||||
else
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
bool TransactionAcquire::takeNode(const std::list<SHAMapNode>& nodeIDs,
|
||||
const std::list< std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||
{
|
||||
if (mComplete || mFailed)
|
||||
return true;
|
||||
std::list<SHAMapNode>::const_iterator nodeIDit = nodeIDs.begin();
|
||||
std::list< std::vector<unsigned char> >::const_iterator nodeDatait = data.begin();
|
||||
while (nodeIDit != nodeIDs.end())
|
||||
{
|
||||
if (nodeIDit->isRoot())
|
||||
{
|
||||
if (!mMap->addRootNode(getHash(), *nodeDatait))
|
||||
return false;
|
||||
}
|
||||
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait))
|
||||
return false;
|
||||
++nodeIDit;
|
||||
++nodeDatait;
|
||||
}
|
||||
trigger(peer);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LedgerConsensus::abort()
|
||||
{
|
||||
}
|
||||
|
||||
int LedgerConsensus::startup()
|
||||
{
|
||||
return 5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LedgerConsensus::timerEntry()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire)
|
||||
{
|
||||
boost::unordered_map<uint256, SHAMap::pointer>::iterator it = mComplete.find(hash);
|
||||
if (it == mComplete.end())
|
||||
{ // we have not completed acuiqiring this ledger
|
||||
if (doAcquire)
|
||||
{
|
||||
TransactionAcquire::pointer& acquiring = mAcquiring[hash];
|
||||
if (!acquiring)
|
||||
{
|
||||
acquiring = boost::make_shared<TransactionAcquire>(hash);
|
||||
startAcquiring(acquiring);
|
||||
}
|
||||
}
|
||||
return SHAMap::pointer();
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void LedgerConsensus::startAcquiring(TransactionAcquire::pointer acquire)
|
||||
{
|
||||
boost::unordered_map< uint256, std::vector< boost::weak_ptr<Peer> > >::iterator it =
|
||||
mPeerData.find(acquire->getHash());
|
||||
|
||||
if (it != mPeerData.end())
|
||||
{ // Add any peers we already know have his transaction set
|
||||
std::vector< boost::weak_ptr<Peer> >& peerList = it->second;
|
||||
std::vector< boost::weak_ptr<Peer> >::iterator pit = peerList.begin();
|
||||
while (pit != peerList.end())
|
||||
{
|
||||
Peer::pointer pr = pit->lock();
|
||||
if (!pr)
|
||||
pit = peerList.erase(pit);
|
||||
else
|
||||
{
|
||||
acquire->peerHas(pr);
|
||||
++pit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::removePosition(LedgerProposal& position)
|
||||
{
|
||||
// WRITEME
|
||||
}
|
||||
|
||||
void LedgerConsensus::addPosition(LedgerProposal& position)
|
||||
{
|
||||
// WRITEME
|
||||
}
|
||||
|
||||
bool LedgerConsensus::peerPosition(LedgerProposal::pointer newPosition)
|
||||
{
|
||||
LedgerProposal::pointer& currentPosition = mPeerPositions[newPosition->getPeerID()];
|
||||
if (!currentPosition)
|
||||
{
|
||||
if (newPosition->getProposeSeq() <= currentPosition->getProposeSeq())
|
||||
return false;
|
||||
|
||||
// change in position
|
||||
removePosition(*currentPosition);
|
||||
}
|
||||
|
||||
currentPosition = newPosition;
|
||||
addPosition(*currentPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,36 +12,32 @@
|
||||
#include "LedgerProposal.h"
|
||||
#include "Peer.h"
|
||||
|
||||
class LCPosition
|
||||
{ // A position taken by one of our trusted peers
|
||||
class TransactionAcquire : public PeerSet, public boost::enable_shared_from_this<TransactionAcquire>
|
||||
{ // A transaction set we are trying to acquire
|
||||
public:
|
||||
typedef boost::shared_ptr<TransactionAcquire> pointer;
|
||||
|
||||
protected:
|
||||
uint256 mPubKeyHash;
|
||||
CKey::pointer mPubKey;
|
||||
uint256 mPreviousPosition, mCurrentPosition;
|
||||
uint32 mSequence;
|
||||
SHAMap::pointer mMap;
|
||||
bool mHaveRoot;
|
||||
|
||||
void onTimer() { trigger(Peer::pointer()); }
|
||||
void newPeer(Peer::pointer peer) { trigger(peer); }
|
||||
|
||||
void done();
|
||||
void trigger(Peer::pointer);
|
||||
boost::weak_ptr<PeerSet> pmDowncast();
|
||||
|
||||
public:
|
||||
typedef boost::shared_ptr<LCPosition> pointer;
|
||||
|
||||
// for remote positions
|
||||
LCPosition(uint32 closingSeq, uint32 proposeSeq, const uint256& previousTxHash,
|
||||
const uint256& currentTxHash, CKey::pointer nodePubKey, const std::string& signature);
|
||||
TransactionAcquire(const uint256& hash);
|
||||
|
||||
// for our initial position
|
||||
LCPosition(CKey::pointer privKey, uint32 ledgerSeq, const uint256& currentPosition);
|
||||
SHAMap::pointer getMap() { return mMap; }
|
||||
|
||||
// for our subsequent positions
|
||||
LCPosition(LCPosition::pointer previousPosition, CKey::pointer privKey, const uint256& newPosition);
|
||||
|
||||
const uint256& getPubKeyHash() const { return mPubKeyHash; }
|
||||
const uint256& getCurrentPosition() const { return mCurrentPosition; }
|
||||
uint32 getSeq() const { return mSequence; }
|
||||
|
||||
bool verifySignature(const uint256& hash, const std::vector<unsigned char>& signature) const;
|
||||
void setPosition(const uint256& position, uint32 sequence);
|
||||
bool takeNode(const std::list<SHAMapNode>& IDs, const std::list< std::vector<unsigned char> >& data,
|
||||
Peer::pointer);
|
||||
};
|
||||
|
||||
|
||||
class LCTransaction
|
||||
{ // A transaction that may be disputed
|
||||
protected:
|
||||
@@ -75,19 +71,24 @@ protected:
|
||||
Ledger::pointer mPreviousLedger, mCurrentLedger;
|
||||
LedgerProposal::pointer mCurrentProposal;
|
||||
|
||||
LCPosition::pointer mOurPosition;
|
||||
LedgerProposal::pointer mOurPosition;
|
||||
|
||||
// Convergence tracking, trusted peers indexed by hash of public key
|
||||
boost::unordered_map<uint256, LCPosition::pointer> mPeerPositions;
|
||||
boost::unordered_map<uint256, LedgerProposal::pointer, hash_SMN> mPeerPositions;
|
||||
|
||||
// Transaction Sets, indexed by hash of transaction tree
|
||||
boost::unordered_map<uint256, SHAMap::pointer> mComplete;
|
||||
boost::unordered_map<uint256, TransactionAcquire::pointer> mAcquiring;
|
||||
boost::unordered_map<uint256, SHAMap::pointer, hash_SMN> mComplete;
|
||||
boost::unordered_map<uint256, TransactionAcquire::pointer, hash_SMN> mAcquiring;
|
||||
|
||||
// Peer sets
|
||||
boost::unordered_map<uint256, std::vector< boost::weak_ptr<Peer> > > mPeerData;
|
||||
boost::unordered_map<uint256, std::vector< boost::weak_ptr<Peer> >, hash_SMN> mPeerData;
|
||||
|
||||
void weHave(const uint256& id, Peer::pointer avoidPeer);
|
||||
void startAcquiring(TransactionAcquire::pointer);
|
||||
SHAMap::pointer find(const uint256& hash);
|
||||
|
||||
void addPosition(LedgerProposal&);
|
||||
void removePosition(LedgerProposal&);
|
||||
|
||||
public:
|
||||
LedgerConsensus(Ledger::pointer previousLedger, Ledger::pointer currentLedger) :
|
||||
@@ -98,21 +99,19 @@ public:
|
||||
Ledger::pointer peekPreviousLedger() { return mPreviousLedger; }
|
||||
Ledger::pointer peekCurrentLedger() { return mCurrentLedger; }
|
||||
|
||||
LCPosition::pointer getCreatePeerPosition(const uint256& pubKeyHash);
|
||||
|
||||
SHAMap::pointer getTransactionTree(const uint256& hash);
|
||||
SHAMap::pointer getTransactionTree(const uint256& hash, bool doAcquire);
|
||||
TransactionAcquire::pointer getAcquiring(const uint256& hash);
|
||||
void acquireComplete(const uint256& hash);
|
||||
|
||||
LCPosition::pointer getPeerPosition(const uint256& peer);
|
||||
|
||||
// high-level functions
|
||||
void abort();
|
||||
bool peerPosition(Peer::pointer peer, const Serializer& report);
|
||||
int timerEntry(void);
|
||||
|
||||
bool peerPosition(LedgerProposal::pointer);
|
||||
|
||||
bool peerHasSet(Peer::pointer peer, const std::vector<uint256>& sets);
|
||||
|
||||
bool peerGaveNodes(Peer::pointer peer, const uint256& setHash,
|
||||
const std::list<SHAMapNode>& nodeIDs, const std::list< std::vector<unsigned char> >& nodeData);
|
||||
int timerEntry(void);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,59 +3,44 @@
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
LedgerProposal::LedgerProposal(SerializerIterator& it) : mKey(boost::make_shared<CKey>())
|
||||
#include "key.h"
|
||||
#include "Application.h"
|
||||
|
||||
LedgerProposal::LedgerProposal(uint32 closingSeq, uint32 proposeSeq, const uint256& proposeTx,
|
||||
const std::string& pubKey) : mCurrentHash(proposeTx),
|
||||
mProposeSeq(proposeSeq), mKey(boost::make_shared<CKey>())
|
||||
{
|
||||
if (it.get32() != sProposeMagic)
|
||||
throw std::runtime_error("Not a ledger proposal");
|
||||
|
||||
mPreviousLedger = it.get256();
|
||||
mCurrentHash = it.get256();
|
||||
mPrevHash = it.get256();
|
||||
mProposeSeq = it.get32();
|
||||
if (mKey->SetPubKey(it.getVL()))
|
||||
throw std::runtime_error("Unable to set public key");
|
||||
mSignature = it.getVL();
|
||||
|
||||
if (!mKey->SetPubKey(pubKey))
|
||||
throw std::runtime_error("Invalid public key in proposal");
|
||||
mPreviousLedger = theApp->getMasterLedger().getClosedLedger()->getHash();
|
||||
mPeerID = Serializer::getSHA512Half(mKey->GetPubKey());
|
||||
|
||||
if (!mKey->Verify(getSigningHash(), mSignature))
|
||||
throw std::runtime_error("Ledger proposal invalid");
|
||||
}
|
||||
|
||||
|
||||
LedgerProposal::LedgerProposal(CKey::pointer mPrivateKey, const uint256& prevLgr, const uint256& position) :
|
||||
mPreviousLedger(prevLgr), mCurrentHash(position), mProposeSeq(0), mKey(mPrivateKey)
|
||||
{
|
||||
mPeerID = Serializer::getSHA512Half(mKey->GetPubKey());
|
||||
if (!mKey->Sign(getSigningHash(), mSignature))
|
||||
throw std::runtime_error("Unable to sign proposal");
|
||||
}
|
||||
|
||||
LedgerProposal::LedgerProposal(LedgerProposal::pointer previous, const uint256& newp) :
|
||||
mPeerID(previous->mPeerID), mPreviousLedger(previous->mPreviousLedger), mPrevHash(previous->mCurrentHash),
|
||||
mCurrentHash(newp), mProposeSeq(previous->mProposeSeq + 1), mKey(previous->mKey)
|
||||
mPeerID(previous->mPeerID), mPreviousLedger(previous->mPreviousLedger),
|
||||
mCurrentHash(newp), mProposeSeq(previous->mProposeSeq + 1), mKey(previous->mKey)
|
||||
{
|
||||
if (!mKey->Sign(getSigningHash(), mSignature))
|
||||
throw std::runtime_error("Unable to sign proposal");
|
||||
}
|
||||
|
||||
void LedgerProposal::add(Serializer& s, bool for_signature) const
|
||||
{
|
||||
s.add32(sProposeMagic);
|
||||
s.add256(mPreviousLedger);
|
||||
s.add256(mCurrentHash);
|
||||
s.add256(mPrevHash);
|
||||
s.add32(mProposeSeq);
|
||||
|
||||
if (for_signature)
|
||||
return;
|
||||
|
||||
s.addVL(mKey->GetPubKey());
|
||||
s.addVL(mSignature);
|
||||
;
|
||||
}
|
||||
|
||||
uint256 LedgerProposal::getSigningHash() const
|
||||
{
|
||||
Serializer s(104);
|
||||
add(s, true);
|
||||
Serializer s(72);
|
||||
s.add32(sProposeMagic);
|
||||
s.add32(mProposeSeq);
|
||||
s.add256(mPreviousLedger);
|
||||
s.add256(mCurrentHash);
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
bool LedgerProposal::checkSign(const std::string& signature)
|
||||
{
|
||||
return mKey->Verify(getSigningHash(), signature);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,9 @@ class LedgerProposal
|
||||
{
|
||||
protected:
|
||||
|
||||
uint256 mPeerID, mPreviousLedger, mPrevHash, mCurrentHash;
|
||||
uint256 mPeerID, mPreviousLedger, mCurrentHash;
|
||||
uint32 mProposeSeq;
|
||||
CKey::pointer mKey;
|
||||
std::vector<unsigned char> mSignature;
|
||||
// std::vector<uint256> mAddedTx, mRemovedTx;
|
||||
|
||||
static const uint32 sProposeMagic = 0x50525000; // PRP
|
||||
@@ -26,7 +25,7 @@ public:
|
||||
typedef boost::shared_ptr<LedgerProposal> pointer;
|
||||
|
||||
// proposal from peer
|
||||
LedgerProposal(SerializerIterator& it);
|
||||
LedgerProposal(uint32 closingSeq, uint32 proposeSeq, const uint256& propose, const std::string& pubKey);
|
||||
|
||||
// our first proposal
|
||||
LedgerProposal(CKey::pointer privateKey, const uint256& prevLedger, const uint256& position);
|
||||
@@ -34,11 +33,10 @@ public:
|
||||
// our following proposals
|
||||
LedgerProposal(LedgerProposal::pointer previous, const uint256& newPosition);
|
||||
|
||||
void add(Serializer&, bool for_signature) const;
|
||||
uint256 getSigningHash() const;
|
||||
bool checkSign(const std::string& signature);
|
||||
|
||||
const uint256& getPeerID() const { return mPeerID; }
|
||||
const uint256& getPrevHash() const { return mPrevHash; }
|
||||
const uint256& getCurrentHash() const { return mCurrentHash; }
|
||||
const uint256& getPrevLedger() const { return mPreviousLedger; }
|
||||
uint32 getProposeSeq() const { return mProposeSeq; }
|
||||
|
||||
@@ -386,18 +386,42 @@ int NetworkOPs::beginConsensus(Ledger::pointer closingLedger)
|
||||
return mConsensus->startup();
|
||||
}
|
||||
|
||||
bool NetworkOPs::proposeLedger(uint32 closingSeq, uint32 proposeSeq,
|
||||
const uint256& prevHash, const uint256& proposeHash, const std::string& pubKey, const std::string& signature)
|
||||
bool NetworkOPs::proposeLedger(uint32 closingSeq, uint32 proposeSeq, const uint256& proposeHash,
|
||||
const std::string& pubKey, const std::string& signature)
|
||||
{
|
||||
uint256 nodeID = Serializer::getSHA512Half(pubKey);
|
||||
if (mMode != omFULL)
|
||||
return true;
|
||||
|
||||
LedgerProposal::pointer proposal =
|
||||
boost::make_shared<LedgerProposal>(closingSeq, proposeSeq, proposeHash, pubKey);
|
||||
if (!proposal->checkSign(signature))
|
||||
{
|
||||
std::cerr << "Ledger proposal fails signature check" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is this node on our UNL?
|
||||
// WRITEME
|
||||
|
||||
// Are we currently closing?
|
||||
Ledger::pointer currentLedger = theApp->getMasterLedger().getCurrentLedger();
|
||||
|
||||
// Yes: Is it an update?
|
||||
// WRITEME
|
||||
if (!mConsensus)
|
||||
{
|
||||
if ((getNetworkTimeNC() + 2) >= currentLedger->getCloseTimeNC())
|
||||
setStateTimer(beginConsensus(currentLedger));
|
||||
if (!mConsensus) return true;
|
||||
}
|
||||
|
||||
return mConsensus->peerPosition(proposal);
|
||||
}
|
||||
|
||||
SHAMap::pointer NetworkOPs::getTXMap(const uint256& hash)
|
||||
{ // WRITEME
|
||||
return SHAMap::pointer();
|
||||
}
|
||||
|
||||
bool NetworkOPs::gotTXData(boost::shared_ptr<Peer> peer, const uint256& hash,
|
||||
const std::list<SHAMapNode>& nodeIDs, const std::list< std::vector<unsigned char> >& nodeData)
|
||||
{ // WRITEME
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -66,13 +66,16 @@ public:
|
||||
|
||||
// tree synchronization operations
|
||||
bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID,
|
||||
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
|
||||
const std::vector<unsigned char>& myNode, std::list< std::vector<unsigned char> >& newNodes);
|
||||
bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId,
|
||||
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
|
||||
const std::vector<unsigned char>& myNode, std::list< std::vector<unsigned char> >& newNodes);
|
||||
|
||||
// ledger proposal/close functions
|
||||
bool proposeLedger(uint32 closingSeq, uint32 proposeSeq, const uint256& prevHash, const uint256& proposeHash,
|
||||
bool proposeLedger(uint32 closingSeq, uint32 proposeSeq, const uint256& proposeHash,
|
||||
const std::string& pubKey, const std::string& signature);
|
||||
bool gotTXData(boost::shared_ptr<Peer> peer, const uint256& hash,
|
||||
const std::list<SHAMapNode>& nodeIDs, const std::list< std::vector<unsigned char> >& nodeData);
|
||||
SHAMap::pointer getTXMap(const uint256& hash);
|
||||
|
||||
// network state machine
|
||||
void checkState(const boost::system::error_code& result);
|
||||
|
||||
218
src/Peer.cpp
218
src/Peer.cpp
@@ -603,16 +603,15 @@ void Peer::recvTransaction(newcoin::TMTransaction& packet)
|
||||
|
||||
void Peer::recvPropose(boost::shared_ptr<newcoin::TMProposeSet> packet)
|
||||
{
|
||||
if ((packet->previoustxhash().size() != 32) || (packet->currenttxhash().size() != 32) ||
|
||||
(packet->nodepubkey().size() < 28) || (packet->signature().size() < 56))
|
||||
if ((packet->currenttxhash().size() != 32) || (packet->nodepubkey().size() < 28) ||
|
||||
(packet->signature().size() < 56))
|
||||
return;
|
||||
|
||||
uint32 closingSeq = packet->closingseq(), proposeSeq = packet->proposeseq();
|
||||
uint256 previousTxHash, currentTxHash;
|
||||
memcpy(previousTxHash.begin(), packet->previoustxhash().data(), 32);
|
||||
uint256 currentTxHash;
|
||||
memcpy(currentTxHash.begin(), packet->currenttxhash().data(), 32);
|
||||
|
||||
if(theApp->getOPs().proposeLedger(closingSeq, proposeSeq, previousTxHash, currentTxHash,
|
||||
if(theApp->getOPs().proposeLedger(closingSeq, proposeSeq, currentTxHash,
|
||||
packet->nodepubkey(), packet->signature()))
|
||||
{ // FIXME: Not all nodes will want proposals
|
||||
PackedMessage::pointer message = boost::make_shared<PackedMessage>(packet, newcoin::mtPROPOSE_LEDGER);
|
||||
@@ -693,106 +692,161 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet)
|
||||
|
||||
void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
{
|
||||
// Figure out what ledger they want
|
||||
Ledger::pointer ledger;
|
||||
if (packet.has_ledgerhash())
|
||||
{
|
||||
uint256 ledgerhash;
|
||||
if (packet.ledgerhash().size() != 32)
|
||||
SHAMap::pointer map;
|
||||
boost::shared_ptr<newcoin::TMLedgerData> reply = boost::make_shared<newcoin::TMLedgerData>();
|
||||
|
||||
if (packet.itype() == newcoin::liTS_CANDIDATE)
|
||||
{ // Request is for a transaction candidate set
|
||||
Ledger::pointer ledger;
|
||||
if ((!packet.has_ledgerhash() || packet.ledgerhash().size() != 32))
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
memcpy(&ledgerhash, packet.ledgerhash().data(), 32);
|
||||
ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash);
|
||||
}
|
||||
else if (packet.has_ledgerseq())
|
||||
ledger = theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq());
|
||||
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCURRENT))
|
||||
ledger = theApp->getMasterLedger().getCurrentLedger();
|
||||
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSING))
|
||||
{
|
||||
ledger = theApp->getMasterLedger().getClosedLedger();
|
||||
}
|
||||
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSED) )
|
||||
{
|
||||
ledger = theApp->getMasterLedger().getClosedLedger();
|
||||
if (ledger && !ledger->isClosed())
|
||||
ledger = theApp->getMasterLedger().getLedgerBySeq(ledger->getLedgerSeq() - 1);
|
||||
uint256 txHash;
|
||||
memcpy(txHash.begin(), packet.ledgerhash().data(), 32);
|
||||
map = theApp->getOPs().getTXMap(txHash);
|
||||
if (!map)
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
reply->set_ledgerhash(txHash.begin(), txHash.size());
|
||||
reply->set_type(newcoin::liTS_CANDIDATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
if( (!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq()!=ledger->getLedgerSeq())) )
|
||||
{
|
||||
punishPeer(PP_UNKNOWN_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out what information they want
|
||||
boost::shared_ptr<newcoin::TMLedgerData> data = boost::make_shared<newcoin::TMLedgerData>();
|
||||
uint256 lHash = ledger->getHash();
|
||||
data->set_ledgerhash(lHash.begin(), lHash.size());
|
||||
data->set_ledgerseq(ledger->getLedgerSeq());
|
||||
data->set_type(packet.itype());
|
||||
|
||||
if(packet.itype() == newcoin::liBASE)
|
||||
{
|
||||
Serializer nData(116);
|
||||
ledger->addRaw(nData);
|
||||
data->add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength());
|
||||
}
|
||||
else if ( (packet.itype()==newcoin::liTX_NODE) || (packet.itype()==newcoin::liAS_NODE) )
|
||||
{
|
||||
SHAMap::pointer map=(packet.itype()==newcoin::liTX_NODE) ? ledger->peekTransactionMap()
|
||||
: ledger->peekAccountStateMap();
|
||||
if(!map) return;
|
||||
if(packet.nodeids_size()==0)
|
||||
{ // Figure out what ledger they want
|
||||
Ledger::pointer ledger;
|
||||
if (packet.has_ledgerhash())
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
for(int i=0; i<packet.nodeids().size(); i++)
|
||||
{
|
||||
SHAMapNode mn(packet.nodeids(0).data(), packet.nodeids(i).size());
|
||||
if(!mn.isValid())
|
||||
uint256 ledgerhash;
|
||||
if (packet.ledgerhash().size() != 32)
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::list<std::vector<unsigned char> > rawNodes;
|
||||
if(map->getNodeFat(mn, nodeIDs, rawNodes))
|
||||
{
|
||||
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
||||
std::list<std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||
for(nodeIDIterator = nodeIDs.begin(), rawNodeIterator = rawNodes.begin();
|
||||
nodeIDIterator != nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator)
|
||||
{
|
||||
Serializer nID(33);
|
||||
nodeIDIterator->addIDRaw(nID);
|
||||
newcoin::TMLedgerNode* node = data->add_nodes();
|
||||
node->set_nodeid(nID.getDataPtr(), nID.getLength());
|
||||
node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size());
|
||||
}
|
||||
}
|
||||
memcpy(ledgerhash.begin(), packet.ledgerhash().data(), 32);
|
||||
ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash);
|
||||
}
|
||||
else if (packet.has_ledgerseq())
|
||||
ledger = theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq());
|
||||
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCURRENT))
|
||||
ledger = theApp->getMasterLedger().getCurrentLedger();
|
||||
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSED) )
|
||||
{
|
||||
ledger = theApp->getMasterLedger().getClosedLedger();
|
||||
if (ledger && !ledger->isClosed())
|
||||
ledger = theApp->getMasterLedger().getLedgerBySeq(ledger->getLedgerSeq() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
if( (!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq()!=ledger->getLedgerSeq())) )
|
||||
{
|
||||
punishPeer(PP_UNKNOWN_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill out the reply
|
||||
uint256 lHash = ledger->getHash();
|
||||
reply->set_ledgerhash(lHash.begin(), lHash.size());
|
||||
reply->set_ledgerseq(ledger->getLedgerSeq());
|
||||
reply->set_type(packet.itype());
|
||||
|
||||
if(packet.itype() == newcoin::liBASE)
|
||||
{ // they want the ledger base data
|
||||
Serializer nData(128);
|
||||
ledger->addRaw(nData);
|
||||
reply->add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength());
|
||||
PackedMessage::pointer oPacket = boost::make_shared<PackedMessage>
|
||||
(PackedMessage::MessagePointer(reply), newcoin::mtLEDGER);
|
||||
sendPacket(oPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((packet.itype() == newcoin::liTX_NODE) || (packet.itype() == newcoin::liAS_NODE))
|
||||
map = (packet.itype() == newcoin::liTX_NODE) ?
|
||||
ledger->peekTransactionMap() : ledger->peekAccountStateMap();
|
||||
}
|
||||
else
|
||||
|
||||
if ((!map) || (packet.nodeids_size() == 0))
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i<packet.nodeids().size(); ++i)
|
||||
{
|
||||
SHAMapNode mn(packet.nodeids(0).data(), packet.nodeids(i).size());
|
||||
if(!mn.isValid())
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::list< std::vector<unsigned char> > rawNodes;
|
||||
if(map->getNodeFat(mn, nodeIDs, rawNodes))
|
||||
{
|
||||
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
||||
std::list< std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||
for(nodeIDIterator = nodeIDs.begin(), rawNodeIterator = rawNodes.begin();
|
||||
nodeIDIterator != nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator)
|
||||
{
|
||||
Serializer nID(33);
|
||||
nodeIDIterator->addIDRaw(nID);
|
||||
newcoin::TMLedgerNode* node = reply->add_nodes();
|
||||
node->set_nodeid(nID.getDataPtr(), nID.getLength());
|
||||
node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
PackedMessage::pointer oPacket = boost::make_shared<PackedMessage>
|
||||
(PackedMessage::MessagePointer(data), newcoin::mtLEDGER);
|
||||
(PackedMessage::MessagePointer(reply), newcoin::mtLEDGER);
|
||||
sendPacket(oPacket);
|
||||
}
|
||||
|
||||
void Peer::recvLedger(newcoin::TMLedgerData& packet)
|
||||
{
|
||||
if (packet.nodes().size() <= 0)
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet.type() == newcoin::liTS_CANDIDATE)
|
||||
{ // got data for a candidate transaction set
|
||||
uint256 hash;
|
||||
if(packet.ledgerhash().size() != 32)
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
memcpy(hash.begin(), packet.ledgerhash().data(), 32);
|
||||
|
||||
|
||||
std::list<SHAMapNode> nodeIDs;
|
||||
std::list< std::vector<unsigned char> > nodeData;
|
||||
|
||||
for (int i = 0; i < packet.nodes().size(); ++i)
|
||||
{
|
||||
const newcoin::TMLedgerNode& node = packet.nodes(i);
|
||||
if (!node.has_nodeid() || !node.has_nodedata())
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size()));
|
||||
nodeData.push_back(std::vector<unsigned char>(node.nodedata().begin(), node.nodedata().end()));
|
||||
}
|
||||
if (!theApp->getOPs().gotTXData(shared_from_this(), hash, nodeIDs, nodeData))
|
||||
punishPeer(PP_UNWANTED_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()))
|
||||
punishPeer(PP_UNWANTED_DATA);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ uint256 Serializer::get256(int offset) const
|
||||
{
|
||||
uint256 ret;
|
||||
if ((offset + (256 / 8)) > mData.size()) return ret;
|
||||
memcpy(&ret, &(mData.front()) + offset, (256 / 8));
|
||||
memcpy(ret.begin(), &(mData.front()) + offset, (256 / 8));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
20
src/key.h
20
src/key.h
@@ -188,7 +188,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
CSecret GetSecret() const
|
||||
CSecret GetSecret()
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
@@ -207,7 +207,7 @@ public:
|
||||
return BN_dup(EC_KEY_get0_private_key(pkey));
|
||||
}
|
||||
|
||||
CPrivKey GetPrivKey() const
|
||||
CPrivKey GetPrivKey()
|
||||
{
|
||||
unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
@@ -260,7 +260,7 @@ public:
|
||||
vchSig.clear();
|
||||
unsigned char pchSig[10000];
|
||||
unsigned int nSize = 0;
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
|
||||
if (!ECDSA_sign(0, (unsigned char*)hash.begin(), hash.size(), pchSig, &nSize, pkey))
|
||||
return false;
|
||||
|
||||
vchSig.resize(nSize);
|
||||
@@ -268,14 +268,24 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const
|
||||
bool Verify(const uint256& hash, const void *sig, size_t sigLen) const
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||
if (ECDSA_verify(0, hash.begin(), hash.size(), (const unsigned char *) sig, sigLen, pkey) != 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const
|
||||
{
|
||||
return Verify(hash, &vchSig[0], vchSig.size());
|
||||
}
|
||||
|
||||
bool Verify(const uint256& hash, const std::string sig) const
|
||||
{
|
||||
return Verify(hash, sig.data(), sig.size());
|
||||
}
|
||||
|
||||
// ECIES functions. These throw on failure
|
||||
|
||||
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
|
||||
|
||||
@@ -103,12 +103,11 @@ message TMStatusChange {
|
||||
message TMProposeSet {
|
||||
required uint32 closingSeq = 1;
|
||||
required uint32 proposeSeq = 2;
|
||||
required bytes previousTxHash = 3; // 0 if first proposal, hash we no longer propose
|
||||
required bytes currentTxHash = 4; // the hash of the ledger we are proposing
|
||||
required bytes nodePubKey = 5;
|
||||
required bytes signature = 6; // signature of above fields
|
||||
repeated bytes addedTransactions = 7; // not required if number is large
|
||||
repeated bytes removedTransactions = 8; // not required if number is large
|
||||
required bytes currentTxHash = 3; // the hash of the ledger we are proposing
|
||||
required bytes nodePubKey = 4;
|
||||
required bytes signature = 5; // signature of above fields
|
||||
repeated bytes addedTransactions = 6; // not required if number is large
|
||||
repeated bytes removedTransactions = 7; // not required if number is large
|
||||
}
|
||||
|
||||
// Announce to a peer that we have fully acquired a transaction set
|
||||
@@ -221,13 +220,12 @@ enum TMLedgerInfoType {
|
||||
enum TMLedgerType {
|
||||
ltACCEPTED = 0;
|
||||
ltCURRENT = 1;
|
||||
ltCLOSING = 2;
|
||||
ltCLOSED = 3;
|
||||
ltCLOSED = 2;
|
||||
}
|
||||
|
||||
message TMGetLedger {
|
||||
optional TMLedgerType ltype = 1;
|
||||
optional bytes ledgerHash = 2;
|
||||
optional bytes ledgerHash = 2; // Can also be the transaction set hash if liTS_CANDIDATE
|
||||
optional uint32 ledgerSeq = 3;
|
||||
required TMLedgerInfoType itype = 4;
|
||||
repeated bytes nodeIDs = 5;
|
||||
|
||||
Reference in New Issue
Block a user