Thuta Learning
ရှာဖွေရန်
ProjectsSecurityadvanced

Mini Blockchain Project — အပိုင်း ၃: Wallet, Signature နဲ့ Chain Validation ဖြင့် အပြီးသတ်ခြင်း

စိတ်လျှော့ပါ။ ဒီခန်းကို စာအုပ်လိုမဟုတ်ဘဲ စကားပြောသလိုပဲ၊ နားလည်လွယ်အောင် ရှင်းပါမယ်။

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Mini Blockchain Project — အပိုင်း ၃: Wallet, Signature နဲ့ Chain Validation ဖြင့် အပြီးသတ်ခြင်း ကို လက်တွေ့ project ထဲမှာ အသုံးချတတ်မယ်
  • ကိုယ်တိုင် code ရေးပြီး run ကြည့်တတ်မယ်
  • Project တစ်ခုလုံးကို အဆင့်လိုက် ဆောက်တတ်မယ်

ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်

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 နမူနာ

javascript
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());
You should see
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 လုပ်ထားတာဖြစ်ပါတယ်။

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • Transaction ကို sign လုပ်တဲ့အခါ signingKey ရဲ့ public key ကို fromAddress နဲ့ တိုက်စစ်ဖို့ မေ့ပြီး wallet အမှား private key နဲ့ sign လို့ရနေအောင် ထားလိုက်ခြင်း
  • Tamper test လုပ်တဲ့အခါ data ကိုပြောင်းပြီးနောက် block.hash field ကိုပါ manual ပြန်ရေးလိုက်မိလို့ isChainValid() က true အတု ပြန်ပြနေခြင်း (data ပဲ ပြောင်းပြီး hash field ကို မထိမှ tamper-detection ကို မှန်ကန်စွာ စမ်းသပ်ရာရောက်ပါတယ်)

အခု ကိုယ်တိုင် စမ်းကြည့်

Wallet key pair ကို နှစ်စုံထပ်ထုတ်ပြီး wallet A ကနေ wallet B ဆီ transaction တစ်ခု sign လုပ်ပြီး ပို့ကြည့်ပါ၊ ပြီးရင် isValid() က true ပြန်ပေးမလား 5 မိနစ်အတွင်း စမ်းကြည့်ပါ။

You'll know it worked when: Tamper မလုပ်ခင် isChainValid() က true ကို print ထုတ်ပြီး၊ chain[1].data ကို manual ပြင်ပြီးနောက် ထပ်ခေါ်တဲ့အခါ false ကို print ထုတ်ပြပါလိမ့်မယ် — ဒါက blockchain ရဲ့ tamper-detection အလုပ်လုပ်ပုံကို သက်သေပြနေတာပါ။