LCOV - code coverage report
Current view: top level - src/evo - providertx.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 88 90 97.8 %
Date: 2026-06-25 07:23:43 Functions: 65 67 97.0 %

          Line data    Source code
       1             : // Copyright (c) 2018-2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #ifndef BITCOIN_EVO_PROVIDERTX_H
       6             : #define BITCOIN_EVO_PROVIDERTX_H
       7             : 
       8             : #include <bls/bls.h>
       9             : #include <evo/dmn_types.h>
      10             : #include <evo/netinfo.h>
      11             : #include <evo/specialtx.h>
      12             : #include <primitives/transaction.h>
      13             : #include <util/std23.h>
      14             : 
      15             : #include <consensus/validation.h>
      16             : #include <key_io.h>
      17             : #include <netaddress.h>
      18             : #include <pubkey.h>
      19             : 
      20             : #include <univalue.h>
      21             : #include <gsl/pointers.h>
      22             : 
      23             : class CBlockIndex;
      24             : class ChainstateManager;
      25             : class TxValidationState;
      26             : struct RPCResult;
      27             : 
      28             : namespace ProTxVersion {
      29             : enum : uint16_t {
      30             :     LegacyBLS = 1,
      31             :     BasicBLS  = 2,
      32             :     ExtAddr   = 3,
      33             : };
      34             : 
      35             : /** Get highest permissible ProTx version based on flags set. */
      36       50303 : [[nodiscard]] constexpr uint16_t GetMax(const bool is_basic_scheme_active, const bool is_extended_addr)
      37             : {
      38       50303 :     if (is_basic_scheme_active) {
      39       50011 :         if (is_extended_addr) {
      40             :             // Requires *both* forks to be active to use extended addresses. is_basic_scheme_active could
      41             :             // be set to false due to RPC specialization, so we must evaluate is_extended_addr *last* to
      42             :             // avoid accidentally upgrading a legacy BLS node to basic BLS due to v24 activation.
      43       41560 :             return ProTxVersion::ExtAddr;
      44             :         }
      45        8451 :         return ProTxVersion::BasicBLS;
      46             :     }
      47         292 :     return ProTxVersion::LegacyBLS;
      48       50303 : }
      49             : 
      50             : /** Get highest permissible ProTx version based on deployment status
      51             :  *  Note: The override is needed because some RPCs need to use deployment status information for everything *except*
      52             :  *        the BLS version upgrade since they are specializations for a specific BLS version. This is a one-off.
      53             :  *  TODO: Resolve this oddity. Consider deprecating legacy BLS-only RPCs so we can remove them eventually.
      54             :  */
      55             : template <typename T>
      56             : [[nodiscard]] uint16_t GetMaxFromDeployment(gsl::not_null<const CBlockIndex*> pindexPrev, const ChainstateManager& chainman,
      57             :                                             std::optional<bool> is_basic_override = std::nullopt);
      58             : } // namespace ProTxVersion
      59             : 
      60       36670 : class CProRegTx
      61             : {
      62             : public:
      63             :     static constexpr auto SPECIALTX_TYPE = TRANSACTION_PROVIDER_REGISTER;
      64             : 
      65       16133 :     uint16_t nVersion{ProTxVersion::LegacyBLS}; // message version
      66       16133 :     MnType nType{MnType::Regular};
      67       16133 :     uint16_t nMode{0};                                     // only 0 supported for now
      68       16133 :     COutPoint collateralOutpoint{uint256(), (uint32_t)-1}; // if hash is null, we refer to a ProRegTx output
      69       16133 :     std::shared_ptr<NetInfoInterface> netInfo{nullptr};
      70       16133 :     uint160 platformNodeID{};
      71       16133 :     uint16_t platformP2PPort{0};
      72       16133 :     uint16_t platformHTTPPort{0};
      73             :     CKeyID keyIDOwner;
      74             :     CBLSLazyPublicKey pubKeyOperator;
      75             :     CKeyID keyIDVoting;
      76       16133 :     uint16_t nOperatorReward{0};
      77             :     CScript scriptPayout;
      78             :     uint256 inputsHash; // replay protection
      79             :     std::vector<unsigned char> vchSig;
      80             : 
      81       57591 :     SERIALIZE_METHODS(CProRegTx, obj)
      82             :     {
      83       19197 :         READWRITE(
      84             :                 obj.nVersion
      85             :         );
      86       19197 :         if (obj.nVersion == 0 ||
      87       19195 :             obj.nVersion > ProTxVersion::GetMax(/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true)) {
      88             :             // unknown version, bail out early
      89           2 :             return;
      90             :         }
      91             : 
      92       19195 :         READWRITE(
      93             :                 obj.nType,
      94             :                 obj.nMode,
      95             :                 obj.collateralOutpoint,
      96             :                 NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo),
      97             :                                   obj.nVersion >= ProTxVersion::ExtAddr),
      98             :                 obj.keyIDOwner,
      99             :                 CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.pubKeyOperator), (obj.nVersion == ProTxVersion::LegacyBLS)),
     100             :                 obj.keyIDVoting,
     101             :                 obj.nOperatorReward,
     102             :                 obj.scriptPayout,
     103             :                 obj.inputsHash
     104             :         );
     105       19195 :         if (obj.nType == MnType::Evo) {
     106        1926 :             READWRITE(
     107             :                 obj.platformNodeID);
     108        1926 :             if (obj.nVersion < ProTxVersion::ExtAddr) {
     109        1512 :                 READWRITE(
     110             :                 obj.platformP2PPort,
     111             :                 obj.platformHTTPPort);
     112        1512 :             }
     113        1926 :         }
     114       19195 :         if (!(s.GetType() & SER_GETHASH)) {
     115       16536 :             READWRITE(obj.vchSig);
     116       16536 :         }
     117       19197 :     }
     118             : 
     119             :     // When signing with the collateral key, we don't sign the hash but a generated message instead
     120             :     // This is needed for HW wallet support which can only sign text messages as of now
     121             :     std::string MakeSignString() const;
     122             : 
     123             :     std::string ToString() const;
     124             : 
     125             :     [[nodiscard]] static RPCResult GetJsonHelp(const std::string& key, bool optional);
     126             :     [[nodiscard]] UniValue ToJson() const;
     127             : 
     128             :     bool IsTriviallyValid(gsl::not_null<const CBlockIndex*> pindexPrev, const ChainstateManager& chainman,
     129             :                           TxValidationState& state) const;
     130             : };
     131             : 
     132       16339 : class CProUpServTx
     133             : {
     134             : public:
     135             :     static constexpr auto SPECIALTX_TYPE = TRANSACTION_PROVIDER_UPDATE_SERVICE;
     136             : 
     137       16339 :     uint16_t nVersion{ProTxVersion::LegacyBLS}; // message version
     138       16339 :     MnType nType{MnType::Regular};
     139             :     uint256 proTxHash;
     140       16339 :     std::shared_ptr<NetInfoInterface> netInfo{nullptr};
     141       16339 :     uint160 platformNodeID{};
     142       16339 :     uint16_t platformP2PPort{0};
     143       16339 :     uint16_t platformHTTPPort{0};
     144             :     CScript scriptOperatorPayout;
     145             :     uint256 inputsHash; // replay protection
     146             :     CBLSSignature sig;
     147             : 
     148       62664 :     SERIALIZE_METHODS(CProUpServTx, obj)
     149             :     {
     150       20888 :         READWRITE(
     151             :                 obj.nVersion
     152             :         );
     153       20888 :         if (obj.nVersion == 0 ||
     154       20886 :             obj.nVersion > ProTxVersion::GetMax(/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true)) {
     155             :             // unknown version, bail out early
     156           2 :             return;
     157             :         }
     158       20886 :         if (obj.nVersion >= ProTxVersion::BasicBLS) {
     159       20347 :             READWRITE(
     160             :                 obj.nType);
     161       20347 :         }
     162       20886 :         READWRITE(
     163             :                 obj.proTxHash,
     164             :                 NetInfoSerWrapper(const_cast<std::shared_ptr<NetInfoInterface>&>(obj.netInfo),
     165             :                                   obj.nVersion >= ProTxVersion::ExtAddr),
     166             :                 obj.scriptOperatorPayout,
     167             :                 obj.inputsHash
     168             :         );
     169       20886 :         if (obj.nType == MnType::Evo) {
     170        1321 :             READWRITE(
     171             :                 obj.platformNodeID);
     172        1321 :             if (obj.nVersion < ProTxVersion::ExtAddr) {
     173        1039 :                 READWRITE(
     174             :                 obj.platformP2PPort,
     175             :                 obj.platformHTTPPort);
     176        1039 :             }
     177        1321 :         }
     178       20886 :         if (!(s.GetType() & SER_GETHASH)) {
     179       16719 :             READWRITE(
     180             :                     CBLSSignatureVersionWrapper(const_cast<CBLSSignature&>(obj.sig), (obj.nVersion == ProTxVersion::LegacyBLS))
     181             :             );
     182       16719 :         }
     183       20888 :     }
     184             : 
     185             :     std::string ToString() const;
     186             : 
     187             :     [[nodiscard]] static RPCResult GetJsonHelp(const std::string& key, bool optional);
     188             :     [[nodiscard]] UniValue ToJson() const;
     189             : 
     190             :     bool IsTriviallyValid(gsl::not_null<const CBlockIndex*> pindexPrev, const ChainstateManager& chainman,
     191             :                           TxValidationState& state) const;
     192             : };
     193             : 
     194        1084 : class CProUpRegTx
     195             : {
     196             : public:
     197             :     static constexpr auto SPECIALTX_TYPE = TRANSACTION_PROVIDER_UPDATE_REGISTRAR;
     198             : 
     199         542 :     uint16_t nVersion{ProTxVersion::LegacyBLS}; // message version
     200             :     uint256 proTxHash;
     201         542 :     uint16_t nMode{0}; // only 0 supported for now
     202             :     CBLSLazyPublicKey pubKeyOperator;
     203             :     CKeyID keyIDVoting;
     204             :     CScript scriptPayout;
     205             :     uint256 inputsHash; // replay protection
     206             :     std::vector<unsigned char> vchSig;
     207             : 
     208        2118 :     SERIALIZE_METHODS(CProUpRegTx, obj)
     209             :     {
     210         706 :         READWRITE(
     211             :                 obj.nVersion
     212             :         );
     213         706 :         if (obj.nVersion == 0 ||
     214         704 :             obj.nVersion > ProTxVersion::GetMax(/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true)) {
     215             :             // unknown version, bail out early
     216           2 :             return;
     217             :         }
     218         704 :         READWRITE(
     219             :                 obj.proTxHash,
     220             :                 obj.nMode,
     221             :                 CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.pubKeyOperator), (obj.nVersion == ProTxVersion::LegacyBLS)),
     222             :                 obj.keyIDVoting,
     223             :                 obj.scriptPayout,
     224             :                 obj.inputsHash
     225             :         );
     226         704 :         if (!(s.GetType() & SER_GETHASH)) {
     227         550 :             READWRITE(
     228             :                     obj.vchSig
     229             :             );
     230         550 :         }
     231         706 :     }
     232             : 
     233             :     std::string ToString() const;
     234             : 
     235             :     [[nodiscard]] static RPCResult GetJsonHelp(const std::string& key, bool optional);
     236             :     [[nodiscard]] UniValue ToJson() const;
     237             : 
     238             :     bool IsTriviallyValid(gsl::not_null<const CBlockIndex*> pindexPrev, const ChainstateManager& chainman,
     239             :                           TxValidationState& state) const;
     240             : };
     241             : 
     242         830 : class CProUpRevTx
     243             : {
     244             : public:
     245             :     static constexpr auto SPECIALTX_TYPE = TRANSACTION_PROVIDER_UPDATE_REVOKE;
     246             : 
     247             :     // these are just informational and do not have any effect on the revocation
     248             :     enum {
     249             :         REASON_NOT_SPECIFIED = 0,
     250             :         REASON_TERMINATION_OF_SERVICE = 1,
     251             :         REASON_COMPROMISED_KEYS = 2,
     252             :         REASON_CHANGE_OF_KEYS = 3,
     253             :         REASON_LAST = REASON_CHANGE_OF_KEYS
     254             :     };
     255             : 
     256         415 :     uint16_t nVersion{ProTxVersion::LegacyBLS}; // message version
     257             :     uint256 proTxHash;
     258         415 :     uint16_t nReason{REASON_NOT_SPECIFIED};
     259             :     uint256 inputsHash; // replay protection
     260             :     CBLSSignature sig;
     261             : 
     262        1581 :     SERIALIZE_METHODS(CProUpRevTx, obj)
     263             :     {
     264         527 :         READWRITE(
     265             :                 obj.nVersion
     266             :         );
     267         527 :         if (obj.nVersion == 0 ||
     268         527 :             obj.nVersion > ProTxVersion::GetMax(/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true)) {
     269             :             // unknown version, bail out early
     270           0 :             return;
     271             :         }
     272         527 :         READWRITE(
     273             :                 obj.proTxHash,
     274             :                 obj.nReason,
     275             :                 obj.inputsHash
     276             :         );
     277         527 :         if (!(s.GetType() & SER_GETHASH)) {
     278         421 :             READWRITE(
     279             :                     CBLSSignatureVersionWrapper(const_cast<CBLSSignature&>(obj.sig), (obj.nVersion == ProTxVersion::LegacyBLS))
     280             :             );
     281         421 :         }
     282         527 :     }
     283             : 
     284             :     std::string ToString() const;
     285             : 
     286             :     [[nodiscard]] static RPCResult GetJsonHelp(const std::string& key, bool optional);
     287             :     [[nodiscard]] UniValue ToJson() const;
     288             : 
     289             :     bool IsTriviallyValid(gsl::not_null<const CBlockIndex*> pindexPrev, const ChainstateManager& chainman,
     290             :                           TxValidationState& state) const;
     291             : };
     292             : 
     293             : template <typename ProTx>
     294        7864 : static bool CheckInputsHash(const CTransaction& tx, const ProTx& proTx, TxValidationState& state)
     295             : {
     296        7864 :     if (uint256 inputsHash = CalcTxInputsHash(tx); inputsHash != proTx.inputsHash) {
     297           0 :         return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-inputs-hash");
     298             :     }
     299        7864 :     return true;
     300        7864 : }
     301             : 
     302             : #endif // BITCOIN_EVO_PROVIDERTX_H

Generated by: LCOV version 1.16