net: add Dash network message short IDs, allocate range 128 onwards

Also, add add `getqrinfo` and `qrinfo` to `allNetMessageTypes[]` and
`netMessageTypesViolateBlocksOnly[]`
This commit is contained in:
Kittywhiskers Van Gogh 2024-10-24 14:22:03 +00:00
parent 3a18f087bf
commit 9f476c6775
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
3 changed files with 105 additions and 7 deletions

View File

@ -1015,7 +1015,7 @@ namespace {
* Only message types that are actually implemented in this codebase need to be listed, as other
* messages get ignored anyway - whether we know how to decode them or not.
*/
const std::array<std::string, 33> V2_MESSAGE_IDS = {
const std::array<std::string, 33> V2_BITCOIN_IDS = {
"", // 12 bytes follow encoding the message type like in V1
NetMsgType::ADDR,
NetMsgType::BLOCK,
@ -1052,6 +1052,91 @@ const std::array<std::string, 33> V2_MESSAGE_IDS = {
""
};
/** List of short messages allocated in Dash's reserved namespace, in order.
*
* Slots should not be reused unless the switchover has already been done
* by a protocol upgrade, the old message is no longer supported by the client
* and a new slot wasn't already allotted for the message.
*/
const std::array<std::string, 40> V2_DASH_IDS = {
NetMsgType::SPORK,
NetMsgType::GETSPORKS,
NetMsgType::SENDDSQUEUE,
NetMsgType::DSACCEPT,
NetMsgType::DSVIN,
NetMsgType::DSFINALTX,
NetMsgType::DSSIGNFINALTX,
NetMsgType::DSCOMPLETE,
NetMsgType::DSSTATUSUPDATE,
NetMsgType::DSTX,
NetMsgType::DSQUEUE,
NetMsgType::SYNCSTATUSCOUNT,
NetMsgType::MNGOVERNANCESYNC,
NetMsgType::MNGOVERNANCEOBJECT,
NetMsgType::MNGOVERNANCEOBJECTVOTE,
NetMsgType::GETMNLISTDIFF,
NetMsgType::MNLISTDIFF,
NetMsgType::QSENDRECSIGS,
NetMsgType::QFCOMMITMENT,
NetMsgType::QCONTRIB,
NetMsgType::QCOMPLAINT,
NetMsgType::QJUSTIFICATION,
NetMsgType::QPCOMMITMENT,
NetMsgType::QWATCH,
NetMsgType::QSIGSESANN,
NetMsgType::QSIGSHARESINV,
NetMsgType::QGETSIGSHARES,
NetMsgType::QBSIGSHARES,
NetMsgType::QSIGREC,
NetMsgType::QSIGSHARE,
NetMsgType::QGETDATA,
NetMsgType::QDATA,
NetMsgType::CLSIG,
NetMsgType::ISDLOCK,
NetMsgType::MNAUTH,
NetMsgType::GETHEADERS2,
NetMsgType::SENDHEADERS2,
NetMsgType::HEADERS2,
NetMsgType::GETQUORUMROTATIONINFO,
NetMsgType::QUORUMROTATIONINFO
};
/** A complete set of short IDs
*
* Bitcoin takes up short IDs upto 128 (lower half) while Dash can take
* up short IDs between 128 and 256 (upper half) most of the array will
* have entries that correspond to nothing.
*
* To distinguish between entries that are *meant* to correspond to
* nothing versus empty space, use IsValidV2ShortID()
*/
constexpr std::array<std::string_view, 256> V2ShortIDs() {
static_assert(std::size(V2_BITCOIN_IDS) <= 128);
static_assert(std::size(V2_DASH_IDS) <= 128);
std::array<std::string_view, 256> ret{};
for (size_t idx{0}; idx < std::size(ret); idx++) {
if (idx < 128 && idx < std::size(V2_BITCOIN_IDS)) {
ret[idx] = V2_BITCOIN_IDS[idx];
} else if (idx >= 128 && idx - 128 < std::size(V2_DASH_IDS)) {
ret[idx] = V2_DASH_IDS[idx - 128];
} else {
ret[idx] = "";
}
}
return ret;
}
bool IsValidV2ShortID(uint8_t first_byte) {
// Since we have filled the namespace of short IDs, we have to preserve
// the expected behaviour of coming up short when going beyond Bitcoin's
// and Dash's *used* slots. We do this by checking if the byte is within
// the range where a valid message is expected to reside.
return first_byte < std::size(V2_BITCOIN_IDS) ||
(first_byte >= 128 && static_cast<uint8_t>(first_byte - 128) < std::size(V2_DASH_IDS));
}
class V2MessageMap
{
std::unordered_map<std::string, uint8_t> m_map;
@ -1059,8 +1144,10 @@ class V2MessageMap
public:
V2MessageMap() noexcept
{
for (size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
m_map.emplace(V2_MESSAGE_IDS[i], i);
for (size_t i = 1; i < std::size(V2ShortIDs()); ++i) {
if (IsValidV2ShortID(i)) {
m_map.emplace(V2ShortIDs()[i], i);
}
}
}
@ -1524,9 +1611,9 @@ std::optional<std::string> V2Transport::GetMessageType(Span<const uint8_t>& cont
if (first_byte != 0) {
// Short (1 byte) encoding.
if (first_byte < std::size(V2_MESSAGE_IDS)) {
if (IsValidV2ShortID(first_byte)) {
// Valid short message id.
return V2_MESSAGE_IDS[first_byte];
return std::string{V2ShortIDs()[first_byte]};
} else {
// Unknown short message id.
return std::nullopt;

View File

@ -166,7 +166,10 @@ const static std::string allNetMessageTypes[] = {
NetMsgType::MNAUTH,
NetMsgType::GETHEADERS2,
NetMsgType::SENDHEADERS2,
NetMsgType::HEADERS2};
NetMsgType::HEADERS2,
NetMsgType::GETQUORUMROTATIONINFO,
NetMsgType::QUORUMROTATIONINFO
};
const static std::vector<std::string> allNetMessageTypesVec(std::begin(allNetMessageTypes), std::end(allNetMessageTypes));
/** Message types that are not allowed by blocks-relay-only policy.
@ -184,6 +187,7 @@ const static std::string netMessageTypesViolateBlocksOnly[] = {
NetMsgType::DSSTATUSUPDATE,
NetMsgType::DSTX,
NetMsgType::DSVIN,
NetMsgType::GETQUORUMROTATIONINFO,
NetMsgType::QBSIGSHARES,
NetMsgType::QCOMPLAINT,
NetMsgType::QCONTRIB,
@ -197,6 +201,7 @@ const static std::string netMessageTypesViolateBlocksOnly[] = {
NetMsgType::QSIGSESANN,
NetMsgType::QSIGSHARE,
NetMsgType::QSIGSHARESINV,
NetMsgType::QUORUMROTATIONINFO,
NetMsgType::QWATCH,
NetMsgType::TX,
};

View File

@ -1537,7 +1537,13 @@ BOOST_AUTO_TEST_CASE(v2transport_test)
tester.CompareSessionIDs();
auto msg_data_1 = g_insecure_rand_ctx.randbytes<uint8_t>(MAX_PROTOCOL_MESSAGE_LENGTH); // test that receiving max size payload works
auto msg_data_2 = g_insecure_rand_ctx.randbytes<uint8_t>(MAX_PROTOCOL_MESSAGE_LENGTH); // test that sending max size payload works
tester.SendMessage(uint8_t(InsecureRandRange(223) + 33), {}); // unknown short id
tester.SendMessage([]() {
if (g_insecure_rand_ctx.randbool()) {
return static_cast<uint8_t>(InsecureRandRange(95) + 33); // Bitcoin's range
} else {
return static_cast<uint8_t>(InsecureRandRange(88) + 40 + 128); // Dash's range
}
}(), {}); // unknown short id
tester.SendMessage(uint8_t(2), msg_data_1); // "block" short id
tester.AddMessage("blocktxn", msg_data_2); // schedule blocktxn to be sent to us
ret = tester.Interact();