mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge #6370: backport: merge bitcoin#23499, #23832, #24136, #24265, #23819, #23595, #24486, #15423, #24784, #24956, #25016, #25060 (auxiliary backports: part 21)
02320032c7
merge bitcoin#25060: add LIFETIMEBOUND to GetFirstStoredBlock()::start_time (Kittywhiskers Van Gogh)cfda9e5eb5
merge bitcoin#25016: GetFirstStoredBlock() and getblockchaininfo follow-ups (Kittywhiskers Van Gogh)99d028e9e1
merge bitcoin#24956: Call CHECK_NONFATAL only once where needed (Kittywhiskers Van Gogh)87b556d322
refactor: use loop to iterate through `SoftForkDescPushBack` args (Kittywhiskers Van Gogh)80615b8c01
merge bitcoin#24784: deduplicate integer serialization in RollingBloom benchmark (Kittywhiskers Van Gogh)092a11e2d1
merge bitcoin#15423: Query Tor for correct -onion configuration (Kittywhiskers Van Gogh)74dceb3c5c
merge bitcoin#24486: dedup sqlite blob binding (Kittywhiskers Van Gogh)aa945c2c1d
merge bitcoin#23595: Add ParseHex<std::byte>() helper (Kittywhiskers Van Gogh)c2defe7210
merge bitcoin#23819: don't serialize block hash twice (Kittywhiskers Van Gogh)9a8d6e149f
merge bitcoin#24265: Drop StripRedundantLastElementsOfPath() function (Kittywhiskers Van Gogh)2d299f128a
merge bitcoin#24136: Extract CTxIn::MAX_SEQUENCE_NONFINAL constant, rework BIP 65/68/112 docs (Kittywhiskers Van Gogh)9aacee78ae
merge bitcoin#23832: Changes time variables from int to chrono (Kittywhiskers Van Gogh)06bf649e1b
merge bitcoin#23499: Add interfaces::Node::broadCastTransaction method (Kittywhiskers Van Gogh) Pull request description: ## Breaking Changes None expected. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)** - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation **(note: N/A)** - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK02320032c7
Tree-SHA512: b633e1caac95e565d43e28cef7c915f65952fbabdf55624090bc587c75b84fc04474bb6cd8625219ba828da172391c3d2d1aa6db998927312055c82caaad7ba0
This commit is contained in:
commit
5dbe58c996
@ -76,7 +76,7 @@ bool BaseIndex::Init()
|
||||
if (!m_best_block_index) {
|
||||
// index is not built yet
|
||||
// make sure we have all block data back to the genesis
|
||||
prune_violation = GetFirstStoredBlock(active_chain.Tip()) != active_chain.Genesis();
|
||||
prune_violation = m_chainstate->m_blockman.GetFirstStoredBlock(*active_chain.Tip()) != active_chain.Genesis();
|
||||
}
|
||||
// in case the index has a best block set and is not fully synced
|
||||
// check if we have the required blocks to continue building the index
|
||||
|
@ -1470,7 +1470,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
||||
|
||||
// Warn about relative -datadir path.
|
||||
if (args.IsArgSet("-datadir") && !fs::PathFromString(args.GetArg("-datadir", "")).is_absolute()) {
|
||||
if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {
|
||||
LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
|
||||
"current working directory '%s'. This is fragile, because if Dash Core is started in the future "
|
||||
"from a different location, it will be unable to locate the current data files. There could "
|
||||
|
@ -35,6 +35,7 @@ class UniValue;
|
||||
class Proxy;
|
||||
struct bilingual_str;
|
||||
enum class SynchronizationState;
|
||||
enum class TransactionError;
|
||||
struct CNodeStateStats;
|
||||
struct NodeContext;
|
||||
|
||||
@ -264,6 +265,9 @@ public:
|
||||
//! Get unspent outputs associated with a transaction.
|
||||
virtual bool getUnspentOutput(const COutPoint& output, Coin& coin) = 0;
|
||||
|
||||
//! Broadcast transaction.
|
||||
virtual TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, bilingual_str& err_string) = 0;
|
||||
|
||||
//! Get wallet loader.
|
||||
virtual WalletLoader& walletLoader() = 0;
|
||||
|
||||
|
@ -348,11 +348,11 @@ bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
|
||||
return key.Derive(out.key, out.chaincode, _nChild, chaincode);
|
||||
}
|
||||
|
||||
void CExtKey::SetSeed(Span<const uint8_t> seed)
|
||||
void CExtKey::SetSeed(Span<const std::byte> seed)
|
||||
{
|
||||
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
|
||||
CHMAC_SHA512{hashkey, sizeof(hashkey)}.Write(seed.data(), seed.size()).Finalize(vout.data());
|
||||
CHMAC_SHA512{hashkey, sizeof(hashkey)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data());
|
||||
key.Set(vout.data(), vout.data() + 32, true);
|
||||
memcpy(chaincode.begin(), vout.data() + 32, 32);
|
||||
nDepth = 0;
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
|
||||
//! Simple read-only vector-like interface.
|
||||
unsigned int size() const { return (fValid ? keydata.size() : 0); }
|
||||
const unsigned char* data() const { return keydata.data(); }
|
||||
const std::byte* data() const { return reinterpret_cast<const std::byte*>(keydata.data()); }
|
||||
const unsigned char* begin() const { return keydata.data(); }
|
||||
const unsigned char* end() const { return keydata.data() + size(); }
|
||||
|
||||
@ -188,7 +188,7 @@ struct CExtKey {
|
||||
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
|
||||
bool Derive(CExtKey& out, unsigned int nChild) const;
|
||||
CExtPubKey Neuter() const;
|
||||
void SetSeed(Span<const uint8_t> seed);
|
||||
void SetSeed(Span<const std::byte> seed);
|
||||
};
|
||||
|
||||
/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
|
||||
|
@ -79,11 +79,11 @@ static constexpr int32_t MAX_PEER_OBJECT_IN_FLIGHT = 100;
|
||||
/** Maximum number of announced objects from a peer */
|
||||
static constexpr int32_t MAX_PEER_OBJECT_ANNOUNCEMENTS = 2 * MAX_INV_SZ;
|
||||
/** How many microseconds to delay requesting transactions from inbound peers */
|
||||
static constexpr std::chrono::microseconds INBOUND_PEER_TX_DELAY{std::chrono::seconds{2}};
|
||||
/** How long to wait (in microseconds) before downloading a transaction from an additional peer */
|
||||
static constexpr std::chrono::microseconds GETDATA_TX_INTERVAL{std::chrono::seconds{60}};
|
||||
/** Maximum delay (in microseconds) for transaction requests to avoid biasing some peers over others. */
|
||||
static constexpr std::chrono::microseconds MAX_GETDATA_RANDOM_DELAY{std::chrono::seconds{2}};
|
||||
static constexpr auto INBOUND_PEER_TX_DELAY{2s};
|
||||
/** How long to wait before downloading a transaction from an additional peer */
|
||||
static constexpr auto GETDATA_TX_INTERVAL{60s};
|
||||
/** Maximum delay for transaction requests to avoid biasing some peers over others. */
|
||||
static constexpr auto MAX_GETDATA_RANDOM_DELAY{2s};
|
||||
/** How long to wait (expiry * factor microseconds) before expiring an in-flight getdata request to a peer */
|
||||
static constexpr int64_t TX_EXPIRY_INTERVAL_FACTOR = 10;
|
||||
static_assert(INBOUND_PEER_TX_DELAY >= MAX_GETDATA_RANDOM_DELAY,
|
||||
@ -112,7 +112,7 @@ static constexpr auto STALE_CHECK_INTERVAL{150s}; // 2.5 minutes (~block interva
|
||||
/** How frequently to check for extra outbound peers and disconnect */
|
||||
static constexpr auto EXTRA_PEER_CHECK_INTERVAL{45s};
|
||||
/** Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict */
|
||||
static constexpr std::chrono::seconds MINIMUM_CONNECT_TIME{30};
|
||||
static constexpr auto MINIMUM_CONNECT_TIME{30s};
|
||||
/** SHA256("main address relay")[0:8] */
|
||||
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL;
|
||||
/// Age after which a stale block will no longer be served if requested as
|
||||
@ -122,7 +122,7 @@ static constexpr int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60;
|
||||
/// limiting block relay. Set to one week, denominated in seconds.
|
||||
static constexpr int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60;
|
||||
/** Time between pings automatically sent out for latency probing and keepalive */
|
||||
static constexpr std::chrono::minutes PING_INTERVAL{2};
|
||||
static constexpr auto PING_INTERVAL{2min};
|
||||
/** The maximum number of entries in a locator */
|
||||
static const unsigned int MAX_LOCATOR_SZ = 101;
|
||||
/** Number of blocks that can be requested at any given time from a single peer. */
|
||||
@ -153,17 +153,17 @@ static const int MAX_UNCONNECTING_HEADERS = 10;
|
||||
/** Minimum blocks required to signal NODE_NETWORK_LIMITED */
|
||||
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
|
||||
/** Average delay between local address broadcasts */
|
||||
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24h;
|
||||
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24h};
|
||||
/** Average delay between peer address broadcasts */
|
||||
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL = 30s;
|
||||
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL{30s};
|
||||
/** Average delay between trickled inventory transmissions for inbound peers.
|
||||
* Blocks and peers with NetPermissionFlags::NoBan permission bypass this. */
|
||||
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL = 5s;
|
||||
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL{5s};
|
||||
/** Average delay between trickled inventory transmissions for outbound peers.
|
||||
* Use a smaller delay as there is less privacy concern for them.
|
||||
* Blocks and peers with NetPermissionFlags::NoBan permission bypass this.
|
||||
* Masternode outbound peers get half this delay. */
|
||||
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL = 2s;
|
||||
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
|
||||
/** Maximum rate of inventory items to send per second.
|
||||
* Limits the impact of low-fee transaction floods.
|
||||
* We have 4 times smaller block times in Dash, so we need to push 4 times more invs per 1MB. */
|
||||
@ -459,7 +459,7 @@ struct CNodeState {
|
||||
* - its chain tip has at least as much work as ours
|
||||
*
|
||||
* CHAIN_SYNC_TIMEOUT: if a peer's best known block has less work than our tip,
|
||||
* set a timeout CHAIN_SYNC_TIMEOUT seconds in the future:
|
||||
* set a timeout CHAIN_SYNC_TIMEOUT in the future:
|
||||
* - If at timeout their best known block now has more work than our tip
|
||||
* when the timeout was set, then either reset the timeout or clear it
|
||||
* (after comparing against our current tip's work)
|
||||
@ -1479,11 +1479,11 @@ std::chrono::microseconds GetObjectInterval(int invType)
|
||||
switch(invType)
|
||||
{
|
||||
case MSG_QUORUM_RECOVERED_SIG:
|
||||
return std::chrono::seconds{15};
|
||||
return 15s;
|
||||
case MSG_CLSIG:
|
||||
return std::chrono::seconds{5};
|
||||
return 5s;
|
||||
case MSG_ISDLOCK:
|
||||
return std::chrono::seconds{10};
|
||||
return 10s;
|
||||
default:
|
||||
return GETDATA_TX_INTERVAL;
|
||||
}
|
||||
@ -1606,7 +1606,7 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
|
||||
|
||||
// Schedule next run for 10-15 minutes in the future.
|
||||
// We add randomness on every cycle to avoid the possibility of P2P fingerprinting.
|
||||
const std::chrono::milliseconds delta = std::chrono::minutes{10} + GetRandMillis(std::chrono::minutes{5});
|
||||
const std::chrono::milliseconds delta = 10min + GetRandMillis(5min);
|
||||
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
|
||||
}
|
||||
|
||||
@ -1709,7 +1709,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
|
||||
// since pingtime does not update until the ping is complete, which might take a while.
|
||||
// So, if a ping is taking an unusually long time in flight,
|
||||
// the caller can immediately detect that this is happening.
|
||||
std::chrono::microseconds ping_wait{0};
|
||||
auto ping_wait{0us};
|
||||
if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
|
||||
ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
|
||||
}
|
||||
@ -1955,7 +1955,7 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
|
||||
scheduler.scheduleEvery([this] { this->CheckForStaleTipAndEvictPeers(); }, std::chrono::seconds{EXTRA_PEER_CHECK_INTERVAL});
|
||||
|
||||
// schedule next run for 10-15 minutes in the future
|
||||
const std::chrono::milliseconds delta = std::chrono::minutes{10} + GetRandMillis(std::chrono::minutes{5});
|
||||
const std::chrono::milliseconds delta = 10min + GetRandMillis(5min);
|
||||
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
|
||||
}
|
||||
|
||||
@ -2566,10 +2566,10 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
|
||||
std::vector<CInv> vNotFound;
|
||||
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
|
||||
|
||||
const std::chrono::seconds now = GetTime<std::chrono::seconds>();
|
||||
const auto now{GetTime<std::chrono::seconds>()};
|
||||
// Get last mempool request time
|
||||
const std::chrono::seconds mempool_req = tx_relay != nullptr ? tx_relay->m_last_mempool_req.load()
|
||||
: std::chrono::seconds::min();
|
||||
const auto mempool_req = tx_relay != nullptr ? tx_relay->m_last_mempool_req.load()
|
||||
: std::chrono::seconds::min();
|
||||
|
||||
// Process as many TX items from the front of the getdata queue as
|
||||
// possible, since they're common and it's efficient to batch process
|
||||
@ -3868,7 +3868,7 @@ void PeerManagerImpl::ProcessMessage(
|
||||
int64_t nSince = nNow - 10 * 60;
|
||||
|
||||
// Update/increment addr rate limiting bucket.
|
||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||
const auto current_time{GetTime<std::chrono::microseconds>()};
|
||||
if (peer->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {
|
||||
// Don't increment bucket if it's already full
|
||||
const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
|
||||
@ -3963,7 +3963,7 @@ void PeerManagerImpl::ProcessMessage(
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||
const auto current_time{GetTime<std::chrono::microseconds>()};
|
||||
uint256* best_block{nullptr};
|
||||
|
||||
for (CInv& inv : vInv) {
|
||||
@ -4401,7 +4401,7 @@ void PeerManagerImpl::ProcessMessage(
|
||||
}
|
||||
}
|
||||
if (!fRejectedParents) {
|
||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||
const auto current_time{GetTime<std::chrono::microseconds>()};
|
||||
|
||||
for (const uint256& parent_txid : unique_parents) {
|
||||
CInv _inv(MSG_TX, parent_txid);
|
||||
@ -5659,7 +5659,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||
// If we get here, the outgoing message serialization version is set and can't change.
|
||||
const CNetMsgMaker msgMaker(pto->GetCommonVersion());
|
||||
|
||||
const auto current_time = GetTime<std::chrono::microseconds>();
|
||||
const auto current_time{GetTime<std::chrono::microseconds>()};
|
||||
|
||||
if (pto->IsAddrFetchConn() && current_time - pto->m_connected > 10 * AVG_ADDRESS_BROADCAST_INTERVAL) {
|
||||
LogPrint(BCLog::NET_NETCONN, "addrfetch connection timeout; disconnecting peer=%d\n", pto->GetId());
|
||||
|
@ -421,10 +421,10 @@ bool BlockManager::IsBlockPruned(const CBlockIndex* pblockindex)
|
||||
return (m_have_pruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0);
|
||||
}
|
||||
|
||||
const CBlockIndex* GetFirstStoredBlock(const CBlockIndex* start_block) {
|
||||
const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& start_block)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
assert(start_block);
|
||||
const CBlockIndex* last_block = start_block;
|
||||
const CBlockIndex* last_block = &start_block;
|
||||
while (last_block->pprev && (last_block->pprev->nStatus & BLOCK_HAVE_DATA)) {
|
||||
last_block = last_block->pprev;
|
||||
}
|
||||
|
@ -5,9 +5,10 @@
|
||||
#ifndef BITCOIN_NODE_BLOCKSTORAGE_H
|
||||
#define BITCOIN_NODE_BLOCKSTORAGE_H
|
||||
|
||||
#include <attributes.h>
|
||||
#include <chain.h>
|
||||
#include <fs.h>
|
||||
#include <protocol.h> // For CMessageHeader::MessageStartChars
|
||||
#include <protocol.h>
|
||||
#include <sync.h>
|
||||
#include <txdb.h>
|
||||
|
||||
@ -196,6 +197,9 @@ public:
|
||||
//! Returns last CBlockIndex* that is a checkpoint
|
||||
const CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
//! Find the first block that is not pruned
|
||||
const CBlockIndex* GetFirstStoredBlock(const CBlockIndex& start_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
/** True if any block files have ever been pruned. */
|
||||
bool m_have_pruned = false;
|
||||
|
||||
@ -206,9 +210,6 @@ public:
|
||||
void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
};
|
||||
|
||||
//! Find the first block that is not pruned
|
||||
const CBlockIndex* GetFirstStoredBlock(const CBlockIndex* start_block) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
void CleanupBlockRevFiles();
|
||||
|
||||
/** Open a block file (blk?????.dat) */
|
||||
|
@ -496,6 +496,10 @@ public:
|
||||
LOCK(::cs_main);
|
||||
return chainman().ActiveChainstate().CoinsTip().GetCoin(output, coin);
|
||||
}
|
||||
TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, bilingual_str& err_string) override
|
||||
{
|
||||
return BroadcastTransaction(*m_context, std::move(tx), err_string, max_tx_fee, /*relay=*/ true, /*wait_callback=*/ false);
|
||||
}
|
||||
WalletLoader& walletLoader() override
|
||||
{
|
||||
return *Assert(m_context->wallet_loader);
|
||||
|
@ -74,25 +74,45 @@ public:
|
||||
CScript scriptSig;
|
||||
uint32_t nSequence;
|
||||
|
||||
/* Setting nSequence to this value for every input in a transaction
|
||||
* disables nLockTime. */
|
||||
/**
|
||||
* Setting nSequence to this value for every input in a transaction
|
||||
* disables nLockTime/IsFinalTx().
|
||||
* It fails OP_CHECKLOCKTIMEVERIFY/CheckLockTime() for any input that has
|
||||
* it set (BIP 65).
|
||||
* It has SEQUENCE_LOCKTIME_DISABLE_FLAG set (BIP 68/112).
|
||||
*/
|
||||
static const uint32_t SEQUENCE_FINAL = 0xffffffff;
|
||||
/**
|
||||
* This is the maximum sequence number that enables both nLockTime and
|
||||
* OP_CHECKLOCKTIMEVERIFY (BIP 65).
|
||||
* It has SEQUENCE_LOCKTIME_DISABLE_FLAG set (BIP 68/112).
|
||||
*/
|
||||
static const uint32_t MAX_SEQUENCE_NONFINAL{SEQUENCE_FINAL - 1};
|
||||
|
||||
/* Below flags apply in the context of BIP 68*/
|
||||
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
|
||||
* relative lock-time. */
|
||||
// Below flags apply in the context of BIP 68. BIP 68 requires the tx
|
||||
// version to be set to 2, or higher.
|
||||
/**
|
||||
* If this flag is set, CTxIn::nSequence is NOT interpreted as a
|
||||
* relative lock-time.
|
||||
* It skips SequenceLocks() for any input that has it set (BIP 68).
|
||||
* It fails OP_CHECKSEQUENCEVERIFY/CheckSequence() for any input that has
|
||||
* it set (BIP 112).
|
||||
*/
|
||||
static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1U << 31);
|
||||
|
||||
/* If CTxIn::nSequence encodes a relative lock-time and this flag
|
||||
/**
|
||||
* If CTxIn::nSequence encodes a relative lock-time and this flag
|
||||
* is set, the relative lock-time has units of 512 seconds,
|
||||
* otherwise it specifies blocks with a granularity of 1. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
|
||||
|
||||
/* If CTxIn::nSequence encodes a relative lock-time, this mask is
|
||||
/**
|
||||
* If CTxIn::nSequence encodes a relative lock-time, this mask is
|
||||
* applied to extract that lock-time from the sequence field. */
|
||||
static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
|
||||
|
||||
/* In order to use the same number of bits to encode roughly the
|
||||
/**
|
||||
* In order to use the same number of bits to encode roughly the
|
||||
* same wall-clock duration, and because blocks are naturally
|
||||
* limited to occur every 600s on average, the minimum granularity
|
||||
* for time-based relative lock-time is fixed at 512 seconds.
|
||||
|
@ -108,8 +108,8 @@ void PSBTOperationsDialog::broadcastTransaction()
|
||||
|
||||
CTransactionRef tx = MakeTransactionRef(mtx);
|
||||
bilingual_str err_string;
|
||||
TransactionError error = BroadcastTransaction(
|
||||
*m_client_model->node().context(), tx, err_string, DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true, /* await_callback */ false);
|
||||
TransactionError error =
|
||||
m_client_model->node().broadcastTransaction(tx, DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), err_string);
|
||||
|
||||
if (error == TransactionError::OK) {
|
||||
showStatus(tr("Transaction broadcast successfully! Transaction ID: %1")
|
||||
|
@ -1335,8 +1335,9 @@ static RPCHelpMan pruneblockchain()
|
||||
CChain& active_chain = active_chainstate.m_chain;
|
||||
|
||||
int heightParam = request.params[0].get_int();
|
||||
if (heightParam < 0)
|
||||
if (heightParam < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative block height.");
|
||||
}
|
||||
|
||||
// Height value more than a billion is too high to be a block height, and
|
||||
// too low to be a block time (corresponds to timestamp from Sep 2001).
|
||||
@ -1361,8 +1362,8 @@ static RPCHelpMan pruneblockchain()
|
||||
}
|
||||
|
||||
PruneBlockFilesManual(active_chainstate, height);
|
||||
const CBlockIndex* block = CHECK_NONFATAL(active_chain.Tip());
|
||||
const CBlockIndex* last_block = GetFirstStoredBlock(block);
|
||||
const CBlockIndex& block{*CHECK_NONFATAL(active_chain.Tip())};
|
||||
const CBlockIndex* last_block{active_chainstate.m_blockman.GetFirstStoredBlock(block)};
|
||||
|
||||
return static_cast<uint64_t>(last_block->nHeight);
|
||||
},
|
||||
@ -1782,10 +1783,10 @@ RPCHelpMan getblockchaininfo()
|
||||
LOCK(cs_main);
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
|
||||
const CBlockIndex* tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
|
||||
const int height = tip->nHeight;
|
||||
const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
|
||||
const int height{tip.nHeight};
|
||||
|
||||
const auto ehfSignals = CHECK_NONFATAL(node.mnhf_manager)->GetSignalsStage(tip);
|
||||
const auto ehfSignals{CHECK_NONFATAL(node.mnhf_manager)->GetSignalsStage(&tip)};
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
if (args.IsArgSet("-devnet")) {
|
||||
@ -1795,18 +1796,17 @@ RPCHelpMan getblockchaininfo()
|
||||
}
|
||||
obj.pushKV("blocks", height);
|
||||
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
|
||||
obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
|
||||
obj.pushKV("difficulty", (double)GetDifficulty(tip));
|
||||
obj.pushKV("time", (int64_t)tip->nTime);
|
||||
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
|
||||
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
|
||||
obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
|
||||
obj.pushKV("difficulty", GetDifficulty(&tip));
|
||||
obj.pushKV("time", tip.GetBlockTime());
|
||||
obj.pushKV("mediantime", tip.GetMedianTimePast());
|
||||
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), &tip));
|
||||
obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload());
|
||||
obj.pushKV("chainwork", tip->nChainWork.GetHex());
|
||||
obj.pushKV("chainwork", tip.nChainWork.GetHex());
|
||||
obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
|
||||
obj.pushKV("pruned", fPruneMode);
|
||||
if (fPruneMode) {
|
||||
const CBlockIndex* block = CHECK_NONFATAL(tip);
|
||||
obj.pushKV("pruneheight", GetFirstStoredBlock(block)->nHeight);
|
||||
obj.pushKV("pruneheight", chainman.m_blockman.GetFirstStoredBlock(tip)->nHeight);
|
||||
|
||||
// if 0, execution bypasses the whole if block.
|
||||
bool automatic_pruning{args.GetArg("-prune", 0) != 1};
|
||||
@ -1818,24 +1818,28 @@ RPCHelpMan getblockchaininfo()
|
||||
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
UniValue softforks(UniValue::VOBJ);
|
||||
// sorted by activation block
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_BIP147);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CSV);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DIP0001);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DIP0003);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DIP0008);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DIP0020);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DIP0024);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_BRR);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_V19);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_V20);
|
||||
SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_MN_RR);
|
||||
SoftForkDescPushBack(tip, ehfSignals, softforks, consensusParams, Consensus::DEPLOYMENT_WITHDRAWALS);
|
||||
SoftForkDescPushBack(tip, ehfSignals, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
|
||||
for (auto deploy : { /* sorted by activation block */
|
||||
Consensus::DEPLOYMENT_HEIGHTINCB,
|
||||
Consensus::DEPLOYMENT_DERSIG,
|
||||
Consensus::DEPLOYMENT_CLTV,
|
||||
Consensus::DEPLOYMENT_BIP147,
|
||||
Consensus::DEPLOYMENT_CSV,
|
||||
Consensus::DEPLOYMENT_DIP0001,
|
||||
Consensus::DEPLOYMENT_DIP0003,
|
||||
Consensus::DEPLOYMENT_DIP0008,
|
||||
Consensus::DEPLOYMENT_DIP0020,
|
||||
Consensus::DEPLOYMENT_DIP0024,
|
||||
Consensus::DEPLOYMENT_BRR,
|
||||
Consensus::DEPLOYMENT_V19,
|
||||
Consensus::DEPLOYMENT_V20,
|
||||
Consensus::DEPLOYMENT_MN_RR }) {
|
||||
SoftForkDescPushBack(&tip, softforks, consensusParams, deploy);
|
||||
}
|
||||
for (auto ehf_deploy : { /* sorted by activation block */
|
||||
Consensus::DEPLOYMENT_WITHDRAWALS,
|
||||
Consensus::DEPLOYMENT_TESTDUMMY }) {
|
||||
SoftForkDescPushBack(&tip, ehfSignals, softforks, consensusParams, ehf_deploy);
|
||||
}
|
||||
obj.pushKV("softforks", softforks);
|
||||
|
||||
obj.pushKV("warnings", GetWarnings(false).original);
|
||||
|
@ -58,7 +58,12 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
|
||||
if (nOutput < 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
|
||||
|
||||
uint32_t nSequence = (rawTx.nLockTime ? CTxIn::SEQUENCE_FINAL - 1 : CTxIn::SEQUENCE_FINAL);
|
||||
uint32_t nSequence;
|
||||
if (rawTx.nLockTime) {
|
||||
nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; /* CTxIn::SEQUENCE_FINAL - 1 */
|
||||
} else {
|
||||
nSequence = CTxIn::SEQUENCE_FINAL;
|
||||
}
|
||||
|
||||
// set the sequence number if passed in the parameters object
|
||||
const UniValue& sequenceObj = find_value(o, "sequence");
|
||||
|
@ -120,11 +120,12 @@ const std::vector<std::string> TEST5 = {
|
||||
"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL"
|
||||
};
|
||||
|
||||
void RunTest(const TestVector &test) {
|
||||
std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
|
||||
void RunTest(const TestVector& test)
|
||||
{
|
||||
std::vector<std::byte> seed{ParseHex<std::byte>(test.strHexMaster)};
|
||||
CExtKey key;
|
||||
CExtPubKey pubkey;
|
||||
key.SetSeed(seed);
|
||||
key.SetSeed(MakeByteSpan(seed));
|
||||
pubkey = key.Neuter();
|
||||
for (const TestDerivation &derive : test.vDerive) {
|
||||
unsigned char data[74];
|
||||
|
@ -348,7 +348,7 @@ uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||
return fuzzed_data_provider.ConsumeBool() ?
|
||||
fuzzed_data_provider.PickValueInArray({
|
||||
CTxIn::SEQUENCE_FINAL,
|
||||
CTxIn::SEQUENCE_FINAL - 1
|
||||
CTxIn::MAX_SEQUENCE_NONFINAL,
|
||||
}) :
|
||||
fuzzed_data_provider.ConsumeIntegral<uint32_t>();
|
||||
}
|
||||
|
@ -153,6 +153,98 @@ BOOST_AUTO_TEST_CASE(intarg)
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetArg("-bar", 11), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(patharg)
|
||||
{
|
||||
const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY);
|
||||
SetupArgs({dir});
|
||||
ResetArgs("");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{});
|
||||
|
||||
const fs::path root_path{"/"};
|
||||
ResetArgs("-dir=/");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
|
||||
|
||||
ResetArgs("-dir=/.");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
|
||||
|
||||
ResetArgs("-dir=/./");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
|
||||
|
||||
ResetArgs("-dir=/.//");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
|
||||
|
||||
#ifdef WIN32
|
||||
const fs::path win_root_path{"C:\\"};
|
||||
ResetArgs("-dir=C:\\");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
|
||||
|
||||
ResetArgs("-dir=C:/");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
|
||||
|
||||
ResetArgs("-dir=C:\\\\");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
|
||||
|
||||
ResetArgs("-dir=C:\\.");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
|
||||
|
||||
ResetArgs("-dir=C:\\.\\");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
|
||||
|
||||
ResetArgs("-dir=C:\\.\\\\");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
|
||||
#endif
|
||||
|
||||
const fs::path absolute_path{"/home/user/.bitcoin"};
|
||||
ResetArgs("-dir=/home/user/.bitcoin");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/root/../home/user/.bitcoin");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/home/./user/.bitcoin");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/home/user/.bitcoin/");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/home/user/.bitcoin//");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/home/user/.bitcoin/.");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/home/user/.bitcoin/./");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
ResetArgs("-dir=/home/user/.bitcoin/.//");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
|
||||
|
||||
const fs::path relative_path{"user/.bitcoin"};
|
||||
ResetArgs("-dir=user/.bitcoin");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=somewhere/../user/.bitcoin");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=user/./.bitcoin");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=user/.bitcoin/");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=user/.bitcoin//");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=user/.bitcoin/.");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=user/.bitcoin/./");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
|
||||
ResetArgs("-dir=user/.bitcoin/.//");
|
||||
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(doubledash)
|
||||
{
|
||||
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
|
||||
|
@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_parse)
|
||||
continue;
|
||||
}
|
||||
std::string exp_base58string = test[0].get_str();
|
||||
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
|
||||
const std::vector<std::byte> exp_payload{ParseHex<std::byte>(test[1].get_str())};
|
||||
const UniValue &metadata = test[2].get_obj();
|
||||
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
|
||||
SelectParams(find_value(metadata, "chain").get_str());
|
||||
|
@ -478,7 +478,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
|
||||
// absolute height locked
|
||||
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
|
||||
tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
|
||||
tx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL;
|
||||
prevheights[0] = baseheight + 3;
|
||||
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
|
||||
hash = tx.GetHash();
|
||||
|
@ -48,6 +48,7 @@ static const float RECONNECT_TIMEOUT_EXP = 1.5;
|
||||
* this is belt-and-suspenders sanity limit to prevent memory exhaustion.
|
||||
*/
|
||||
static const int MAX_LINE_LENGTH = 100000;
|
||||
static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050;
|
||||
|
||||
/****** Low-level TorControlConnection ********/
|
||||
|
||||
@ -333,6 +334,73 @@ TorController::~TorController()
|
||||
}
|
||||
}
|
||||
|
||||
void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||
{
|
||||
// NOTE: We can only get here if -onion is unset
|
||||
std::string socks_location;
|
||||
if (reply.code == 250) {
|
||||
for (const auto& line : reply.lines) {
|
||||
if (0 == line.compare(0, 20, "net/listeners/socks=")) {
|
||||
const std::string port_list_str = line.substr(20);
|
||||
std::vector<std::string> port_list = SplitString(port_list_str, ' ');
|
||||
|
||||
for (auto& portstr : port_list) {
|
||||
if (portstr.empty()) continue;
|
||||
if ((portstr[0] == '"' || portstr[0] == '\'') && portstr.size() >= 2 && (*portstr.rbegin() == portstr[0])) {
|
||||
portstr = portstr.substr(1, portstr.size() - 2);
|
||||
if (portstr.empty()) continue;
|
||||
}
|
||||
socks_location = portstr;
|
||||
if (0 == portstr.compare(0, 10, "127.0.0.1:")) {
|
||||
// Prefer localhost - ignore other ports
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!socks_location.empty()) {
|
||||
LogPrint(BCLog::TOR, "tor: Get SOCKS port command yielded %s\n", socks_location);
|
||||
} else {
|
||||
LogPrintf("tor: Get SOCKS port command returned nothing\n");
|
||||
}
|
||||
} else if (reply.code == 510) { // 510 Unrecognized command
|
||||
LogPrintf("tor: Get SOCKS port command failed with unrecognized command (You probably should upgrade Tor)\n");
|
||||
} else {
|
||||
LogPrintf("tor: Get SOCKS port command failed; error code %d\n", reply.code);
|
||||
}
|
||||
|
||||
CService resolved;
|
||||
Assume(!resolved.IsValid());
|
||||
if (!socks_location.empty()) {
|
||||
resolved = LookupNumeric(socks_location, DEFAULT_TOR_SOCKS_PORT);
|
||||
}
|
||||
if (!resolved.IsValid()) {
|
||||
// Fallback to old behaviour
|
||||
resolved = LookupNumeric("127.0.0.1", DEFAULT_TOR_SOCKS_PORT);
|
||||
}
|
||||
|
||||
Assume(resolved.IsValid());
|
||||
LogPrint(BCLog::TOR, "tor: Configuring onion proxy for %s\n", resolved.ToStringAddrPort());
|
||||
Proxy addrOnion = Proxy(resolved, true);
|
||||
SetProxy(NET_ONION, addrOnion);
|
||||
|
||||
const auto onlynets = gArgs.GetArgs("-onlynet");
|
||||
|
||||
const bool onion_allowed_by_onlynet{
|
||||
!gArgs.IsArgSet("-onlynet") ||
|
||||
std::any_of(onlynets.begin(), onlynets.end(), [](const auto& n) {
|
||||
return ParseNetwork(n) == NET_ONION;
|
||||
})};
|
||||
|
||||
if (onion_allowed_by_onlynet) {
|
||||
// If NET_ONION is reachable, then the below is a noop.
|
||||
//
|
||||
// If NET_ONION is not reachable, then none of -proxy or -onion was given.
|
||||
// Since we are here, then -torcontrol and -torpassword were given.
|
||||
SetReachable(NET_ONION, true);
|
||||
}
|
||||
}
|
||||
|
||||
void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||
{
|
||||
if (reply.code == 250) {
|
||||
@ -376,25 +444,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
|
||||
// Now that we know Tor is running setup the proxy for onion addresses
|
||||
// if -onion isn't set to something else.
|
||||
if (gArgs.GetArg("-onion", "") == "") {
|
||||
CService resolved(LookupNumeric("127.0.0.1", 9050));
|
||||
Proxy addrOnion = Proxy(resolved, true);
|
||||
SetProxy(NET_ONION, addrOnion);
|
||||
|
||||
const auto onlynets = gArgs.GetArgs("-onlynet");
|
||||
|
||||
const bool onion_allowed_by_onlynet{
|
||||
!gArgs.IsArgSet("-onlynet") ||
|
||||
std::any_of(onlynets.begin(), onlynets.end(), [](const auto& n) {
|
||||
return ParseNetwork(n) == NET_ONION;
|
||||
})};
|
||||
|
||||
if (onion_allowed_by_onlynet) {
|
||||
// If NET_ONION is reachable, then the below is a noop.
|
||||
//
|
||||
// If NET_ONION is not reachable, then none of -proxy or -onion was given.
|
||||
// Since we are here, then -torcontrol and -torpassword were given.
|
||||
SetReachable(NET_ONION, true);
|
||||
}
|
||||
_conn.Command("GETINFO net/listeners/socks", std::bind(&TorController::get_socks_cb, this, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
// Finally - now create the service
|
||||
|
@ -140,6 +140,8 @@ private:
|
||||
std::vector<uint8_t> clientNonce;
|
||||
|
||||
public:
|
||||
/** Callback for GETINFO net/listeners/socks result */
|
||||
void get_socks_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for ADD_ONION result */
|
||||
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for AUTHENTICATE result */
|
||||
|
@ -261,19 +261,6 @@ static bool CheckValid(const std::string& key, const util::SettingsValue& val, u
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
fs::path StripRedundantLastElementsOfPath(const fs::path& path)
|
||||
{
|
||||
auto result = path;
|
||||
while (result.filename().empty() || fs::PathToString(result.filename()) == ".") {
|
||||
result = result.parent_path();
|
||||
}
|
||||
|
||||
assert(fs::equivalent(result, path.lexically_normal()));
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to
|
||||
// #include class definitions for all members.
|
||||
// For example, m_settings has an internal dependency on univalue.
|
||||
@ -420,6 +407,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
fs::path ArgsManager::GetPathArg(std::string pathlike_arg) const
|
||||
{
|
||||
auto result = fs::PathFromString(GetArg(pathlike_arg, "")).lexically_normal();
|
||||
// Remove trailing slash, if present.
|
||||
return result.has_filename() ? result : result.parent_path();
|
||||
}
|
||||
|
||||
const fs::path ArgsManager::GetBlocksDirPath() const
|
||||
{
|
||||
LOCK(cs_args);
|
||||
@ -430,7 +424,7 @@ const fs::path ArgsManager::GetBlocksDirPath() const
|
||||
if (!path.empty()) return path;
|
||||
|
||||
if (IsArgSet("-blocksdir")) {
|
||||
path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", "")));
|
||||
path = fs::absolute(GetPathArg("-blocksdir"));
|
||||
if (!fs::is_directory(path)) {
|
||||
path = "";
|
||||
return path;
|
||||
@ -454,9 +448,9 @@ const fs::path ArgsManager::GetDataDir(bool net_specific) const
|
||||
// this function
|
||||
if (!path.empty()) return path;
|
||||
|
||||
std::string datadir = GetArg("-datadir", "");
|
||||
const fs::path datadir{GetPathArg("-datadir")};
|
||||
if (!datadir.empty()) {
|
||||
path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir)));
|
||||
path = fs::absolute(datadir);
|
||||
if (!fs::is_directory(path)) {
|
||||
path = "";
|
||||
return path;
|
||||
@ -476,7 +470,6 @@ const fs::path ArgsManager::GetDataDir(bool net_specific) const
|
||||
}
|
||||
}
|
||||
|
||||
path = StripRedundantLastElementsOfPath(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -871,8 +864,8 @@ fs::path GetBackupsDir()
|
||||
|
||||
bool CheckDataDirOption()
|
||||
{
|
||||
std::string datadir = gArgs.GetArg("-datadir", "");
|
||||
return datadir.empty() || fs::is_directory(fs::absolute(fs::PathFromString(datadir)));
|
||||
const fs::path datadir{gArgs.GetPathArg("-datadir")};
|
||||
return datadir.empty() || fs::is_directory(fs::absolute(datadir));
|
||||
}
|
||||
|
||||
fs::path GetConfigFile(const std::string& confPath)
|
||||
|
@ -283,6 +283,16 @@ protected:
|
||||
*/
|
||||
const std::map<std::string, std::vector<util::SettingsValue>> GetCommandLineArgs() const;
|
||||
|
||||
/**
|
||||
* Get a normalized path from a specified pathlike argument
|
||||
*
|
||||
* It is guaranteed that the returned path has no trailing slashes.
|
||||
*
|
||||
* @param pathlike_arg Pathlike argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir")
|
||||
* @return Normalized path which is get from a specified pathlike argument
|
||||
*/
|
||||
fs::path GetPathArg(std::string pathlike_arg) const;
|
||||
|
||||
/**
|
||||
* Get blocks directory path
|
||||
*
|
||||
|
@ -2306,12 +2306,12 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
::g_stats_client->gauge("blocks.tip.SigOps", nSigOps, 1.0f);
|
||||
|
||||
TRACE6(validation, block_connected,
|
||||
block.GetHash().data(),
|
||||
block_hash.data(),
|
||||
pindex->nHeight,
|
||||
block.vtx.size(),
|
||||
nInputs,
|
||||
nSigOps,
|
||||
GetTimeMicros() - nTimeStart // in microseconds (µs)
|
||||
nTime8 - nTimeStart // in microseconds (µs)
|
||||
);
|
||||
|
||||
return true;
|
||||
|
@ -140,7 +140,7 @@ void CHDChain::DeriveChildExtKey(uint32_t nAccountIndex, bool fInternal, uint32_
|
||||
CExtKey changeKey; //key at m/purpose'/coin_type'/account'/change
|
||||
CExtKey childKey; //key at m/purpose'/coin_type'/account'/change/address_index
|
||||
|
||||
masterKey.SetSeed(vchSeed);
|
||||
masterKey.SetSeed(MakeByteSpan(vchSeed));
|
||||
|
||||
// Use hardened derivation for purpose, coin_type and account
|
||||
// (keys >= 0x80000000 are hardened after bip32)
|
||||
|
@ -24,7 +24,7 @@
|
||||
bool VerifyWallets(interfaces::Chain& chain)
|
||||
{
|
||||
if (gArgs.IsArgSet("-walletdir")) {
|
||||
fs::path wallet_dir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||
const fs::path wallet_dir{gArgs.GetPathArg("-walletdir")};
|
||||
std::error_code error;
|
||||
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
|
||||
// It also lets the fs::exists and fs::is_directory checks below pass on windows, since they return false
|
||||
|
@ -1007,7 +1007,7 @@ RPCHelpMan dumpwallet()
|
||||
file << "# HD seed: " << HexStr(vchSeed) << "\n\n";
|
||||
|
||||
CExtKey masterKey;
|
||||
masterKey.SetSeed(vchSeed);
|
||||
masterKey.SetSeed(MakeByteSpan(vchSeed));
|
||||
|
||||
file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n";
|
||||
|
||||
|
@ -350,7 +350,7 @@ void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
|
||||
|
||||
CExtKey masterKey;
|
||||
SecureVector vchSeed = hdChainCurrent.GetSeed();
|
||||
masterKey.SetSeed(vchSeed);
|
||||
masterKey.SetSeed(MakeByteSpan(vchSeed));
|
||||
CKeyID master_id = masterKey.key.GetPubKey().GetID();
|
||||
|
||||
std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(m_storage.GetDatabase());
|
||||
|
@ -36,6 +36,22 @@ static void ErrorLogCallback(void* arg, int code, const char* msg)
|
||||
LogPrintf("SQLite Error. Code: %d. Message: %s\n", code, msg);
|
||||
}
|
||||
|
||||
static bool BindBlobToStatement(sqlite3_stmt* stmt,
|
||||
int index,
|
||||
Span<const std::byte> blob,
|
||||
const std::string& description)
|
||||
{
|
||||
int res = sqlite3_bind_blob(stmt, index, blob.data(), blob.size(), SQLITE_STATIC);
|
||||
if (res != SQLITE_OK) {
|
||||
LogPrintf("Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res));
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::optional<int> ReadPragmaInteger(sqlite3* db, const std::string& key, const std::string& description, bilingual_str& error)
|
||||
{
|
||||
std::string stmt_text = strprintf("PRAGMA %s", key);
|
||||
@ -376,14 +392,8 @@ bool SQLiteBatch::ReadKey(CDataStream&& key, CDataStream& value)
|
||||
assert(m_read_stmt);
|
||||
|
||||
// Bind: leftmost parameter in statement is index 1
|
||||
int res = sqlite3_bind_blob(m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
|
||||
if (res != SQLITE_OK) {
|
||||
LogPrintf("%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
|
||||
sqlite3_clear_bindings(m_read_stmt);
|
||||
sqlite3_reset(m_read_stmt);
|
||||
return false;
|
||||
}
|
||||
res = sqlite3_step(m_read_stmt);
|
||||
if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false;
|
||||
int res = sqlite3_step(m_read_stmt);
|
||||
if (res != SQLITE_ROW) {
|
||||
if (res != SQLITE_DONE) {
|
||||
// SQLITE_DONE means "not found", don't log an error in that case.
|
||||
@ -417,23 +427,11 @@ bool SQLiteBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrit
|
||||
|
||||
// Bind: leftmost parameter in statement is index 1
|
||||
// Insert index 1 is key, 2 is value
|
||||
int res = sqlite3_bind_blob(stmt, 1, key.data(), key.size(), SQLITE_STATIC);
|
||||
if (res != SQLITE_OK) {
|
||||
LogPrintf("%s: Unable to bind key to statement: %s\n", __func__, sqlite3_errstr(res));
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
return false;
|
||||
}
|
||||
res = sqlite3_bind_blob(stmt, 2, value.data(), value.size(), SQLITE_STATIC);
|
||||
if (res != SQLITE_OK) {
|
||||
LogPrintf("%s: Unable to bind value to statement: %s\n", __func__, sqlite3_errstr(res));
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
return false;
|
||||
}
|
||||
if (!BindBlobToStatement(stmt, 1, key, "key")) return false;
|
||||
if (!BindBlobToStatement(stmt, 2, value, "value")) return false;
|
||||
|
||||
// Execute
|
||||
res = sqlite3_step(stmt);
|
||||
int res = sqlite3_step(stmt);
|
||||
sqlite3_clear_bindings(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
if (res != SQLITE_DONE) {
|
||||
@ -448,16 +446,10 @@ bool SQLiteBatch::EraseKey(CDataStream&& key)
|
||||
assert(m_delete_stmt);
|
||||
|
||||
// Bind: leftmost parameter in statement is index 1
|
||||
int res = sqlite3_bind_blob(m_delete_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
|
||||
if (res != SQLITE_OK) {
|
||||
LogPrintf("%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
|
||||
sqlite3_clear_bindings(m_delete_stmt);
|
||||
sqlite3_reset(m_delete_stmt);
|
||||
return false;
|
||||
}
|
||||
if (!BindBlobToStatement(m_delete_stmt, 1, key, "key")) return false;
|
||||
|
||||
// Execute
|
||||
res = sqlite3_step(m_delete_stmt);
|
||||
int res = sqlite3_step(m_delete_stmt);
|
||||
sqlite3_clear_bindings(m_delete_stmt);
|
||||
sqlite3_reset(m_delete_stmt);
|
||||
if (res != SQLITE_DONE) {
|
||||
@ -472,18 +464,11 @@ bool SQLiteBatch::HasKey(CDataStream&& key)
|
||||
assert(m_read_stmt);
|
||||
|
||||
// Bind: leftmost parameter in statement is index 1
|
||||
bool ret = false;
|
||||
int res = sqlite3_bind_blob(m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
|
||||
if (res == SQLITE_OK) {
|
||||
res = sqlite3_step(m_read_stmt);
|
||||
if (res == SQLITE_ROW) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false;
|
||||
int res = sqlite3_step(m_read_stmt);
|
||||
sqlite3_clear_bindings(m_read_stmt);
|
||||
sqlite3_reset(m_read_stmt);
|
||||
return ret;
|
||||
return res == SQLITE_ROW;
|
||||
}
|
||||
|
||||
bool SQLiteBatch::StartCursor()
|
||||
|
@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(bip39_vectors)
|
||||
CExtKey key;
|
||||
CExtPubKey pubkey;
|
||||
|
||||
key.SetSeed(seed);
|
||||
key.SetSeed(MakeByteSpan(seed));
|
||||
pubkey = key.Neuter();
|
||||
|
||||
// printf("CBitcoinExtKey: %s\n", EncodeExtKey(key).c_str());
|
||||
|
@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
|
||||
bool result = m_wallet_loader->verify();
|
||||
BOOST_CHECK(result == true);
|
||||
}
|
||||
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||
fs::path walletdir = gArgs.GetPathArg("-walletdir");
|
||||
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
|
||||
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
||||
}
|
||||
@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
|
||||
bool result = m_wallet_loader->verify();
|
||||
BOOST_CHECK(result == true);
|
||||
}
|
||||
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||
fs::path walletdir = gArgs.GetPathArg("-walletdir");
|
||||
fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
|
||||
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
||||
}
|
||||
@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
|
||||
bool result = m_wallet_loader->verify();
|
||||
BOOST_CHECK(result == true);
|
||||
}
|
||||
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||
fs::path walletdir = gArgs.GetPathArg("-walletdir");
|
||||
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
|
||||
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
||||
}
|
||||
@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
|
||||
bool result = m_wallet_loader->verify();
|
||||
BOOST_CHECK(result == true);
|
||||
}
|
||||
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||
fs::path walletdir = gArgs.GetPathArg("-walletdir");
|
||||
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
|
||||
BOOST_CHECK_EQUAL(walletdir, expected_path);
|
||||
}
|
||||
|
@ -5866,7 +5866,7 @@ void CWallet::SetupDescriptorScriptPubKeyMans()
|
||||
|
||||
// Get the extended key
|
||||
CExtKey master_key;
|
||||
master_key.SetSeed(seed_key);
|
||||
master_key.SetSeed(MakeByteSpan(seed_key));
|
||||
|
||||
for (bool internal : {false, true}) {
|
||||
{ // OUTPUT_TYPE is only one: LEGACY
|
||||
|
@ -12,7 +12,7 @@ fs::path GetWalletDir()
|
||||
fs::path path;
|
||||
|
||||
if (gArgs.IsArgSet("-walletdir")) {
|
||||
path = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
|
||||
path = gArgs.GetPathArg("-walletdir");
|
||||
if (!fs::is_directory(path)) {
|
||||
// If the path specified doesn't exist, we return the deliberately
|
||||
// invalid empty string.
|
||||
|
Loading…
Reference in New Issue
Block a user