Browse Source

Merge pull request #333 from miketout/dev

Update deprecation height and version number
pull/334/head
Alex R English 3 years ago
committed by GitHub
parent
commit
359371f9d8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .gitlab-ci.yml
  2. 3
      README.md
  3. 3
      doc/man/verus-cli/linux/README.txt
  4. 4
      doc/man/verus-cli/mac/README.txt
  5. 4
      doc/man/verus-cli/windows/README.txt
  6. 4
      src/deprecation.h
  7. 5
      src/komodo_utils.h
  8. 2
      src/main.cpp
  9. 1
      src/miner.h
  10. 9
      src/net.cpp
  11. 1
      src/pbaas/identity.cpp
  12. 33
      src/pbaas/pbaas.cpp
  13. 11
      src/pbaas/reserves.cpp
  14. 54
      src/rpc/mining.cpp
  15. 87
      src/rpc/pbaasrpc.cpp
  16. 4
      src/script/script.cpp
  17. 2
      src/version.h
  18. 62
      src/wallet/wallet.cpp

4
.gitlab-ci.yml

@ -6,7 +6,9 @@ stages:
####START#### PROJECT LEVEL VARIABLES ####START####
########################################################################################################################
variables:
VERSION: 0.7.3-4
VERSION: 0.7.3-5
VERUS_CLI_ARM64_LINUX: Verus-CLI-Linux-v${VERSION}-arm64.tar.gz
VERUS_CLI_LINUX_X86_64: Verus-CLI-Linux-v${VERSION}-x86_64.tar.gz
VERUS_CLI_WINDOWS: Verus-CLI-Windows-v${VERSION}.zip

3
README.md

@ -1,4 +1,5 @@
## VerusCoin version 0.7.3-4
## VerusCoin version 0.7.3-5
Arguably the world's most advanced technology, zero knowledge privacy-centric blockchain, Verus Coin brings Sapling performance and zero knowledge features to an intelligent system with interchain smart contracts and a completely original, combined proof of stake/proof of work consensus algorithm that solves the nothing at stake problem. With this and its approach towards CPU mining and ASICs, Verus Coin strives to be one of the most naturally decentralizing and attack resistant blockchains in existence.

3
doc/man/verus-cli/linux/README.txt

@ -1,4 +1,5 @@
VerusCoin Command Line Tools v0.7.3-4
VerusCoin Command Line Tools v0.7.3-5
Contents:
verusd - VerusCoin daemon

4
doc/man/verus-cli/mac/README.txt

@ -1,4 +1,6 @@
VerusCoin Command Line Tools v0.7.3-4
VerusCoin Command Line Tools v0.7.3-5
Contents:
verusd - VerusCoin daemon.
verus - VerusCoin command line utility.

4
doc/man/verus-cli/windows/README.txt

@ -1,4 +1,6 @@
VerusCoin Command Line Tools v0.7.3-4
VerusCoin Command Line Tools v0.7.3-5
Contents:
verusd.exe - VerusCoin daemon
verus.exe - VerusCoin command line utility

4
src/deprecation.h

@ -8,7 +8,9 @@
// Deprecation policy:
// * Shut down 20 weeks' worth of blocks after the estimated release block height.
// * A warning is shown during the 2 weeks' worth of blocks prior to shut down.
static const int APPROX_RELEASE_HEIGHT = 1520000;
static const int APPROX_RELEASE_HEIGHT = 1537000;
static const int WEEKS_UNTIL_DEPRECATION = 20;
static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 60 * 24);

5
src/komodo_utils.h

@ -1845,8 +1845,6 @@ void komodo_args(char *argv0)
mapArgs["-ac_supply"] = "5000000000000000";
mapArgs["-ac_eras"] = "1";
mapArgs["-ac_reward"] = "1200000000";
std::string halving = GetArg("-ac_halving", "2111115"); // this assignment is required for an ARM compiler workaround
mapArgs["-ac_halving"] = halving; // allow testing easily with different values here
mapArgs["-ac_decay"] = "0";
mapArgs["-ac_options"] = "72"; // OPTION_ID_REFERRALS + OPTION_CANBERESERVE
mapArgs["-ac_end"] = "0";
@ -1860,6 +1858,9 @@ void komodo_args(char *argv0)
{
LogPrintf("Config file for %s not found.\n", name.c_str());
}
std::string halving = GetArg("-ac_halving", mapArgs.count("-ac_halving") ? mapArgs["-ac_halving"] : "2111115"); // this assignment is required for an ARM compiler workaround
mapArgs["-ac_halving"] = halving; // allow testing easily with different values here
}
else
{

2
src/main.cpp

@ -1824,7 +1824,7 @@ bool AcceptToMemoryPoolInt(CTxMemPool& pool, CValidationState &state, const CTra
if (pool.mapNextTx.count(outpoint))
{
// Disable replacement feature for now
//fprintf(stderr,"pool.mapNextTx.count\n");
//printf("%s: outpoint already spent in mempool by tx: %s\n", __func__, pool.mapNextTx[outpoint].ptx->GetHash().GetHex().c_str());
return state.Invalid(false, REJECT_INVALID, "bad-txns-inputs-spent");
}
}

1
src/miner.h

@ -29,6 +29,7 @@ struct CBlockTemplate
/** Generate a new block, without valid proof-of-work */
CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn, bool isStake=false);
CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const std::vector<CTxOut> &minerOutputs, bool isStake=false);
#ifdef ENABLE_WALLET
boost::optional<CScript> GetMinerScriptPubKey(CReserveKey& reservekey);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, bool isStake=false);

9
src/net.cpp

@ -1274,9 +1274,14 @@ void ThreadSocketHandler()
void ThreadDNSAddressSeed()
{
// goal: only query DNS seeds if address need is acute
// goal: only query DNS seeds if address need is acute and connect is not set
if ((addrman.size() > 0) &&
(!GetBoolArg("-forcednsseed", false))) {
(!GetBoolArg("-forcednsseed", false)))
{
if (!(mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0))
{
return;
}
MilliSleep(11 * 1000);
LOCK(cs_vNodes);

1
src/pbaas/identity.cpp

@ -529,6 +529,7 @@ bool ValidateSpendingIdentityReservation(const CTransaction &tx, int32_t outNum,
// referrer must be mined in when this transaction is put into the mem pool
if (heightOut >= height || !firstReferralIdentity.IsValid() || firstReferralIdentity.parent != ASSETCHAINS_CHAINID)
{
//printf("%s: cannot find first instance of: %s\n", __func__, EncodeDestination(CIdentityID(newName.referral)).c_str());
return state.Error("Invalid identity registration referral");
}

33
src/pbaas/pbaas.cpp

@ -1611,7 +1611,9 @@ bool CConnectedChains::GetReserveDeposits(const uint160 &currencyID, const CCoin
}
for (auto &oneConfirmed : confirmedUTXOs)
{
if (view.GetCoins(oneConfirmed.first.txhash, coin) && coin.IsAvailable(oneConfirmed.first.index))
if (!mempool.mapNextTx.count(COutPoint(oneConfirmed.first.txhash, oneConfirmed.first.index)) &&
view.GetCoins(oneConfirmed.first.txhash, coin) &&
coin.IsAvailable(oneConfirmed.first.index))
{
reserveDeposits.push_back(CInputDescriptor(oneConfirmed.second.script, oneConfirmed.second.satoshis,
CTxIn(oneConfirmed.first.txhash, oneConfirmed.first.index)));
@ -1624,6 +1626,7 @@ bool CConnectedChains::GetReserveDeposits(const uint160 &currencyID, const CCoin
{
COptCCParams p;
if (!oneUnconfirmed.first.spending &&
!mempool.mapNextTx.count(COutPoint(oneUnconfirmed.first.txhash, oneUnconfirmed.first.index)) &&
view.GetCoins(oneUnconfirmed.first.txhash, coin) &&
coin.IsAvailable(oneUnconfirmed.first.index))
{
@ -2462,20 +2465,38 @@ bool CConnectedChains::CreateLatestImports(const CCurrencyDefinition &sourceSyst
}
{
std::set<uint256> txesToShow;
for (auto &oneIn : newImportTx.vin)
{
if (!view.HaveCoins(oneIn.prevout.hash))
{
/*UniValue jsonTx(UniValue::VOBJ);
uint256 hashBlk;
TxToUniv(newImportTx, hashBlk, jsonTx);
printf("%s\n", jsonTx.write(1,2).c_str()); //*/
printf("%s: cannot find input in view %s\n", __func__, oneIn.prevout.hash.GetHex().c_str());
}
else
{
txesToShow.insert(oneIn.prevout.hash);
}
}
/* DEBUG output only
for (auto &oneTxId : txesToShow)
{
CTransaction inputTx;
uint256 inputBlkHash;
if (myGetTransaction(oneTxId, inputTx, inputBlkHash))
{
UniValue uni(UniValue::VOBJ);
TxToUniv(inputTx, inputBlkHash, uni);
printf("%s: inputTx:\n%s\n", __func__, uni.write(1,2).c_str());
}
else
{
printf("%s: unable to retrieve input transaction: %s\n", __func__, oneTxId.GetHex().c_str());
}
} //*/
// put our transaction in place of any others
std::list<CTransaction> removed;
//std::list<CTransaction> removed;
//mempool.removeConflicts(newImportTx, removed);
// add to mem pool and relay

11
src/pbaas/reserves.cpp

@ -2492,6 +2492,7 @@ bool CReserveTransactionDescriptor::AddReserveTransferImportOutputs(const CCurre
// convert fees to next destination native, if necessary/possible
CCurrencyDefinition curNextDest = ConnectedChains.GetCachedCurrency(curTransfer.destination.gatewayID);
uint160 nextDestSysID = curNextDest.IsGateway() ? curNextDest.gatewayID : curNextDest.systemID;
// if it's already in the correct currency, nothing to do, otherwise convert if we can
if (curTransfer.feeCurrencyID != nextDestSysID)
{
@ -2534,6 +2535,16 @@ bool CReserveTransactionDescriptor::AddReserveTransferImportOutputs(const CCurre
AddReserveOutput(nextDestSysID, reserveFromFrac);
AddReserveOutConverted(nextDestSysID, reserveFromFrac);
} else
{
if (curTransfer.feeCurrencyID == systemDestID)
{
nativeOut = curTransfer.destination.fees;
}
else
{
AddReserveOutput(nextDestSysID, curTransfer.destination.fees);
}
}
}

54
src/rpc/mining.cpp

@ -533,7 +533,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
UniValue chainNames(UniValue::VARR);
for (auto chain : chains)
{
chainNames.push_back(chain.name);
chainNames.push_back(EncodeDestination(CIdentityID(chain.GetID())) + " (" + chain.name + ")");
}
obj.push_back(Pair("mergeminedchains", chainNames));
}
@ -605,9 +605,14 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
"\nArguments:\n"
"1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n"
" {\n"
" \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n"
" \"capabilities\":[ (array, optional) A list of strings\n"
" \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
" \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n"
" \"rewarddistribution\":{\n"
" \"(recipientaddress)\":n, (addressorid, relativeweight) key value to determine distribution\n"
" \"(recipientaddress)\":n,\n"
" \"...\n"
" \"}\n"
" \"capabilities\":[ (array, optional) A list of strings\n"
" \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
" ,...\n"
" ]\n"
" }\n"
@ -679,6 +684,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
{
const UniValue& oparam = params[0].get_obj();
const UniValue& modeval = find_value(oparam, "mode");
if (modeval.isStr())
strMode = modeval.get_str();
else if (modeval.isNull())
@ -808,12 +814,46 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
delete pblocktemplate;
pblocktemplate = NULL;
}
UniValue recipientWeights;
if (params.size() > 0 &&
(recipientWeights = find_value(params[0], "recipientdistribution")).isArray() &&
recipientWeights.size() &&
recipientWeights[0].isObject())
{
std::vector<CTxOut> minerOutputs;
for (int i = 0; i < recipientWeights.size(); i++)
{
if (!recipientWeights[i].isObject())
{
throw JSONRPCError(RPC_INVALID_PARAMS, "recipientdistribution must be an array of objects, each specifing a valid address as key and relative weight value");
}
std::vector<std::string> keys = recipientWeights[i].getKeys();
std::vector<UniValue> values = recipientWeights[i].getValues();
if (keys.size() != 1 || values.size() != 1)
{
throw JSONRPCError(RPC_INVALID_PARAMS, "Each object in recipientdistribution array must have one valid address as key and one relative weight value");
}
CTxDestination oneDest = DecodeDestination(keys[0]);
CAmount relVal = 0;
if (oneDest.which() == COptCCParams::ADDRTYPE_INVALID ||
!(relVal = uni_get_int64(values[0])))
{
throw JSONRPCError(RPC_INVALID_PARAMS, "Invalid destination or zero weight specified in recipientdistribution array");
}
minerOutputs.push_back(CTxOut(relVal, GetScriptForDestination(oneDest)));
}
pblocktemplate = CreateNewBlock(Params(), minerOutputs, false);
}
else
{
#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain);
pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1);
CReserveKey reservekey(pwalletMain);
pblocktemplate = CreateNewBlockWithKey(reservekey, chainActive.LastTip()->GetHeight()+1);
#else
pblocktemplate = CreateNewBlockWithKey();
pblocktemplate = CreateNewBlockWithKey();
#endif
}
/* keep Zcash script-based approach for reference
boost::shared_ptr<CReserveScript> coinbaseScript;

87
src/rpc/pbaasrpc.cpp

@ -331,27 +331,54 @@ std::pair<uint160, CTransferDestination> ValidateTransferDestination(const std::
// set default peer nodes in the current connected chains
bool SetPeerNodes(const UniValue &nodes)
{
if (!nodes.isArray() || nodes.size() == 0)
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
{
return false;
printf("%s: Ignoring seednodes due to nodes specified in \"-connect\" parameter\n", __func__);
LogPrintf("%s: Ignoring seednodes due to nodes specified in \"-connect\" parameter\n", __func__);
std::vector<std::string> connectNodes = mapMultiArgs["-connect"];
for (int i = 0; i < connectNodes.size(); i++)
{
CNodeData oneNode = CNodeData(connectNodes[i], "");
if (oneNode.networkAddress != "")
{
ConnectedChains.defaultPeerNodes.push_back(oneNode);
}
}
}
else
{
if (!nodes.isArray() || nodes.size() == 0)
{
return false;
}
LOCK(ConnectedChains.cs_mergemining);
ConnectedChains.defaultPeerNodes.clear();
LOCK(ConnectedChains.cs_mergemining);
ConnectedChains.defaultPeerNodes.clear();
for (int i = 0; i < nodes.size(); i++)
{
CNodeData oneNode(nodes[i]);
if (oneNode.networkAddress != "")
for (int i = 0; i < nodes.size(); i++)
{
ConnectedChains.defaultPeerNodes.push_back(oneNode);
CNodeData oneNode(nodes[i]);
if (oneNode.networkAddress != "")
{
ConnectedChains.defaultPeerNodes.push_back(oneNode);
}
}
std::vector<std::string> seedNodes = mapMultiArgs["-seednode"];
for (int i = 0; i < seedNodes.size(); i++)
{
CNodeData oneNode = CNodeData(seedNodes[i], "");
if (oneNode.networkAddress != "")
{
ConnectedChains.defaultPeerNodes.push_back(oneNode);
}
}
}
std::vector<std::string> seedNodes = mapMultiArgs["-seednode"];
for (int i = 0; i < seedNodes.size(); i++)
std::vector<std::string> addNodes = mapMultiArgs["-addnode"];
for (int i = 0; i < addNodes.size(); i++)
{
CNodeData oneNode = CNodeData(seedNodes[i], "");
CNodeData oneNode = CNodeData(addNodes[i], "");
if (oneNode.networkAddress != "")
{
ConnectedChains.defaultPeerNodes.push_back(oneNode);
@ -360,16 +387,22 @@ bool SetPeerNodes(const UniValue &nodes)
// set all command line parameters into mapArgs from chain definition
vector<string> nodeStrs;
for (auto node : ConnectedChains.defaultPeerNodes)
{
nodeStrs.push_back(node.networkAddress);
}
mapMultiArgs["-seednode"] = nodeStrs;
for (auto &oneNode : seedNodes)
if (!(mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0))
{
mapMultiArgs["-seednode"] = nodeStrs;
}
for (auto &oneNode : nodeStrs)
{
AddOneShot(oneNode);
}
if (int port = ConnectedChains.GetThisChainPort())
{
mapArgs["-port"] = to_string(port);
@ -3154,7 +3187,7 @@ UniValue estimateconversion(const UniValue& params, bool fHelp)
{
throw runtime_error(
"estimateconversion '{\"currency\":\"name\",\"convertto\":\"name\",\"amount\":n}'\n"
"\nThis estimates conversion from one currency to another, taking into account pending conversions and slippage.\n"
"\nThis estimates conversion from one currency to another, taking into account pending conversions, fees and slippage.\n"
"\nArguments\n"
"1. {\n"
@ -3360,11 +3393,15 @@ UniValue sendcurrency(const UniValue& params, bool fHelp)
" \"currency\": \"name\" (string, required) Name of the source currency to send in this output, defaults to native of chain\n"
" \"amount\":amount (numeric, required) The numeric amount of currency, denominated in source currency\n"
" \"convertto\":\"name\", (string, optional) Valid currency to convert to, either a reserve of a fractional, or fractional\n"
" \"exportto\":\"name\", (string, optional) Valid chain or system name or ID to export to\n"
" \"feecurrency\":\"name\", (string, optional) Valid currency that should be pulled from the current wallet and used to pay fee\n"
" \"via\":\"name\", (string, optional) If source and destination currency are reserves, via is a common fractional to convert through\n"
" \"address\":\"dest\" (string, required) The address and optionally chain/system after the \"@\" as a system specific destination\n"
" \"refundto\":\"dest\" (string, optional) For pre-conversions, this is where refunds will go, defaults to fromaddress\n"
" \"memo\":memo (string, optional) If destination is a zaddr (not supported on testnet), a string message (not hexadecimal) to include.\n"
" \"preconvert\":\"false\", (bool, optional) convert to currency at market price (default=false), only works if transaction is mined before start of currency\n"
" \"burn\":\"false\", (bool, optional) destroy the currency and subtract it from the supply. Currency must be a token.\n"
" \"mintnew\":\"false\", (bool, optional) if the transaction is sent from the currency ID of a centralized currency, this creates new currency to send\n"
" }, ... ]\n"
"3. \"feeamount\" (bool, optional) specific fee amount requested instead of default miner's fee\n"
@ -3491,9 +3528,10 @@ UniValue sendcurrency(const UniValue& params, bool fHelp)
exportToStr.size() ||
burnCurrency ||
mintNew ||
preConvert))
preConvert ||
sourceCurrencyID != ASSETCHAINS_CHAINID))
{
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot convert, preconvert, mint, cross-chain send, or burn currency being sent to a z-address.");
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot convert, preconvert, mint, cross-chain send, burn or send non-native currency when sending to a z-address.");
}
// re-encode destination, in case it is specified as the private address of an ID
@ -4078,7 +4116,7 @@ UniValue sendcurrency(const UniValue& params, bool fHelp)
// if we're converting and then sending, we don't need an initial fee, so all
// fees go into the final destination
dest.type |= dest.FLAG_DEST_GATEWAY;
dest.gatewayID = destSystemID;
dest.gatewayID = exportSystemDef.GetID();
CChainNotarizationData cnd;
if (!GetNotarizationData(convertToCurrencyID, cnd) ||
!cnd.IsConfirmed())
@ -4912,9 +4950,16 @@ UniValue definecurrency(const UniValue& params, bool fHelp)
"name and ID as the currency being defined.\n"
"\nArguments\n"
" {\n"
" \"options\" : n, (int, optional) bits:\n"
" 1 = FRACTIONAL, 2 = IDRESTRICTED, 4 = IDSTAKING, 8 = IDREFERRALS\n"
" 0x10 = IDREFERRALSREQUIRED, 0x20 = TOKEN, 0x40 = CANBERESERVE\n"
" \"options\" : n, (int, optional) bits (in hexadecimal):\n"
" 1 = FRACTIONAL\n"
" 2 = IDRESTRICTED\n"
" 4 = IDSTAKING\n"
" 8 = IDREFERRALS\n"
" 0x10 = IDREFERRALSREQUIRED\n"
" 0x20 = TOKEN\n"
" 0x40 = CANBERESERVE\n"
" 0x100 = IS_PBAAS_CHAIN\n"
"\n"
" \"name\" : \"xxxx\", (string, required) name of existing identity with no active or pending blockchain\n"
" \"idregistrationprice\" : \"xx.xx\", (value, required) price of an identity in native currency\n"
" \"idreferrallevels\" : n, (int, required) how many levels ID referrals go back in reward\n"

4
src/script/script.cpp

@ -1232,7 +1232,9 @@ std::set<CIndexID> COptCCParams::GetIndexKeys() const
CNameReservation nameRes;
if (vData.size() && (nameRes = CNameReservation(vData[0])).IsValid())
{
destinations.insert(CIndexID(CCrossChainRPCData::GetConditionID(nameRes.name, evalCode)));
uint160 parent = ASSETCHAINS_CHAINID;
uint160 ourID = CIdentity::GetID(nameRes.name, parent);
destinations.insert(CIndexID(CCrossChainRPCData::GetConditionID(ourID, evalCode)));
}
break;
}

2
src/version.h

@ -35,6 +35,6 @@ static const int MEMPOOL_GD_VERSION = 60002;
static const int NO_BLOOM_VERSION = 170004;
#define KOMODO_VERSION "0.2.1"
#define VERUS_VERSION "0.7.3-4"
#define VERUS_VERSION "0.7.3-5"
#endif // BITCOIN_VERSION_H

62
src/wallet/wallet.cpp

@ -2669,14 +2669,15 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
{
if (unspentOutputs.size() > MAX_OUR_UTXOS_ID_RESCAN)
{
continue;
unspentOutputs.clear();
}
// the exception would currently be if all of the following are true:
// 1) We have spending, not just signing power over the ID,
// 2) the ID has no separate revoke and recover, so it cannot be pulled back, and
// 3) the ID does not have an average of < 0.00001 in native outputs of a random sample
// of its UTXOs
if (canSignCanSpend.second &&
if (unspentOutputs.size() &&
canSignCanSpend.second &&
identity.revocationAuthority == identity.recoveryAuthority &&
identity.revocationAuthority == idID)
{
@ -2703,12 +2704,12 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
if (!counted.size() ||
(total / (CAmount)counted.size() < 10000))
{
continue;
unspentOutputs.clear();
}
}
else
else if (unspentOutputs.size())
{
continue;
unspentOutputs.clear();
}
}
@ -2752,6 +2753,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
{
CAddressUnspentKey unspentKey(CScript::P2ID, idID, wtx.first, k);
CBlockIndex *pIndex = mapBlockIndex[wtx.second.hashBlock];
unspentTxSet.insert(wtx.first);
unspentOutputs.push_back(
make_pair(unspentKey, CAddressUnspentValue(oneOut.nValue, oneOut.scriptPubKey, pIndex->GetHeight())));
// if we add one on a tx, no need to check more here
@ -2808,13 +2810,12 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
continue;
}
wtx.SetMerkleBranch(block);
AddToWallet(wtx, false, &walletdb);
}
AddToWallet(wtx, false, &walletdb);
pWtx = GetWalletTx(newOut.first.txhash);
}
}
else if (pWtx = GetWalletTx(newOut.first.txhash))
else if (pWtx)
{
if (!(ExtractDestinations(newOut.second.script, newTypeRet, newAddressRet, newNRequired, this, &newCanSign, &newCanSpend, nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
{
@ -2823,7 +2824,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
}
// if we were or are now in the wallet, we need to see if we should record new spends
if (pWtx != nullptr && newOut.second.script.IsPayToCryptoCondition())
if (pWtx)
{
// while we know there is an unspent index to this ID on the new transaction output, we don't know
// if there are other outputs to this ID on the transaction, which are already spent.
@ -2831,17 +2832,22 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
// not consider them spent.
uint256 spendBlkHash;
CTransaction spendTx;
std::vector<CTxOut> checkIfSpent = pWtx->vout;
std::vector<std::pair<uint256, int>> checkIfSpent;
for (int counter = 0; counter < pWtx->vout.size(); counter++)
{
checkIfSpent.push_back(std::make_pair(pWtx->GetHash(), counter));
}
const CWalletTx *txToCheck = pWtx;
for (int i = 0; i < checkIfSpent.size(); i++)
{
// if it really came from the unspent index and is the same output, don't bother looking for a spend
if (unspentTxSet.count(newOut.first.txhash) && newOut.first.index == i)
if (txToCheck->GetHash() != checkIfSpent[i].first)
{
continue;
txToCheck = GetWalletTx(checkIfSpent[i].first);
}
// if we can't spend it, no need to check for spends
if (!(ExtractDestinations(checkIfSpent[i].scriptPubKey,
if (!(txToCheck &&
ExtractDestinations(txToCheck->vout[checkIfSpent[i].second].scriptPubKey,
newTypeRet,
newAddressRet,
newNRequired,
@ -2854,12 +2860,18 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
}
CSpentIndexValue spentInfo;
CSpentIndexKey spentKey(newOut.first.txhash, i);
if (GetSpentIndex(spentKey, spentInfo))
CSpentIndexKey spentKey(checkIfSpent[i].first, checkIfSpent[i].second);
// if it's spent, we need to put spender in the wallet
// if the spender has outputs that we can now spend due to the ID,
// we need to check for those being spent as well
if (GetSpentIndex(spentKey, spentInfo) &&
!spentInfo.IsNull())
{
if (GetWalletTx(spentInfo.txid) == nullptr &&
const CWalletTx *pSpendingTx = GetWalletTx(spentInfo.txid);
if (pSpendingTx == nullptr &&
spentInfo.blockHeight <= nHeight &&
myGetTransaction(spentInfo.txid, spendTx, spendBlkHash) && !spendBlkHash.IsNull())
myGetTransaction(spentInfo.txid, spendTx, spendBlkHash) &&
!spendBlkHash.IsNull())
{
CWalletTx spendWtx(this, spendTx);
@ -2876,7 +2888,19 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
// add these outputs to the outputs we need to check if spent
// as long as we are adding spending transactions that are earlier
// or up to this height, we follow the spends
checkIfSpent.insert(checkIfSpent.end(), spendTx.vout.begin(), spendTx.vout.end());
for (int counter = 0; counter < spendTx.vout.size(); counter++)
{
checkIfSpent.push_back(std::make_pair(spendTx.GetHash(), counter));
}
}
}
else if (pSpendingTx &&
spentInfo.blockHeight <= nHeight)
{
// we may have outputs on a spending transaction that should be considered as well
for (int counter = 0; counter < pSpendingTx->vout.size(); counter++)
{
checkIfSpent.push_back(std::make_pair(pSpendingTx->GetHash(), counter));
}
}
}

Loading…
Cancel
Save