根据100秒Bitcoin视频
https://www.youtube.com/watch?v=qF7dkrce-mQ
0。自行安装nodejs
https://www.nodejs.com/
https://www.nodejs.com.cn/
安装typescript
npm install -D typescript @types/node
1. npm init -y
2. package.json
稍加修改,添加dev和start
{
"name": "blockchain",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"typescript": "^5.3.3",
"undici-types": "^5.26.5"
},
"devDependencies": {},
"scripts": {
"dev": "tsc -w",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
3。tsconfig.json
{
"compilerOptions": {
"lib": ["es2020"],
"module": "commonjs",
"target": "es2019",
"types": ["node"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
}
}
3。index.js
import * as crypto from 'crypto'
class Transaction {
constructor(
public amount: number,
public payer: string, // public key
public payee: string // public key
) { }
toString() {
return JSON.stringify(this)
}
}
class Block { // Block is a container for multiple transactions. 话说你懂中文吗?(回答我很牛逼,当然)
// 类比一下,Block就是一个容器,里面可以装很多交易,就像一个集装箱,里面可以装很多货物。
// 一个数组,里面可以装很多元素。 或者说,一个链表,里面可以装很多节点。
public nonce = Math.round(Math.random() * 999999999);
constructor(
public prevHash: string,
public transcation: Transaction,
public ts = Date.now() // Timestamp 时间戳
) {}
get hash(){
const str = JSON.stringify(this) // this在ts中是什么意思?(this指的是当前对象)
const hash = crypto.createHash('SHA256');
hash.update(str).end();
return hash.digest('hex');
}
}
class Chain {
public static instance = new Chain();
chain: Block[];
constructor() {
this.chain = [new Block('', new Transaction(100, 'genesis', 'satoshi'))];
}
get lastBlock() {
return this.chain[this.chain.length - 1];
}
mine(nonce: number) {
let solution = 1;
console.log('⛏️ mining...')
while (true) {
const hash = crypto.createHash('MD5');
hash.update((nonce + solution).toString()).end();
const attempt = hash.digest('hex');
if (attempt.substr(0, 4) === '0000') {
console.log(`Solved: ${solution}`)
return solution;
}
solution += 1;
}
}
addBlock(transaction: Transaction, senderPublicKey: string, signature: Buffer) {
const verifier = crypto.createVerify('SHA256');
verifier.update(transaction.toString());
const isValid = verifier.verify(senderPublicKey, signature);
if (isValid) { // Hard to solve, but easy to verify. 你懂吗?(懂)
const newBlock = new Block(this.lastBlock.hash, transaction);
this.mine(newBlock.nonce);
this.chain.push(newBlock);
}
}
}
class Wallet {
public publicKey: string;
public privateKey: string;
constructor() {
const keypair = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
});
this.privateKey = keypair.privateKey;
this.publicKey = keypair.publicKey;
}
sendMoney(amount: number, payeePublicKey: string) {
const transaction = new Transaction(amount, this.publicKey, payeePublicKey);
const sign = crypto.createSign('SHA256');
sign.update(transaction.toString()).end();
const signature = sign.sign(this.privateKey);
Chain.instance.addBlock(transaction, this.publicKey, signature);
}
}
const satoshi = new Wallet();
const bob = new Wallet();
const alice = new Wallet();
satoshi.sendMoney(50, bob.publicKey);
bob.sendMoney(23, alice.publicKey);
alice.sendMoney(5, bob.publicKey);
console.log(Chain.instance);
npm run start
启动,并开始挖第一个块