UNPKG

@atomiqlabs/chain-starknet

Version:

Starknet specific base implementation

142 lines (123 loc) 5.14 kB
import {BtcStoredHeader, StatePredictorUtils} from "@atomiqlabs/base"; import {StarknetBtcHeader, StarknetBtcHeaderType} from "./StarknetBtcHeader"; import {Buffer} from "buffer"; import {BigNumberish, cairo, Uint256} from "starknet"; import {bigNumberishToBuffer, bufferToU32Array, u32ArrayToBuffer, isUint256, toHex} from "../../../utils/Utils"; export type StarknetBtcStoredHeaderType = { blockheader: StarknetBtcHeader | StarknetBtcHeaderType, block_hash: BigNumberish[], chain_work: BigNumberish | Uint256, block_height: BigNumberish, last_diff_adjustment: BigNumberish, prev_block_timestamps: BigNumberish[] } export class StarknetBtcStoredHeader implements BtcStoredHeader<StarknetBtcHeader> { blockheader: StarknetBtcHeader; block_hash: number[]; chain_work: Uint256; block_height: number; last_diff_adjustment: number; prev_block_timestamps: number[]; constructor(obj: StarknetBtcStoredHeaderType) { this.blockheader = obj.blockheader instanceof StarknetBtcHeader ? obj.blockheader : new StarknetBtcHeader(obj.blockheader); this.block_hash = obj.block_hash.map(val => Number(val)); this.chain_work = isUint256(obj.chain_work) ? obj.chain_work : cairo.uint256(obj.chain_work); this.block_height = Number(obj.block_height); this.last_diff_adjustment = Number(obj.last_diff_adjustment); this.prev_block_timestamps = obj.prev_block_timestamps.map(val => Number(val)); } getBlockheight(): number { return this.block_height; } getChainWork(): Buffer { return bigNumberishToBuffer(this.chain_work, 32); } getHeader(): StarknetBtcHeader { return this.blockheader; } getLastDiffAdjustment(): number { return this.last_diff_adjustment; } getPrevBlockTimestamps(): number[] { return this.prev_block_timestamps; } getBlockHash(): Buffer { return u32ArrayToBuffer(this.block_hash).reverse(); } /** * Computes prevBlockTimestamps for a next block, shifting the old block timestamps to the left & appending * this block's timestamp to the end * * @private */ private computeNextBlockTimestamps(): number[] { const prevBlockTimestamps = [...this.prev_block_timestamps]; for(let i=1;i<10;i++) { prevBlockTimestamps[i-1] = prevBlockTimestamps[i]; } prevBlockTimestamps[9] = this.blockheader.getTimestamp(); return prevBlockTimestamps; } /** * Computes total chain work after a new header with "nbits" is added to the chain * * @param nbits * @private */ private computeNextChainWork(nbits: number): Buffer { const chainWork = [...this.getChainWork()]; StatePredictorUtils.addInPlace(chainWork, [...StatePredictorUtils.getChainwork(nbits)]); return Buffer.from(chainWork); } /** * Computes lastDiffAdjustment, this changes only once every DIFF_ADJUSTMENT_PERIOD blocks * * @param headerTimestamp * @private */ private computeNextLastDiffAdjustment(headerTimestamp: number) { const blockheight = this.block_height+1; let lastDiffAdjustment = this.last_diff_adjustment; if(blockheight % StatePredictorUtils.DIFF_ADJUSTMENT_PERIOD === 0) { lastDiffAdjustment = headerTimestamp; } return lastDiffAdjustment; } computeNext(header: StarknetBtcHeader): StarknetBtcStoredHeader { return new StarknetBtcStoredHeader({ chain_work: "0x"+this.computeNextChainWork(header.getNbits()).toString("hex"), prev_block_timestamps: this.computeNextBlockTimestamps(), block_height: this.block_height+1, last_diff_adjustment: this.computeNextLastDiffAdjustment(header.getTimestamp()), block_hash: bufferToU32Array(header.getHash()), blockheader: header }); } serialize(): BigNumberish[] { return [ ...this.blockheader.serialize(), ...this.block_hash, this.chain_work.low, this.chain_work.high, this.block_height, this.last_diff_adjustment, ...this.prev_block_timestamps ] } static fromSerializedFeltArray(span: BigNumberish[]): StarknetBtcStoredHeader { const blockheader = StarknetBtcHeader.fromSerializedFeltArray(span); const block_hash = span.splice(0, 8).map(toHex); const chain_work = {low: span.shift(), high: span.shift()}; const block_height = toHex(span.shift()); const last_diff_adjustment = toHex(span.shift()); const prev_block_timestamps = span.splice(0, 10).map(toHex); return new StarknetBtcStoredHeader({ blockheader, block_hash, chain_work, block_height, last_diff_adjustment, prev_block_timestamps }); } }