validation: Templatize ValidationState instead of subclassing #17399

pull jkczyz wants to merge 3 commits into bitcoin:master from jkczyz:2019-11-validation-state changing 15 files +58 −125
  1. jkczyz commented at 1:16 am on November 7, 2019: contributor

    This removes boilerplate code in the subclasses which otherwise only differ by the result type.

    The subclassing was introduced in a27a295.

  2. DrahtBot added the label Utils/log/libs on Nov 7, 2019
  3. DrahtBot added the label Validation on Nov 7, 2019
  4. ryanofsky approved
  5. ryanofsky commented at 2:14 am on November 7, 2019: member

    Code review ACK aa67e6d736fab1cf125687f3393a3eb259fb8608.

    Medium concept ACK. Nice that this eliminates duplicate code. Added #includes and template function might slow down compilation a bit, though.

  6. DrahtBot commented at 3:36 am on November 7, 2019: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #18077 (net: Add NAT-PMP port forwarding support by hebasto)
    • #17828 (net: Use log categories when logging events that P2P peers can trigger arbitrarily by practicalswift)
    • #17812 (config, net, test: asmap functional tests and feature refinements by jonatack)
    • #17737 (Add ChainstateManager, remove BlockManager global by jamesob)
    • #17479 (Return BlockValidationState from ProcessNewBlock if CheckBlock/AcceptBlock fails by jnewbery)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  7. in src/consensus/validation.h:89 in aa67e6d736 outdated
    87     std::string m_reject_reason;
    88     std::string m_debug_message;
    89-protected:
    90-    void Invalid(const std::string &reject_reason="",
    91+public:
    92+    ValidationState() : m_mode(MODE_VALID) {}
    


    promag commented at 10:28 am on November 7, 2019:
    nit, in L85 do } m_mode{MODE_VALID}; and drop constructor?

    jkczyz commented at 6:30 pm on November 7, 2019:
    The diff here is a bit misleading as I’m actually moving Invalid to the public section and not modifying the constructor. Is the convention to put this in a separate a commit? Or would it be considered outside the scope of the PR?

    promag commented at 9:26 pm on November 8, 2019:
    Right, but the constructor could still be dropped.

    jkczyz commented at 10:16 pm on November 8, 2019:
    Understood. But that doesn’t answer either of my questions… 🤔

    promag commented at 3:37 pm on November 11, 2019:
    IMHO could be added in “Templatize ValidationState instead of subclassing”, but no big deal.

    jkczyz commented at 11:24 pm on November 11, 2019:
    Ended up doing this separately in 7470037 as it gives cleaner diffs.
  8. in src/consensus/tx_check.h:8 in aa67e6d736 outdated
    4@@ -5,6 +5,8 @@
    5 #ifndef BITCOIN_CONSENSUS_TX_CHECK_H
    6 #define BITCOIN_CONSENSUS_TX_CHECK_H
    7 
    8+#include <consensus/validation.h>
    


    promag commented at 10:33 am on November 7, 2019:
    You can still forward declare TxValidationState and BlockValidationState where needed and avoid the issues pointed by @ryanofsky?

    jkczyz commented at 6:28 pm on November 7, 2019:

    This causes a compilation error:

    0In file included from consensus/tx_check.cpp:8:
    1./consensus/validation.h:115:7: error: typedef redefinition with different types ('ValidationState<TxValidationResult>' vs 'TxValidationState')
    2using TxValidationState = ValidationState<TxValidationResult>;
    3      ^
    4./consensus/tx_check.h:16:7: note: previous definition is here
    5class TxValidationState;
    

    I’d have to forward declare the full template type and enum then use that in the function declaration.

    0enum class TxValidationResult;
    1template <typename Result>
    2class ValidationState;
    3
    4bool CheckTransaction(const CTransaction& tx, ValidationState<TxValidationResult>& state);
    

    Seems a bit verbose and would mismatch the function definition. FWIW, here are some pros and cons of forward declaring that I’m aware of.

  9. promag commented at 10:34 am on November 7, 2019: member
    Concept ACK.
  10. laanwj commented at 8:37 am on November 8, 2019: member

    Concept ACK.

    Added #includes and template function might slow down compilation a bit, though.

    Yes, although this is a quite straightforward use of templates, no boost nested template horrors, so I hope it’s not too bad.

  11. in src/util/validation.h:15 in aa67e6d736 outdated
    13+#include <string>
    14 
    15 /** Convert ValidationState to a human-readable message for logging */
    16-std::string FormatStateMessage(const ValidationState &state);
    17+template <typename Result>
    18+std::string FormatStateMessage(const ValidationState<Result>& state)
    


    ajtowns commented at 11:35 am on November 8, 2019:

    Could move this into ValidationState directly, and make it

    0std::string FormatStateMessage() const { return m_reject_reason + (m_debug_message.empty() ? "" : ", " + m_debug_message); }
    

    jkczyz commented at 10:15 pm on November 8, 2019:
    Done in 7239d01 but named it ToString since #16688 uses it for valid states as well.
  12. in src/consensus/validation.h:115 in aa67e6d736 outdated
    140-        ValidationState::Invalid(reject_reason, debug_message);
    141-        return false;
    142-    }
    143-    BlockValidationResult GetResult() const { return m_result; }
    144-};
    145+using TxValidationState = ValidationState<TxValidationResult>;
    


    ajtowns commented at 11:38 am on November 8, 2019:
    I think you can do class TxValidationState : ValidationState<TxValidationResult> { }; and still be able to use forward declarations class TxValidationState; fwiw.

    jkczyz commented at 10:15 pm on November 8, 2019:
    Good idea! Done in 0468628.
  13. ajtowns commented at 11:39 am on November 8, 2019: member
    Concept ACK
  14. jnewbery commented at 8:21 pm on November 8, 2019: member
    Concept ACK. Will review code once @ajtowns’s comments are addressed.
  15. jkczyz force-pushed on Nov 8, 2019
  16. jkczyz force-pushed on Nov 8, 2019
  17. DrahtBot added the label Needs rebase on Nov 8, 2019
  18. promag commented at 9:27 pm on November 8, 2019: member
    Nice suggestions from @ajtowns!
  19. jkczyz force-pushed on Nov 8, 2019
  20. DrahtBot removed the label Needs rebase on Nov 8, 2019
  21. practicalswift commented at 12:44 pm on November 11, 2019: contributor
    Concept ACK: new code is easier to reason about
  22. in src/util/validation.cpp:8 in 0468628e81 outdated
    14-    return strprintf("%s%s",
    15-        state.GetRejectReason(),
    16-        state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage());
    17-}
    18-
    19 const std::string strMessageMagic = "Bitcoin Signed Message:\n";
    


    jnewbery commented at 2:48 pm on November 11, 2019:
    It seems a bit sad to leave this const all by itself in this implementation file. Perhaps move it to the header file and change to a constexpr? Bonus points for renaming util/validation.h to util/strings.h since it isn’t anything to do with validation any more, and I can’t find anywhere that would be a better home for this const.

    MarcoFalke commented at 4:06 pm on November 11, 2019:
    I don’t thing std::string can be constexpr. Also, moving it to the header file might inline it in every translation unit. Probably doesn’t matter for a short string like this, but no need to change existing code to make it worse.

    jnewbery commented at 4:49 pm on November 11, 2019:
    You’re right. std::string can’t be constexpr.

    jkczyz commented at 11:14 pm on November 11, 2019:

    Looking at the references to strMessageMagic, they are always of the form:

    0CHashWriter ss(SER_GETHASH, 0);
    1ss << strMessageMagic;
    2ss << strMessage;
    

    And then the result of its GetHash is passed to either SignCompact or RecoverCompact, and the variable ss is never used again.

    So the above code could be refactored into a function where strMessageMagic is just an implementation detail. Given that, is there a more appropriate place for it? What does ss stand for here?


    jnewbery commented at 11:19 pm on November 11, 2019:

    What does ss stand for here?

    Not sure. Serialization stream?


    jnewbery commented at 11:22 pm on November 11, 2019:
    (there have been CDataStream ss variables in the codebase since Satoshi era)

    jkczyz commented at 0:41 am on November 12, 2019:

    Perhaps I could move that boilerplate code to util/hash.h as HashMessage?

    0uint256 HashMessage(const std::string& message);
    

    Open to more suitable naming for the file and function. Note that util/string.h already exists for string joining, so the plural version may be confusing.

    Would likely leave this to a follow-up PR given I’d be refactoring call sites.


    jnewbery commented at 7:38 pm on November 13, 2019:

    Open to more suitable naming for the file and function

    Perhaps /util/message.h?

    Would likely leave this to a follow-up PR given I’d be refactoring call sites.

    Yeah, anything other than a simple rename should be left as a follow-up PR.


    jkczyz commented at 6:28 am on November 22, 2019:
    Opened #17557 with the refactor.

    jkczyz commented at 6:17 pm on February 28, 2020:
    Rebased and was able to remove util/validation.h and util/validation.cpp now that #17577 is merged.
  23. jnewbery commented at 2:56 pm on November 11, 2019: member

    Tested ACK 0468628e8191c574d2568f5e9e7fa15dd43d80f2. Nice tidy up!

    One suggestion for getting rid of a now almost-empty file. Can be done in this PR or a follow-up.

  24. promag commented at 3:57 pm on November 11, 2019: member

    Code review ACK 0468628e8191c574d2568f5e9e7fa15dd43d80f2.

    Restarted failed job on travis.

  25. jkczyz force-pushed on Nov 11, 2019
  26. jnewbery commented at 7:41 pm on November 13, 2019: member
    utACK 2948ebd29d0a53f11aefc8546bcac4125c726cc6
  27. DrahtBot added the label Needs rebase on Nov 28, 2019
  28. jkczyz force-pushed on Nov 30, 2019
  29. jkczyz commented at 0:58 am on November 30, 2019: contributor
    Rebased and updated to account for #17624 in 1452949.
  30. DrahtBot removed the label Needs rebase on Nov 30, 2019
  31. ariard commented at 5:25 pm on December 6, 2019: member

    Code review ACK 1452949.

    About the increase compilation time concern, on my system compare to master it’s even a bit slightly slightly faster.

  32. MarcoFalke commented at 6:00 pm on December 20, 2019: member

    ACK 14529499743e071ddc091e5508e1eea4532e754d 🎏

    Signature:

     0-----BEGIN PGP SIGNED MESSAGE-----
     1Hash: SHA512
     2
     3ACK 14529499743e071ddc091e5508e1eea4532e754d 🎏
     4-----BEGIN PGP SIGNATURE-----
     5
     6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
     7pUgCpgv/XrM9w3dqV6IqX53LVCU81lx6hex2Gjbb8X0wb2rfaBxS1H/y+DHq9cPs
     8iBh6bp5HGABL2dRPcS3mvyBzA9lbWu4MZVzqu728m9m2tUdMjnezxzz0tZOhmcWL
     9vW8+UpYVnr4UahR9k5X2N06v7YoqkpNmQ06aSOkRCNd7XPkjOAh3SN5zOSUjs1n8
    102wUOPPNAbBS5UgFt6vTPTzm6AMNWp+fXtqnSIe84JFkefEoFo0EW1f72Nyb1agrG
    1170Cxd+Ph4de0yZq+lvcrZz62JPOGwF8AWW8ls+82hOFMmmxI1eduQPo9xuEvv14b
    12euvSNwjmUenZBhldWXAR0ct13O3NNgSzdbWZjBomqtDFDa5MpcOGHeCppYmxykD7
    137FX/+Ye7Q181D7vXBFj/YBEGqPyIuLIm0NV1N6EPl8gYiqaK0c7UF0TJPqwWE6k1
    14HjhDdT4cD9rZrcl9u6mt2zdjcavNuyfMO13seNINZVXuNkgleta/sCh2edQU41XL
    15I09hdKhh
    16=2AEE
    17-----END PGP SIGNATURE-----
    

    Timestamp of file with hash 70e15c1a24082f6b136c95c7920ed1bc271fccb39fdfee1f98976554082edd59 -

  33. jnewbery commented at 11:23 pm on December 20, 2019: member

    utACK 14529499743e071ddc091e5508e1eea4532e754d

    Since the initialization relies on [TX|BLOCK]_RESULT_UNSET being 0, what do you think of:

     0--- a/src/consensus/validation.h
     1+++ b/src/consensus/validation.h
     2@@ -16,7 +16,7 @@
     3   * provider of the transaction should be banned/ignored/disconnected/etc.
     4   */
     5 enum class TxValidationResult {
     6-    TX_RESULT_UNSET,         //!< initial value. Tx has not yet been rejected
     7+    TX_RESULT_UNSET = 0,     //!< initial value. Tx has not yet been rejected. Must be zero/first defined enumerator for default initialization.
     8     TX_CONSENSUS,            //!< invalid by consensus rules
     9     /**
    10      * Invalid by a change to consensus rules more recent than SegWit.
    11@@ -50,7 +50,7 @@ enum class TxValidationResult {
    12   * useful for some other use-cases.
    13   */
    14 enum class BlockValidationResult {
    15-    BLOCK_RESULT_UNSET,      //!< initial value. Block has not yet been rejected
    16+    BLOCK_RESULT_UNSET = 0,  //!< initial value. Block has not yet been rejected. Must be zero/first defined enumerator for default initialization.
    17     BLOCK_CONSENSUS,         //!< invalid by consensus rules (excluding any below reasons)
    18     /**
    19      * Invalid by a change to consensus rules more recent than SegWit.
    
  34. jkczyz force-pushed on Dec 22, 2019
  35. jkczyz commented at 3:46 am on December 22, 2019: contributor

    utACK 1452949

    Since the initialization relies on [TX|BLOCK]_RESULT_UNSET being 0, what do you think of:

     0--- a/src/consensus/validation.h
     1+++ b/src/consensus/validation.h
     2@@ -16,7 +16,7 @@
     3   * provider of the transaction should be banned/ignored/disconnected/etc.
     4   */
     5 enum class TxValidationResult {
     6-    TX_RESULT_UNSET,         //!< initial value. Tx has not yet been rejected
     7+    TX_RESULT_UNSET = 0,     //!< initial value. Tx has not yet been rejected. Must be zero/first defined enumerator for default initialization.
     8     TX_CONSENSUS,            //!< invalid by consensus rules
     9     /**
    10      * Invalid by a change to consensus rules more recent than SegWit.
    11@@ -50,7 +50,7 @@ enum class TxValidationResult {
    12   * useful for some other use-cases.
    13   */
    14 enum class BlockValidationResult {
    15-    BLOCK_RESULT_UNSET,      //!< initial value. Block has not yet been rejected
    16+    BLOCK_RESULT_UNSET = 0,  //!< initial value. Block has not yet been rejected. Must be zero/first defined enumerator for default initialization.
    17     BLOCK_CONSENSUS,         //!< invalid by consensus rules (excluding any below reasons)
    18     /**
    19      * Invalid by a change to consensus rules more recent than SegWit.
    

    Good call. Pushed a975974. @promag @ariard @MarcoFalke You can verify the change with git range-diff abb30de63 145294997 a975974f4.

  36. jnewbery commented at 3:38 pm on December 22, 2019: member
    ACK a975974
  37. DrahtBot added the label Needs rebase on Jan 2, 2020
  38. jkczyz force-pushed on Jan 3, 2020
  39. jkczyz commented at 8:40 pm on January 3, 2020: contributor
    Rebased
  40. jnewbery commented at 9:00 pm on January 3, 2020: member
    reACK 2afff87a88a3f539cece488f927386a6e106cdc2
  41. DrahtBot removed the label Needs rebase on Jan 3, 2020
  42. ariard commented at 11:16 pm on January 3, 2020: member
    ACK 2afff87, only change since 1452949 is default initialization first member of TxValidationResult/BlockValidationResult enums to 0.
  43. MarcoFalke deleted a comment on Jan 7, 2020
  44. DrahtBot added the label Needs rebase on Jan 9, 2020
  45. jkczyz force-pushed on Jan 9, 2020
  46. jkczyz force-pushed on Jan 9, 2020
  47. jkczyz commented at 10:47 pm on January 9, 2020: contributor

    Rebased to account for changes in #16688. Specifically, pushed 7bb194ba252191b531803ad2952c984c70d192da to:

    • Account for changes to FormatStateMessage made in 72f3227c83810936e7a334304e5fd7c6dab8e91b and 6edebacb2191373e76d79a4972d6192300976096
    • Update use of FormatStateMessage in f9abf4ab6d3d3e4d4b7e90723020b5422a141a6f

    Can be verified with:

    0git range-diff 17e14ac..2afff87 e7f8450..bf5bc26
    
  48. DrahtBot removed the label Needs rebase on Jan 9, 2020
  49. jnewbery commented at 6:43 pm on January 10, 2020: member
    code review ACK bf5bc260e914e2413bed4041e5089fdee03a344a
  50. DrahtBot added the label Needs rebase on Jan 29, 2020
  51. Refactor FormatStateMessage into ValidationState 0aed17ef28
  52. Remove ValidationState's constructor 10e85d4adc
  53. Templatize ValidationState instead of subclassing
    This removes boilerplate code in the subclasses which otherwise only
    differ by the result type.
    10efc0487c
  54. jkczyz force-pushed on Feb 28, 2020
  55. DrahtBot removed the label Needs rebase on Feb 28, 2020
  56. MarcoFalke commented at 7:17 pm on February 28, 2020: member

    ACK 10efc0487c442bccb0e4a9ac29452af1592a3cf2 🐱

    Signature:

     0-----BEGIN PGP SIGNED MESSAGE-----
     1Hash: SHA512
     2
     3ACK 10efc0487c442bccb0e4a9ac29452af1592a3cf2 🐱
     4-----BEGIN PGP SIGNATURE-----
     5
     6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
     7pUiSBQv9GTJ4FVCrg3wq2XM0X75nYvO3+OK32UmnzgXDJjk7Pghohc7v7mUhqpnc
     8hmwCVwvvs9r5PdRx2BYx/GgPi6UEQ0KSjZfDxKUYcA7lMYCcHlHUxoohNj0mssN+
     9hpuGhzhBEYyX1jHNFazpSMSlKVPvesXQRHgo4Kw4EyyI1EU1Mpdi/nPWpsY6Of0y
    10Gg49gHJVvMp08RmkTVLRBWF0KqUATRfUTgqVUr5bit3tKZZPacxaiXSE8W8WXRa5
    11Nb6e1WHAa8+jWqlahlCFJnw4UoyXSIHtijhBgVliCo7wX5Lj588VjouQeaXEIufZ
    12q823LmNj8QdOwnNnE9wMSKYX/kQaGB+R3KRDpH+s6zHub86fA0/oz3dkER4XWaIM
    13DZNcYPnJYNgWtZ9f99uIC87pHeQ3kFA+5/xroVzjPvFEGLv7euwlgZn0v2rb2dB5
    14vgmIwvEH/B8/pH3GvL65yGCVFrkVA5rAnNGViav0KJujkWXukc0fkC9to5urHnwB
    15oz7K+tzI
    16=g9Fg
    17-----END PGP SIGNATURE-----
    

    Timestamp of file with hash 02d3cb1c7845b1a605977e2f801af0118c57df49376b61c77970f1807528dacf -

  57. practicalswift commented at 7:47 pm on February 29, 2020: contributor
    ACK 10e85d4adc9b7dbbda63e00195e0a962f51e4d2c – patch looks correct
  58. ajtowns commented at 12:53 pm on March 1, 2020: member
    ACK 10efc0487c442bccb0e4a9ac29452af1592a3cf2 – looks good to me
  59. jonatack commented at 2:06 pm on March 1, 2020: member
    ACK 10efc048 code review, build/tests green, nice cleanup
  60. MarcoFalke merged this on Mar 1, 2020
  61. MarcoFalke closed this on Mar 1, 2020

  62. practicalswift commented at 8:37 pm on March 1, 2020: contributor
    post-merge ACK 10efc0487c442bccb0e4a9ac29452af1592a3cf2
  63. sidhujag referenced this in commit 12748b0c7c on Mar 2, 2020
  64. deadalnix referenced this in commit 46a3c8ef67 on Nov 9, 2020
  65. jasonbcox referenced this in commit 0bc9d84a6c on Nov 9, 2020
  66. jasonbcox referenced this in commit 0f17907934 on Nov 9, 2020
  67. sidhujag referenced this in commit c07d8cbb4c on Nov 10, 2020
  68. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-18 21:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me