diff --git a/src/blind.cpp b/src/blind.cpp index 2c2d12d6ee..5f465f1e1d 100644 --- a/src/blind.cpp +++ b/src/blind.cpp @@ -225,8 +225,8 @@ int BlindTransaction(std::vector& input_value_blinding_factors, const { // Sanity check input data and output_pubkey size, clear other output data assert(tx.vout.size() >= output_pubkeys.size()); - assert(tx.vin.size()+GetNumIssuances(tx) >= issuance_blinding_privkey.size()); - assert(tx.vin.size()+GetNumIssuances(tx) >= token_blinding_privkey.size()); + assert(tx.vin.size()+GetNumIssuances(CTransaction(tx)) >= issuance_blinding_privkey.size()); + assert(tx.vin.size()+GetNumIssuances(CTransaction(tx)) >= token_blinding_privkey.size()); out_val_blind_factors.clear(); out_val_blind_factors.resize(tx.vout.size()); out_asset_blind_factors.clear(); diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index da3195b869..16d206bb85 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -212,10 +212,10 @@ public: } return result; } - void learnRelatedScripts(const CPubKey& key, OutputType type) override { m_wallet.LearnRelatedScripts(key, type); } + void learnRelatedScripts(const CPubKey& key, OutputType type) override { m_wallet->LearnRelatedScripts(key, type); } CPubKey getBlindingPubKey(const CScript& script) override { - return m_wallet.GetBlindingPubKey(script); + return m_wallet->GetBlindingPubKey(script); } bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override { @@ -272,10 +272,10 @@ public: std::set assets_seen; for (const auto& rec : recipients) { if (assets_seen.insert(rec.asset).second) { - pending->m_keys.emplace_back(new CReserveKey(&m_wallet)); + pending->m_keys.emplace_back(new CReserveKey(&*m_wallet)); } } - if (!m_wallet->CreateTransaction(*locked_chain, recipients, pending->m_tx, pending->m_key, fee, change_pos, + if (!m_wallet->CreateTransaction(*locked_chain, recipients, pending->m_tx, pending->m_keys, fee, change_pos, fail_reason, coin_control, sign)) { return {}; } diff --git a/src/policy/policy.h b/src/policy/policy.h index 97476b13a0..b01db3c271 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -106,7 +106,7 @@ extern CFeeRate dustRelayFee; extern unsigned int nBytesPerSigOp; /** Compute the virtual transaction size (weight reinterpreted as bytes). */ -int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost); +int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost = 0); int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0); int64_t GetVirtualTransactionInputSize(const CTransaction& tx, const size_t nIn, int64_t nSigOpCost = 0); diff --git a/src/psbt.cpp b/src/psbt.cpp index 0fb7d49d7d..b6fa344862 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -304,7 +304,7 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti result = *psbtx.tx; for (unsigned int i = 0; i < result.vin.size(); ++i) { result.vin[i].scriptSig = psbtx.inputs[i].final_script_sig; - result.vin[i].scriptWitness = psbtx.inputs[i].final_script_witness; + result.witness.vtxinwit[i].scriptWitness = psbtx.inputs[i].final_script_witness; } return true; } diff --git a/src/psbt.h b/src/psbt.h index c889dad361..e42baba3d7 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -477,8 +477,9 @@ struct PartiallySignedTransaction UnserializeFromVector(os, mtx); tx = std::move(mtx); // Make sure that all scriptSigs and scriptWitnesses are empty - for (const CTxIn& txin : tx->vin) { - if (!txin.scriptSig.empty() || !txin.scriptWitness.IsNull()) { + for (unsigned int i = 0; i < tx->vin.size(); i++) { + const CTxIn& txin = tx->vin[i]; + if (!txin.scriptSig.empty() || !tx->witness.vtxinwit[i].scriptWitness.IsNull()) { throw std::ios_base::failure("Unsigned tx does not have empty scriptSigs and scriptWitnesses."); } } diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index d444c196ed..34c9bb34af 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -341,7 +341,8 @@ void BitcoinApplication::initializeResult(bool success) if (paymentServer) { paymentServer->setOptionsModel(optionsModel); #ifdef ENABLE_BIP70 - connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK); + //TODO(stevenroose) fix + //connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK); #endif } #endif diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 78dacb7bcb..ba284ae68d 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -89,7 +89,9 @@ static std::string DummyAddress(const CChainParams ¶ms) CPubKey dummy_key(dummydata); ScriptHash script_dest(uint160(), dummy_key); std::string dest_str = EncodeDestination(script_dest); - DecodeBase58(dest_str, sourcedata); + if (!DecodeBase58(dest_str, sourcedata)) { + return ""; + } for(int i=0; i<256; ++i) { // Try every trailing byte std::string s = EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size()); if (!IsValidDestinationString(s)) { diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 7552b67fa0..902c58b462 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -22,7 +22,6 @@ #include -static const uint64_t GB_BYTES = 1000000000LL; /* Minimum free space (in GB) needed for data directory */ constexpr uint64_t BLOCK_CHAIN_SIZE = 1; /* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */ diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index dc9f02de9a..fb4bd3570d 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -17,10 +17,10 @@ static const struct { const int iconColorHueShift; const int iconColorSaturationReduction; } network_styles[] = { - {"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""}, - {"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")}, + {"main", QAPP_APP_NAME_DEFAULT, 0, 0}, + {"test", QAPP_APP_NAME_TESTNET, 70, 30}, {"liquidv1", "Liquid-Qt-liquidv1", 0, 0}, - {"regtest", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"} + {"regtest", QAPP_APP_NAME_REGTEST, 160, 30} }; static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles); diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp index da25d83175..63f2b8ab5e 100644 --- a/src/qt/test/apptests.cpp +++ b/src/qt/test/apptests.cpp @@ -69,7 +69,7 @@ void AppTests::appTests() m_app.parameterSetup(); m_app.createOptionsModel(true /* reset settings */); QScopedPointer style( - NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString()))); + NetworkStyle::instantiate(Params().NetworkIDString())); m_app.setupPlatformStyle(); m_app.createWindow(style.data()); connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests); diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index c532ffbbfe..ffceaf6a2b 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -102,7 +102,8 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr -void Shuffle(I first, I last, R&& rng) -{ - while (first != last) { - size_t j = rng.randrange(last - first); - if (j) { - using std::swap; - swap(*first, *(first + j)); - } - ++first; - } -} - #endif // BITCOIN_RANDOM_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d8d58dec08..e71cc6db3a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1363,7 +1363,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.pushKV("difficulty", (double)GetDifficulty(tip)); } obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast()); - obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip)); + obj.pushKV("verificationprogress", GuessVerificationProgress(tip, Params().GetConsensus().nPowTargetSpacing)); obj.pushKV("initialblockdownload", IsInitialBlockDownload()); if (!g_signed_blocks) { obj.pushKV("chainwork", tip->nChainWork.GetHex()); @@ -2342,14 +2342,14 @@ UniValue scantxoutset(const JSONRPCRequest& request) const Coin& coin = it.second; const CTxOut& txo = coin.out; input_txos.push_back(txo); - total_in += txo.nValue; + total_in += txo.nValue.GetAmount(); UniValue unspent(UniValue::VOBJ); unspent.pushKV("txid", outpoint.hash.GetHex()); unspent.pushKV("vout", (int32_t)outpoint.n); unspent.pushKV("scriptPubKey", HexStr(txo.scriptPubKey.begin(), txo.scriptPubKey.end())); unspent.pushKV("desc", descriptors[txo.scriptPubKey]); - unspent.pushKV("amount", ValueFromAmount(txo.nValue)); + unspent.pushKV("amount", ValueFromAmount(txo.nValue.GetAmount())); unspent.pushKV("height", (int32_t)coin.nHeight); unspents.push_back(unspent); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a47a85ae18..2cc9cf3115 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1005,7 +1005,7 @@ UniValue getnewblockhex(const JSONRPCRequest& request) CScript feeDestinationScript = Params().GetConsensus().mandatory_coinbase_destination; if (feeDestinationScript == CScript()) feeDestinationScript = CScript() << OP_TRUE; - std::unique_ptr pblocktemplate(BlockAssembler(Params()).CreateNewBlock(feeDestinationScript, true, required_wait)); + std::unique_ptr pblocktemplate(BlockAssembler(Params()).CreateNewBlock(feeDestinationScript, required_wait)); if (!pblocktemplate.get()) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty"); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 89ddfaec17..3281fd68a6 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -213,7 +213,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) } if (!fVerbose) { - return EncodeHexTx(*tx, RPCSerializationFlags()); + return EncodeHexTx(CTransaction(*tx), RPCSerializationFlags()); } UniValue result(UniValue::VOBJ); @@ -580,8 +580,8 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."}, {"output_assets", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "A json object of addresses to the assets (label or hex ID) used to pay them. (default: bitcoin)", { - {"address", RPCArg::Type::STR, RPCArg::Optional::OMMITED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, - {"fee", RPCArg::Type::STR, RPCArg::Optional::OMMITED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, + {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, + {"fee", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, }, }, }, @@ -608,7 +608,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3], request.params[4]); - return EncodeHexTx(CTransaction(rawTx)); + return EncodeHexTx(CTransaction(rawTx), RPCSerializationFlags()); } static UniValue decoderawtransaction(const JSONRPCRequest& request) @@ -865,7 +865,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) UpdateTransaction(mergedTx, i, sigdata); } - return EncodeHexTx(CTransaction(mergedTx)); + return EncodeHexTx(CTransaction(mergedTx), RPCSerializationFlags()); } UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType) @@ -1029,7 +1029,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con bool fComplete = vErrors.empty(); UniValue result(UniValue::VOBJ); - result.pushKV("hex", EncodeHexTx(CTransaction(mtx))); + result.pushKV("hex", EncodeHexTx(CTransaction(mtx), RPCSerializationFlags())); result.pushKV("complete", fComplete); if (!vErrors.empty()) { result.pushKV("errors", vErrors); @@ -1708,8 +1708,8 @@ UniValue createpsbt(const JSONRPCRequest& request) " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."}, {"output_assets", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "A json object of addresses to the assets (label or hex ID) used to pay them. (default: bitcoin)", { - {"address", RPCArg::Type::STR, RPCArg::Optional::OMMITED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, - {"fee", RPCArg::Type::STR, RPCArg::Optional::OMMITED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, + {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, + {"fee", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A key-value pair. The key (string) is the bitcoin address, the value is the asset label or asset ID."}, }, }, }, @@ -1944,7 +1944,7 @@ UniValue rawblindrawtransaction(const JSONRPCRequest& request) if (num_pubkeys == 0 && n_blinded_ins == 0) { // Vacuous, just return the transaction - return EncodeHexTx(tx); + return EncodeHexTx(CTransaction(tx), RPCSerializationFlags()); } else if (n_blinded_ins > 0 && num_pubkeys == 0) { // No notion of wallet, cannot complete this blinding without passed-in pubkey throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to blind transaction: Add another output to blind in order to complete the blinding."); @@ -1952,7 +1952,7 @@ UniValue rawblindrawtransaction(const JSONRPCRequest& request) if (fIgnoreBlindFail) { // Just get rid of the ECDH key in the nonce field and return tx.vout[keyIndex].nNonce.SetNull(); - return EncodeHexTx(tx); + return EncodeHexTx(CTransaction(tx), RPCSerializationFlags()); } else { throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to blind transaction: Add another output to blind in order to complete the blinding."); } @@ -1965,7 +1965,7 @@ UniValue rawblindrawtransaction(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to blind transaction: Are you sure each asset type to blind is represented in the inputs?"); } - return EncodeHexTx(tx); + return EncodeHexTx(CTransaction(tx), RPCSerializationFlags()); } struct RawIssuanceDetails @@ -2189,7 +2189,7 @@ UniValue rawissueasset(const JSONRPCRequest& request) UniValue obj(UniValue::VOBJ); if (issuances_til_now == issuances.size()) { - obj.pushKV("hex", EncodeHexTx(mtx, RPCSerializationFlags())); + obj.pushKV("hex", EncodeHexTx(CTransaction(mtx), RPCSerializationFlags())); } obj.pushKV("vin", details.input_index); obj.pushKV("entropy", details.entropy.GetHex()); @@ -2287,7 +2287,7 @@ UniValue rawreissueasset(const JSONRPCRequest& request) } UniValue ret(UniValue::VOBJ); - ret.pushKV("hex", EncodeHexTx(mtx, RPCSerializationFlags())); + ret.pushKV("hex", EncodeHexTx(CTransaction(mtx), RPCSerializationFlags())); return ret; } @@ -2485,7 +2485,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request) bool all_final = true; bool only_missing_sigs = true; bool only_missing_final = false; - CAmount in_amt = 0; + CAmountMap in_amts; for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) { PSBTInput& input = psbtx.inputs[i]; UniValue input_univ(UniValue::VOBJ); @@ -2494,7 +2494,8 @@ UniValue analyzepsbt(const JSONRPCRequest& request) // Check for a UTXO CTxOut utxo; if (psbtx.GetInputUTXO(utxo, i)) { - in_amt += utxo.nValue; + //TODO(gwillen) do PSBT inputs always have explicit assets & amounts? + in_amts[utxo.nAsset.GetAsset()] += utxo.nValue.GetAmount(); input_univ.pushKV("has_utxo", true); } else { input_univ.pushKV("has_utxo", false); @@ -2564,14 +2565,15 @@ UniValue analyzepsbt(const JSONRPCRequest& request) } if (calc_fee) { // Get the output amount - CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), 0, - [](int a, const CTxOut& b) { - return a += b.nValue; + CAmountMap out_amts = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmountMap(), + [](CAmountMap map, const CTxOut& b) { + map[b.nAsset.GetAsset()] += b.nValue.GetAmount(); + return map; } ); // Get the fee - CAmount fee = in_amt - out_amt; + CAmountMap fee = in_amts - out_amts; // Estimate the size CMutableTransaction mtx(*psbtx.tx); @@ -2583,7 +2585,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request) PSBTInput& input = psbtx.inputs[i]; if (SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true)) { mtx.vin[i].scriptSig = input.final_script_sig; - mtx.vin[i].scriptWitness = input.final_script_witness; + mtx.witness.vtxinwit[i].scriptWitness = input.final_script_witness; Coin newcoin; if (!psbtx.GetInputUTXO(newcoin.out, i)) { @@ -2603,10 +2605,10 @@ UniValue analyzepsbt(const JSONRPCRequest& request) size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS)); result.pushKV("estimated_vsize", (int)size); // Estimate fee rate - CFeeRate feerate(fee, size); + CFeeRate feerate(fee[::policyAsset], size); result.pushKV("estimated_feerate", feerate.ToString()); } - result.pushKV("fee", ValueFromAmount(fee)); + result.pushKV("fee", AmountMapToUniv(fee, "")); if (only_missing_sigs) { result.pushKV("next", "signer"); diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 473c8128ba..076be670ad 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -464,20 +464,10 @@ public: } }; +//TODO(stevenroose) remove if unused CScript P2PKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(PKHash(pubkey)); } CScript P2PKGetScript(const CPubKey& pubkey) { return GetScriptForRawPubKey(pubkey); } CScript P2WPKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(WitnessV0KeyHash(pubkey.GetID())); } - -/** A parsed multi(...) descriptor. */ -class MultisigDescriptor : public Descriptor -{ - int m_threshold; - std::vector> m_providers; - -public: - MultisigDescriptor(int threshold, std::vector> providers) : m_threshold(threshold), m_providers(std::move(providers)) {} -}; - CScript ConvertP2SH(const CScript& script) { return GetScriptForDestination(ScriptHash(script)); } CScript ConvertP2WSH(const CScript& script) { return GetScriptForDestination(WitnessV0ScriptHash(script)); } @@ -531,7 +521,7 @@ protected: { CKeyID id = keys[0].GetID(); out.pubkeys.emplace(id, keys[0]); - return Singleton(GetScriptForDestination(id)); + return Singleton(GetScriptForDestination(PKHash(id))); } public: PKHDescriptor(std::unique_ptr prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pkh") {} @@ -561,12 +551,12 @@ protected: CKeyID id = keys[0].GetID(); out.pubkeys.emplace(id, keys[0]); ret.emplace_back(GetScriptForRawPubKey(keys[0])); // P2PK - ret.emplace_back(GetScriptForDestination(id)); // P2PKH + ret.emplace_back(GetScriptForDestination(PKHash(id))); // P2PKH if (keys[0].IsCompressed()) { CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(id)); out.scripts.emplace(CScriptID(p2wpkh), p2wpkh); ret.emplace_back(p2wpkh); - ret.emplace_back(GetScriptForDestination(CScriptID(p2wpkh))); // P2SH-P2WPKH + ret.emplace_back(GetScriptForDestination(ScriptHash(CScriptID(p2wpkh)))); // P2SH-P2WPKH } return ret; } @@ -589,7 +579,7 @@ public: class SHDescriptor final : public DescriptorImpl { protected: - std::vector MakeScripts(const std::vector&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(CScriptID(*script))); } + std::vector MakeScripts(const std::vector&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(ScriptHash(CScriptID(*script)))); } public: SHDescriptor(std::unique_ptr desc) : DescriptorImpl({}, std::move(desc), "sh") {} }; diff --git a/src/test/blind_tests.cpp b/src/test/blind_tests.cpp index e706667861..e3cf57e8f7 100644 --- a/src/test/blind_tests.cpp +++ b/src/test/blind_tests.cpp @@ -72,32 +72,32 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) tx3.vout.push_back(CTxOut(bitcoinID, 100, CScript() << OP_TRUE)); // Fee outputs are blank scriptpubkeys, and unblinded value/asset tx3.vout.push_back(CTxOut(bitcoinID, 22, CScript())); - BOOST_CHECK(VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); // Malleate the output and check for correct handling of bad commitments // These will fail IsValid checks std::vector asset_copy(tx3.vout[0].nAsset.vchCommitment); std::vector value_copy(tx3.vout[0].nValue.vchCommitment); tx3.vout[0].nAsset.vchCommitment[0] = 122; - BOOST_CHECK(!VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); tx3.vout[0].nAsset.vchCommitment = asset_copy; tx3.vout[0].nValue.vchCommitment[0] = 122; - BOOST_CHECK(!VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); tx3.vout[0].nValue.vchCommitment = value_copy; // Make sure null values are handled correctly tx3.vout[0].nAsset.SetNull(); - BOOST_CHECK(!VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); tx3.vout[0].nAsset.vchCommitment = asset_copy; tx3.vout[0].nValue.SetNull(); - BOOST_CHECK(!VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); tx3.vout[0].nValue.vchCommitment = value_copy; // Bad nonce values will result in failure to deserialize tx3.vout[0].nNonce.SetNull(); - BOOST_CHECK(VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); tx3.vout[0].nNonce.vchCommitment = tx3.vout[0].nValue.vchCommitment; - BOOST_CHECK(!VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); // Try to blind with a single non-fee output, which fails as its blinding factor ends up being zero. std::vector input_blinds; @@ -125,7 +125,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, tx3) == 2); BOOST_CHECK(!tx3.vout[0].nValue.IsExplicit()); BOOST_CHECK(!tx3.vout[2].nValue.IsExplicit()); - BOOST_CHECK(VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); CAmount unblinded_amount; BOOST_CHECK(UnblindConfidentialPair(key2, tx3.vout[0].nValue, tx3.vout[0].nAsset, tx3.vout[0].nNonce, op_true, tx3.witness.vtxoutwit[0].vchRangeproof, unblinded_amount, blind3, unblinded_id, asset_blind) == 0); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) blind_ozz = tx3.vout[0]; tx3.vout[1].nValue = CConfidentialValue(tx3.vout[1].nValue.GetAmount() - 1); - BOOST_CHECK(!VerifyAmounts(inputs, tx3, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false)); } { @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) tx4.vout.push_back(CTxOut(bitcoinID, 30, CScript() << OP_TRUE)); tx4.vout.push_back(CTxOut(bitcoinID, 40, CScript() << OP_TRUE)); tx4.vout.push_back(CTxOut(bitcoinID, 111+100-30-40, CScript())); - BOOST_CHECK(!VerifyAmounts(inputs, tx4, nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate. + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate. std::vector input_blinds; std::vector input_asset_blinds; @@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) tx4.vout.push_back(CTxOut(bitcoinID, 50, CScript() << OP_TRUE)); // Fee tx4.vout.push_back(CTxOut(bitcoinID, 111+100-30-40-50, CScript())); - BOOST_CHECK(!VerifyAmounts(inputs, tx4, nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate. + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate. std::vector input_blinds; std::vector input_asset_blinds; @@ -231,7 +231,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) BOOST_CHECK(tx4.vout[1].nValue.IsExplicit()); BOOST_CHECK(!tx4.vout[2].nValue.IsExplicit()); // This one broken - BOOST_CHECK(VerifyAmounts(inputs, tx4, nullptr, false)); + BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx4), nullptr, false)); CAmount unblinded_amount; CAsset asset_out; @@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) BOOST_CHECK(UnblindConfidentialPair(key2, tx4.vout[2].nValue, tx4.vout[2].nAsset, tx4.vout[2].nNonce, op_true, tx4.witness.vtxoutwit[2].vchRangeproof, unblinded_amount, blind4, asset_out, asset_blinder_out) == 0); tx4.vout[3].nValue = CConfidentialValue(tx4.vout[3].nValue.GetAmount() - 1); - BOOST_CHECK(!VerifyAmounts(inputs, tx4, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), nullptr, false)); // Check wallet borromean-based rangeproof results against expected args size_t proof_size = DEFAULT_RANGEPROOF_SIZE; @@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) tx5.vout.push_back(CTxOut(otherID, 1, CScript())); // Blinds don't balance - BOOST_CHECK(!VerifyAmounts(inputs, tx5, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx5), nullptr, false)); // Blinding setup stuff std::vector input_blinds; @@ -323,27 +323,27 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) // No blinding keys for fees, bails out blinding nothing, still invalid due to imbalance BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == -1); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); // Last will be implied blank keys output_pubkeys.resize(4); // Blind transaction, verify amounts txtemp = tx5; BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == 4); - BOOST_CHECK(VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); // Transaction may not have spendable 0-value output txtemp.vout.push_back(CTxOut(CAsset(), 0, CScript() << OP_TRUE)); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); // Create imbalance by removing fees, should still be able to blind txtemp = tx5; txtemp.vout.resize(5); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); txtemp.vout.resize(4); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == 4); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); txtemp = tx5; // Remove other input, make surjection proof impossible for 2 "otherID" outputs @@ -362,9 +362,9 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) t_input_asset_blinds.resize(1); t_input_assets.resize(1); t_input_amounts.resize(1); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); BOOST_CHECK(BlindTransaction(t_input_blinds, t_input_asset_blinds, t_input_assets, t_input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == 2); - BOOST_CHECK(!VerifyAmounts(inputs, txtemp, nullptr, false)); + BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false)); } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index 71e449aff0..7b1bfc3054 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -206,7 +206,6 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // not caching invalidity (if that changes, delete this test case). std::vector scriptchecks; BOOST_CHECK(CheckInputs(CTransaction(spend_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks)); ->>>>>>> 519b0bc5dc5155b6f7e2362c2105552bb7618ad0 BOOST_CHECK_EQUAL(scriptchecks.size(), 1U); // Test that CheckInputs returns true iff DERSIG-enforcing flags are diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index f04667777f..c1c4667390 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -128,7 +128,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin if (g_con_elementsmode && nFeeOutput == -1) { CMutableTransaction with_fee_output = CMutableTransaction{*wtx.tx}; with_fee_output.vout.push_back(CTxOut(::policyAsset, 0, CScript())); - txSize = GetVirtualTransactionSize(with_fee_output); + txSize = GetVirtualTransactionSize(CTransaction(with_fee_output)); } const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet); if (maxNewTxSize < 0) { diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 9f13ff255d..e8304b8681 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -652,17 +652,17 @@ UniValue importwallet(const JSONRPCRequest& request) assert(key.VerifyPubKey(pubkey)); CKeyID keyid = pubkey.GetID(); if (pwallet->HaveKey(keyid)) { - pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid)); + pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(PKHash(keyid))); continue; } - pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(keyid)); + pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(PKHash(keyid))); if (!pwallet->AddKeyPubKey(key, pubkey)) { fGood = false; continue; } pwallet->mapKeyMetadata[keyid].nCreateTime = time; if (has_label) - pwallet->SetAddressBook(keyid, label, "receive"); + pwallet->SetAddressBook(PKHash(keyid), label, "receive"); nTimeBegin = std::min(nTimeBegin, time); progress++; } @@ -1260,7 +1260,7 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !privkey_map.empty()) { throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); } - if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !blinding_privkey.empty()) { + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !str_blinding_key.empty()) { throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import blinding keys to a wallet with private keys disabled"); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ffd038ba83..802c50bf88 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -417,17 +417,17 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) " \"UNSET\"\n" " \"ECONOMICAL\"\n" " \"CONSERVATIVE\""}, - {"assetlabel", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Hex asset id or asset label for balance." - {"assetlabel", RPCArg::Type::BOOL, /* default */ true, "Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs." + {"assetlabel", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Hex asset id or asset label for balance."}, + {"ignoreblindfail", RPCArg::Type::BOOL, /* default */ "true", "Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs."}, }, RPCResult{ "\"txid\" (string) The transaction id.\n" }, RPCExamples{ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1") - + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"") - + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true") - + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"") + + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"") + + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true") + + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"") }, }.ToString()); @@ -932,7 +932,7 @@ static UniValue sendmany(const JSONRPCRequest& request) {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "A key-value pair where the key is the address used and the value is an asset label or hex asset ID."}, }, }, - {"ignoreblindfail", RPCArg::Type::BOOL, /* default */ true, "Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs."}, + {"ignoreblindfail", RPCArg::Type::BOOL, /* default */ "true", "Return a transaction even when a blinding attempt fails due to number of blinded inputs/outputs."}, }, RPCResult{ "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n" @@ -1239,7 +1239,7 @@ public: struct tallyitem { - CAmountMap nAmount; + CAmountMap mapAmount; int nConf{std::numeric_limits::max()}; std::vector txids; bool fIsWatchonly{false}; @@ -5422,7 +5422,7 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef mtx.witness.vtxinwit.push_back(txinwit); // Estimate fee for transaction, decrement fee output(including witness data) - unsigned int nBytes = GetVirtualTransactionSize(mtx) + + unsigned int nBytes = GetVirtualTransactionSize(CTransaction(mtx)) + (1+1+72+1+33/WITNESS_SCALE_FACTOR); CCoinControl coin_control; CAmount nFeeNeeded = GetMinimumFee(*pwallet, nBytes, coin_control, mempool, ::feeEstimator, nullptr); @@ -5433,7 +5433,7 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef UniValue ret(UniValue::VOBJ); // Return hex - std::string strHex = EncodeHexTx(mtx, RPCSerializationFlags()); + std::string strHex = EncodeHexTx(CTransaction(mtx), RPCSerializationFlags()); ret.pushKV("hex", strHex); // Additional block lee-way to avoid bitcoin block races @@ -5792,7 +5792,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request) if (num_pubkeys == 0 && n_blinded_ins == 0) { // Vacuous, just return the transaction - return EncodeHexTx(tx); + return EncodeHexTx(CTransaction(tx)); } else if (n_blinded_ins > 0 && num_pubkeys == 0) { // Blinded inputs need to balanced with something to be valid, make a dummy. CTxOut newTxOut(tx.vout.back().nAsset.GetAsset(), 0, CScript() << OP_RETURN); @@ -5803,7 +5803,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request) if (ignore_blind_fail) { // Just get rid of the ECDH key in the nonce field and return tx.vout[key_index].nNonce.SetNull(); - return EncodeHexTx(tx); + return EncodeHexTx(CTransaction(tx)); } else { throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to blind transaction: Add another output to blind in order to complete the blinding."); } @@ -5815,7 +5815,7 @@ UniValue blindrawtransaction(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to blind transaction: Are you sure each asset type to blind is represented in the inputs?"); } - return EncodeHexTx(tx); + return EncodeHexTx(CTransaction(tx)); } static UniValue unblindrawtransaction(const JSONRPCRequest& request) @@ -5855,7 +5855,7 @@ static UniValue unblindrawtransaction(const JSONRPCRequest& request) FillBlinds(pwallet, tx, output_value_blinds, output_asset_blinds, output_pubkeys, asset_keys, token_keys); UniValue result(UniValue::VOBJ); - result.pushKV("hex", EncodeHexTx(tx)); + result.pushKV("hex", EncodeHexTx(CTransaction(tx))); return result; } diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index aa9f858978..a1c126ca96 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -58,7 +58,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) BOOST_CHECK(result.last_failed_block.IsNull()); BOOST_CHECK(result.last_scanned_block.IsNull()); BOOST_CHECK(!result.last_scanned_height); - BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 0); + BOOST_CHECK_EQUAL(wallet.GetImmatureBalance()[CAsset()], 0); } // Verify ScanForWalletTransactions picks up transactions in both the old @@ -110,7 +110,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash()); BOOST_CHECK(result.last_scanned_block.IsNull()); BOOST_CHECK(!result.last_scanned_height); - BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 0); + BOOST_CHECK_EQUAL(wallet.GetImmatureBalance()[CAsset()], 0); } } @@ -492,9 +492,10 @@ static size_t CalculateNestedKeyhashInputSize(bool use_max_sig) assert(false); } - CTxIn tx_in; - UpdateInput(tx_in, sig_data); - return (size_t)GetVirtualTransactionInputSize(tx_in); + CMutableTransaction tx; + tx.vin.resize(1); + UpdateTransaction(tx, 0, sig_data); + return (size_t)GetVirtualTransactionInputSize(CTransaction(tx), 0); } BOOST_FIXTURE_TEST_CASE(dummy_input_size_test, TestChain100Setup) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f8ece85bcf..e494e080c6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1704,7 +1704,7 @@ int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, // implies that we can sign for every input. return -1; } - return GetVirtualTransactionInputSize(txn, 0, 0); + return GetVirtualTransactionInputSize(CTransaction(txn), 0, 0); } void CWalletTx::GetAmounts(std::list& listReceived, @@ -3681,12 +3681,6 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std } } - //TODO(stevenroose) check if this shuffling doesn't break things - // Shuffle selected coins and fill in final vin - txNew.vin.clear(); - std::vector selected_coins(setCoins.begin(), setCoins.end()); - Shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext()); - // Note how the sequence number is set to non-maxint so that // the nLockTime set above actually works. //