ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်
Wallets, keys, wallet-safety chapter တွေမှာ သင်ခဲ့တဲ့ public/private key concept ကို ဒီနောက်ဆုံးအပိုင်းမှာ တကယ်လက်တွေ့ ချိတ်ဆက်ပါမယ်။ Real wallet တစ်ခုက private key နဲ့ transaction ကို sign လုပ်ပြီး public key (wallet address) နဲ့ တခြားသူတွေက verify လုပ်နိုင်ပါတယ်။ ဒါ့အပြင် blockchain ရဲ့ core security property ဖြစ်တဲ့ immutability ကို isChainValid() function တစ်ခုရေးပြီး သက်သေပြပါမယ် — block တစ်ခုချင်းစီရဲ့ hash ကို ပြန်တွက်ပြီး မူရင်း hash နဲ့ တူမတူ၊ previousHash link မှန်မမှန် စစ်ဆေးတာဖြစ်ပါတယ်။ Chain ထဲက data တစ်ခုကို manual tamper လုပ်ကြည့်ပြီး validation function က ဖမ်းမိလား စမ်းသပ်ခြင်းအားဖြင့် ဒီ project တစ်ခုလုံးကို ပြီးစီးအောင် အနှစ်ချုပ်လုပ်ပါမယ်။
လက်တွေ့ ဆောက်ကြည့်မယ်
crypto.generateKeyPairSync('ec', {namedCurve:'secp256k1'}) နဲ့ wallet keyPair တစ်စုံ generate လုပ်ပါ။ Transaction class ထဲမှာ calculateHash(), sign(signingKey), isValid() method သုံးခု ထည့်ပါ — sign() ထဲမှာ private key နဲ့ transaction hash ကို sign လုပ်ပြီး signature field သိမ်းပါ၊ isValid() ထဲမှာ public key နဲ့ signature ကို verify ပြန်စစ်ပါ။ Blockchain class ထဲမှာ isChainValid() method ရေးပါ — for loop နဲ့ chain[i].hash ကို calculateHash() ပြန်ခေါ်တွက်ပြီး ညီမညီ၊ chain[i].previousHash === chain[i-1].hash ဟုတ်မဟုတ် စစ်ပါ။ နောက်ဆုံး console.log(myChain.isChainValid()) ကို true ပြရင် chain[1].data ကို manual ပြောင်းပြီး ထပ် isChainValid() ခေါ်ကြည့်ပါ — false ပြန်ပြရပါလိမ့်မယ်။
Code နမူနာ
const crypto = require('crypto');
const { generateKeyPairSync, sign, verify } = crypto;
// 1. Wallet key pair
const { publicKey, privateKey } = generateKeyPairSync('ec', {
namedCurve: 'secp256k1',
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
});
class Transaction {
constructor(fromAddress, toAddress, amount) {
this.fromAddress = fromAddress;
this.toAddress = toAddress;
this.amount = amount;
}
calculateHash() {
return crypto
.createHash('sha256')
.update(this.fromAddress + this.toAddress + this.amount)
.digest('hex');
}
sign(signingKeyPem) {
this.signature = sign('sha256', Buffer.from(this.calculateHash()), signingKeyPem).toString('hex');
}
isValid(publicKeyPem) {
if (!this.signature) return false;
return verify('sha256', Buffer.from(this.calculateHash()), publicKeyPem, Buffer.from(this.signature, 'hex'));
}
}
class Blockchain {
// ... chain, difficulty, mineBlock လို part 2 ကလာတဲ့ property/method တွေ ဆက်သုံးပါ
isChainValid() {
for (let i = 1; i < this.chain.length; i++) {
const current = this.chain[i];
const previous = this.chain[i - 1];
if (current.hash !== current.calculateHash()) return false;
if (current.previousHash !== previous.hash) return false;
}
return true;
}
}
const tx = new Transaction('wallet-A', 'wallet-B', 25);
tx.sign(privateKey);
console.log('Transaction valid?', tx.isValid(publicKey));
// tamper test (myChain က Part 1-2 ကနေ ဆက်ခံထားတဲ့ instance)
console.log('Blockchain valid?', myChain.isChainValid());
myChain.chain[1].data = { amount: 999999 };
console.log('Blockchain valid after tamper?', myChain.isChainValid());
Tamper မလုပ်ခင် isChainValid() က true ကို print ထုတ်ပြီး၊ chain[1].data ကို manual ပြင်ပြီးနောက် ထပ်ခေါ်တဲ့အခါ false ကို print ထုတ်ပြပါလိမ့်မယ် — ဒါက blockchain ရဲ့ tamper-detection အလုပ်လုပ်ပုံကို သက်သေပြနေတာပါ။၅ မိနစ် စမ်းကြည့်
Wallet key pair ကို နှစ်စုံထပ်ထုတ်ပြီး wallet A ကနေ wallet B ဆီ transaction တစ်ခု sign လုပ်ပြီး ပို့ကြည့်ပါ၊ ပြီးရင် isValid() က true ပြန်ပေးမလား 5 မိနစ်အတွင်း စမ်းကြည့်ပါ။
သတိလေးတစ်ချက်
Private key ကို console.log() နဲ့ print ထုတ်ခြင်း၊ GitHub repo ထဲထည့်ခြင်းစတာတွေ လက်တွေ့ project မှာ လုံးဝမလုပ်သင့်ပါဘူး — ဒီ demo က local learning အတွက်သာ throwaway key ကို generate လုပ်ထားတာဖြစ်ပါတယ်။