]> Git Repo - VerusCoin.git/commitdiff
Ensure VRSC compatibility with fundamental new changes
authorMichael Toutonghi <[email protected]>
Wed, 8 May 2019 02:40:32 +0000 (19:40 -0700)
committerMichael Toutonghi <[email protected]>
Wed, 8 May 2019 02:40:32 +0000 (19:40 -0700)
12 files changed:
src/komodo_utils.h
src/main.cpp
src/main.h
src/miner.cpp
src/pbaas/notarization.cpp
src/pbaas/pbaas.cpp
src/pbaas/pbaas.h
src/primitives/transaction.cpp
src/rpc/pbaasrpc.cpp
src/script/script_ext.cpp
src/wallet/asyncrpcoperation_shieldcoinbase.cpp
src/wallet/wallet.cpp

index 7eb8ae662808d973ec4ff7f30a14c8098fa42174..ac0e37e98344ccd3784ae72578f823c654bd7f95 100644 (file)
@@ -1674,11 +1674,9 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
         }
     }
     if ( nHeight == 1 )
-        if ( ASSETCHAINS_LASTERA == 0 )
-            subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff);
-        else
-            subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff);
-
+    {
+        subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff);
+    }
     return(subsidy);
 }
 
index 3b0269d705b444cc19e3ac016574b3f7b98043b4..1c8da3d3f3cf66ea8bffa14fb026fd0d3cada76e 100644 (file)
@@ -731,22 +731,25 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
         }
     }
     
-    BOOST_FOREACH(const CTxIn& txin, tx.vin)
+    if (!tx.IsCoinBase())
     {
-        // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
-        // keys. (remember the 520 byte limit on redeemScript size) That works
-        // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
-        // bytes of scriptSig, which we round off to 1650 bytes for some minor
-        // future-proofing. That's also enough to spend a 20-of-20
-        // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
-        // considered standard)
-        if (txin.scriptSig.size() > 1650) {
-            reason = "scriptsig-size";
-            return false;
-        }
-        if (!txin.scriptSig.IsPushOnly()) {
-            reason = "scriptsig-not-pushonly";
-            return false;
+        BOOST_FOREACH(const CTxIn& txin, tx.vin)
+        {
+            // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
+            // keys. (remember the 520 byte limit on redeemScript size) That works
+            // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
+            // bytes of scriptSig, which we round off to 1650 bytes for some minor
+            // future-proofing. That's also enough to spend a 20-of-20
+            // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
+            // considered standard)
+            if (txin.scriptSig.size() > 1650) {
+                reason = "scriptsig-size";
+                return false;
+            }
+            if (!txin.scriptSig.IsPushOnly()) {
+                reason = "scriptsig-not-pushonly";
+                return false;
+            }
         }
     }
     
@@ -960,24 +963,28 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
  */
 bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeight)
 {
-    // if time locks are on, ensure that this coin base is time locked exactly as it should be
+    bool valid = true, timelocked = false;
+    CTxDestination firstDest;
+    // if time locks are on, ensure that this coin base is time locked exactly as it should be, or invalidate
     if (((uint64_t)tx.GetValueOut() >= ASSETCHAINS_TIMELOCKGTE) || 
         (((nHeight >= 31680) || strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0) && komodo_ac_block_subsidy(nHeight) >= ASSETCHAINS_TIMELOCKGTE))
     {
         CScriptID scriptHash;
+        valid = false;
+        timelocked = true;
 
         // to be valid, it must be a P2SH transaction and have an op_return in vout[1] that 
         // holds the full output script, which may include multisig, etc., but starts with 
         // the time lock verify of the correct time lock for this block height
-        if (tx.vout.size() == 2 &&
-            CScriptExt(tx.vout[0].scriptPubKey).IsPayToScriptHash(&scriptHash) &&
-            tx.vout[1].scriptPubKey.size() >= 7 && // minimum for any possible future to prevent out of bounds
-            tx.vout[1].scriptPubKey[0] == OP_RETURN)
+        if (CScriptExt(tx.vout[0].scriptPubKey).IsPayToScriptHash(&scriptHash) &&
+            tx.vout.back().scriptPubKey.size() >= 7 && // minimum for any possible future to prevent out of bounds
+            tx.vout.back().scriptPubKey[0] == OP_RETURN)
         {
             opcodetype op;
             std::vector<uint8_t> opretData = std::vector<uint8_t>();
-            CScript::const_iterator it = tx.vout[1].scriptPubKey.begin() + 1;
-            if (tx.vout[1].scriptPubKey.GetOp2(it, op, &opretData))
+            CScript::const_iterator it = tx.vout.back().scriptPubKey.begin() + 1;
+            if (tx.vout.back().scriptPubKey.GetOp2(it, op, &opretData))
             {
                 if (opretData.size() > 0 && opretData.data()[0] == OPRETTYPE_TIMELOCK)
                 {
@@ -988,14 +995,42 @@ bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeigh
                         opretScript.IsCheckLockTimeVerify(&unlocktime) &&
                         komodo_block_unlocktime(nHeight) == unlocktime)
                     {
-                        return(true);
+                        if (ExtractDestination(opretScript, firstDest))
+                        {
+                            valid = true;
+                        }
                     }
                 }
             }
         }
-        return(false);
     }
-    return(true);
+
+    // if there is a premine, make sure it is the right amount and goes to the correct recipient
+    if (!IsVerusActive && valid && nHeight == 1)
+    {
+        if (ConnectedChains.ThisChain().premine && !ConnectedChains.ThisChain().address.IsNull())
+        {
+            if (!timelocked && !(ExtractDestination(tx.vout[0].scriptPubKey, firstDest)))
+            {
+                valid = false;
+            }
+            else if (tx.vout[0].nValue != ConnectedChains.ThisChain().premine || GetDestinationID(firstDest) != ConnectedChains.ThisChain().address)
+            {
+                valid = false;
+            }
+        }
+
+        // ensure that if this is a PBaaS chain, block 1 includes notarization appropriately derived from the chain definition
+        // transaction. the coinbase must contain a matching notarization out, and the notarization must agree with our start height
+        CPBaaSNotarization pbn(tx);
+
+        if (!pbn.IsValid() || pbn.notarizationHeight < ConnectedChains.ThisChain().startBlock)
+        {
+            valid = false;
+        }
+    }
+
+    return valid;
 }
 
 /**
@@ -2153,6 +2188,11 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
     //return nSubsidy;
 }
 
+CAmount GetBlockOnePremine()
+{
+    return ASSETCHAINS_SUPPLY * COIN;
+}
+
 bool IsInitialBlockDownload()
 {
     const CChainParams& chainParams = Params();
index d8507139c0ba39b84f18fdd736bac69f91ec83c7..2fa6dd9d0903ec9ca593ddabb8fbe50a4e5b2441 100644 (file)
@@ -239,6 +239,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b
 /** Find the best known block, and make it the tip of the block chain */
 bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL);
 CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
+CAmount GetBlockOnePremine();
 
 /**
  * Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target.
index 009fc243884cbb05932570bef817359bf7f46476..5d3d48b2a8a72d0ff6539b788dc0c52fa36c0f88 100644 (file)
@@ -355,11 +355,15 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
         int64_t pbaasTransparentIn = 0;
         int64_t pbaasTransparentOut = 0;
         int64_t blockSubsidy = GetBlockSubsidy(nHeight, consensusParams);
+
         uint256 mmrRoot;
         vector<CInputDescriptor> notarizationInputs;
 
         // make earned notarization only if this is not the notary chain and we have enough subsidy
+        //
         // TODO: allow this to proceed if no subsidy and earned notarizations pay no reward as well
+        // we will need to provide a notarization reward option, even for non-fungible chains, just to enable
+        // creation of the notarizations
         if (!IsVerusActive() && (blockSubsidy > PBAAS_MINNOTARIZATIONOUTPUT * 2))
         {
             // if we don't have a connected root PBaaS chain, we can't properly check
@@ -717,6 +721,17 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
                 return 0;
             }
         }
+        else if (!IsVerusActive() && stakeHeight == 1)
+        {
+            // first block, send normal reward to the miner, and premine to the specified address in the
+            // chain definition
+            if (!ConnectedChains.ThisChain().address.IsNull() && GetBlockOnePremine())
+            {
+                // move miner output to output 1 and put premine in output 0
+                txNew.vout.push_back(CTxOut(txNew.vout[0].nValue - GetBlockOnePremine(), txNew.vout[0].scriptPubKey));
+                txNew.vout[0] = CTxOut(GetBlockOnePremine(), GetScriptForDestination(CTxDestination(ConnectedChains.ThisChain().address)));
+            }
+        }
 
         txNew.nExpiryHeight = 0;
         txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
@@ -726,12 +741,17 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
 
         // check if coinbase transactions must be time locked at current subsidy and prepend the time lock
         // to transaction if so, cast for GTE operator
-        if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE)
+        CAmount cbValueOut = 0;
+        for (auto txout : txNew.vout)
+        {
+            cbValueOut += txout.nValue;
+        }
+        if (cbValueOut >= ASSETCHAINS_TIMELOCKGTE)
         {
             int32_t opretlen, p2shlen, scriptlen;
             CScriptExt opretScript = CScriptExt();
 
-            txNew.vout.resize(2);
+            txNew.vout.push_back(CTxOut());
 
             // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins
             // protected only by the time lock rather than 100% inaccessible
@@ -745,8 +765,8 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
             opretScript += scriptPubKeyIn;
 
             txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript));
-            txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK);
-            txNew.vout[1].nValue = 0;
+            txNew.vout.back().scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK);
+            txNew.vout.back().nValue = 0;
         } // timelocks and commissions are currently incompatible due to validation complexity of the combination
         else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 )
         {
@@ -762,6 +782,10 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
             //printf("autocreate commision vout\n");
         }
 
+        // finalize input of coinbase
+        txNew.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(0)) + COINBASE_FLAGS;
+        assert(txNew.vin[0].scriptSig.size() <= 100);
+
         // add final notarization and instant spend fixups
         if (pbaasNotarizationTx)
         {
@@ -798,7 +822,6 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
             CPBaaSNotarization pbn(pblock->vtx[pbaasNotarizationTx]);
             txNew.vout.insert(coinbaseOutIt, MakeCC1of1Vout(EVAL_EARNEDNOTARIZATION, needed, pk, vKeys, pbn));
             txNew.vout[0].nValue = txNew.vout[0].nValue - needed;
-            pblock->vtx[0] = txNew;
 
             // bind to the right output of the coinbase
             mntx.vin.push_back(CTxIn(txNew.GetHash(), pbaasCoinbaseInstantSpendOut));
@@ -981,22 +1004,33 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int &
     }
     ++nExtraNonce;
 
-    // extra nonce is kept in the header, not in the coinbase any longer
-    // this allows instant spend transactions to use coinbase funds for
-    // inputs by ensuring that once created, the coinbase transaction hash
-    // will not continue to change
-    CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
-    s << nExtraNonce;
-    std::vector<unsigned char> vENonce(s.begin(), s.end());
-    assert(pblock->ExtraDataLen() >= vENonce.size());
-    pblock->SetExtraData(vENonce.data(), vENonce.size());
-    /*
-    unsigned int nHeight = pindexPrev->GetHeight()+1; // Height first in coinbase required for block.version=2
-    CMutableTransaction txCoinbase(pblock->vtx[0]);
-    txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
-    assert(txCoinbase.vin[0].scriptSig.size() <= 100);
-    pblock->vtx[0] = txCoinbase;
-    */
+    int32_t nHeight = pindexPrev->GetHeight() + 1;
+
+    if (CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight) >= CConstVerusSolutionVector::activationHeight.SOLUTION_VERUSV3)
+    {
+        // extra nonce is kept in the header, not in the coinbase any longer
+        // this allows instant spend transactions to use coinbase funds for
+        // inputs by ensuring that once final, the coinbase transaction hash
+        // will not continue to change
+        CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
+        s << nExtraNonce;
+        std::vector<unsigned char> vENonce(s.begin(), s.end());
+
+        printf("pblock->ExtraDataLen() == %u, vENonce.size() == %lu\n", pblock->ExtraDataLen(), vENonce.size());
+
+        assert(pblock->ExtraDataLen() >= vENonce.size());
+        pblock->SetExtraData(vENonce.data(), vENonce.size());
+    }
+    else
+    {
+        // finalize input of coinbase
+        CMutableTransaction txcb(pblock->vtx[0]);
+        txcb.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
+        assert(txcb.vin[0].scriptSig.size() <= 100);
+        pblock->vtx[0] = txcb;
+    }
+
+    printf("Coinbase Script: %s\n", pblock->vtx[0].vout[0].scriptPubKey.ToString().c_str());
 
     if (buildMerkle)
     {
index 58e576e0c23838b57a411501c2fef7cb51f15ecc..a469e99f0e318a17f63aeca66b8a8401b119fd9b 100644 (file)
@@ -975,8 +975,7 @@ uint256 CreateAcceptedNotarization(const CBlock &blk, CTransaction &entx, int32_
                 vNodes[i]->copyStats(stats);
                 if (vNodes[i]->fSuccessfullyConnected && !vNodes[i]->fInbound)
                 {
-                    CBitcoinAddress bca(CKeyID(vNodes[i]->hashPaymentAddress));
-                    pbn.nodes.push_back(CNodeData(vNodes[i]->addr.ToString(), bca.ToString()));
+                    pbn.nodes.push_back(CNodeData(vNodes[i]->addr.ToString(), CKeyID(vNodes[i]->hashPaymentAddress)));
                 }
             }
         }
@@ -1223,15 +1222,14 @@ uint256 SubmitAcceptedNotarization()
  */
 bool ValidateAcceptedNotarization(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn)
 {
-    // this validates the spending transaction
-    // first and foremost, check the following two things:
+    // TODO: this validates the spending transaction
+    // check the following things:
     // 1. It represents a valid PoS or merge mined block on the other chain, and contains the header in the opret
     // 2. The MMR and proof provided for the currently asserted block can prove the provided header. The provided
     //    header can prove the last block referenced.
-
-    // if those are true, then check if we have all relevant inputs, including that we properly finalize all necessary transactions
-    // we will jump back 10 transactions, if there are that many in our thread, validate the 10th, invalidate
-    // any notarizations that do not derive from that notarization, and spend as inputs
+    // 3. This notarization is not a superset of an earlier notarization posted before it that it does not
+    //    reference. If that is the case, it is rejected.
+    // 4. Has all relevant inputs, including finalizes all necessary transactions, both confirmed and orphaned
     printf("ValidateAcceptedNotarization\n");
     return true;
 }
index 616022347fd687d7c7adb330466cd6bddfa49517..633fbc8e7454224491556da3c525b2fd0725a834 100644 (file)
@@ -222,14 +222,15 @@ std::vector<CBaseChainObject *> RetrieveOpRetArray(const CScript &opRetScript)
 CNodeData::CNodeData(UniValue &obj)
 {
     networkAddress = uni_get_str(find_value(obj, "networkaddress"));
-    paymentAddress = uni_get_str(find_value(obj, "paymentaddress"));
+    CBitcoinAddress ba(uni_get_str(find_value(obj, "paymentaddress")));
+    ba.GetKeyID(paymentAddress);
 }
 
 UniValue CNodeData::ToUniValue() const
 {
     UniValue obj(UniValue::VOBJ);
     obj.push_back(Pair("networkaddress", networkAddress));
-    obj.push_back(Pair("paymentaddress", paymentAddress));
+    obj.push_back(Pair("paymentaddress", CBitcoinAddress(paymentAddress).ToString()));
     return obj;
 }
 
@@ -237,7 +238,8 @@ CPBaaSChainDefinition::CPBaaSChainDefinition(const UniValue &obj)
 {
     nVersion = PBAAS_VERSION;
     name = uni_get_str(find_value(obj, "name"));
-    address = uni_get_str(find_value(obj, "address"));
+    CBitcoinAddress ba(uni_get_str(find_value(obj, "paymentaddress")));
+    ba.GetKeyID(address);
     premine = uni_get_int64(find_value(obj, "premine"));
     conversion = uni_get_int64(find_value(obj, "conversion"));
     launchFee = uni_get_int64(find_value(obj, "launchfee"));
@@ -341,7 +343,7 @@ UniValue CPBaaSChainDefinition::ToUniValue() const
     UniValue obj(UniValue::VOBJ);
     obj.push_back(Pair("version", (int64_t)nVersion));
     obj.push_back(Pair("name", name));
-    obj.push_back(Pair("address", address));
+    obj.push_back(Pair("paymentaddress", CBitcoinAddress(CTxDestination(address)).ToString()));
     obj.push_back(Pair("premine", (int64_t)premine));
     obj.push_back(Pair("conversion", (int64_t)conversion));
     obj.push_back(Pair("launchfee", (int64_t)launchFee));
index 81f0d10754f8474b46a466b2dcc537b863d19146..07287a103331977f3627d21c4c03542ced90e893 100644 (file)
@@ -362,13 +362,17 @@ class CNodeData
 {
 public:
     std::string networkAddress;
-    std::string paymentAddress;
+    CKeyID paymentAddress;
 
     CNodeData() {}
     CNodeData(UniValue &);
-
+    CNodeData(std::string netAddr, uint160 paymentKeyID) : networkAddress(netAddr), paymentAddress(paymentKeyID) {}
     CNodeData(std::string netAddr, std::string paymentAddr) :
-        networkAddress(netAddr), paymentAddress(paymentAddr) {}
+        networkAddress(netAddr)
+    {
+        CBitcoinAddress ba(paymentAddr);
+        ba.GetKeyID(paymentAddress);
+    }
     
     ADD_SERIALIZE_METHODS;
 
@@ -391,7 +395,7 @@ public:
 
     uint32_t nVersion;                      // version of this chain definition data structure to allow for extensions (not daemon version)
     std::string name;                       // chain name, maximum 64 characters
-    std::string address;                    // non-purchased/converted premine and fee recipient address
+    CKeyID address;                         // non-purchased/converted premine and fee recipient address
     int64_t premine;                        // initial supply that is distributed to the premine output address, but not purchased
     int64_t conversion;                     // factor / 100000000 for conversion of VRSC to coin on launch
     int64_t launchFee;                      // ratio of satoshis to send from contribution to convertible to fee address
@@ -427,7 +431,6 @@ public:
                           int32_t BillingPeriod, int64_t NotaryReward, std::vector<CNodeData> &Nodes) :
                             nVersion(PBAAS_VERSION),
                             name(Name),
-                            address(Address),
                             premine(Premine),
                             conversion(Conversion),
                             launchFee(LaunchFee),
@@ -448,6 +451,8 @@ public:
             Name.resize(KOMODO_ASSETCHAIN_MAXLEN - 1);
         }
         name = Name;
+        CBitcoinAddress ba(Address);
+        ba.GetKeyID(address);
     }
 
     ADD_SERIALIZE_METHODS;
index 0fbcf2fca4028925d949d2b2dc418ed668cbec6d..8043fbfe4fbb98ea2421a5aafd980e0930f7561d 100644 (file)
@@ -384,14 +384,12 @@ int64_t CTransaction::UnlockTime(uint32_t voutNum) const
 {
     if (vout.size() > voutNum + 1 && vout[voutNum].scriptPubKey.IsPayToScriptHash())
     {
-        uint32_t voutNext = voutNum + 1;
-
         std::vector<uint8_t> opretData;
         uint160 scriptID = uint160(std::vector<unsigned char>(vout[voutNum].scriptPubKey.begin() + 2, vout[voutNum].scriptPubKey.begin() + 22));
-        CScript::const_iterator it = vout[voutNext].scriptPubKey.begin() + 1;
+        CScript::const_iterator it = vout.back().scriptPubKey.begin() + 1;
 
         opcodetype op;
-        if (vout[voutNext].scriptPubKey.GetOp2(it, op, &opretData))
+        if (vout.back().scriptPubKey.GetOp2(it, op, &opretData))
         {
             if (opretData.size() > 0 && opretData.data()[0] == OPRETTYPE_TIMELOCK)
             {
index e607a5431805f846298db95c26c27f28d09114fc..954b53f7d7765ca99cd6797353778202bc6dab11 100644 (file)
@@ -562,7 +562,7 @@ UniValue getnotarizationdata(const UniValue& params, bool fHelp)
 
 // get inputs for all of the unspent reward outputs sent to a specific reward type for the range specified
 // returns the total input amount
-CAmount GetUnspentRewardInputs(const CPBaaSChainDefinition &chainDef, vector<CTxIn> &vinputs, uint160 baseAddress, int32_t serviceCode, int32_t height)
+CAmount GetUnspentRewardInputs(const CPBaaSChainDefinition &chainDef, vector<CInputDescriptor> &inputs, uint160 baseAddress, int32_t serviceCode, int32_t height)
 {
     CAmount retval = 0;
 
@@ -579,47 +579,74 @@ CAmount GetUnspentRewardInputs(const CPBaaSChainDefinition &chainDef, vector<CTx
         // we need to look through the inputs to ensure that they are
         // actual service reward outputs in the correct billing periof, since we don't currently prevent other types of transaction outputs from being
         // sent to the same address, though doing so would burn its value anyhow
+
+        LOCK(cs_main);
         for (auto output : unspentOutputs)
         {
             // printf("txid: %s\n", it->first.txhash.GetHex().c_str());
-            CTransaction ntx;
-            uint256 blkHash;
             CServiceReward sr;
-            if (myGetTransaction(output.first.txhash, ntx, blkHash) && 
-                (sr = CServiceReward(ntx)).IsValid() && 
-                sr.serviceType == SERVICE_NOTARIZATION &&
-                sr.billingPeriod <= billingPeriod)
+            CCoins coins;
+            if (pcoinsTip->GetCoins(output.first.txhash, coins))
             {
-                vinputs.push_back(CTxIn(output.first.txhash, output.first.index));
-                retval += output.second.satoshis;
-            }
-            else
-            {
-                LogPrintf("GetUnspentRewardInputs: cannot retrieve transaction %s\n", output.first.txhash.GetHex().c_str());
-                printf("GetUnspentRewardInputs: cannot retrieve transaction %s\n", output.first.txhash.GetHex().c_str());
+                for (auto txout : coins.vout)
+                {
+                    COptCCParams p;
+                    if (!txout.IsNull() && IsPayToCryptoCondition(txout.scriptPubKey, p) && p.evalCode == EVAL_SERVICEREWARD)
+                    {
+                        FromVector(p.vData[0], sr);
+                        if (sr.IsValid())
+                        {
+                            inputs.push_back(CInputDescriptor(txout.scriptPubKey, txout.nValue, CTxIn(output.first.txhash, output.first.index)));
+                            retval += txout.nValue;
+                        }
+                    }
+                    else
+                    {
+                        LogPrintf("GetUnspentRewardInputs: cannot retrieve transaction %s\n", output.first.txhash.GetHex().c_str());
+                        printf("GetUnspentRewardInputs: cannot retrieve transaction %s\n", output.first.txhash.GetHex().c_str());
+                    }
+                }
             }
         }
     }
     return retval;
 }
 
-
-
 // this adds any new notarization rewards that have been sent to the notarization reward pool for this
 // billing period since last accepted notarization, up to a maximum number of inputs
-CAmount AddNewNotarizationRewards(CPBaaSChainDefinition &chainDef, CMutableTransaction mnewTx, int32_t height)
+CAmount AddNewNotarizationRewards(CPBaaSChainDefinition &chainDef, vector<CInputDescriptor> &inputs, CMutableTransaction mnewTx, int32_t height)
 {
     // get current chain info
     CAmount newIn = 0;
-    vector<CTxIn> newInputs;
-    newIn = GetUnspentRewardInputs(chainDef, newInputs, chainDef.GetChainID(), SERVICE_NOTARIZATION, height);
-    for (auto input : newInputs)
+    newIn = GetUnspentRewardInputs(chainDef, inputs, chainDef.GetChainID(), SERVICE_NOTARIZATION, height);
+    for (auto input : inputs)
     {
-        mnewTx.vin.push_back(input);
+        mnewTx.vin.push_back(input.txIn);
     }
     return newIn;
 }
 
+UniValue submitnotarizationpayment(const UniValue& params, bool fHelp)
+{
+    if (fHelp || params.size() != 1)
+    {
+        throw runtime_error(
+            "submitnotarizationpayment \"chainid\" \"amount\" \"billingperiod\"\n"
+            "\nAdds some amount of funds to a specific billing period of a PBaaS chain, which will be released\n"
+            "\nin the form of payments to notaries whose notarizations are confirmed.\n"
+
+            "\nArguments\n"
+
+            "\nResult:\n"
+
+            "\nExamples:\n"
+            + HelpExampleCli("submitacceptednotarization", "\"hextx\"")
+            + HelpExampleRpc("submitacceptednotarization", "\"hextx\"")
+        );
+    }
+
+}
+
 UniValue submitacceptednotarization(const UniValue& params, bool fHelp)
 {
     if (fHelp || params.size() != 1)
@@ -765,14 +792,14 @@ UniValue submitacceptednotarization(const UniValue& params, bool fHelp)
 
                 // add all inputs that might provide notary reward and calculate notary reward based on that plus current
                 // notarization input value divided by number of blocks left in billing period, times blocks per notarization
-                if (GetChainDefinition(pbn.chainID, chainDef))
+                if (pindex && GetChainDefinition(pbn.chainID, chainDef))
                 {
-                    valueIn += AddNewNotarizationRewards(chainDef, mnewTx, chainActive.LastTip()->GetHeight());
+                    valueIn += AddNewNotarizationRewards(chainDef, notarizationInputs, mnewTx, pindex->GetHeight());
                 }
                 else
                 {
-                    LogPrintf("AddNewNotarizationRewards: cannot find chain %s, possible corrupted database\n", chainDef.name.c_str());
-                    printf("AddNewNotarizationRewards: cannot find chain %s, possible corrupted database\n", chainDef.name.c_str());
+                    LogPrintf("submitacceptednotarization: cannot find chain %s, possible corrupted database\n", chainDef.name.c_str());
+                    printf("submitacceptednotarization: cannot find chain %s, possible corrupted database\n", chainDef.name.c_str());
                 }
 
             }
@@ -790,7 +817,7 @@ UniValue submitacceptednotarization(const UniValue& params, bool fHelp)
             }
 
             // minimum amount must go to main thread and finalization, then divide what is left among blocks in the billing period
-            uint64_t blocksLeft = chainDef.billingPeriod - (pbn.notarizationHeight % chainDef.billingPeriod);
+            uint64_t blocksLeft = chainDef.billingPeriod - (confirmedPBN.notarizationHeight % chainDef.billingPeriod);
             CAmount valueOut;
             if (blocksLeft <= CPBaaSNotarization::MIN_BLOCKS_BETWEEN_ACCEPTED)
             {
@@ -899,7 +926,6 @@ UniValue submitacceptednotarization(const UniValue& params, bool fHelp)
     throw JSONRPCError(RPC_VERIFY_REJECTED, "Failed to get notarizaton data for chainID: " + pbn.chainID.GetHex());
 }
 
-
 UniValue getcrossnotarization(const UniValue& params, bool fHelp)
 {
     if (fHelp || params.size() < 2 || params.size() > 3)
@@ -1241,7 +1267,7 @@ UniValue definechain(const UniValue& params, bool fHelp)
             "\nArguments\n"
             "      {\n"
             "         \"name\"       : \"xxxx\",    (string, required) unique Verus ecosystem-wide name/symbol of this PBaaS chain\n"
-            "         \"address\"    : \"Rxxx\",    (string, optional) premine and launch fee recipient\n"
+            "         \"paymentaddress\" : \"Rxxx\", (string, optional) premine and launch fee recipient\n"
             "         \"premine\"    : \"n\",       (int,    optional) amount of coins that will be premined and distributed to premine address\n"
             "         \"convertible\" : \"n\",      (int,    optional) amount of coins that may be converted from Verus, price determined by total contribution\n"
             "         \"launchfee\"  : \"n\",       (int,    optional) VRSC fee for conversion at startup, multiplied by amount, divided by 100000000\n"
@@ -1888,6 +1914,8 @@ static const CRPCCommand commands[] =
     { "pbaas",        "getnotarizationdata",          &getnotarizationdata,    true  },
     { "pbaas",        "getcrossnotarization",         &getcrossnotarization,   true  },
     { "pbaas",        "definechain",                  &definechain,            true  },
+    { "pbaas",        "submitacceptednotarization",   &submitacceptednotarization, true  },
+    { "pbaas",        "submitnotarizationpayment",    &submitnotarizationpayment, true  },
     { "pbaas",        "addmergedblock",               &addmergedblock,         true  }
 };
 
index 613b50c0594fa3ba206f33367e984f76589a0031..045b2d14c92cb1ebee7d8f9e2946ba832ae8e14b 100644 (file)
@@ -94,14 +94,14 @@ bool CScriptExt::ExtractVoutDestination(const CTransaction& tx, int32_t voutNum,
     CScriptExt spk = tx.vout[voutNum].scriptPubKey;
 
     // if this is a timelocked transaction, get the destination behind the time lock
-    if (tx.IsCoinBase() && tx.vout.size() == 2 && voutNum == 0 &&
+    if (tx.IsCoinBase() && voutNum == 0 &&
         spk.IsPayToScriptHash(&scriptHash) &&
-        tx.vout[1].scriptPubKey.IsOpReturn())
+        tx.vout.back().scriptPubKey.IsOpReturn())
     {
         opcodetype op;
         std::vector<uint8_t> opretData = std::vector<uint8_t>();
-        CScript::const_iterator it = tx.vout[1].scriptPubKey.begin() + 1;
-        if (tx.vout[1].scriptPubKey.GetOp2(it, op, &opretData))
+        CScript::const_iterator it = tx.vout.back().scriptPubKey.begin() + 1;
+        if (tx.vout.back().scriptPubKey.GetOp2(it, op, &opretData))
         {
             if (opretData.size() > 0 && opretData[0] == OPRETTYPE_TIMELOCK)
             {
index 6cf14d4c8cb58c5226ff126d31da6ee57eb733d6..4feea62d6afa9a144de0f3f5e93dcfad23965aea 100644 (file)
@@ -270,6 +270,9 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c
 
     // Add transparent inputs
     for (auto t : m_op->inputs_) {
+        m_op->builder_.SetLockTime((uint32_t)(chainActive.Height()));
+        m_op->builder_.AddTransparentInput(COutPoint(t.txid, t.vout), t.scriptPubKey, t.amount, 0xfffffffe);
+        /*
         if ((uint64_t)t.amount >= ASSETCHAINS_TIMELOCKGTE)
         {
             m_op->builder_.SetLockTime((uint32_t)(chainActive.Height()));
@@ -279,11 +282,14 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c
         {
             m_op->builder_.AddTransparentInput(COutPoint(t.txid, t.vout), t.scriptPubKey, t.amount);
         }
+        */
     }
 
     // Send all value to the target z-addr
     m_op->builder_.SendChangeTo(zaddr, ovk);
 
+    
+
     // Build the transaction
     auto maybe_tx = m_op->builder_.Build();
     if (!maybe_tx) {
index 72c480d11eeda39dc030c2cb9aa4e41b228fed5e..8815953a29b4b099435fbbb672cf95f541025916 100644 (file)
@@ -2297,16 +2297,16 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum)
                         return ret;
                 }
             }
-            else if (tx.vout.size() > (voutNext = voutNum + 1) &&
-                tx.vout[voutNext].scriptPubKey.size() > 7 &&
-                tx.vout[voutNext].scriptPubKey[0] == OP_RETURN)
+            else if (tx.vout.size() > (voutNum + 1) &&
+                tx.vout.back().scriptPubKey.size() > 7 &&
+                tx.vout.back().scriptPubKey[0] == OP_RETURN)
             {
                 // get the opret script from next vout, verify that the front is CLTV and hash matches
                 // if so, remove it and use the solver
                 opcodetype op;
                 std::vector<uint8_t> opretData;
-                CScript::const_iterator it = tx.vout[voutNext].scriptPubKey.begin() + 1;
-                if (tx.vout[voutNext].scriptPubKey.GetOp2(it, op, &opretData))
+                CScript::const_iterator it = tx.vout.back().scriptPubKey.begin() + 1;
+                if (tx.vout.back().scriptPubKey.GetOp2(it, op, &opretData))
                 {
                     if (opretData.size() > 0 && opretData[0] == OPRETTYPE_TIMELOCK)
                     {
This page took 0.100399 seconds and 4 git commands to generate.