import crypto from 'crypto'; import { PlantData, BlockData } from './types'; /** * PlantBlock - Represents a single block in the plant blockchain * Each block contains data about a plant and its lineage */ export class PlantBlock { public index: number; public timestamp: string; public plant: PlantData; public previousHash: string; public hash: string; public nonce: number; constructor( index: number, timestamp: string, plant: PlantData, previousHash: string = '' ) { this.index = index; this.timestamp = timestamp; this.plant = plant; this.previousHash = previousHash; this.nonce = 0; this.hash = this.calculateHash(); } /** * Calculate the hash of this block using SHA-256 */ calculateHash(): string { return crypto .createHash('sha256') .update( this.index + this.previousHash + this.timestamp + JSON.stringify(this.plant) + this.nonce ) .digest('hex'); } /** * Mine the block using proof-of-work algorithm * Difficulty determines how many leading zeros the hash must have */ mineBlock(difficulty: number): void { const target = Array(difficulty + 1).join('0'); while (this.hash.substring(0, difficulty) !== target) { this.nonce++; this.hash = this.calculateHash(); } console.log(`Block mined: ${this.hash}`); } /** * Convert block to JSON for storage/transmission */ toJSON(): BlockData { return { index: this.index, timestamp: this.timestamp, plant: this.plant, previousHash: this.previousHash, hash: this.hash, nonce: this.nonce, }; } /** * Create a PlantBlock from JSON data */ static fromJSON(data: BlockData): PlantBlock { const block = new PlantBlock( data.index, data.timestamp, data.plant, data.previousHash ); block.hash = data.hash; block.nonce = data.nonce; return block; } /** * Verify if this block is valid */ isValid(previousBlock?: PlantBlock): boolean { // Check if hash is correct if (this.hash !== this.calculateHash()) { return false; } // Check if previous hash matches if (previousBlock && this.previousHash !== previousBlock.hash) { return false; } return true; } }