LCOV - code coverage report
Current view: top level - src - blocksignature.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 48 59 81.4 %
Date: 2025-02-23 09:33:43 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2017-2021 The PIVX 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             : #include "blocksignature.h"
       6             : 
       7             : #include "script/standard.h"
       8             : #include "zpiv/zpivmodule.h"
       9             : 
      10        1937 : static bool GetKeyIDFromUTXO(const CTxOut& utxo, CKeyID& keyIDRet)
      11             : {
      12        3874 :     std::vector<valtype> vSolutions;
      13        1937 :     txnouttype whichType;
      14        2006 :     if (utxo.scriptPubKey.empty() || !Solver(utxo.scriptPubKey, whichType, vSolutions))
      15           0 :         return false;
      16        1937 :     if (whichType == TX_PUBKEY) {
      17          68 :         keyIDRet = CPubKey(vSolutions[0]).GetID();
      18          68 :         return true;
      19             :     }
      20        1869 :     if (whichType == TX_PUBKEYHASH || whichType == TX_COLDSTAKE) {
      21        1869 :         keyIDRet = CKeyID(uint160(vSolutions[0]));
      22        1869 :         return true;
      23             :     }
      24           0 :     if (whichType == TX_EXCHANGEADDR) {
      25           0 :         keyIDRet = CExchangeKeyID(uint160(vSolutions[0]));
      26           0 :         return true;
      27             :     }
      28             :     return false;
      29             : }
      30             : 
      31        1977 : bool SignBlockWithKey(CBlock& block, const CKey& key)
      32             : {
      33        1977 :     if (!key.Sign(block.GetHash(), block.vchBlockSig))
      34           0 :         return error("%s: failed to sign block hash with key", __func__);
      35             : 
      36             :     return true;
      37             : }
      38             : 
      39        1937 : bool SignBlock(CBlock& block, const CKeyStore& keystore)
      40             : {
      41        1937 :     CKeyID keyID;
      42        1937 :     if (!GetKeyIDFromUTXO(block.vtx[1]->vout[1], keyID)) {
      43           0 :         return error("%s: failed to find key for PoS", __func__);
      44             :     }
      45             : 
      46        3874 :     CKey key;
      47        1937 :     if (!keystore.GetKey(keyID, key))
      48           0 :         return error("%s: failed to get key from keystore", __func__);
      49             : 
      50        1937 :     return SignBlockWithKey(block, key);
      51             : }
      52             : 
      53       42856 : bool CheckBlockSignature(const CBlock& block)
      54             : {
      55       42856 :     if (block.IsProofOfWork())
      56       36061 :         return block.vchBlockSig.empty();
      57             : 
      58        6795 :     if (block.vchBlockSig.empty())
      59           0 :         return error("%s: vchBlockSig is empty!", __func__);
      60             : 
      61             :     /** Each block is signed by the private key of the input that is staked. This can be either zPIV or normal UTXO
      62             :      *  zPIV: Each zPIV has a keypair associated with it. The serial number is a hash of the public key.
      63             :      *  UTXO: The public key that signs must match the public key associated with the first utxo of the coinstake tx.
      64             :      */
      65        6795 :     CPubKey pubkey;
      66        6795 :     bool fzPIVStake = block.vtx[1]->vin[0].IsZerocoinSpend();
      67        6795 :     if (fzPIVStake) {
      68           0 :         libzerocoin::CoinSpend spend = ZPIVModule::TxInToZerocoinSpend(block.vtx[1]->vin[0]);
      69           0 :         pubkey = spend.getPubKey();
      70             :     } else {
      71        6795 :         txnouttype whichType;
      72       13580 :         std::vector<valtype> vSolutions;
      73        6795 :         const CTxOut& txout = block.vtx[1]->vout[1];
      74        6795 :         if (!Solver(txout.scriptPubKey, whichType, vSolutions))
      75          10 :             return false;
      76             : 
      77        6795 :         if (whichType == TX_PUBKEY) {
      78          88 :             valtype& vchPubKey = vSolutions[0];
      79          88 :             pubkey = CPubKey(vchPubKey);
      80        6707 :         } else if (whichType == TX_PUBKEYHASH) {
      81        6701 :             const CTxIn& txin = block.vtx[1]->vin[0];
      82             :             // Check if the scriptSig is for a p2pk or a p2pkh
      83       13402 :             if (txin.scriptSig.size() == 73) { // Sig size + DER signature size.
      84             :                 // If the input is for a p2pk and the output is a p2pkh.
      85             :                 // We don't have the pubkey to verify the block sig anywhere in this block.
      86             :                 // p2pk scriptsig only contains the signature and p2pkh scriptpubkey only contain the hash.
      87             :                 return false;
      88             :             } else {
      89       13382 :                 unsigned int start = 1 + (unsigned int) *txin.scriptSig.begin(); // skip sig
      90        6691 :                 if (start >= txin.scriptSig.size() - 1) return false;
      91       13382 :                 pubkey = CPubKey(txin.scriptSig.begin()+start+1, txin.scriptSig.end());
      92             :             }
      93           6 :         } else if (whichType == TX_COLDSTAKE) {
      94             :             // pick the public key from the P2CS input
      95           6 :             const CTxIn& txin = block.vtx[1]->vin[0];
      96          12 :             unsigned int start = 1 + (unsigned int) *txin.scriptSig.begin(); // skip sig
      97          12 :             if (start >= txin.scriptSig.size() - 1) return false;
      98           6 :             start += 1 + (int) *(txin.scriptSig.begin()+start); // skip flag
      99           6 :             if (start >= txin.scriptSig.size() - 1) return false;
     100          12 :             pubkey = CPubKey(txin.scriptSig.begin()+start+1, txin.scriptSig.end());
     101             :         }
     102             :     }
     103             : 
     104        6785 :     if (!pubkey.IsValid())
     105           0 :         return error("%s: invalid pubkey %s", __func__, HexStr(pubkey));
     106             : 
     107        6785 :     return pubkey.Verify(block.GetHash(), block.vchBlockSig);
     108             : }

Generated by: LCOV version 1.14