You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.0 KiB
105 lines
3.0 KiB
4 years ago
|
import { getblock, getblockcount, getblockhash, getrawtransaction } from "../jsonrpc/index.ts";
|
||
4 years ago
|
|
||
4 years ago
|
import config from "../config/config.ts";
|
||
|
import miners from "./miners.ts";
|
||
|
import { hexToAscii } from "../utils.ts";
|
||
4 years ago
|
|
||
|
export interface IBlock {
|
||
|
height: number;
|
||
|
// hash: string;
|
||
4 years ago
|
signals: boolean | undefined;
|
||
4 years ago
|
coinbase: string | undefined;
|
||
|
miner: string | undefined;
|
||
4 years ago
|
}
|
||
|
|
||
4 years ago
|
let blocks: IBlock[] = [];
|
||
4 years ago
|
|
||
4 years ago
|
async function createBlock(height: number): Promise<IBlock> {
|
||
|
const blockHash = await getblockhash(height);
|
||
4 years ago
|
const block = await getblock(blockHash);
|
||
|
|
||
|
const generationTransactionTxId = block.tx[0];
|
||
|
const generationTransaction = await getrawtransaction(generationTransactionTxId, block.hash);
|
||
|
const coinbase = hexToAscii(generationTransaction.vin[0].coinbase ?? "");
|
||
|
|
||
|
const miner = (() => {
|
||
|
for (const [tag, minerInfo] of Object.entries(miners.coinbase_tags)) {
|
||
|
if (coinbase.includes(tag)) {
|
||
|
return minerInfo.name;
|
||
|
}
|
||
|
}
|
||
|
return undefined;
|
||
|
})();
|
||
|
|
||
4 years ago
|
return {
|
||
4 years ago
|
coinbase,
|
||
|
miner,
|
||
|
height: block.height,
|
||
4 years ago
|
// hash: blockheader.hash,
|
||
4 years ago
|
signals: (block.version & (config.fork.versionBit + 1)) === config.fork.versionBit + 1,
|
||
4 years ago
|
};
|
||
|
}
|
||
|
|
||
4 years ago
|
async function setupPeriod(blockCount: number, startHeight: number, endHeight: number): Promise<IBlock[]> {
|
||
|
const blocks: IBlock[] = [];
|
||
|
for (let i = startHeight; i < endHeight; i++) {
|
||
4 years ago
|
if (i > blockCount) {
|
||
|
blocks.push({
|
||
|
height: i,
|
||
|
signals: undefined,
|
||
4 years ago
|
coinbase: undefined,
|
||
|
miner: undefined,
|
||
4 years ago
|
});
|
||
|
continue;
|
||
|
}
|
||
4 years ago
|
try {
|
||
4 years ago
|
blocks.push(await createBlock(i));
|
||
4 years ago
|
} catch (error) {
|
||
|
console.error("Block boostrapping failed");
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
|
||
4 years ago
|
return blocks;
|
||
|
}
|
||
|
|
||
|
export async function bootstrapBlocks() {
|
||
|
console.log("Bootstrapping block data...");
|
||
|
|
||
|
let blockCount = await getblockcount();
|
||
|
const difficultyPeriodStartHeight = blockCount - (blockCount % 2016);
|
||
|
const difficultyPeriodEndHeight = difficultyPeriodStartHeight + 2016;
|
||
|
console.log(`Current block height is ${blockCount}`);
|
||
|
blocks = await setupPeriod(blockCount, difficultyPeriodStartHeight, difficultyPeriodEndHeight);
|
||
|
|
||
4 years ago
|
setInterval(async () => {
|
||
|
const newBlockCount = await getblockcount();
|
||
|
if (newBlockCount > blockCount) {
|
||
4 years ago
|
console.log("Found new block");
|
||
|
if (newBlockCount % 2016 === 0) {
|
||
|
blockCount = newBlockCount;
|
||
|
console.log("New block period!");
|
||
|
const difficultyPeriodStartHeight = blockCount - (blockCount % 2016);
|
||
|
const difficultyPeriodEndHeight = difficultyPeriodStartHeight + 2016;
|
||
|
|
||
|
console.log(`Current block height is ${blockCount}`);
|
||
|
blocks = await setupPeriod(blockCount, difficultyPeriodStartHeight, difficultyPeriodEndHeight);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (let i = blockCount + 1; i <= newBlockCount; i++) {
|
||
4 years ago
|
const block = await createBlock(i);
|
||
|
blocks[i % 2016] = block;
|
||
4 years ago
|
console.log(`Block ${i} set`);
|
||
4 years ago
|
}
|
||
4 years ago
|
blockCount = newBlockCount;
|
||
4 years ago
|
}
|
||
|
}, 10 * 1000);
|
||
|
|
||
4 years ago
|
console.log("Done.");
|
||
|
}
|
||
|
|
||
|
export function getBlocks() {
|
||
|
return blocks;
|
||
|
}
|