From 0c821d176cd4b6b74320ddc95efa7735c17b60c2 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 22 May 2012 07:57:33 -0700 Subject: [PATCH] Peer logic for handling requests and responses for TX set data during ledger consensus building. --- src/Peer.cpp | 210 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 87 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index 172c420294..a39e5224b4 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -692,8 +692,11 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet) void Peer::recvGetLedger(newcoin::TMGetLedger& packet) { + SHAMap::pointer map; + boost::shared_ptr reply = boost::make_shared(); + if (packet.itype() == newcoin::liTS_CANDIDATE) - { + { // Request is for a transaction candidate set Ledger::pointer ledger; if ((!packet.has_ledgerhash() || packet.ledgerhash().size() != 32)) { @@ -702,115 +705,148 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) } uint256 txHash; memcpy(txHash.begin(), packet.ledgerhash().data(), 32); - SHAMap::pointer txMap = theApp->getOPs().getTXMap(txHash); - if (!txMap) + map = theApp->getOPs().getTXMap(txHash); + if (!map) { punishPeer(PP_INVALID_REQUEST); return; } - // WRITEME - } - - // Figure out what ledger they want - Ledger::pointer ledger; - if (packet.has_ledgerhash()) - { - uint256 ledgerhash; - if (packet.ledgerhash().size() != 32) - { - punishPeer(PP_INVALID_REQUEST); - return; - } - 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::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); + 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 data = boost::make_shared(); - 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 nodeIDs; - std::list > rawNodes; - if(map->getNodeFat(mn, nodeIDs, rawNodes)) - { - std::vector::iterator nodeIDIterator; - std::list >::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::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 nodeIDs; + std::list< std::vector > rawNodes; + if(map->getNodeFat(mn, nodeIDs, rawNodes)) + { + std::vector::iterator nodeIDIterator; + std::list< std::vector >::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::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 nodeIDs; + std::list< std::vector > 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(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); }