Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions contrib/guix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ We achieve bootstrappability by using Guix as a functional package manager.

# Requirements

Conservatively, a x86_64 machine with:
Conservatively, you will need an x86_64 machine with:

- 16GB of free disk space on the partition that /gnu/store will reside in
- 8GB of free disk space **per platform triple** you're planning on building
Expand Down Expand Up @@ -437,9 +437,8 @@ In the extraordinarily rare case where you messed up your Guix installation in
an irreversible way, you may want to completely purge Guix from your system and
start over.

1. Uninstall Guix itself according to the way you installed it. (e.g. `sudo apt
purge guix` for Ubuntu packaging, `sudo make uninstall` for
built-from-source).
1. Uninstall Guix itself according to the way you installed it (e.g. `sudo apt
Copy link
Collaborator

@knst knst Nov 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be partial due to missing changes in doc/build-openbsd.md (depends on bitcoin#22335)

purge guix` for Ubuntu packaging, `sudo make uninstall` for a build from source).
2. Remove all build users and groups

You may check for relevant users and groups using:
Expand Down
4 changes: 4 additions & 0 deletions doc/release-notes-22407.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Updated RPC
--------

- `getblockchaininfo` now returns a new `time` field, that provides the chain tip time.
49 changes: 27 additions & 22 deletions src/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, in
return &mapInfo[nId];
}

void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
{
AssertLockHeld(cs);

Expand All @@ -156,11 +156,13 @@ void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
int nId1 = vRandom[nRndPos1];
int nId2 = vRandom[nRndPos2];

assert(mapInfo.count(nId1) == 1);
assert(mapInfo.count(nId2) == 1);
const auto it_1{mapInfo.find(nId1)};
const auto it_2{mapInfo.find(nId2)};
assert(it_1 != mapInfo.end());
assert(it_2 != mapInfo.end());

mapInfo[nId1].nRandomPos = nRndPos2;
mapInfo[nId2].nRandomPos = nRndPos1;
it_1->second.nRandomPos = nRndPos2;
it_2->second.nRandomPos = nRndPos1;

vRandom[nRndPos1] = nId2;
vRandom[nRndPos2] = nId1;
Expand Down Expand Up @@ -425,7 +427,7 @@ void CAddrMan::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
}
}

CAddrInfo CAddrMan::Select_(bool newOnly)
CAddrInfo CAddrMan::Select_(bool newOnly) const
{
AssertLockHeld(cs);

Expand All @@ -448,8 +450,9 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
}
int nId = vvTried[nKBucket][nKBucketPos];
assert(mapInfo.count(nId) == 1);
CAddrInfo& info = mapInfo[nId];
const auto it_found{mapInfo.find(nId)};
assert(it_found != mapInfo.end());
const CAddrInfo& info{it_found->second};
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30))
return info;
fChanceFactor *= 1.2;
Expand All @@ -465,8 +468,9 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
}
int nId = vvNew[nUBucket][nUBucketPos];
assert(mapInfo.count(nId) == 1);
CAddrInfo& info = mapInfo[nId];
const auto it_found{mapInfo.find(nId)};
assert(it_found != mapInfo.end());
const CAddrInfo& info{it_found->second};
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30))
return info;
fChanceFactor *= 1.2;
Expand Down Expand Up @@ -517,15 +521,15 @@ int CAddrMan::Check_()

for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) {
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
if (vvTried[n][i] != -1) {
if (!setTried.count(vvTried[n][i]))
return -11;
if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey, m_asmap) != n)
return -17;
if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) != i)
return -18;
setTried.erase(vvTried[n][i]);
}
if (vvTried[n][i] != -1) {
if (!setTried.count(vvTried[n][i]))
return -11;
if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey, m_asmap) != n)
return -17;
if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) != i)
return -18;
setTried.erase(vvTried[n][i]);
}
}
}

Expand Down Expand Up @@ -553,7 +557,7 @@ int CAddrMan::Check_()
}
#endif

void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network)
void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const
{
AssertLockHeld(cs);

Expand All @@ -573,9 +577,10 @@ void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size

int nRndPos = insecure_rand.randrange(vRandom.size() - n) + n;
SwapRandom(n, nRndPos);
assert(mapInfo.count(vRandom[n]) == 1);
const auto it{mapInfo.find(vRandom[n])};
assert(it != mapInfo.end());

const CAddrInfo& ai = mapInfo[vRandom[n]];
const CAddrInfo& ai{it->second};

// Filter by network (optional)
if (network != std::nullopt && ai.GetNetClass() != network) continue;
Expand Down
28 changes: 15 additions & 13 deletions src/addrman.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class CAddrInfo : public CAddress
bool fInTried{false};

//! position in vRandom
int nRandomPos{-1};
mutable int nRandomPos{-1};

friend class CAddrMan;

Expand Down Expand Up @@ -544,12 +544,12 @@ class CAddrMan
}

//! Mark an entry as accessible.
void Good(const CService &addr, bool test_before_evict = true, int64_t nTime = GetAdjustedTime())
void Good(const CService &addr, int64_t nTime = GetAdjustedTime())
EXCLUSIVE_LOCKS_REQUIRED(!cs)
{
LOCK(cs);
Check();
Good_(addr, test_before_evict, nTime);
Good_(addr, /* test_before_evict */ true, nTime);
Check();
}

Expand Down Expand Up @@ -587,7 +587,7 @@ class CAddrMan
/**
* Choose an address to connect to.
*/
CAddrInfo Select(bool newOnly = false)
CAddrInfo Select(bool newOnly = false) const
EXCLUSIVE_LOCKS_REQUIRED(!cs)
{
LOCK(cs);
Expand All @@ -604,7 +604,7 @@ class CAddrMan
* @param[in] max_pct Maximum percentage of addresses to return (0 = all).
* @param[in] network Select only addresses of this network (nullopt = all).
*/
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network)
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
EXCLUSIVE_LOCKS_REQUIRED(!cs)
{
LOCK(cs);
Expand Down Expand Up @@ -650,12 +650,12 @@ class CAddrMan
uint256 nKey;

//! Source of random numbers for randomization in inner loops
FastRandomContext insecure_rand;
mutable FastRandomContext insecure_rand GUARDED_BY(cs);

private:
//! A mutex to protect the inner data structures.
mutable Mutex cs;

private:
//! Serialization versions.
enum Format : uint8_t {
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
Expand Down Expand Up @@ -688,7 +688,9 @@ class CAddrMan
std::map<CService, int> mapAddr GUARDED_BY(cs);

//! randomly-ordered vector of all nIds
std::vector<int> vRandom GUARDED_BY(cs);
//! This is mutable because it is unobservable outside the class, so any
//! changes to it (even in const methods) are also unobservable.
mutable std::vector<int> vRandom GUARDED_BY(cs);

// number of "tried" entries
int nTried GUARDED_BY(cs);
Expand Down Expand Up @@ -718,7 +720,7 @@ class CAddrMan
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Swap two elements in vRandom.
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs);
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Move an entry from the "new" table(s) to the "tried" table
void MakeTried(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
Expand All @@ -739,7 +741,7 @@ class CAddrMan
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs);
CAddrInfo Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);

//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
Expand All @@ -748,7 +750,7 @@ class CAddrMan
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Consistency check
void Check()
void Check() const
EXCLUSIVE_LOCKS_REQUIRED(cs)
{
#ifdef DEBUG_ADDRMAN
Expand All @@ -762,7 +764,7 @@ class CAddrMan

#ifdef DEBUG_ADDRMAN
//! Perform consistency check. Returns an error code or zero.
int Check_() EXCLUSIVE_LOCKS_REQUIRED(cs);
int Check_() const EXCLUSIVE_LOCKS_REQUIRED(cs);
#endif

/**
Expand All @@ -773,7 +775,7 @@ class CAddrMan
* @param[in] max_pct Maximum percentage of addresses to return (0 = all).
* @param[in] network Select only addresses of this network (nullopt = all).
*/
void GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) EXCLUSIVE_LOCKS_REQUIRED(cs);
void GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);

/** We have successfully connected to this peer. Calling this function
* updates the CAddress's nTime, which is used in our IsTerrible()
Expand Down
2 changes: 1 addition & 1 deletion src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}

unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags)
{
unsigned int nSigOps = GetLegacySigOpCount(tx);

Expand Down
2 changes: 1 addition & 1 deletion src/consensus/tx_verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
* @param[out] flags Script verification flags
* @return Total signature operation count for a tx
*/
unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs, int flags);
unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs, uint32_t flags);

/**
* Check if transaction is final and can be included in a block with the
Expand Down
37 changes: 37 additions & 0 deletions src/node/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <consensus/validation.h>
#include <index/txindex.h>
#include <net.h>
#include <net_processing.h>
#include <node/blockstorage.h>
#include <txmempool.h>
#include <validation.h>
#include <validationinterface.h>
Expand Down Expand Up @@ -90,3 +92,38 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t

return TransactionError::OK;
}

CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock)
{
LOCK(cs_main);

if (mempool && !block_index) {
CTransactionRef ptx = mempool->get(hash);
if (ptx) return ptx;
}
if (g_txindex) {
CTransactionRef tx;
uint256 block_hash;
if (g_txindex->FindTx(hash, block_hash, tx)) {
if (!block_index || block_index->GetBlockHash() == block_hash) {
// Don't return the transaction if the provided block hash doesn't match.
// The case where a transaction appears in multiple blocks (e.g. reorgs or
// BIP30) is handled by the block lookup below.
hashBlock = block_hash;
return tx;
}
}
}
if (block_index) {
CBlock block;
if (ReadBlockFromDisk(block, block_index, consensusParams)) {
for (const auto& tx : block.vtx) {
if (tx->GetHash() == hash) {
hashBlock = block_index->GetBlockHash();
return tx;
}
}
}
}
return nullptr;
}
20 changes: 20 additions & 0 deletions src/node/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
#include <primitives/transaction.h>
#include <util/error.h>

class CBlockIndex;
class CTxMemPool;
struct NodeContext;
namespace Consensus {
struct Params;
}

/** Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
* Also used by the GUI when broadcasting a completed PSBT.
Expand Down Expand Up @@ -38,4 +43,19 @@ static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10};
*/
[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& highfee, bool relay, bool wait_callback, bool bypass_limits = false);

/**
* Return transaction with a given hash.
* If mempool is provided and block_index is not provided, check it first for the tx.
* If -txindex is available, check it next for the tx.
* Finally, if block_index is provided, check for tx by reading entire block from disk.
*
* @param[in] block_index The block to read from disk, or nullptr
* @param[in] mempool If provided, check mempool for tx
* @param[in] hash The txid
* @param[in] consensusParams The params
* @param[out] hashBlock The block hash, if the tx was found via -txindex or block_index
* @returns The tx if found, otherwise nullptr
*/
CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock);

#endif // BITCOIN_NODE_TRANSACTION_H
4 changes: 3 additions & 1 deletion src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1662,7 +1662,8 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
{RPCResult::Type::NUM, "headers", "the current number of headers we have validated"},
{RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"},
{RPCResult::Type::NUM, "difficulty", "the current difficulty"},
{RPCResult::Type::NUM, "mediantime", "median time for the current best block"},
{RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
{RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
{RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"},
{RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"},
{RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},
Expand Down Expand Up @@ -1720,6 +1721,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->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("initialblockdownload", active_chainstate.IsInitialBlockDownload());
Expand Down
10 changes: 5 additions & 5 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
RPCHelpMan{
"getrawtransaction",
"\nReturn the raw transaction data.\n"
"\nBy default this function only works for mempool transactions. When called with a blockhash\n"
"argument, getrawtransaction will return the transaction if the specified block is available and\n"
"the transaction is found in that block. When called without a blockhash argument, getrawtransaction\n"
"will return the transaction if it is in the mempool, or if -txindex is enabled and the transaction\n"
"is in a block in the blockchain.\n"

"\nBy default, this call only returns a transaction if it is in the mempool. If -txindex is enabled\n"
"and no blockhash argument is passed, it will return the transaction if it is in the mempool or any block.\n"
"If a blockhash argument is passed, it will return the transaction if\n"
"the specified block is available and the transaction is in that block.\n"
"\nHint: Use gettransaction for wallet transactions.\n"

"\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
Expand Down
Loading