diff --git a/doc/REST-interface.md b/doc/REST-interface.md index d67a4ba0c7..ca88ce0c6d 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -98,11 +98,8 @@ $ curl localhost:19998/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76 "scriptPubKey" : { "asm" : "OP_DUP OP_HASH160 1c7cebb529b86a04c683dfa87be49de35bcf589e OP_EQUALVERIFY OP_CHECKSIG", "hex" : "76a9141c7cebb529b86a04c683dfa87be49de35bcf589e88ac", - "reqSigs" : 1, "type" : "pubkeyhash", - "addresses" : [ - "mi7as51dvLJsizWnTMurtRmrP8hG2m1XvD" - ] + "address" : "mi7as51dvLJsizWnTMurtRmrP8hG2m1XvD" } } ] diff --git a/doc/release-notes-20286.md b/doc/release-notes-20286.md new file mode 100644 index 0000000000..4678eea7e2 --- /dev/null +++ b/doc/release-notes-20286.md @@ -0,0 +1,16 @@ +Updated RPCs +------------ + +- The following RPCs: `gettxout`, `getrawtransaction`, `decoderawtransaction`, + `decodescript`, `gettransaction`, and REST endpoints: `/rest/tx`, + `/rest/getutxos`, `/rest/block` deprecated the following fields (which are no + longer returned in the responses by default): `addresses`, `reqSigs`. + The `-deprecatedrpc=addresses` flag must be passed for these fields to be + included in the RPC response. Note that these fields are attributes of + the `scriptPubKey` object returned in the RPC response. However, in the response + of `decodescript` these fields are top-level attributes, and included again as attributes + of the `scriptPubKey` object. + +- When creating a hex-encoded Dash transaction using the `dash-tx` utility + with the `-json` option set, the following fields: `addresses`, `reqSigs` are no longer + returned in the tx output of the response. diff --git a/doc/release-notes-21359.md b/doc/release-notes-21359.md new file mode 100644 index 0000000000..f86c72f5c4 --- /dev/null +++ b/doc/release-notes-21359.md @@ -0,0 +1,7 @@ +Wallet +------ + +- The `fundrawtransaction`, `send` and `walletcreatefundedpsbt` RPCs now support an `include_unsafe` option + that when `true` allows using unsafe inputs to fund the transaction. + Note that the resulting transaction may become invalid if one of the unsafe inputs disappears. + If that happens, the transaction must be funded with different inputs and republished. diff --git a/src/Makefile.am b/src/Makefile.am index d63dff71cf..c5d69a6c0a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -287,12 +287,12 @@ BITCOIN_CORE_H = \ rpc/blockchain.h \ rpc/client.h \ rpc/mining.h \ - rpc/net.h \ rpc/protocol.h \ rpc/rawtransaction_util.h \ rpc/register.h \ rpc/request.h \ rpc/server.h \ + rpc/server_util.h \ rpc/util.h \ saltedhasher.h \ scheduler.h \ @@ -510,6 +510,7 @@ libbitcoin_server_a_SOURCES = \ rpc/quorums.cpp \ rpc/rawtransaction.cpp \ rpc/server.cpp \ + rpc/server_util.cpp \ script/sigcache.cpp \ shutdown.cpp \ spork.cpp \ diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index a599a2ed25..9859c2a5f6 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -676,7 +676,7 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, static void OutputTxJSON(const CTransaction& tx) { UniValue entry(UniValue::VOBJ); - TxToUniv(tx, uint256(), entry); + TxToUniv(tx, uint256(), /* include_addresses */ false, entry); std::string jsonOutput = entry.write(4); tfm::format(std::cout, "%s\n", jsonOutput); diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 7498b1524d..9c79ef5f52 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -1538,7 +1538,7 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx CCoinControl coin_control; coin_control.nCoinType = CoinType::ONLY_COINJOIN_COLLATERAL; - m_wallet.AvailableCoins(vCoins, true, &coin_control); + m_wallet.AvailableCoins(vCoins, &coin_control); if (vCoins.empty()) { strReason = strprintf("%s requires a collateral transaction and could not locate an acceptable input!", gCoinJoinName); diff --git a/src/core_io.h b/src/core_io.h index 1d19461e53..91a8f01617 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -45,8 +45,8 @@ UniValue ValueFromAmount(const CAmount amount); std::string FormatScript(const CScript& script); std::string EncodeHexTx(const CTransaction& tx); std::string SighashToStr(unsigned char sighash_type); -void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex, bool include_addresses); void ScriptToUniv(const CScript& script, UniValue& out, bool include_address); -void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, const CSpentIndexTxInfo* ptxSpentInfo = nullptr, const CTxUndo* txundo = nullptr); +void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_addresses, UniValue& entry, bool include_hex = true, const CTxUndo* txundo = nullptr, const CSpentIndexTxInfo* ptxSpentInfo = nullptr); #endif // BITCOIN_CORE_IO_H diff --git a/src/core_write.cpp b/src/core_write.cpp index c27b0c0f58..ffad7897ff 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -166,10 +166,13 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address) } } +// TODO: from v21 ("addresses" and "reqSigs" deprecated) this method should be refactored to remove the `include_addresses` option +// this method can also be combined with `ScriptToUniv` as they will overlap void ScriptPubKeyToUniv(const CScript& scriptPubKey, - UniValue& out, bool fIncludeHex) + UniValue& out, bool fIncludeHex, bool include_addresses) { TxoutType type; + CTxDestination address; std::vector addresses; int nRequired; @@ -182,17 +185,22 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey, return; } - out.pushKV("reqSigs", nRequired); + if (ExtractDestination(scriptPubKey, address)) { + out.pushKV("address", EncodeDestination(address)); + } out.pushKV("type", GetTxnOutputType(type)); - UniValue a(UniValue::VARR); - for (const CTxDestination& addr : addresses) { - a.push_back(EncodeDestination(addr)); + if (include_addresses) { + UniValue a(UniValue::VARR); + for (const CTxDestination& addr : addresses) { + a.push_back(EncodeDestination(addr)); + } + out.pushKV("addresses", a); + out.pushKV("reqSigs", nRequired); } - out.pushKV("addresses", a); } -void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, const CSpentIndexTxInfo* ptxSpentInfo, const CTxUndo* txundo) +void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_addresses, UniValue& entry, bool include_hex, const CTxUndo* txundo, const CSpentIndexTxInfo* ptxSpentInfo) { uint256 txid = tx.GetHash(); entry.pushKV("txid", txid.GetHex()); @@ -260,7 +268,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, out.pushKV("n", (int64_t)i); UniValue o(UniValue::VOBJ); - ScriptPubKeyToUniv(txout.scriptPubKey, o, true); + ScriptPubKeyToUniv(txout.scriptPubKey, o, true, include_addresses); out.pushKV("scriptPubKey", o); // Add spent information if spentindex is enabled diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 0504616f38..0694c92fe2 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -398,6 +398,7 @@ public: /** Implement PeerManager */ void CheckForStaleTipAndEvictPeers() override; + std::optional FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override; bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; } void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);; @@ -1862,6 +1863,39 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex) (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT); } +std::optional PeerManagerImpl::FetchBlock(NodeId peer_id, const CBlockIndex& block_index) +{ + if (fImporting) return "Importing..."; + if (fReindex) return "Reindexing..."; + + LOCK(cs_main); + // Ensure this peer exists and hasn't been disconnected + CNodeState* state = State(peer_id); + if (state == nullptr) return "Peer does not exist"; + + // Mark block as in-flight unless it already is (for this peer). + // If a block was already in-flight for a different peer, its BLOCKTXN + // response will be dropped. + const uint256& hash{block_index.GetBlockHash()}; + if (!MarkBlockAsInFlight(peer_id, hash, &block_index)) return "Already requested from this peer"; + + // Construct message to request the block + std::vector invs{CInv(MSG_BLOCK, hash)}; + + // Send block request message to the peer + bool success = m_connman.ForNode(peer_id, [this, &invs](CNode* node) { + const CNetMsgMaker msgMaker(node->GetCommonVersion()); + this->m_connman.PushMessage(node, msgMaker.Make(NetMsgType::GETDATA, invs)); + return true; + }); + + if (!success) return "Peer not fully connected"; + + LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", + hash.ToString(), peer_id); + return std::nullopt; +} + std::unique_ptr PeerManager::make(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman, BanMan* banman, CScheduler &scheduler, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, diff --git a/src/net_processing.h b/src/net_processing.h index 8c575a3e64..4edf1f371e 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -66,6 +66,15 @@ public: const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); virtual ~PeerManager() { } + /** + * Attempt to manually fetch block from a given peer. We must already have the header. + * + * @param[in] peer_id The peer id + * @param[in] block_index The blockindex + * @returns std::nullopt if a request was successfully made, otherwise an error message + */ + virtual std::optional FetchBlock(NodeId peer_id, const CBlockIndex& block_index) = 0; + /** Get statistics from node state */ virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const = 0; diff --git a/src/rest.cpp b/src/rest.cpp index 2bc53cb16b..3ba29564fe 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 49b39817f1..3b2874b910 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -29,6 +31,7 @@ #include #include #include +#include #include #include