|
4 | 4 | #include <xrpld/app/ledger/LedgerMaster.h> |
5 | 5 | #include <xrpld/app/ledger/TransactionStateSF.h> |
6 | 6 | #include <xrpld/app/main/Application.h> |
| 7 | +#include <xrpld/app/misc/AmendmentTable.h> |
7 | 8 | #include <xrpld/overlay/Overlay.h> |
8 | 9 |
|
9 | 10 | #include <xrpl/basics/Log.h> |
@@ -819,22 +820,54 @@ InboundLedger::receiveNode(protocol::TMLedgerData& packet, SHAMapAddNode& san) |
819 | 820 | { |
820 | 821 | auto const f = filter.get(); |
821 | 822 |
|
822 | | - for (auto const& node : packet.nodes()) |
| 823 | + for (auto const& ledgerNode : packet.nodes()) |
823 | 824 | { |
824 | | - auto const nodeID = deserializeSHAMapNodeID(node.nodeid()); |
825 | | - |
826 | | - if (!nodeID) |
827 | | - throw std::runtime_error("data does not properly deserialize"); |
| 825 | + auto nodeSlice = makeSlice(ledgerNode.nodedata()); |
| 826 | + auto treeNode = SHAMapTreeNode::makeFromWire(nodeSlice); |
| 827 | + if (!treeNode) |
| 828 | + { |
| 829 | + JLOG(journal_.warn()) << "Got invalid node data"; |
| 830 | + san.incInvalid(); |
| 831 | + return; |
| 832 | + } |
| 833 | + auto const nodeKey = static_cast<SHAMapLeafNode const*>(treeNode.get())->peekItem()->key(); |
828 | 834 |
|
829 | | - if (nodeID->isRoot()) |
| 835 | + SHAMapNodeID nodeID; |
| 836 | + if (app_.getAmendmentTable().isSupported(fixLedgerNodeDepth)) |
830 | 837 | { |
831 | | - san += map.addRootNode(rootHash, makeSlice(node.nodedata()), f); |
| 838 | + nodeID = SHAMapNodeID::createID(ledgerNode.nodedepth(), nodeKey); |
832 | 839 | } |
833 | 840 | else |
834 | 841 | { |
835 | | - san += map.addKnownNode(*nodeID, makeSlice(node.nodedata()), f); |
| 842 | + auto const nid = deserializeSHAMapNodeID(ledgerNode.nodeid()); |
| 843 | + if (!nid) |
| 844 | + { |
| 845 | + JLOG(journal_.warn()) << "Got invalid node id"; |
| 846 | + san.incInvalid(); |
| 847 | + return; |
| 848 | + } |
| 849 | + nodeID = *nid; |
| 850 | + |
| 851 | + // For leaf nodes, verify that the passed-in node ID is actually |
| 852 | + // the same as what the node ID should be, given the position of |
| 853 | + // the node in the SHAMap. |
| 854 | + if (treeNode->isLeaf()) |
| 855 | + { |
| 856 | + auto const expectedID = SHAMapNodeID::createID(nodeID.getDepth(), nodeKey); |
| 857 | + if (nodeID.getNodeID() != expectedID.getNodeID()) |
| 858 | + { |
| 859 | + JLOG(journal_.warn()) << "Got invalid node id"; |
| 860 | + san.incInvalid(); |
| 861 | + return; |
| 862 | + } |
| 863 | + } |
836 | 864 | } |
837 | 865 |
|
| 866 | + if (nodeID.isRoot()) |
| 867 | + san += map.addRootNode(rootHash, nodeSlice, f); |
| 868 | + else |
| 869 | + san += map.addKnownNode(nodeID, nodeSlice, f); |
| 870 | + |
838 | 871 | if (!san.isGood()) |
839 | 872 | { |
840 | 873 | JLOG(journal_.warn()) << "Received bad node data"; |
@@ -1044,13 +1077,15 @@ InboundLedger::processData(std::shared_ptr<Peer> peer, protocol::TMLedgerData& p |
1044 | 1077 |
|
1045 | 1078 | ScopedLockType sl(mtx_); |
1046 | 1079 |
|
1047 | | - // Verify node IDs and data are complete |
1048 | | - for (auto const& node : packet.nodes()) |
| 1080 | + // Verify nodes are complete |
| 1081 | + for (auto const& ledgerNode : packet.nodes()) |
1049 | 1082 | { |
1050 | | - if (!node.has_nodeid() || !node.has_nodedata()) |
| 1083 | + if (!ledgerNode.has_nodedata() || |
| 1084 | + (app_.getAmendmentTable().isSupported(fixLedgerNodeDepth) && !ledgerNode.has_nodedepth()) || |
| 1085 | + (!app_.getAmendmentTable().isSupported(fixLedgerNodeDepth) && !ledgerNode.has_nodeid())) |
1051 | 1086 | { |
1052 | | - JLOG(journal_.warn()) << "Got bad node"; |
1053 | | - peer->charge(Resource::feeMalformedRequest, "ledger_data bad node"); |
| 1087 | + JLOG(journal_.warn()) << "Got malformed ledger node"; |
| 1088 | + peer->charge(Resource::feeMalformedRequest, "ledger_node"); |
1054 | 1089 | return -1; |
1055 | 1090 | } |
1056 | 1091 | } |
|
0 commit comments