aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/rawtransaction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc/rawtransaction.cpp')
-rw-r--r--src/rpc/rawtransaction.cpp69
1 files changed, 59 insertions, 10 deletions
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 7bdf09812b..0cb34a0cca 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -7,6 +7,7 @@
#include <coins.h>
#include <consensus/validation.h>
#include <core_io.h>
+#include <index/txindex.h>
#include <init.h>
#include <keystore.h>
#include <validation.h>
@@ -47,6 +48,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags());
if (!hashBlock.IsNull()) {
+ LOCK(cs_main);
+
entry.pushKV("blockhash", hashBlock.GetHex());
CBlockIndex* pindex = LookupBlockIndex(hashBlock);
if (pindex) {
@@ -141,8 +144,6 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
+ HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"")
);
- LOCK(cs_main);
-
bool in_active_chain = true;
uint256 hash = ParseHashV(request.params[0], "parameter 1");
CBlockIndex* blockindex = nullptr;
@@ -159,6 +160,8 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
}
if (!request.params[2].isNull()) {
+ LOCK(cs_main);
+
uint256 blockhash = ParseHashV(request.params[2], "parameter 3");
blockindex = LookupBlockIndex(blockhash);
if (!blockindex) {
@@ -167,6 +170,11 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
in_active_chain = chainActive.Contains(blockindex);
}
+ bool f_txindex_ready = false;
+ if (g_txindex && !blockindex) {
+ f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
+ }
+
CTransactionRef tx;
uint256 hash_block;
if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) {
@@ -176,10 +184,12 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
throw JSONRPCError(RPC_MISC_ERROR, "Block not available");
}
errmsg = "No such transaction found in the provided block";
+ } else if (!g_txindex) {
+ errmsg = "No such mempool transaction. Use -txindex to enable blockchain transaction queries";
+ } else if (!f_txindex_ready) {
+ errmsg = "No such mempool transaction. Blockchain transactions are still in the process of being indexed";
} else {
- errmsg = fTxIndex
- ? "No such mempool or blockchain transaction"
- : "No such mempool transaction. Use -txindex to enable blockchain transaction queries";
+ errmsg = "No such mempool or blockchain transaction";
}
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions.");
}
@@ -229,19 +239,18 @@ UniValue gettxoutproof(const JSONRPCRequest& request)
oneTxid = hash;
}
- LOCK(cs_main);
-
CBlockIndex* pblockindex = nullptr;
-
uint256 hashBlock;
- if (!request.params[1].isNull())
- {
+ if (!request.params[1].isNull()) {
+ LOCK(cs_main);
hashBlock = uint256S(request.params[1].get_str());
pblockindex = LookupBlockIndex(hashBlock);
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
} else {
+ LOCK(cs_main);
+
// Loop through txids and try to find which block they're in. Exit loop once a block is found.
for (const auto& tx : setTxids) {
const Coin& coin = AccessByTxid(*pcoinsTip, tx);
@@ -252,6 +261,14 @@ UniValue gettxoutproof(const JSONRPCRequest& request)
}
}
+
+ // Allow txindex to catch up if we need to query it and before we acquire cs_main.
+ if (g_txindex && !pblockindex) {
+ g_txindex->BlockUntilSyncedToCurrentChain();
+ }
+
+ LOCK(cs_main);
+
if (pblockindex == nullptr)
{
CTransactionRef tx;
@@ -597,6 +614,38 @@ UniValue decodescript(const JSONRPCRequest& request)
// P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
// don't return the address for a P2SH of the P2SH.
r.pushKV("p2sh", EncodeDestination(CScriptID(script)));
+ // P2SH and witness programs cannot be wrapped in P2WSH, if this script
+ // is a witness program, don't return addresses for a segwit programs.
+ if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") {
+ txnouttype which_type;
+ std::vector<std::vector<unsigned char>> solutions_data;
+ Solver(script, which_type, solutions_data);
+ // Uncompressed pubkeys cannot be used with segwit checksigs.
+ // If the script contains an uncompressed pubkey, skip encoding of a segwit program.
+ if ((which_type == TX_PUBKEY) || (which_type == TX_MULTISIG)) {
+ for (const auto& solution : solutions_data) {
+ if ((solution.size() != 1) && !CPubKey(solution).IsCompressed()) {
+ return r;
+ }
+ }
+ }
+ UniValue sr(UniValue::VOBJ);
+ CScript segwitScr;
+ if (which_type == TX_PUBKEY) {
+ segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0].begin(), solutions_data[0].end())));
+ } else if (which_type == TX_PUBKEYHASH) {
+ segwitScr = GetScriptForDestination(WitnessV0KeyHash(solutions_data[0]));
+ } else {
+ // Scripts that are not fit for P2WPKH are encoded as P2WSH.
+ // Newer segwit program versions should be considered when then become available.
+ uint256 scriptHash;
+ CSHA256().Write(script.data(), script.size()).Finalize(scriptHash.begin());
+ segwitScr = GetScriptForDestination(WitnessV0ScriptHash(scriptHash));
+ }
+ ScriptPubKeyToUniv(segwitScr, sr, true);
+ sr.pushKV("p2sh-segwit", EncodeDestination(CScriptID(segwitScr)));
+ r.pushKV("segwit", sr);
+ }
}
return r;