Skip to content

Commit

Permalink
Keep the entire list of blockhashes in memory, and vend the latest _u…
Browse files Browse the repository at this point in the history
…nused_ one.
  • Loading branch information
steveluscher committed Oct 6, 2024
1 parent 3568f48 commit b0e5f51
Showing 1 changed file with 34 additions and 14 deletions.
48 changes: 34 additions & 14 deletions utils/blockhash.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,33 @@ async function getDifferenceBetweenSlotHeightAndBlockHeight() {
return absoluteSlot - blockHeight;
}

function getLatestBlockhashFromNotification(
function getLatestBlockhashesFromNotification(
{
context: { slot },
value: {
data: {
parsed: {
info: [{ blockhash }],
info: blockhashes,
},
},
},
},
differenceBetweenSlotHeightAndBlockHeight
) {
return {
return blockhashes.map(({ blockhash }) => ({
blockhash,
lastValidBlockHeight:
slot - differenceBetweenSlotHeightAndBlockHeight + 150n,
};
}));
}

let resolveInitialLatestBlockhash;
let latestBlockhashPromise = new Promise((resolve) => {
resolveInitialLatestBlockhash = resolve;
let resolveInitialLatestBlockhashes;
let latestBlockhashesPromise = new Promise((resolve) => {
resolveInitialLatestBlockhashes = resolve;
});

let usedBlockhashes = new Set();

(async () => {
let attempts = 0;
while (true) {
Expand All @@ -61,18 +63,25 @@ let latestBlockhashPromise = new Promise((resolve) => {
// If the RPC node fails to respond within 5 seconds, throw an error.
timeout(5000),
]);
// Iterate over the notificatons forever, constantly updating the `latestBlockhash` cache.
// Iterate over the notificatons forever, constantly updating the `latestBlockhashes` cache.
for await (const notification of recentBlockhashesNotifications) {
const nextLatestBlockhash = getLatestBlockhashFromNotification(
const nextLatestBlockhashes = getLatestBlockhashesFromNotification(
notification,
differenceBetweenSlotHeightAndBlockHeight
);
const nextUsedBlockhashes = new Set();
for (const { blockhash } of nextLatestBlockhashes) {
if (usedBlockhashes.has(blockhash)) {
nextUsedBlockhashes.add(blockhash)
}
}
usedBlockhashes = nextUsedBlockhashes;
attempts = 0;
if (resolveInitialLatestBlockhash) {
resolveInitialLatestBlockhash(nextLatestBlockhash);
resolveInitialLatestBlockhash = undefined;
if (resolveInitialLatestBlockhashes) {
resolveInitialLatestBlockhashes(nextLatestBlockhashes);
resolveInitialLatestBlockhashes = undefined;
} else {
latestBlockhashPromise = Promise.resolve(nextLatestBlockhash);
latestBlockhashesPromise = Promise.resolve(nextLatestBlockhashes);
}
}
} catch (e) {
Expand All @@ -94,5 +103,16 @@ let latestBlockhashPromise = new Promise((resolve) => {
})();

export async function getLatestBlockhash() {
return await latestBlockhashPromise;
const latestBlockhashes = await latestBlockhashesPromise;
const latestUnusedBlockhash = latestBlockhashes.find(
({ blockhash }) => !usedBlockhashes.has(blockhash),
);
if (!latestUnusedBlockhash) {
console.error(
`${new Date().toISOString()} ERROR: Ran out of unused blockhashes before the subscription could replenish them`,
);
process.exit(0);
}
usedBlockhashes.add(latestUnusedBlockhash.blockhash);
return latestUnusedBlockhash;
}

0 comments on commit b0e5f51

Please sign in to comment.