Merge branch 'bip30_protections_and_blockheight' into 'development'

fix(BlockchainInMemory): BIP30 protections and fetchChainTip

See merge request GeneralProtocols/xo/stack!110
This commit is contained in:
Jim Hamill
2025-07-14 00:27:00 +00:00
@@ -23,8 +23,9 @@ import {
createVirtualMachineBCH, createVirtualMachineBCH,
} from '@bitauth/libauth'; } from '@bitauth/libauth';
// Local Blockchain Adapter. /**
// This simulates the BCH Blockchain. * @remarks This provider DOES NOT enforce the 100 confirmations Coinbase Transaction rule.
**/
export class BlockchainInMemory extends BaseBlockchain { export class BlockchainInMemory extends BaseBlockchain {
static async from<T extends typeof BlockchainInMemory>(this: T) { static async from<T extends typeof BlockchainInMemory>(this: T) {
const blockchain = new this(); const blockchain = new this();
@@ -104,10 +105,14 @@ export class BlockchainInMemory extends BaseBlockchain {
return blockHeader; return blockHeader;
} }
// TODO: Implement a method for fetching the chain tip.
// This is a placeholder for now.
async fetchChainTip(): Promise<BlockchainChainTip> { async fetchChainTip(): Promise<BlockchainChainTip> {
throw new Error('Not implemented yet'); const height = this.blockHeaders.length;
const blockHeader = this.blockHeaders[height - 1];
return {
height,
blockHeader,
};
} }
async broadcastTransaction( async broadcastTransaction(
@@ -347,14 +352,6 @@ export class BlockchainInMemory extends BaseBlockchain {
} }
async mineBlock(outputs: Array<Output>): Promise<void> { async mineBlock(outputs: Array<Output>): Promise<void> {
// Create a block header from the current timestamp.
const newBlockHeader = BlockHeader.generateRandom(
Math.floor(Date.now() / 1000),
);
// Add it to our list of block headers.
this.blockHeaders.push(newBlockHeader);
// Create a transaction that pays to our subscribed address. // Create a transaction that pays to our subscribed address.
const transaction = Transaction.fromRaw({ const transaction = Transaction.fromRaw({
version: 2, version: 2,
@@ -370,6 +367,24 @@ export class BlockchainInMemory extends BaseBlockchain {
outputs, outputs,
}); });
// Calculate the hash of this transaction.
const coinbaseTxHash = transaction.toHash();
// Ensure that this transaction hash does not already exist (as per BIP30).
if (this.transactions.has(coinbaseTxHash.toHex())) {
throw new Error(
`Transaction ID "${coinbaseTxHash.toHex()}" already exists (see BIP30 for details)`,
);
}
// Create a block header from the current timestamp.
const newBlockHeader = BlockHeader.generateRandom(
Math.floor(Date.now() / 1000),
);
// Add it to our list of block headers.
this.blockHeaders.push(newBlockHeader);
// Broadcast that transaction. // Broadcast that transaction.
await this.broadcastTransaction(transaction, { skipValidation: true }); await this.broadcastTransaction(transaction, { skipValidation: true });
} }