Add time methods to the Chain interface
And use them to remove uses of chainActive and mapBlockIndex in wallet code This commit does not change behavior. Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
This commit is contained in:
parent
700c42b85d
commit
d93c4c1d6e
5 changed files with 43 additions and 17 deletions
|
@ -46,6 +46,18 @@ class LockImpl : public Chain::Lock
|
||||||
assert(block != nullptr);
|
assert(block != nullptr);
|
||||||
return block->GetBlockHash();
|
return block->GetBlockHash();
|
||||||
}
|
}
|
||||||
|
int64_t getBlockTime(int height) override
|
||||||
|
{
|
||||||
|
CBlockIndex* block = ::chainActive[height];
|
||||||
|
assert(block != nullptr);
|
||||||
|
return block->GetBlockTime();
|
||||||
|
}
|
||||||
|
int64_t getBlockMedianTimePast(int height) override
|
||||||
|
{
|
||||||
|
CBlockIndex* block = ::chainActive[height];
|
||||||
|
assert(block != nullptr);
|
||||||
|
return block->GetMedianTimePast();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>
|
class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -48,6 +49,13 @@ public:
|
||||||
|
|
||||||
//! Get block hash. Height must be valid or this function will abort.
|
//! Get block hash. Height must be valid or this function will abort.
|
||||||
virtual uint256 getBlockHash(int height) = 0;
|
virtual uint256 getBlockHash(int height) = 0;
|
||||||
|
|
||||||
|
//! Get block time. Height must be valid or this function will abort.
|
||||||
|
virtual int64_t getBlockTime(int height) = 0;
|
||||||
|
|
||||||
|
//! Get block median time past. Height must be valid or this function
|
||||||
|
//! will abort.
|
||||||
|
virtual int64_t getBlockMedianTimePast(int height) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Return Lock interface. Chain is locked when this is called, and
|
//! Return Lock interface. Chain is locked when this is called, and
|
||||||
|
|
|
@ -333,8 +333,13 @@ public:
|
||||||
if (mi == m_wallet.mapWallet.end()) {
|
if (mi == m_wallet.mapWallet.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
num_blocks = locked_chain->getHeight().value_or(-1);
|
if (Optional<int> height = locked_chain->getHeight()) {
|
||||||
block_time = ::chainActive.Tip()->GetBlockTime();
|
num_blocks = *height;
|
||||||
|
block_time = locked_chain->getBlockTime(*height);
|
||||||
|
} else {
|
||||||
|
num_blocks = -1;
|
||||||
|
block_time = -1;
|
||||||
|
}
|
||||||
tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
|
tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,7 +569,8 @@ UniValue importwallet(const JSONRPCRequest& request)
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
||||||
}
|
}
|
||||||
nTimeBegin = chainActive.Tip()->GetBlockTime();
|
Optional<int> tip_height = locked_chain->getHeight();
|
||||||
|
nTimeBegin = tip_height ? locked_chain->getBlockTime(*tip_height) : 0;
|
||||||
|
|
||||||
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
|
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
|
||||||
file.seekg(0, file.beg);
|
file.seekg(0, file.beg);
|
||||||
|
@ -774,7 +775,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
|
||||||
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
|
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
|
||||||
const Optional<int> tip_height = locked_chain->getHeight();
|
const Optional<int> tip_height = locked_chain->getHeight();
|
||||||
file << strprintf("# * Best block at time of backup was %i (%s),\n", tip_height.value_or(-1), tip_height ? locked_chain->getBlockHash(*tip_height).ToString() : "(missing block hash)");
|
file << strprintf("# * Best block at time of backup was %i (%s),\n", tip_height.value_or(-1), tip_height ? locked_chain->getBlockHash(*tip_height).ToString() : "(missing block hash)");
|
||||||
file << strprintf("# mined on %s\n", FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()));
|
file << strprintf("# mined on %s\n", tip_height ? FormatISO8601DateTime(locked_chain->getBlockTime(*tip_height)) : "(missing block time)");
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|
||||||
// add the base58check encoded extended master if the wallet uses HD
|
// add the base58check encoded extended master if the wallet uses HD
|
||||||
|
@ -1232,15 +1233,16 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
|
||||||
EnsureWalletIsUnlocked(pwallet);
|
EnsureWalletIsUnlocked(pwallet);
|
||||||
|
|
||||||
// Verify all timestamps are present before importing any keys.
|
// Verify all timestamps are present before importing any keys.
|
||||||
now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0;
|
const Optional<int> tip_height = locked_chain->getHeight();
|
||||||
|
now = tip_height ? locked_chain->getBlockMedianTimePast(*tip_height) : 0;
|
||||||
for (const UniValue& data : requests.getValues()) {
|
for (const UniValue& data : requests.getValues()) {
|
||||||
GetImportTimestamp(data, now);
|
GetImportTimestamp(data, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int64_t minimumTimestamp = 1;
|
const int64_t minimumTimestamp = 1;
|
||||||
|
|
||||||
if (fRescan && chainActive.Tip()) {
|
if (fRescan && tip_height) {
|
||||||
nLowestTimestamp = chainActive.Tip()->GetBlockTime();
|
nLowestTimestamp = locked_chain->getBlockTime(*tip_height);
|
||||||
} else {
|
} else {
|
||||||
fRescan = false;
|
fRescan = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3715,11 +3715,12 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
|
||||||
}
|
}
|
||||||
|
|
||||||
// map in which we'll infer heights of other keys
|
// map in which we'll infer heights of other keys
|
||||||
CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin
|
const Optional<int> tip_height = locked_chain.getHeight();
|
||||||
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
|
const int max_height = tip_height && *tip_height > 144 ? *tip_height - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
|
||||||
|
std::map<CKeyID, int> mapKeyFirstBlock;
|
||||||
for (const CKeyID &keyid : GetKeys()) {
|
for (const CKeyID &keyid : GetKeys()) {
|
||||||
if (mapKeyBirth.count(keyid) == 0)
|
if (mapKeyBirth.count(keyid) == 0)
|
||||||
mapKeyFirstBlock[keyid] = pindexMax;
|
mapKeyFirstBlock[keyid] = max_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there are no such keys, we're done
|
// if there are no such keys, we're done
|
||||||
|
@ -3730,17 +3731,15 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
|
||||||
for (const auto& entry : mapWallet) {
|
for (const auto& entry : mapWallet) {
|
||||||
// iterate over all wallet transactions...
|
// iterate over all wallet transactions...
|
||||||
const CWalletTx &wtx = entry.second;
|
const CWalletTx &wtx = entry.second;
|
||||||
CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock);
|
if (Optional<int> height = locked_chain.getBlockHeight(wtx.hashBlock)) {
|
||||||
if (pindex && chainActive.Contains(pindex)) {
|
|
||||||
// ... which are already in a block
|
// ... which are already in a block
|
||||||
int nHeight = pindex->nHeight;
|
|
||||||
for (const CTxOut &txout : wtx.tx->vout) {
|
for (const CTxOut &txout : wtx.tx->vout) {
|
||||||
// iterate over all their outputs
|
// iterate over all their outputs
|
||||||
for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
|
for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
|
||||||
// ... and all their affected keys
|
// ... and all their affected keys
|
||||||
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
|
std::map<CKeyID, int>::iterator rit = mapKeyFirstBlock.find(keyid);
|
||||||
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
|
if (rit != mapKeyFirstBlock.end() && *height < rit->second)
|
||||||
rit->second = pindex;
|
rit->second = *height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3748,7 +3747,7 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
|
||||||
|
|
||||||
// Extract block timestamps for those keys
|
// Extract block timestamps for those keys
|
||||||
for (const auto& entry : mapKeyFirstBlock)
|
for (const auto& entry : mapKeyFirstBlock)
|
||||||
mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off
|
mapKeyBirth[entry.first] = locked_chain.getBlockTime(entry.second) - TIMESTAMP_WINDOW; // block times can be 2h off
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue