fMineBlocksOnDemand = false;
fTestnetToBeDeprecatedFieldRPC = false;
- // LogPrintf(">>>>>>>> ac_name = %u\n",GetArg("-ac_name","").c_str());
-
- // if ( GetArg("-ac_name","").c_str()[0] != 0 )
- // {
- // }
- // else
- // {
- // }
-
- checkpointData = (CCheckpointData) {
- boost::assign::map_list_of
- (0, consensus.hashGenesisBlock)
- (2500, uint256S("0x00000006dc968f600be11a86cbfbf7feb61c7577f45caced2e82b6d261d19744"))
- (15000, uint256S("0x00000000b6bc56656812a5b8dcad69d6ad4446dec23b5ec456c18641fb5381ba"))
- (67500, uint256S("0x000000006b366d2c1649a6ebb4787ac2b39c422f451880bc922e3a6fbd723616"))
- (100000, uint256S("0x000000001c5c82cd6baccfc0879e3830fd50d5ede17fa2c37a9a253c610eb285"))
- (133337, uint256S("0x0000000002776ccfaf06cc19857accf3e20c01965282f916b8a886e3e4a05be9"))
- (180000, uint256S("0x000000001205b742eac4a1b3959635bdf8aeada078d6a996df89740f7b54351d"))
- (222222, uint256S("0x000000000cafb9e56445a6cabc8057b57ee6fcc709e7adbfa195e5c7fac61343"))
- (270000, uint256S("0x00000000025c1cfa0258e33ab050aaa9338a3d4aaa3eb41defefc887779a9729"))
- (304600, uint256S("0x00000000028324e022a45014c4a4dc51e95d41e6bceb6ad554c5b65d5cea3ea5"))
- (410100, uint256S("0x0000000002c565958f783a24a4ac17cde898ff525e75ed9baf66861b0b9fcada")),
- 1539405939, // * UNIX timestamp of last checkpoint block
- 3954156, // * total number of transactions between genesis and last checkpoint
- // (the tx=... number in the SetBestChain debug.log lines)
- 5553 // * estimated number of transactions per day after checkpoint
- // total number of tx / (checkpoint block height / (24 * 24))
- };
+ if ( pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,chainparams_commandline,(void *)&consensus) != 0 )
+ {
- // Founders reward script expects a vector of 2-of-3 multisig addresses
- vFoundersRewardAddress = {
- "t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd", /* main-index: 0*/
- "t3cL9AucCajm3HXDhb5jBnJK2vapVoXsop3", /* main-index: 1*/
- "t3fqvkzrrNaMcamkQMwAyHRjfDdM2xQvDTR", /* main-index: 2*/
- "t3TgZ9ZT2CTSK44AnUPi6qeNaHa2eC7pUyF", /* main-index: 3*/
- "t3SpkcPQPfuRYHsP5vz3Pv86PgKo5m9KVmx", /* main-index: 4*/
- "t3Xt4oQMRPagwbpQqkgAViQgtST4VoSWR6S", /* main-index: 5*/
- "t3ayBkZ4w6kKXynwoHZFUSSgXRKtogTXNgb", /* main-index: 6*/
- "t3adJBQuaa21u7NxbR8YMzp3km3TbSZ4MGB", /* main-index: 7*/
- "t3K4aLYagSSBySdrfAGGeUd5H9z5Qvz88t2", /* main-index: 8*/
- "t3RYnsc5nhEvKiva3ZPhfRSk7eyh1CrA6Rk", /* main-index: 9*/
- "t3Ut4KUq2ZSMTPNE67pBU5LqYCi2q36KpXQ", /* main-index: 10*/
- "t3ZnCNAvgu6CSyHm1vWtrx3aiN98dSAGpnD", /* main-index: 11*/
- "t3fB9cB3eSYim64BS9xfwAHQUKLgQQroBDG", /* main-index: 12*/
- "t3cwZfKNNj2vXMAHBQeewm6pXhKFdhk18kD", /* main-index: 13*/
- "t3YcoujXfspWy7rbNUsGKxFEWZqNstGpeG4", /* main-index: 14*/
- "t3bLvCLigc6rbNrUTS5NwkgyVrZcZumTRa4", /* main-index: 15*/
- "t3VvHWa7r3oy67YtU4LZKGCWa2J6eGHvShi", /* main-index: 16*/
- "t3eF9X6X2dSo7MCvTjfZEzwWrVzquxRLNeY", /* main-index: 17*/
- "t3esCNwwmcyc8i9qQfyTbYhTqmYXZ9AwK3X", /* main-index: 18*/
- "t3M4jN7hYE2e27yLsuQPPjuVek81WV3VbBj", /* main-index: 19*/
- "t3gGWxdC67CYNoBbPjNvrrWLAWxPqZLxrVY", /* main-index: 20*/
- "t3LTWeoxeWPbmdkUD3NWBquk4WkazhFBmvU", /* main-index: 21*/
- "t3P5KKX97gXYFSaSjJPiruQEX84yF5z3Tjq", /* main-index: 22*/
- "t3f3T3nCWsEpzmD35VK62JgQfFig74dV8C9", /* main-index: 23*/
- "t3Rqonuzz7afkF7156ZA4vi4iimRSEn41hj", /* main-index: 24*/
- "t3fJZ5jYsyxDtvNrWBeoMbvJaQCj4JJgbgX", /* main-index: 25*/
- "t3Pnbg7XjP7FGPBUuz75H65aczphHgkpoJW", /* main-index: 26*/
- "t3WeKQDxCijL5X7rwFem1MTL9ZwVJkUFhpF", /* main-index: 27*/
- "t3Y9FNi26J7UtAUC4moaETLbMo8KS1Be6ME", /* main-index: 28*/
- "t3aNRLLsL2y8xcjPheZZwFy3Pcv7CsTwBec", /* main-index: 29*/
- "t3gQDEavk5VzAAHK8TrQu2BWDLxEiF1unBm", /* main-index: 30*/
- "t3Rbykhx1TUFrgXrmBYrAJe2STxRKFL7G9r", /* main-index: 31*/
- "t3aaW4aTdP7a8d1VTE1Bod2yhbeggHgMajR", /* main-index: 32*/
- "t3YEiAa6uEjXwFL2v5ztU1fn3yKgzMQqNyo", /* main-index: 33*/
- "t3g1yUUwt2PbmDvMDevTCPWUcbDatL2iQGP", /* main-index: 34*/
- "t3dPWnep6YqGPuY1CecgbeZrY9iUwH8Yd4z", /* main-index: 35*/
- "t3QRZXHDPh2hwU46iQs2776kRuuWfwFp4dV", /* main-index: 36*/
- "t3enhACRxi1ZD7e8ePomVGKn7wp7N9fFJ3r", /* main-index: 37*/
- "t3PkLgT71TnF112nSwBToXsD77yNbx2gJJY", /* main-index: 38*/
- "t3LQtHUDoe7ZhhvddRv4vnaoNAhCr2f4oFN", /* main-index: 39*/
- "t3fNcdBUbycvbCtsD2n9q3LuxG7jVPvFB8L", /* main-index: 40*/
- "t3dKojUU2EMjs28nHV84TvkVEUDu1M1FaEx", /* main-index: 41*/
- "t3aKH6NiWN1ofGd8c19rZiqgYpkJ3n679ME", /* main-index: 42*/
- "t3MEXDF9Wsi63KwpPuQdD6by32Mw2bNTbEa", /* main-index: 43*/
- "t3WDhPfik343yNmPTqtkZAoQZeqA83K7Y3f", /* main-index: 44*/
- "t3PSn5TbMMAEw7Eu36DYctFezRzpX1hzf3M", /* main-index: 45*/
- "t3R3Y5vnBLrEn8L6wFjPjBLnxSUQsKnmFpv", /* main-index: 46*/
- "t3Pcm737EsVkGTbhsu2NekKtJeG92mvYyoN", /* main-index: 47*/
-// "t3PZ9PPcLzgL57XRSG5ND4WNBC9UTFb8DXv", /* main-index: 48*/
-// "t3L1WgcyQ95vtpSgjHfgANHyVYvffJZ9iGb", /* main-index: 49*/
-// "t3JtoXqsv3FuS7SznYCd5pZJGU9di15mdd7", /* main-index: 50*/
-// "t3hLJHrHs3ytDgExxr1mD8DYSrk1TowGV25", /* main-index: 51*/
-// "t3fmYHU2DnVaQgPhDs6TMFVmyC3qbWEWgXN", /* main-index: 52*/
-// "t3T4WmAp6nrLkJ24iPpGeCe1fSWTPv47ASG", /* main-index: 53*/
-// "t3fP6GrDM4QVwdjFhmCxGNbe7jXXXSDQ5dv", /* main-index: 54*/
-};
- assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight());
+ }
}
};
static CMainParams mainParams;
return txOrdered;
}
+// looks through all wallet UTXOs and checks to see if any qualify to stake the block at the current height. it always returns the qualified
+// UTXO with the smallest coin age if there is more than one, as larger coin age will win more often and is worth saving
+// each attempt consists of taking a VerusHash of the following values:
+// ASSETCHAINS_MAGIC, nHeight, txid, voutNum
+bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const
+{
+ arith_uint256 target;
+ arith_uint256 curHash;
+ vector<COutput> vecOutputs;
+ COutput *pwinner = NULL;
+ CBlockIndex *pastBlockIndex;
+ txnouttype whichType;
+ std:vector<std::vector<unsigned char>> vSolutions;
+
+ pBlock->nNonce.SetPOSTarget(bnTarget);
+ target.SetCompact(bnTarget);
+
+ pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
+
+ if (pastBlockIndex = komodo_chainactive(nHeight - 100))
+ {
+ CBlockHeader bh = pastBlockIndex->GetBlockHeader();
+ uint256 pastHash = bh.GetVerusEntropyHash(nHeight - 100);
+ CPOSNonce curNonce;
+
+ BOOST_FOREACH(COutput &txout, vecOutputs)
+ {
+ if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(&(pBlock->nNonce), txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE))
+ {
+ if ((!pwinner || UintToArith256(curNonce) > UintToArith256(pBlock->nNonce)) &&
+ (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH)))
+ {
+ //printf("Found PoS block\nnNonce: %s\n", pBlock->nNonce.GetHex().c_str());
+ pwinner = &txout;
+ curNonce = pBlock->nNonce;
+ }
+ }
+ }
+ if (pwinner)
+ {
+ stakeSource = *(pwinner->tx);
+ voutNum = pwinner->i;
+ pBlock->nNonce = curNonce;
+ return true;
+ }
+ }
+ return false;
+}
+
+int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey pk) const
+{
+ CTransaction stakeSource;
+ int32_t voutNum, siglen = 0;
+ int64_t nValue;
+ txnouttype whichType;
+ std::vector<std::vector<unsigned char>> vSolutions;
+
+ CBlockIndex *tipindex = chainActive.LastTip();
+ uint32_t stakeHeight = tipindex->GetHeight() + 1;
+ bool extendedStake = stakeHeight >= Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight;
+
+ if (!extendedStake)
+ pk = CPubKey();
+
+ bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus());
+
+ if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, tipindex->GetHeight() + 1, bnTarget) ||
+ !Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions))
+ {
+ LogPrintf("Searched for eligible staking transactions, no winners found\n");
+ return 0;
+ }
+
+ bool signSuccess;
+ SignatureData sigdata;
+ uint64_t txfee;
+ auto consensusBranchId = CurrentEpochBranchId(stakeHeight, Params().GetConsensus());
+
+ const CKeyStore& keystore = *pwalletMain;
+ txNew.vin.resize(1);
+ txNew.vout.resize(1);
+ txfee = extendedStake ? DEFAULT_STAKE_TXFEE : 0; // extended stakes will always be rebroadcast, so they require a fee to make it fast
+ txNew.vin[0].prevout.hash = stakeSource.GetHash();
+ txNew.vin[0].prevout.n = voutNum;
+
+ if (whichType == TX_PUBKEY)
+ {
+ txNew.vout[0].scriptPubKey << ToByteVector(vSolutions[0]) << OP_CHECKSIG;
+ if (!pk.IsValid())
+ pk = CPubKey(vSolutions[0]);
+ }
+ else if (whichType == TX_PUBKEYHASH)
+ {
+ txNew.vout[0].scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(vSolutions[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
+ if (extendedStake && !pk.IsValid())
+ {
+ // we need a pubkey, so try to get one from the key ID, if not there, fail
+ if (!keystore.GetPubKey(CKeyID(uint160(vSolutions[0])), pk))
+ return 0;
+ }
+ }
+ else
+ return 0;
+
+ // if we are staking with the extended format, add the opreturn data required
+ if (extendedStake)
+ {
+ uint256 srcBlock = uint256();
+ CBlockIndex *pSrcIndex;
+
+ txNew.vout.push_back(CTxOut());
+ CTxOut &txOut1 = txNew.vout[1];
+ txOut1.nValue = 0;
+ if (!GetTransaction(stakeSource.GetHash(), stakeSource, srcBlock))
+ return 0;
+
+ BlockMap::const_iterator it = mapBlockIndex.find(srcBlock);
+ if (it == mapBlockIndex.end() || (pSrcIndex = it->second) == 0)
+ return 0;
+
+ // !! DISABLE THIS FOR RELEASE: THIS MAKES A CHEAT TRANSACTION FOR EVERY STAKE FOR TESTING
+ CMutableTransaction cheat;
+ cheat = CMutableTransaction(txNew);
++ printf("TESTING ONLY: THIS SHOULD NOT BE ENABLED FOR RELEASE - MAKING CHEAT TRANSACTION FOR TESTING");
+ cheat.vout[1].scriptPubKey << OP_RETURN
+ << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, pSrcIndex->GetBlockHash(), pk).AsVector();
+ // !! DOWN TO HERE
+
+ txOut1.scriptPubKey << OP_RETURN
+ << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, tipindex->GetBlockHash(), pk).AsVector();
+
+ // !! DISABLE THIS FOR RELEASE: REMOVE THIS TOO
+ nValue = cheat.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
+ cheat.nLockTime = 0;
+ CTransaction cheatConst(cheat);
+ SignatureData cheatSig;
+ if (!ProduceSignature(TransactionSignatureCreator(&keystore, &cheatConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, cheatSig, consensusBranchId))
+ fprintf(stderr,"failed to create cheat test signature\n");
+ else
+ {
+ uint8_t *ptr;
+ UpdateTransaction(cheat,0,cheatSig);
+ cheatList.Add(CTxHolder(CTransaction(cheat), tipindex->GetHeight() + 1));
+ }
+ // !! DOWN TO HERE
+ }
+
+ nValue = txNew.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
+
+ txNew.nLockTime = 0;
+ CTransaction txNewConst(txNew);
+ signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, sigdata, consensusBranchId);
+ if (!signSuccess)
+ fprintf(stderr,"failed to create signature\n");
+ else
+ {
+ uint8_t *ptr;
+ UpdateTransaction(txNew,0,sigdata);
+ ptr = (uint8_t *)&sigdata.scriptSig[0];
+ siglen = sigdata.scriptSig.size();
+ for (int i=0; i<siglen; i++)
+ utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
+ }
+ return(siglen);
+}
+
void CWallet::MarkDirty()
{
{
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
CBlock block;
- ReadBlockFromDisk(block, pindex);
+ ReadBlockFromDisk(block, pindex,1);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
- if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
+ if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) {
+ myTxHashes.push_back(tx.GetHash());
ret++;
+ }
}
SproutMerkleTree sproutTree;
pindex = chainActive.Next(pindex);
if (GetTime() >= nNow + 60) {
nNow = GetTime();
- LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
+ LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->GetHeight(), Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
}
}
+
+ // After rescanning, persist Sapling note data that might have changed, e.g. nullifiers.
+ // Do not flush the wallet here for performance reasons.
+ CWalletDB walletdb(strWalletFile, "r+", false);
+ for (auto hash : myTxHashes) {
+ CWalletTx wtx = mapWallet[hash];
+ if (!wtx.mapSaplingNoteData.empty()) {
+ if (!wtx.WriteToDisk(&walletdb)) {
+ LogPrintf("Rescanning... WriteToDisk failed to update Sapling note data for: %s\n", hash.ToString());
+ }
+ }
+ }
+
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
}
return ret;