Skip to content

Commit d4f3e81

Browse files
authored
Fixed incorrect mapping of height/offset ends to starts (#45)
1 parent fc61296 commit d4f3e81

File tree

5 files changed

+77
-9
lines changed

5 files changed

+77
-9
lines changed

index.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Etching } from './src/etching';
33
import { RuneEtchingSpec } from './src/indexer';
44
import { u128, u32, u64, u8 } from './src/integer';
55
import { None, Option, Some } from './src/monads';
6-
import { Rune } from './src/rune';
76
import { RuneId } from './src/runeid';
87
import { Runestone } from './src/runestone';
98
import { SpacedRune } from './src/spacedrune';
@@ -84,8 +83,6 @@ const u128Strict = (n: bigint) => {
8483
return u128(bigN);
8584
};
8685

87-
const SPACERS = ['•', '.'];
88-
8986
// TODO: Add unit tests
9087
/**
9188
* Low level function to allow for encoding runestones without any indexer and transaction checks.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@magiceden-oss/runestone-lib",
3-
"version": "0.7.2-alpha",
3+
"version": "0.8.0-alpha",
44
"description": "",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",

src/indexer/index.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,82 @@ export class RunestoneIndexer {
7171
return;
7272
}
7373

74-
this._updateInProgress = this.updateRuneUtxoBalancesImpl();
74+
this._updateInProgress = this._rpc.getblockhashbyheight
75+
? this.updateRuneUtxoBalancesWithBlockHeightImpl(
76+
this._rpc.getblockhashbyheight.bind(this._rpc)
77+
)
78+
: this.updateRuneUtxoBalancesImpl();
7579
try {
7680
await this._updateInProgress;
7781
} finally {
7882
this._updateInProgress = null;
7983
}
8084
}
8185

86+
private async updateRuneUtxoBalancesWithBlockHeightImpl(
87+
getblockhashbyheight: (blockheight: number) => Promise<string | null>
88+
) {
89+
const currentStorageBlock = await this._storage.getCurrentBlock();
90+
if (currentStorageBlock) {
91+
// walk down until matching hash is found
92+
const reorgBlockhashesToIndex: string[] = [];
93+
let blockheight = currentStorageBlock.height;
94+
let blockhash = await getblockhashbyheight(blockheight);
95+
let storageBlockHash: string | null = currentStorageBlock.hash;
96+
while (storageBlockHash !== blockhash) {
97+
if (blockhash) {
98+
reorgBlockhashesToIndex.push(blockhash);
99+
}
100+
101+
blockheight--;
102+
blockhash = await getblockhashbyheight(blockheight);
103+
storageBlockHash = await this._storage.getBlockhash(blockheight);
104+
}
105+
106+
// process blocks that are reorgs
107+
for (const blockhash of reorgBlockhashesToIndex) {
108+
const blockResult = await this._rpc.getblock({ blockhash, verbosity: 2 });
109+
if (blockResult.error !== null) {
110+
throw blockResult.error;
111+
}
112+
const block = blockResult.result;
113+
114+
const runeUpdater = new RuneUpdater(this._network, block, true, this._storage, this._rpc);
115+
116+
for (const [txIndex, tx] of block.tx.entries()) {
117+
await runeUpdater.indexRunes(tx, txIndex);
118+
}
119+
120+
await this._storage.saveBlockIndex(runeUpdater);
121+
}
122+
}
123+
124+
// start from first rune height or next block height, whichever is greater
125+
let blockheight = Math.max(
126+
Network.getFirstRuneHeight(this._network),
127+
currentStorageBlock ? currentStorageBlock.height + 1 : 0
128+
);
129+
let blockhash = await getblockhashbyheight(blockheight);
130+
while (blockhash !== null) {
131+
const blockResult = await this._rpc.getblock({ blockhash, verbosity: 2 });
132+
if (blockResult.error !== null) {
133+
throw blockResult.error;
134+
}
135+
const block = blockResult.result;
136+
137+
const runeUpdater = new RuneUpdater(this._network, block, false, this._storage, this._rpc);
138+
139+
for (const [txIndex, tx] of block.tx.entries()) {
140+
await runeUpdater.indexRunes(tx, txIndex);
141+
}
142+
143+
await this._storage.saveBlockIndex(runeUpdater);
144+
145+
blockheight++;
146+
blockhash = await getblockhashbyheight(blockheight);
147+
}
148+
}
149+
82150
private async updateRuneUtxoBalancesImpl() {
83151
const newBlockhashesToIndex: string[] = [];
84152

src/indexer/updater.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import * as assert from 'node:assert/strict';
21
import { Artifact, isRunestone } from '../artifact';
32
import {
43
COMMIT_CONFIRMATIONS,
@@ -224,7 +223,9 @@ export class RuneUpdater implements RuneBlockIndex {
224223

225224
const optionVout = pointer
226225
.map((pointer) => Number(pointer))
227-
.inspect((pointer) => assert(pointer < allocated.length))
226+
.inspect((pointer) => {
227+
if (pointer < 0 || pointer >= allocated.length) throw new Error('Pointer is invalid');
228+
})
228229
.orElse(() => {
229230
const entry = [...tx.vout.entries()].find(
230231
([_, txOut]) => !isScriptPubKeyHexOpReturn(txOut.scriptPubKey.hex)
@@ -536,7 +537,7 @@ export class RuneUpdater implements RuneBlockIndex {
536537
? { start: unwrappedTerms.height[0].unwrap() }
537538
: {}),
538539
...(unwrappedTerms.height[1].isSome()
539-
? { start: unwrappedTerms.height[1].unwrap() }
540+
? { end: unwrappedTerms.height[1].unwrap() }
540541
: {}),
541542
},
542543
}
@@ -548,7 +549,7 @@ export class RuneUpdater implements RuneBlockIndex {
548549
? { start: unwrappedTerms.offset[0].unwrap() }
549550
: {}),
550551
...(unwrappedTerms.offset[1].isSome()
551-
? { start: unwrappedTerms.offset[1].unwrap() }
552+
? { end: unwrappedTerms.offset[1].unwrap() }
552553
: {}),
553554
},
554555
}

src/rpcclient.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,6 @@ export interface BitcoinRpcClient {
103103
verbose,
104104
blockhash,
105105
}: T): Promise<RpcResponse<GetRawTransactionReturn<T>>>;
106+
107+
getblockhashbyheight?(blockheight: number): Promise<string | null>;
106108
}

0 commit comments

Comments
 (0)