edit 0: Updated to reflect updates mentioned in #10145 (comment)
This PR separates ProcessMessage into two functions, ContextualProcessMessage and ~ProcessMessage~ Process*Message. This helps with readability, verifiability, and maintainability of the code.
ContextualProcessMessage generates a list of context dependent “whitelists”, all of which must pass for the incoming message before a call to ProcessMessage may be made. If the whitelists fail, the code that follows should be identical to the previous behavior. The choice of whitelists over blacklists is because it is better to explicitly enable the behaviors desired, rather than to try to block the potential bad features (e.g., adding something unsafe and new won’t be permitted in unstudied contexts). This design should be extensible for adding new features (~up to 64 netmsgs total~ unlimited network messages) as well as new contexts (easy to add new whitelists). There should be very little overhead to check these whitelists as it is all ~bitwise~ bool array lookups.
~ProcessMessage now uses an enum to switch to~ Dispatch is now done using a std::map lookup to get the appropriate handler, and is semi “stateless” (the map is const). This makes it easier to verify the code and make dispatch more modular.
I haven’t benchmarked that the conversion from string->~enum~std::pair<handler_t, whitelist_index> has any performance implication, negative or positive. In theory this code could be faster given fewer branch mispredictions due to the ~switch~function pointer call. Another PR could improve the lookup algorithm ~(trivially, inlining getAllNetMessageTypes might help the compiler a lot)~, but unless it is exotic it should be compatible with this design by replacing the map with the desired scheme. ~I didn’t think there was something obviously faster than the linear lookup, because n is small.~ A std::map lookup should be fairly fast, but perhaps a custom map could be faster.
~The correctness of this code is dependent on NetMsgTypeEnum::tag and allNetMessageTypes having the same index order. It would be nice to verify this property at compile time, which should be possible with some recursive constexpr static_assert magic. The default return of ProcessNewMessage is now also false, because the last return is unreachable.~
See #9608 and https://github.com/theuni/bitcoin/commit/f1e4e281e3f1eb884f8010ac941c82752174bdbe for related work/alternatives.