Skip to content

Commit

Permalink
wdb-migration: handle edge case when wdb.addBlock is interrupted.
Browse files Browse the repository at this point in the history
  • Loading branch information
nodech committed Nov 19, 2024
1 parent a914b01 commit 669e8fc
Show file tree
Hide file tree
Showing 5 changed files with 3,193 additions and 247 deletions.
38 changes: 28 additions & 10 deletions lib/wallet/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -925,9 +925,10 @@ class MigrateTXCountTimeIndex extends AbstractMigration {

for await (const {key, value: rawBlockRecord} of rawBlockRecords) {
const height = txlayout.b.decode(key)[0];
const hash = rawBlockRecord.slice(0, 32);
const blockTime = encoding.readU32(rawBlockRecord, 32 + 4);
const txCount = encoding.readU32(rawBlockRecord, 32 + 4 + 4);
const medianTime = await this.getMedianTime(height);
const medianTime = await this.getMedianTime(height, hash);

const hashes = new BufferSet();
let count = 0;
Expand Down Expand Up @@ -1158,27 +1159,44 @@ class MigrateTXCountTimeIndex extends AbstractMigration {
/**
* Get median time for the block.
* @param {Number} height
* @param {Hash} lastHash
* @returns {Promise<Number>}
*/

async getMedianTime(height) {
const getBlockTime = async (height) => {
const cache = this.blockTimeCache.get(height);
async getMedianTime(height, lastHash) {
const getBlockTime = async (bheight) => {
const cache = this.blockTimeCache.get(bheight);

if (cache != null)
return cache;

if (height < 0)
if (bheight < 0)
return null;

const data = await this.ldb.get(this.layout.wdb.h.encode(height));
let time;
const data = await this.ldb.get(this.layout.wdb.h.encode(bheight));

if (!data)
return null;
if (!data) {
// Special case when txlayout.b exists, but txlayout.wdb.h does not.
// This can happen when walletDB is stopped during addBlock.
if (height !== bheight)
return null;

const header = await this.db.client.getBlockHeader(bheight);

if (!header)
return null;

const time = encoding.readU64(data, 32);
// double check hash.
if (header.hash !== lastHash.toString('hex'))
throw new Error('Bad block time response.');

time = header.time;
} else {
time = encoding.readU64(data, 32);
}

this.blockTimeCache.set(height, time);
this.blockTimeCache.set(bheight, time);

return time;
};
Expand Down
Loading

0 comments on commit 669e8fc

Please sign in to comment.