text: // Copyright (c) 2017-2018 The PIVX developers
  // Copyright (c) 2019 The SucreCoin developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include "chain.h"
  #include "main.h"
  #include "stakeinput.h"
  #include "wallet.h"
  
  // XSR Stake
  bool CXSRStake::SetInput(CTransaction txPrev, unsigned int n)
  {
      this->txFrom = txPrev;
      this->nPosition = n;
      return true;
  }
  
  bool CXSRStake::GetTxFrom(CTransaction& tx)
  {
      tx = txFrom;
      return true;
  }
  
  bool CXSRStake::CreateTxIn(CWallet* pwallet, CTxIn& txIn, uint256 hashTxOut)
  {
      txIn = CTxIn(txFrom.GetHash(), nPosition);
      return true;
  }
  
  CAmount CXSRStake::GetValue()
  {
      return txFrom.vout[nPosition].nValue;
  }
  
  bool CXSRStake::CreateTxOuts(CWallet* pwallet, vector<CTxOut>& vout, CAmount nTotal)
  {
      vector<valtype> vSolutions;
      txnouttype whichType;
      CScript scriptPubKeyKernel = txFrom.vout[nPosition].scriptPubKey;
      if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) {
          LogPrintf("CreateCoinStake : failed to parse kernel\n");
          return false;
      }
  
      if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH)
          return false; // Only support pay to public key and pay to address
  
      CScript scriptPubKey;
      if (whichType == TX_PUBKEYHASH) // pay to address type
      {
          // Convert to pay to public key type
          CKey key;
          CKeyID keyID = CKeyID(uint160(vSolutions[0]));
          if (!pwallet->GetKey(keyID, key))
              return false;
  
          scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
      } else
          scriptPubKey = scriptPubKeyKernel;
  
      vout.emplace_back(CTxOut(0, scriptPubKey));
  
      // Calculate if we need to split the output
      if (nTotal / 2 > (CAmount)(pwallet->nStakeSplitThreshold * COIN))
          vout.emplace_back(CTxOut(0, scriptPubKey));
  
      return true;
  }
  
  bool CXSRStake::GetModifier(uint64_t& nStakeModifier)
  {
      int nStakeModifierHeight = 0;
      int64_t nStakeModifierTime = 0;
      GetIndexFrom();
      if (!pindexFrom)
          return error("%s: failed to get index from", __func__);
  
      if (!GetKernelStakeModifier(pindexFrom->GetBlockHash(), nStakeModifier, nStakeModifierHeight, nStakeModifierTime, false))
          return error("CheckStakeKernelHash(): failed to get kernel stake modifier \n");
  
      return true;
  }
  
  CDataStream CXSRStake::GetUniqueness()
  {
      // The unique identifier for a XSR stake is the outpoint
      CDataStream ss(SER_NETWORK, 0);
      ss << nPosition << txFrom.GetHash();
      return ss;
  }
  
  // The block that the UTXO was added to the chain
  CBlockIndex* CXSRStake::GetIndexFrom()
  {
      uint256 hashBlock = 0;
      CTransaction tx;
      if (GetTransaction(txFrom.GetHash(), tx, hashBlock, true)) {
          // If the index is in the chain, then set it as the "index from"
          if (mapBlockIndex.count(hashBlock)) {
              CBlockIndex* pindex = mapBlockIndex.at(hashBlock);
              if (chainActive.Contains(pindex))
                  pindexFrom = pindex;
          }
      } else {
          LogPrintf("%s : failed to find tx %s\n", __func__, txFrom.GetHash().GetHex());
      }
  
      return pindexFrom;
  }