diff --git a/src/libspark/keys.cpp b/src/libspark/keys.cpp index 456e45e203..74440fa012 100644 --- a/src/libspark/keys.cpp +++ b/src/libspark/keys.cpp @@ -1,5 +1,6 @@ #include "keys.h" #include "../hash.h" +#include "../support/cleanse.h" #include "transcript.h" namespace spark { @@ -16,28 +17,29 @@ SpendKey::SpendKey(const Params* params) { SpendKey::SpendKey(const Params* params, const Scalar& r_) { this->params = params; this->r = r_; - std::vector data; - data.resize(32); + std::vector data(32); r.serialize(data.data()); - std::vector result(CSHA256().OUTPUT_SIZE); + std::vector result(CSHA256::OUTPUT_SIZE); CHash256 hash256; std::string prefix1 = "s1_generation"; hash256.Write(reinterpret_cast(prefix1.c_str()), prefix1.size()); hash256.Write(data.data(), data.size()); - hash256.Finalize(&result[0]); - this->s1.memberFromSeed(&result[0]); + hash256.Finalize(result.data()); + this->s1.memberFromSeed(result.data()); - data.clear(); - result.clear(); + // Reset for s2 generation - use memory_cleanse to securely clear cryptographic material + // (memory_cleanse uses OPENSSL_cleanse which is guaranteed not to be optimized away) + memory_cleanse(data.data(), data.size()); + memory_cleanse(result.data(), result.size()); hash256.Reset(); s1.serialize(data.data()); std::string prefix2 = "s2_generation"; hash256.Write(reinterpret_cast(prefix2.c_str()), prefix2.size()); hash256.Write(data.data(), data.size()); - hash256.Finalize(&result[0]); - this->s2.memberFromSeed(&result[0]); + hash256.Finalize(result.data()); + this->s2.memberFromSeed(result.data()); } const Params* SpendKey::get_params() const { @@ -212,7 +214,10 @@ unsigned char Address::decode(const std::string& str) { throw std::invalid_argument("Bad address encoding"); } - // Check the encoding prefix + // Check the hrp length and encoding prefix + if (decoded.hrp.size() < 2) { + throw std::invalid_argument("Bad address format"); + } if (decoded.hrp[0] != ADDRESS_ENCODING_PREFIX) { throw std::invalid_argument("Bad address prefix"); } diff --git a/src/miner.cpp b/src/miner.cpp index 661e959ebd..86817cf6de 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1108,7 +1108,8 @@ void static FiroMiner(const CChainParams &chainparams) { // due to some internal error but also if the keypool is empty. // In the latter case, already the pointer is NULL. if (!coinbaseScript || coinbaseScript->reserveScript.empty()) { - LogPrintf("FiroMiner stop here coinbaseScript=%s, coinbaseScript->reserveScript.empty()=%s\n", coinbaseScript, coinbaseScript->reserveScript.empty()); + LogPrintf("FiroMiner stop here coinbaseScript=%p, coinbaseScript->reserveScript.empty()=%d\n", + coinbaseScript.get(), coinbaseScript ? coinbaseScript->reserveScript.empty() : true); throw std::runtime_error("No coinbase script available (mining requires a wallet)"); } @@ -1141,7 +1142,7 @@ void static FiroMiner(const CChainParams &chainparams) { unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex *pindexPrev = chainActive.Tip(); if (pindexPrev) { - LogPrintf("loop pindexPrev->nHeight=%s\n", pindexPrev->nHeight); + LogPrintf("loop pindexPrev->nHeight=%d\n", pindexPrev->nHeight); } LogPrintf("BEFORE: pblocktemplate\n"); std::unique_ptr pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript, {}); @@ -1164,11 +1165,11 @@ void static FiroMiner(const CChainParams &chainparams) { arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); LogPrintf("hashTarget: %s\n", hashTarget.ToString()); LogPrintf("fTestnet: %d\n", fTestNet); - LogPrintf("pindexPrev->nHeight: %s\n", pindexPrev->nHeight); + LogPrintf("pindexPrev->nHeight: %d\n", pindexPrev->nHeight); LogPrintf("pblock: %s\n", pblock->ToString()); - LogPrintf("pblock->nVersion: %s\n", pblock->nVersion); - LogPrintf("pblock->nTime: %s\n", pblock->nTime); - LogPrintf("pblock->nNonce: %s\n", &pblock->nNonce); + LogPrintf("pblock->nVersion: %d\n", pblock->nVersion); + LogPrintf("pblock->nTime: %u\n", pblock->nTime); + LogPrintf("pblock->nNonce: %u\n", pblock->nNonce); LogPrintf("powLimit: %s\n", Params().GetConsensus().powLimit.ToString()); while (true) { diff --git a/src/spark/sparkwallet.cpp b/src/spark/sparkwallet.cpp index 27587ea6b8..0f1e8f296d 100644 --- a/src/spark/sparkwallet.cpp +++ b/src/spark/sparkwallet.cpp @@ -805,9 +805,14 @@ bool CSparkWallet::CreateSparkMintTransactions( wtxNew.BindWallet(pwalletMain); CMutableTransaction txNew; - txNew.nLockTime = chainActive.Height(); + int nHeight = 0; + { + LOCK(cs_main); + nHeight = chainActive.Height(); + } + txNew.nLockTime = nHeight; - assert(txNew.nLockTime <= (unsigned int) chainActive.Height()); + assert(txNew.nLockTime <= static_cast(nHeight)); assert(txNew.nLockTime < LOCKTIME_THRESHOLD); std::vector outputs_ = outputs; CAmount valueToMint = 0; @@ -844,8 +849,8 @@ bool CSparkWallet::CreateSparkMintTransactions( if (GetRandInt(10) == 0) tx.nLockTime = std::max(0, (int) tx.nLockTime - GetRandInt(100)); - auto nFeeRet = 0; - LogPrintf("nFeeRet=%s\n", nFeeRet); + CAmount nFeeRet = 0; + LogPrintf("nFeeRet=%d\n", nFeeRet); auto itr = valueAndUTXO.begin(); @@ -898,7 +903,7 @@ bool CSparkWallet::CreateSparkMintTransactions( singleTxOutputs.push_back(mintedCoinData); } else { uint64_t remainingMintValue = mintedValue; - while (remainingMintValue > 0){ + while (remainingMintValue > 0 && !remainingOutputs.empty()) { // Create the mint data and push into vector uint64_t singleMintValue = std::min(remainingMintValue, remainingOutputs.begin()->v); spark::MintedCoinData mintedCoinData; @@ -917,23 +922,23 @@ bool CSparkWallet::CreateSparkMintTransactions( } if (subtractFeeFromAmount) { - CAmount singleFee = nFeeRet / singleTxOutputs.size(); - CAmount reminder = nFeeRet % singleTxOutputs.size(); + if (singleTxOutputs.empty()) { + strFailReason = _("Transaction amount too small"); + return false; + } + const CAmount outputCount = static_cast(singleTxOutputs.size()); + const CAmount singleFee = nFeeRet / outputCount; + const CAmount remainder = nFeeRet % outputCount; for (size_t i = 0; i < singleTxOutputs.size(); ++i) { - if (cmp::less_equal(singleTxOutputs[i].v, singleFee)) { - singleTxOutputs.erase(singleTxOutputs.begin() + i); - reminder += singleTxOutputs[i].v - singleFee; - if (!singleTxOutputs.size()) { - strFailReason = _("Transaction amount too small"); - return false; - } - --i; + CAmount feeToSubtract = singleFee; + if (i == 0) { + feeToSubtract += remainder; } - singleTxOutputs[i].v -= singleFee; - if (reminder > 0 && singleTxOutputs[i].v > nFeeRet % singleTxOutputs.size()) {// first receiver pays the remainder not divisible by output count - singleTxOutputs[i].v -= reminder; - reminder = 0; + if (cmp::less_equal(singleTxOutputs[i].v, feeToSubtract)) { + strFailReason = _("Transaction amount too small"); + return false; } + singleTxOutputs[i].v -= feeToSubtract; } } @@ -954,9 +959,10 @@ bool CSparkWallet::CreateSparkMintTransactions( // Choose coins to use CAmount nValueIn = 0; if (!pwalletMain->SelectCoins(itr->second, nValueToSelect, setCoins, nValueIn, coinControl)) { - if (nValueIn < nValueToSelect) { strFailReason = _("Insufficient funds"); + } else { + strFailReason = _("Unable to select coins for minting"); } return false; } @@ -990,7 +996,7 @@ bool CSparkWallet::CreateSparkMintTransactions( // send change to one of the specified change addresses else if (IsArgSet("-change") && mapMultiArgs.at("-change").size() > 0) { CBitcoinAddress address( - mapMultiArgs.at("change")[GetRandInt(mapMultiArgs.at("-change").size())]); + mapMultiArgs.at("-change")[GetRandInt(mapMultiArgs.at("-change").size())]); CKeyID keyID; if (!address.GetKeyID(keyID)) { strFailReason = _("Bad change address"); @@ -1204,7 +1210,7 @@ bool CSparkWallet::CreateSparkMintTransactions( { CValidationState state; if (!mempool.IsTransactionAllowed(*wtx.tx, state)) { - strFailReason = _("Signing transaction failed"); + strFailReason = _("Transaction not allowed in mempool"); return false; } } @@ -1223,12 +1229,14 @@ bool CSparkWallet::CreateSparkMintTransactions( bool added = false; for (auto &utxos : valueAndUTXO) { + if (utxos.second.empty()) + continue; auto const &o = utxos.second.front(); if (o.tx->tx->vout[o.i].scriptPubKey == wtx.tx->vout[nChangePosInOut].scriptPubKey) { utxos.first += val; utxos.second.push_back(out); - added = true; + break; } } @@ -1248,6 +1256,7 @@ bool CSparkWallet::CreateSparkMintTransactions( } if (!autoMintAll && valueToMint > 0) { + strFailReason = _("Unable to mint full amount; only partial minting was possible"); return false; } @@ -1309,7 +1318,7 @@ CWalletTx CSparkWallet::CreateSparkSpendTransaction( } } - int nHeight; + int nHeight = 0; { LOCK(cs_main); nHeight = chainActive.Height(); @@ -1346,7 +1355,7 @@ CWalletTx CSparkWallet::CreateSparkSpendTransaction( // enough, that fee sniping isn't a problem yet, but by implementing a fix // now we ensure code won't be written that makes assumptions about // nLockTime that preclude a fix later. - tx.nLockTime = chainActive.Height(); + tx.nLockTime = nHeight; // Secondly occasionally randomly pick a nLockTime even further back, so // that transactions that are delayed after signing for whatever reason, @@ -1356,53 +1365,59 @@ CWalletTx CSparkWallet::CreateSparkSpendTransaction( tx.nLockTime = std::max(0, static_cast(tx.nLockTime) - GetRandInt(100)); } - assert(tx.nLockTime <= static_cast(chainActive.Height())); + assert(tx.nLockTime <= static_cast(nHeight)); assert(tx.nLockTime < LOCKTIME_THRESHOLD); - std::list coins = GetAvailableSparkCoins(coinControl); - - std::pair> estimated = - SelectSparkCoins(vOut + mintVOut, recipientsToSubtractFee, coins, privateRecipients.size(), recipients.size(), coinControl, additionalTxSize); - std::vector recipients_ = recipients; std::vector> privateRecipients_ = privateRecipients; { - bool remainderSubtracted = false; - fee = estimated.first; - for (size_t i = 0; i < recipients_.size(); i++) { - auto &recipient = recipients_[i]; - - if (recipient.fSubtractFeeFromAmount) { - // Subtract fee equally from each selected recipient. - recipient.nAmount -= fee / recipientsToSubtractFee; - - if (!remainderSubtracted) { - // First receiver pays the remainder not divisible by output count. - recipient.nAmount -= fee % recipientsToSubtractFee; + LOCK2(cs_main, pwalletMain->cs_wallet); + { + std::list coins = GetAvailableSparkCoins(coinControl); + std::pair> estimated = + SelectSparkCoins(vOut + mintVOut, recipientsToSubtractFee, coins, privateRecipients.size(), recipients.size(), coinControl, additionalTxSize); + + bool remainderSubtracted = false; + fee = estimated.first; + const CAmount feePerRecipient = recipientsToSubtractFee > 0 ? fee / recipientsToSubtractFee : 0; + const CAmount feeRemainder = recipientsToSubtractFee > 0 ? fee % recipientsToSubtractFee : 0; + for (size_t i = 0; i < recipients_.size(); i++) { + auto &recipient = recipients_[i]; + + if (recipient.fSubtractFeeFromAmount) { + CAmount feeToSubtract = feePerRecipient; + if (!remainderSubtracted) { + // First receiver pays the remainder not divisible by output count. + feeToSubtract += feeRemainder; + } + if (cmp::less_equal(recipient.nAmount, feeToSubtract)) { + throw std::runtime_error(boost::str( + boost::format(_("Amount for recipient %1% is too small to send after the fee has been deducted")) % i)); + } + // Subtract fee equally from each selected recipient. + recipient.nAmount -= feeToSubtract; remainderSubtracted = true; } } - } - for (size_t i = 0; i < privateRecipients_.size(); i++) { - auto &privateRecipient = privateRecipients_[i]; - - if (privateRecipient.second) { - // Subtract fee equally from each selected recipient. - privateRecipient.first.v -= fee / recipientsToSubtractFee; + for (size_t i = 0; i < privateRecipients_.size(); i++) { + auto &privateRecipient = privateRecipients_[i]; - if (!remainderSubtracted) { - // First receiver pays the remainder not divisible by output count. - privateRecipient.first.v -= fee % recipientsToSubtractFee; + if (privateRecipient.second) { + CAmount feeToSubtract = feePerRecipient; + if (!remainderSubtracted) { + // First receiver pays the remainder not divisible by output count. + feeToSubtract += feeRemainder; + } + if (cmp::less_equal(privateRecipient.first.v, feeToSubtract)) { + throw std::runtime_error(boost::str( + boost::format(_("Amount for private recipient %1% is too small to send after the fee has been deducted")) % i)); + } + // Subtract fee equally from each selected recipient. + privateRecipient.first.v -= feeToSubtract; remainderSubtracted = true; } } - } - - } - { - LOCK2(cs_main, pwalletMain->cs_wallet); - { const spark::Params* params = spark::Params::get_default(); spark::CSparkState *sparkState = spark::CSparkState::GetState(); spark::SpendKey spendKey(params); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index a84627be56..93e8cf9d07 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -519,7 +519,7 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) NotifyEntryRemoved(it->GetSharedTx(), reason); const uint256 hash = it->GetTx().GetHash(); if (!it->GetTx().HasPrivateInputs()) { - LogPrintf("removeUnchecked txHash=%s, IsSpend()=%s\n", hash.ToString(), it->GetTx().HasPrivateInputs()); + LogPrintf("removeUnchecked txHash=%s (no private inputs)\n", hash.ToString()); BOOST_FOREACH(const CTxIn& txin, it->GetTx().vin) mapNextTx.erase(txin.prevout); } diff --git a/src/validation.cpp b/src/validation.cpp index 030eedeb8e..3f89eea07d 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2707,7 +2707,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTimeStart = GetTimeMicros(); //btzc: update nHeight, isVerifyDB // Check it again in case a previous version let a bad block in - LogPrintf("ConnectBlock nHeight=%s, hash=%s\n", pindex->nHeight, block.GetHash().ToString()); + LogPrintf("ConnectBlock nHeight=%d, hash=%s\n", pindex->nHeight, block.GetHash().ToString()); if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck, pindex->nHeight, false)) { LogPrintf("--> failed\n"); return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); @@ -3390,7 +3390,7 @@ void PruneAndFlush() { /** Update chainActive and related internal data structures. */ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams &chainParams) { - LogPrintf("UpdateTip() pindexNew.nHeight=%s\n", pindexNew->nHeight); + LogPrintf("UpdateTip() pindexNew.nHeight=%d\n", pindexNew->nHeight); chainActive.SetTip(pindexNew); // New best block @@ -3640,7 +3640,7 @@ struct ConnectTrace { */ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr& pblock, ConnectTrace& connectTrace) { - LogPrintf("ConnectTip() nHeight=%s\n", pindexNew->nHeight); + LogPrintf("ConnectTip() nHeight=%d\n", pindexNew->nHeight); assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); @@ -4430,7 +4430,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P if (!block.sparkTxInfo) block.sparkTxInfo = std::make_shared(); - LogPrintf("CheckBlock() nHeight=%s, blockHash= %s, isVerifyDB = %s\n", nHeight, block.GetHash().ToString(), isVerifyDB); + LogPrintf("CheckBlock() nHeight=%d, blockHash= %s, isVerifyDB = %d\n", nHeight, block.GetHash().ToString(), isVerifyDB); // These are checks that are independent of context. @@ -4888,7 +4888,7 @@ static bool AcceptBlock(const std::shared_ptr& pblock, CValidation if (!AcceptBlockHeader(block, state, chainparams, &pindex)) return false; - LogPrintf("AcceptBlock nHeight=%s\n", pindex->nHeight); + LogPrintf("AcceptBlock nHeight=%d\n", pindex->nHeight); // Try to process all requested blocks that we don't have, but only // process an unrequested block if it's new and has enough work to // advance our tip, and isn't too many blocks ahead. @@ -5408,7 +5408,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, // check level 0: read from disk if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - LogPrintf("VerifyDB->CheckBlock() nHeight=%s\n", pindex->nHeight); + LogPrintf("VerifyDB->CheckBlock() nHeight=%d\n", pindex->nHeight); // check level 1: verify block validity if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus(), true, true, pindex->nHeight, true)) return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e4d28e436f..a06ea6661a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3832,7 +3832,7 @@ UniValue listunspentlelantusmints(const JSONRPCRequest& request) { std::vector vecOutputs; assert(pwallet != NULL); pwallet->ListAvailableLelantusMintCoins(vecOutputs, false); - LogPrintf("vecOutputs.size()=%s\n", vecOutputs.size()); + LogPrintf("vecOutputs.size()=%zu\n", vecOutputs.size()); BOOST_FOREACH(const COutput &out, vecOutputs) { if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) @@ -3887,7 +3887,7 @@ UniValue listunspentsparkmints(const JSONRPCRequest& request) { std::list coins = pwallet->sparkWallet->GetAvailableSparkCoins(); - LogPrintf("coins.size()=%s\n", coins.size()); + LogPrintf("coins.size()=%zu\n", coins.size()); BOOST_FOREACH(const auto& coin, coins) { UniValue entry(UniValue::VOBJ); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0c4ce96ef5..c9d71264da 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3541,17 +3541,17 @@ void CWallet::ListAvailableLelantusMintCoins(std::vector &vCoins, bool std::list listOwnCoins; CWalletDB walletdb(pwalletMain->strWalletFile); listOwnCoins = zwallet->GetTracker().MintsAsLelantusEntries(true, false); - LogPrintf("listOwnCoins.size()=%s\n", listOwnCoins.size()); + LogPrintf("listOwnCoins.size()=%zu\n", listOwnCoins.size()); for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx *pcoin = &(*it).second; // LogPrintf("pcoin=%s\n", pcoin->GetHash().ToString()); if (!CheckFinalTx(*pcoin)) { - LogPrintf("!CheckFinalTx(*pcoin)=%s\n", !CheckFinalTx(*pcoin)); + LogPrintf("!CheckFinalTx(*pcoin)=%d\n", !CheckFinalTx(*pcoin)); continue; } if (fOnlyConfirmed && !pcoin->IsTrusted()) { - LogPrintf("fOnlyConfirmed = %s, !pcoin->IsTrusted() = %s\n", fOnlyConfirmed, !pcoin->IsTrusted()); + LogPrintf("fOnlyConfirmed = %d, !pcoin->IsTrusted() = %d\n", fOnlyConfirmed, !pcoin->IsTrusted()); continue; } @@ -3562,10 +3562,10 @@ void CWallet::ListAvailableLelantusMintCoins(std::vector &vCoins, bool int nDepth = pcoin->GetDepthInMainChain(); if (nDepth < 0) { - LogPrintf("nDepth=%s\n", nDepth); + LogPrintf("nDepth=%d\n", nDepth); continue; } - LogPrintf("pcoin->tx->vout.size()=%s\n", pcoin->tx->vout.size()); + LogPrintf("pcoin->tx->vout.size()=%zu\n", pcoin->tx->vout.size()); for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) { if (pcoin->tx->vout[i].scriptPubKey.IsLelantusMint() || pcoin->tx->vout[i].scriptPubKey.IsLelantusJMint()) { @@ -3937,7 +3937,12 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // now we ensure code won't be written that makes assumptions about // nLockTime that preclude a fix later. - txNew.nLockTime = chainActive.Height(); + int nHeight = 0; + { + LOCK(cs_main); + nHeight = chainActive.Height(); + } + txNew.nLockTime = nHeight; // Secondly occasionally randomly pick a nLockTime even further back, so // that transactions that are delayed after signing for whatever reason, @@ -3946,7 +3951,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (GetRandInt(10) == 0) txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100)); - assert(txNew.nLockTime <= (unsigned int)chainActive.Height()); + assert(txNew.nLockTime <= static_cast(nHeight)); assert(txNew.nLockTime < LOCKTIME_THRESHOLD); { @@ -4348,9 +4353,14 @@ bool CWallet::CreateLelantusMintTransactions( wtxNew.BindWallet(this); CMutableTransaction txNew; - txNew.nLockTime = chainActive.Height(); + int nHeight = 0; + { + LOCK(cs_main); + nHeight = chainActive.Height(); + } + txNew.nLockTime = nHeight; - assert(txNew.nLockTime <= (unsigned int) chainActive.Height()); + assert(txNew.nLockTime <= static_cast(nHeight)); assert(txNew.nLockTime < LOCKTIME_THRESHOLD); { @@ -4379,8 +4389,8 @@ bool CWallet::CreateLelantusMintTransactions( CHDMint dMint; - auto nFeeRet = 0; - LogPrintf("nFeeRet=%s\n", nFeeRet); + CAmount nFeeRet = 0; + LogPrintf("nFeeRet=%d\n", nFeeRet); auto itr = valueAndUTXO.begin(); @@ -4477,7 +4487,7 @@ bool CWallet::CreateLelantusMintTransactions( // send change to one of the specified change addresses else if (IsArgSet("-change") && mapMultiArgs.at("-change").size() > 0) { CBitcoinAddress address( - mapMultiArgs.at("change")[GetRandInt(mapMultiArgs.at("-change").size())]); + mapMultiArgs.at("-change")[GetRandInt(mapMultiArgs.at("-change").size())]); CKeyID keyID; if (!address.GetKeyID(keyID)) { strFailReason = _("Bad change address"); @@ -4740,7 +4750,7 @@ std::string CWallet::MintAndStoreLelantus(const CAmount& value, if ((value + payTxFee.GetFeePerK()) > GetBalance()) return _("Insufficient funds"); - LogPrintf("payTxFee.GetFeePerK()=%s\n", payTxFee.GetFeePerK()); + LogPrintf("payTxFee.GetFeePerK()=%d\n", payTxFee.GetFeePerK()); int64_t nFeeRequired = 0; int nChangePosRet = -1; @@ -4809,7 +4819,7 @@ std::string CWallet::MintAndStoreSpark( if (cmp::greater((value + payTxFee.GetFeePerK()), GetBalance())) return _("Insufficient funds"); - LogPrintf("payTxFee.GetFeePerK()=%s\n", payTxFee.GetFeePerK()); + LogPrintf("payTxFee.GetFeePerK()=%d\n", payTxFee.GetFeePerK()); int64_t nFeeRequired = 0; int nChangePosRet = -1;