You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge #6636: refactor: replace CDeterministicMNStateDiff macros with boost::hana
0073e9a refactor: replace `CDeterministicMNStateDiff` macros with `boost::hana` (Kittywhiskers Van Gogh)
Pull request description:
## Additional Information
* Dependency for #6627
* Currently, we rely on a set of macros to use a different set of instructions for (de)serializing `pubKeyOperator` in `CDeterministicMNStateDiff`, one of those macros is the following
https://github.com/dashpay/dash/blob/bcd14b05cec7d94986f114ca17bbdadbee701d9b/src/evo/dmnstate.h#L219-L226
If we pretend `DMN_STATE_DIFF_ALL_FIELDS` only pertains to `pubKeyOperator`, the macro would expand as
```c++
if (strcmp("pubKeyOperator", "pubKeyOperator") == 0 && (obj.fields & Field_pubKeyOperator)) {
SER_READ(obj, read_pubkey = true);
READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.state.pubKeyOperator), obj.state.nVersion == CProRegTx::LEGACY_BLS_VERSION));
} else if (obj.fields & Field_pubKeyOperator) READWRITE(obj.state.pubKeyOperator);
```
Even though `READWRITE(obj.state.pubKeyOperator)` is _logically_ unreachable, it is something the compiler still has to evaluate and it can because `READWRITE(obj.state.pubKeyOperator)` is still a valid expression.
But if we need to carve out a similar different rule in a later PR for `newThing` where `newThing` is a `std::shared_ptr<Interface>` that is implemented by the serializable type `Implementation`, the unreachable but still evaluable expression `READWRITE(obj.state.newThing)` cannot be evaluated as you _cannot_ do anything with a pure virtual class, which `Interface` is even though the code right before it uses a wrapper to handle `newThing` correctly.
To sidestep this issue, we need to be able to `constexpr` evaluate what field is being (de)serialized and decide the (de)serialization logic for it accordingly, which will _exclude_ all other logic that doesn't apply _at compile time_. The current macro-based solution doesn't allow for that.
While `std::tuple` allows for storing a heterogenous collection of elements, iterating through it proves to be difficult. `std::apply` proves to be too restrictive for what we need to do ([source](https://stackoverflow.com/a/54053084)) and the capability needed to do this properly, "expansion statements" could be available in C++26 ([source](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2996r0.html)), which is a long time from now.
So, our best option is to use a library that specializes in working with heterogenous collections and thankfully, such a library is already available in Boost called Hana ([source](https://www.boost.org/doc/libs/1_81_0/libs/hana/doc/html/index.html)) and it is headers-only ([source](https://www.boost.org/doc/libs/1_81_0/more/getting_started/unix-variants.html#header-only-libraries), list of all libraries that need building, Hana is not on the list) and is therefore, already available to us.
## Breaking Changes
None expected.
## Checklist
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
- [x] I have added or updated relevant unit/integration/functional/e2e tests
- [x] I have made corresponding changes to the documentation **(note: N/A)**
- [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_
ACKs for top commit:
UdjinM6:
utACK 0073e9a
Tree-SHA512: c0b7e4214e6180f755e6d030bc24f7cb0d5ab0d5fb262a6394bc17d60bf4de0be9148cd0b07cd00f5e78c1b07c156d65c54c25c2ac6fa49bf7d2ae9a406650a8
0 commit comments