Skip to content

Commit

Permalink
Add time methods to the Chain interface
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ryanofsky and Empact committed Jan 15, 2019
1 parent 700c42b commit d93c4c1
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 17 deletions.
12 changes: 12 additions & 0 deletions src/interfaces/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ class LockImpl : public Chain::Lock
assert(block != nullptr);
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>
Expand Down
8 changes: 8 additions & 0 deletions src/interfaces/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <optional.h>

#include <memory>
#include <stdint.h>
#include <string>
#include <vector>

Expand Down Expand Up @@ -48,6 +49,13 @@ class Chain

//! Get block hash. Height must be valid or this function will abort.
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
Expand Down
9 changes: 7 additions & 2 deletions src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,13 @@ class WalletImpl : public Wallet
if (mi == m_wallet.mapWallet.end()) {
return false;
}
num_blocks = locked_chain->getHeight().value_or(-1);
block_time = ::chainActive.Tip()->GetBlockTime();
if (Optional<int> height = locked_chain->getHeight()) {
num_blocks = *height;
block_time = locked_chain->getBlockTime(*height);
} else {
num_blocks = -1;
block_time = -1;
}
tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return true;
}
Expand Down
12 changes: 7 additions & 5 deletions src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,8 @@ UniValue importwallet(const JSONRPCRequest& request)
if (!file.is_open()) {
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());
file.seekg(0, file.beg);
Expand Down Expand Up @@ -774,7 +775,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
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("# 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";

// add the base58check encoded extended master if the wallet uses HD
Expand Down Expand Up @@ -1232,15 +1233,16 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
EnsureWalletIsUnlocked(pwallet);

// 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()) {
GetImportTimestamp(data, now);
}

const int64_t minimumTimestamp = 1;

if (fRescan && chainActive.Tip()) {
nLowestTimestamp = chainActive.Tip()->GetBlockTime();
if (fRescan && tip_height) {
nLowestTimestamp = locked_chain->getBlockTime(*tip_height);
} else {
fRescan = false;
}
Expand Down
19 changes: 9 additions & 10 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
const Optional<int> tip_height = locked_chain.getHeight();
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()) {
if (mapKeyBirth.count(keyid) == 0)
mapKeyFirstBlock[keyid] = pindexMax;
mapKeyFirstBlock[keyid] = max_height;
}

// if there are no such keys, we're done
Expand All @@ -3730,25 +3731,23 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
for (const auto& entry : mapWallet) {
// iterate over all wallet transactions...
const CWalletTx &wtx = entry.second;
CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock);
if (pindex && chainActive.Contains(pindex)) {
if (Optional<int> height = locked_chain.getBlockHeight(wtx.hashBlock)) {
// ... which are already in a block
int nHeight = pindex->nHeight;
for (const CTxOut &txout : wtx.tx->vout) {
// iterate over all their outputs
for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
// ... and all their affected keys
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
rit->second = pindex;
std::map<CKeyID, int>::iterator rit = mapKeyFirstBlock.find(keyid);
if (rit != mapKeyFirstBlock.end() && *height < rit->second)
rit->second = *height;
}
}
}
}

// Extract block timestamps for those keys
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
}

/**
Expand Down

0 comments on commit d93c4c1

Please sign in to comment.