1.1.0
This commit is contained in:
22
src/node/README.md
Normal file
22
src/node/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# src/node/
|
||||
|
||||
The [`src/node/`](./) directory contains code that needs to access node state
|
||||
(state in `CChain`, `CBlockIndex`, `CCoinsView`, `CTxMemPool`, and similar
|
||||
classes).
|
||||
|
||||
Code in [`src/node/`](./) is meant to be segregated from code in
|
||||
[`src/wallet/`](../wallet/) and [`src/qt/`](../qt/), to ensure wallet and GUI
|
||||
code changes don't interfere with node operation, to allow wallet and GUI code
|
||||
to run in separate processes, and to perhaps eventually allow wallet and GUI
|
||||
code to be maintained in separate source repositories.
|
||||
|
||||
As a rule of thumb, code in one of the [`src/node/`](./),
|
||||
[`src/wallet/`](../wallet/), or [`src/qt/`](../qt/) directories should avoid
|
||||
calling code in the other directories directly, and only invoke it indirectly
|
||||
through the more limited [`src/interfaces/`](../interfaces/) classes.
|
||||
|
||||
The [`src/node/`](./) directory is a new directory introduced in
|
||||
[#14978](https://github.com/palladium/palladium/pull/14978) and at the moment is
|
||||
sparsely populated. Eventually more substantial files like
|
||||
[`src/validation.cpp`](../validation.cpp) and
|
||||
[`src/txmempool.cpp`](../txmempool.cpp) might be moved there.
|
||||
23
src/node/coin.cpp
Normal file
23
src/node/coin.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <node/coin.h>
|
||||
|
||||
#include <node/context.h>
|
||||
#include <txmempool.h>
|
||||
#include <validation.h>
|
||||
|
||||
void FindCoins(const NodeContext& node, std::map<COutPoint, Coin>& coins)
|
||||
{
|
||||
assert(node.mempool);
|
||||
LOCK2(cs_main, node.mempool->cs);
|
||||
CCoinsViewCache& chain_view = ::ChainstateActive().CoinsTip();
|
||||
CCoinsViewMemPool mempool_view(&chain_view, *node.mempool);
|
||||
for (auto& coin : coins) {
|
||||
if (!mempool_view.GetCoin(coin.first, coin.second)) {
|
||||
// Either the coin is not in the CCoinsViewCache or is spent. Clear it.
|
||||
coin.second.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/node/coin.h
Normal file
24
src/node/coin.h
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef PALLADIUM_NODE_COIN_H
|
||||
#define PALLADIUM_NODE_COIN_H
|
||||
|
||||
#include <map>
|
||||
|
||||
class COutPoint;
|
||||
class Coin;
|
||||
struct NodeContext;
|
||||
|
||||
/**
|
||||
* Look up unspent output information. Returns coins in the mempool and in the
|
||||
* current chain UTXO set. Iterates through all the keys in the map and
|
||||
* populates the values.
|
||||
*
|
||||
* @param[in] node The node context to use for lookup
|
||||
* @param[in,out] coins map to fill
|
||||
*/
|
||||
void FindCoins(const NodeContext& node, std::map<COutPoint, Coin>& coins);
|
||||
|
||||
#endif // PALLADIUM_NODE_COIN_H
|
||||
73
src/node/coinstats.cpp
Normal file
73
src/node/coinstats.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <node/coinstats.h>
|
||||
|
||||
#include <coins.h>
|
||||
#include <hash.h>
|
||||
#include <serialize.h>
|
||||
#include <validation.h>
|
||||
#include <uint256.h>
|
||||
#include <util/system.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
|
||||
{
|
||||
assert(!outputs.empty());
|
||||
ss << hash;
|
||||
ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase ? 1u : 0u);
|
||||
stats.nTransactions++;
|
||||
for (const auto& output : outputs) {
|
||||
ss << VARINT(output.first + 1);
|
||||
ss << output.second.out.scriptPubKey;
|
||||
ss << VARINT_MODE(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
|
||||
stats.nTransactionOutputs++;
|
||||
stats.nTotalAmount += output.second.out.nValue;
|
||||
stats.nBogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ +
|
||||
2 /* scriptPubKey len */ + output.second.out.scriptPubKey.size() /* scriptPubKey */;
|
||||
}
|
||||
ss << VARINT(0u);
|
||||
}
|
||||
|
||||
//! Calculate statistics about the unspent transaction output set
|
||||
bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
|
||||
{
|
||||
stats = CCoinsStats();
|
||||
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
|
||||
assert(pcursor);
|
||||
|
||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||
stats.hashBlock = pcursor->GetBestBlock();
|
||||
{
|
||||
LOCK(cs_main);
|
||||
stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight;
|
||||
}
|
||||
ss << stats.hashBlock;
|
||||
uint256 prevkey;
|
||||
std::map<uint32_t, Coin> outputs;
|
||||
while (pcursor->Valid()) {
|
||||
COutPoint key;
|
||||
Coin coin;
|
||||
if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
|
||||
if (!outputs.empty() && key.hash != prevkey) {
|
||||
ApplyStats(stats, ss, prevkey, outputs);
|
||||
outputs.clear();
|
||||
}
|
||||
prevkey = key.hash;
|
||||
outputs[key.n] = std::move(coin);
|
||||
stats.coins_count++;
|
||||
} else {
|
||||
return error("%s: unable to read value", __func__);
|
||||
}
|
||||
pcursor->Next();
|
||||
}
|
||||
if (!outputs.empty()) {
|
||||
ApplyStats(stats, ss, prevkey, outputs);
|
||||
}
|
||||
stats.hashSerialized = ss.GetHash();
|
||||
stats.nDiskSize = view->EstimateSize();
|
||||
return true;
|
||||
}
|
||||
34
src/node/coinstats.h
Normal file
34
src/node/coinstats.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef PALLADIUM_NODE_COINSTATS_H
|
||||
#define PALLADIUM_NODE_COINSTATS_H
|
||||
|
||||
#include <amount.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class CCoinsView;
|
||||
|
||||
struct CCoinsStats
|
||||
{
|
||||
int nHeight{0};
|
||||
uint256 hashBlock{};
|
||||
uint64_t nTransactions{0};
|
||||
uint64_t nTransactionOutputs{0};
|
||||
uint64_t nBogoSize{0};
|
||||
uint256 hashSerialized{};
|
||||
uint64_t nDiskSize{0};
|
||||
CAmount nTotalAmount{0};
|
||||
|
||||
//! The number of coins contained.
|
||||
uint64_t coins_count{0};
|
||||
};
|
||||
|
||||
//! Calculate statistics about the unspent transaction output set
|
||||
bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats);
|
||||
|
||||
#endif // PALLADIUM_NODE_COINSTATS_H
|
||||
14
src/node/context.cpp
Normal file
14
src/node/context.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <node/context.h>
|
||||
|
||||
#include <banman.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <net.h>
|
||||
#include <net_processing.h>
|
||||
#include <scheduler.h>
|
||||
|
||||
NodeContext::NodeContext() {}
|
||||
NodeContext::~NodeContext() {}
|
||||
47
src/node/context.h
Normal file
47
src/node/context.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef PALLADIUM_NODE_CONTEXT_H
|
||||
#define PALLADIUM_NODE_CONTEXT_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class BanMan;
|
||||
class CConnman;
|
||||
class CScheduler;
|
||||
class CTxMemPool;
|
||||
class PeerLogicValidation;
|
||||
namespace interfaces {
|
||||
class Chain;
|
||||
class ChainClient;
|
||||
} // namespace interfaces
|
||||
|
||||
//! NodeContext struct containing references to chain state and connection
|
||||
//! state.
|
||||
//!
|
||||
//! This is used by init, rpc, and test code to pass object references around
|
||||
//! without needing to declare the same variables and parameters repeatedly, or
|
||||
//! to use globals. More variables could be added to this struct (particularly
|
||||
//! references to validation objects) to eliminate use of globals
|
||||
//! and make code more modular and testable. The struct isn't intended to have
|
||||
//! any member functions. It should just be a collection of references that can
|
||||
//! be used without pulling in unwanted dependencies or functionality.
|
||||
struct NodeContext {
|
||||
std::unique_ptr<CConnman> connman;
|
||||
CTxMemPool* mempool{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
|
||||
std::unique_ptr<PeerLogicValidation> peer_logic;
|
||||
std::unique_ptr<BanMan> banman;
|
||||
std::unique_ptr<interfaces::Chain> chain;
|
||||
std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
|
||||
std::unique_ptr<CScheduler> scheduler;
|
||||
|
||||
//! Declare default constructor and destructor that are not inline, so code
|
||||
//! instantiating the NodeContext struct doesn't need to #include class
|
||||
//! definitions for all the unique_ptr members.
|
||||
NodeContext();
|
||||
~NodeContext();
|
||||
};
|
||||
|
||||
#endif // PALLADIUM_NODE_CONTEXT_H
|
||||
147
src/node/psbt.cpp
Normal file
147
src/node/psbt.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright (c) 2009-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <amount.h>
|
||||
#include <coins.h>
|
||||
#include <consensus/tx_verify.h>
|
||||
#include <node/psbt.h>
|
||||
#include <policy/policy.h>
|
||||
#include <policy/settings.h>
|
||||
#include <tinyformat.h>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
||||
{
|
||||
// Go through each input and build status
|
||||
PSBTAnalysis result;
|
||||
|
||||
bool calc_fee = true;
|
||||
|
||||
CAmount in_amt = 0;
|
||||
|
||||
result.inputs.resize(psbtx.tx->vin.size());
|
||||
|
||||
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
|
||||
PSBTInput& input = psbtx.inputs[i];
|
||||
PSBTInputAnalysis& input_analysis = result.inputs[i];
|
||||
|
||||
// We set next role here and ratchet backwards as required
|
||||
input_analysis.next = PSBTRole::EXTRACTOR;
|
||||
|
||||
// Check for a UTXO
|
||||
CTxOut utxo;
|
||||
if (psbtx.GetInputUTXO(utxo, i)) {
|
||||
if (!MoneyRange(utxo.nValue) || !MoneyRange(in_amt + utxo.nValue)) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
|
||||
return result;
|
||||
}
|
||||
in_amt += utxo.nValue;
|
||||
input_analysis.has_utxo = true;
|
||||
} else {
|
||||
if (input.non_witness_utxo && psbtx.tx->vin[i].prevout.n >= input.non_witness_utxo->vout.size()) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u specifies invalid prevout", i));
|
||||
return result;
|
||||
}
|
||||
input_analysis.has_utxo = false;
|
||||
input_analysis.is_final = false;
|
||||
input_analysis.next = PSBTRole::UPDATER;
|
||||
calc_fee = false;
|
||||
}
|
||||
|
||||
if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Input %u spends unspendable output", i));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if it is final
|
||||
if (!utxo.IsNull() && !PSBTInputSigned(input)) {
|
||||
input_analysis.is_final = false;
|
||||
|
||||
// Figure out what is missing
|
||||
SignatureData outdata;
|
||||
bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, &outdata);
|
||||
|
||||
// Things are missing
|
||||
if (!complete) {
|
||||
input_analysis.missing_pubkeys = outdata.missing_pubkeys;
|
||||
input_analysis.missing_redeem_script = outdata.missing_redeem_script;
|
||||
input_analysis.missing_witness_script = outdata.missing_witness_script;
|
||||
input_analysis.missing_sigs = outdata.missing_sigs;
|
||||
|
||||
// If we are only missing signatures and nothing else, then next is signer
|
||||
if (outdata.missing_pubkeys.empty() && outdata.missing_redeem_script.IsNull() && outdata.missing_witness_script.IsNull() && !outdata.missing_sigs.empty()) {
|
||||
input_analysis.next = PSBTRole::SIGNER;
|
||||
} else {
|
||||
input_analysis.next = PSBTRole::UPDATER;
|
||||
}
|
||||
} else {
|
||||
input_analysis.next = PSBTRole::FINALIZER;
|
||||
}
|
||||
} else if (!utxo.IsNull()){
|
||||
input_analysis.is_final = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
|
||||
result.next = PSBTRole::EXTRACTOR;
|
||||
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
|
||||
PSBTInputAnalysis& input_analysis = result.inputs[i];
|
||||
result.next = std::min(result.next, input_analysis.next);
|
||||
}
|
||||
assert(result.next > PSBTRole::CREATOR);
|
||||
|
||||
if (calc_fee) {
|
||||
// Get the output amount
|
||||
CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0),
|
||||
[](CAmount a, const CTxOut& b) {
|
||||
if (!MoneyRange(a) || !MoneyRange(b.nValue) || !MoneyRange(a + b.nValue)) {
|
||||
return CAmount(-1);
|
||||
}
|
||||
return a += b.nValue;
|
||||
}
|
||||
);
|
||||
if (!MoneyRange(out_amt)) {
|
||||
result.SetInvalid(strprintf("PSBT is not valid. Output amount invalid"));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the fee
|
||||
CAmount fee = in_amt - out_amt;
|
||||
result.fee = fee;
|
||||
|
||||
// Estimate the size
|
||||
CMutableTransaction mtx(*psbtx.tx);
|
||||
CCoinsView view_dummy;
|
||||
CCoinsViewCache view(&view_dummy);
|
||||
bool success = true;
|
||||
|
||||
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
|
||||
PSBTInput& input = psbtx.inputs[i];
|
||||
Coin newcoin;
|
||||
|
||||
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !psbtx.GetInputUTXO(newcoin.out, i)) {
|
||||
success = false;
|
||||
break;
|
||||
} else {
|
||||
mtx.vin[i].scriptSig = input.final_script_sig;
|
||||
mtx.vin[i].scriptWitness = input.final_script_witness;
|
||||
newcoin.nHeight = 1;
|
||||
view.AddCoin(psbtx.tx->vin[i].prevout, std::move(newcoin), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
CTransaction ctx = CTransaction(mtx);
|
||||
size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
|
||||
result.estimated_vsize = size;
|
||||
// Estimate fee rate
|
||||
CFeeRate feerate(fee, size);
|
||||
result.estimated_feerate = feerate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
54
src/node/psbt.h
Normal file
54
src/node/psbt.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2009-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef PALLADIUM_NODE_PSBT_H
|
||||
#define PALLADIUM_NODE_PSBT_H
|
||||
|
||||
#include <psbt.h>
|
||||
|
||||
/**
|
||||
* Holds an analysis of one input from a PSBT
|
||||
*/
|
||||
struct PSBTInputAnalysis {
|
||||
bool has_utxo; //!< Whether we have UTXO information for this input
|
||||
bool is_final; //!< Whether the input has all required information including signatures
|
||||
PSBTRole next; //!< Which of the BIP 174 roles needs to handle this input next
|
||||
|
||||
std::vector<CKeyID> missing_pubkeys; //!< Pubkeys whose BIP32 derivation path is missing
|
||||
std::vector<CKeyID> missing_sigs; //!< Pubkeys whose signatures are missing
|
||||
uint160 missing_redeem_script; //!< Hash160 of redeem script, if missing
|
||||
uint256 missing_witness_script; //!< SHA256 of witness script, if missing
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds the results of AnalyzePSBT (miscellaneous information about a PSBT)
|
||||
*/
|
||||
struct PSBTAnalysis {
|
||||
Optional<size_t> estimated_vsize; //!< Estimated weight of the transaction
|
||||
Optional<CFeeRate> estimated_feerate; //!< Estimated feerate (fee / weight) of the transaction
|
||||
Optional<CAmount> fee; //!< Amount of fee being paid by the transaction
|
||||
std::vector<PSBTInputAnalysis> inputs; //!< More information about the individual inputs of the transaction
|
||||
PSBTRole next; //!< Which of the BIP 174 roles needs to handle the transaction next
|
||||
std::string error; //!< Error message
|
||||
|
||||
void SetInvalid(std::string err_msg)
|
||||
{
|
||||
estimated_vsize = nullopt;
|
||||
estimated_feerate = nullopt;
|
||||
fee = nullopt;
|
||||
inputs.clear();
|
||||
next = PSBTRole::CREATOR;
|
||||
error = err_msg;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides helpful miscellaneous information about where a PSBT is in the signing workflow.
|
||||
*
|
||||
* @param[in] psbtx the PSBT to analyze
|
||||
* @return A PSBTAnalysis with information about the provided PSBT.
|
||||
*/
|
||||
PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx);
|
||||
|
||||
#endif // PALLADIUM_NODE_PSBT_H
|
||||
85
src/node/transaction.cpp
Normal file
85
src/node/transaction.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <consensus/validation.h>
|
||||
#include <net.h>
|
||||
#include <net_processing.h>
|
||||
#include <node/context.h>
|
||||
#include <validation.h>
|
||||
#include <validationinterface.h>
|
||||
#include <node/transaction.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback)
|
||||
{
|
||||
// BroadcastTransaction can be called by either sendrawtransaction RPC or wallet RPCs.
|
||||
// node.connman is assigned both before chain clients and before RPC server is accepting calls,
|
||||
// and reset after chain clients and RPC sever are stopped. node.connman should never be null here.
|
||||
assert(node.connman);
|
||||
assert(node.mempool);
|
||||
std::promise<void> promise;
|
||||
uint256 hashTx = tx->GetHash();
|
||||
bool callback_set = false;
|
||||
|
||||
{ // cs_main scope
|
||||
LOCK(cs_main);
|
||||
// If the transaction is already confirmed in the chain, don't do anything
|
||||
// and return early.
|
||||
CCoinsViewCache &view = ::ChainstateActive().CoinsTip();
|
||||
for (size_t o = 0; o < tx->vout.size(); o++) {
|
||||
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
|
||||
// IsSpent doesn't mean the coin is spent, it means the output doesn't exist.
|
||||
// So if the output does exist, then this transaction exists in the chain.
|
||||
if (!existingCoin.IsSpent()) return TransactionError::ALREADY_IN_CHAIN;
|
||||
}
|
||||
if (!node.mempool->exists(hashTx)) {
|
||||
// Transaction is not already in the mempool. Submit it.
|
||||
TxValidationState state;
|
||||
if (!AcceptToMemoryPool(*node.mempool, state, std::move(tx),
|
||||
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
|
||||
err_string = state.ToString();
|
||||
if (state.IsInvalid()) {
|
||||
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
|
||||
return TransactionError::MISSING_INPUTS;
|
||||
}
|
||||
return TransactionError::MEMPOOL_REJECTED;
|
||||
} else {
|
||||
return TransactionError::MEMPOOL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Transaction was accepted to the mempool.
|
||||
|
||||
if (wait_callback) {
|
||||
// For transactions broadcast from outside the wallet, make sure
|
||||
// that the wallet has been notified of the transaction before
|
||||
// continuing.
|
||||
//
|
||||
// This prevents a race where a user might call sendrawtransaction
|
||||
// with a transaction to/from their wallet, immediately call some
|
||||
// wallet RPC, and get a stale result because callbacks have not
|
||||
// yet been processed.
|
||||
CallFunctionInValidationInterfaceQueue([&promise] {
|
||||
promise.set_value();
|
||||
});
|
||||
callback_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // cs_main
|
||||
|
||||
if (callback_set) {
|
||||
// Wait until Validation Interface clients have been notified of the
|
||||
// transaction entering the mempool.
|
||||
promise.get_future().wait();
|
||||
}
|
||||
|
||||
if (relay) {
|
||||
RelayTransaction(hashTx, *node.connman);
|
||||
}
|
||||
|
||||
return TransactionError::OK;
|
||||
}
|
||||
33
src/node/transaction.h
Normal file
33
src/node/transaction.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2017-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef PALLADIUM_NODE_TRANSACTION_H
|
||||
#define PALLADIUM_NODE_TRANSACTION_H
|
||||
|
||||
#include <attributes.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <util/error.h>
|
||||
|
||||
struct NodeContext;
|
||||
|
||||
/**
|
||||
* Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
|
||||
*
|
||||
* Mempool submission can be synchronous (will await mempool entry notification
|
||||
* over the CValidationInterface) or asynchronous (will submit and not wait for
|
||||
* notification), depending on the value of wait_callback. wait_callback MUST
|
||||
* NOT be set while cs_main, cs_mempool or cs_wallet are held to avoid
|
||||
* deadlock.
|
||||
*
|
||||
* @param[in] node reference to node context
|
||||
* @param[in] tx the transaction to broadcast
|
||||
* @param[out] err_string reference to std::string to fill with error string if available
|
||||
* @param[in] max_tx_fee reject txs with fees higher than this (if 0, accept any fee)
|
||||
* @param[in] relay flag if both mempool insertion and p2p relay are requested
|
||||
* @param[in] wait_callback wait until callbacks have been processed to avoid stale result due to a sequentially RPC.
|
||||
* return error
|
||||
*/
|
||||
NODISCARD TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
|
||||
|
||||
#endif // PALLADIUM_NODE_TRANSACTION_H
|
||||
50
src/node/utxo_snapshot.h
Normal file
50
src/node/utxo_snapshot.h
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2019 The Palladium Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef PALLADIUM_NODE_UTXO_SNAPSHOT_H
|
||||
#define PALLADIUM_NODE_UTXO_SNAPSHOT_H
|
||||
|
||||
#include <uint256.h>
|
||||
#include <serialize.h>
|
||||
|
||||
//! Metadata describing a serialized version of a UTXO set from which an
|
||||
//! assumeutxo CChainState can be constructed.
|
||||
class SnapshotMetadata
|
||||
{
|
||||
public:
|
||||
//! The hash of the block that reflects the tip of the chain for the
|
||||
//! UTXO set contained in this snapshot.
|
||||
uint256 m_base_blockhash;
|
||||
|
||||
//! The number of coins in the UTXO set contained in this snapshot. Used
|
||||
//! during snapshot load to estimate progress of UTXO set reconstruction.
|
||||
uint64_t m_coins_count = 0;
|
||||
|
||||
//! Necessary to "fake" the base nChainTx so that we can estimate progress during
|
||||
//! initial block download for the assumeutxo chainstate.
|
||||
unsigned int m_nchaintx = 0;
|
||||
|
||||
SnapshotMetadata() { }
|
||||
SnapshotMetadata(
|
||||
const uint256& base_blockhash,
|
||||
uint64_t coins_count,
|
||||
unsigned int nchaintx) :
|
||||
m_base_blockhash(base_blockhash),
|
||||
m_coins_count(coins_count),
|
||||
m_nchaintx(nchaintx) { }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(m_base_blockhash);
|
||||
READWRITE(m_coins_count);
|
||||
READWRITE(m_nchaintx);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // PALLADIUM_NODE_UTXO_SNAPSHOT_H
|
||||
Reference in New Issue
Block a user