15분안에 블록체인 만들기 with js - 1
written by 영수대마왕Referenced by a Savjee's clip (link = https://www.youtube.com/watch?v=zVqczFZr124&t=767s)블록체인에 대한 이야기들이나 비즈니스 모델은 쏟아질 정도로 많이 찾아볼 수 있지만, 개발자로써 실제 블록체인의 모습이 어떤지, 실제 거래가 어떻게 이루어지는지, 마지막으로 그래서 블록체인은 어떻게 구현해야 하는지? 그외에도 지갑, 트렌젝션 등에서 속시원한 답변을 찾기는 힘들었으리라 생각한다.그래서 준비했다. 실제로 자기만의 코인을 만들면서 블록체인을 공부하고, 앞으로 더 개선해야될 점이 무엇인지 생각할 기회를 갖어보자! (코드블럭에 있는거 그대로 복붙하면 돌아감. But 직접 한번 만들어볼것 오류있으면 [email protected] 으로 메일바람.)
What is the Block-Chain?
누구나 읽을 수 있는 블록으로 이루어진 퍼블릭 데이터베이스. 각각의 블록은 immutable properties(변하지 않는 멤버변수?)를 가지고 있다. 그렇기에 한 블록이 한번 체인에 추가되면 절대 변할수 없게 된다.
Why Block-Chain?
앞서 말했듯, 블록체인은 누구나 읽을 수 있는 블록들이 곳곳에 퍼진 퍼블릭 데이터베이스이다. 이러한 특징은 현재 우리가 사용하는 한개의 서버시스템의 최대 약점인 Single Point Of Failure(SPOF, 단일 장애점)를 보안해줄 수 있다.
What will we learn, today?
How to build a block-chain by immutable blocks
- Block의 구성요소
- Block-Chain의 구성
- 어떻게 체인이 유효판별을 하는지? (왜 변조가 불가능한지?)
Ready to Code (in Terminal)
npm init
npm install --save crypto-js
vim ysCoin.js #원하는 편집기 이용하셔도 됨 (sublimeText, WebStorm,...any editors for js are okay)
How to Run (in Terminal)
node ysCoin.js
Block
블록체인의 블록은 크게 두가지로 이루어져있다.
- 자기의 속성을 나타내는 properties.
- properties로 만들어진 hash
properties는 자유롭게 정의할 수 있지만 몇가지 필수 요소가 있다.
- timestamp
- transactions (for trading values, not today)
- hash
- previousHash
- nonce (for mining, not today)
오늘 우리가 구성할 Properties (Transaction 생략)
- index
- timestamp
- data
- previousHash
- hash
const SHA256 = require('crypto-js/sha256');
class Block() {
constructor(index, timeStamp, data, previousHash) {
this.index = index;
this.previousHash = previousHash;
this.timeStamp = timeStamp;
this.data = data;
this.hash = this.calculateHash();
}
calculateHash() {
return SHA256(this.index + this.previousHash + this.timeStamp + JSON.stringify(this.data)).toString;
}
}
- constructor : ES6에서 사용하는 class 생성자. 이 생정자를 통해 각 properties를 할당하자.
- calculateHash : hash암호화 방식중 하나인 SHA256을 이용한 Hash화 함수.
properties인 index, perviousHash, timeStamp, data 를 다 포함해서 (여기선 더하는 방식을 이용) hash를 만듦.SHA256(this.index + this.previousHash + this.timeStamp + JSON.stringify(this.data)).toString
BlockChain
블록체인은 4가지의 행동이 필수적으로 필요하다.
- GenesisBlock 생성하기
- 가장 최근 생성된 Block 가져오기
- Block 추가하기
- Chain이 유효한지 검사하기
GenesisBlock
블록체인의 무결성은 이전에 생성된 블록의 해쉬값의 전파로 이루어진다. 근데 블록체인에 블록이 하나도 없다면????매우 당혹스럽다. 그래서 만든다 최초의 Block, GenesisBlock.
class BlockChain {
constructor(){
this.chain = [this.createGenesisBlock];
}
createGenesisBlock(){
return new Block(0, "01/01/2018", "Genesis Block", "0");
}
getLastestBlock() {
return this.chain[this.chain.length - 1];
}
addBlock(newBlock) {
newBlock.previousHash = this.getLastestBlock().hash;
newBlock.hash = newBlock.calculateHash();
this.chain.push(newBlock);
}
isChainVaild() {
let genesisBlock = this.chain[0];
if (genesisBlock !== genesisBlock.calculateHash()) {
return false;
}
for (let i = 1; i < this.chain.length - 1; i++) {
let previousBlock = this.chain[i - 1];
let currentBlock = this.chain[i];
if (currentBlock.hash !== currentBlock.calculateHash()) {
return false;
}
if(currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
return true;
}
}
- createGenesisBlock : 최초의 블록을 생성한다. 이때 중요한점은 GenesisBlock은 첫번째 블록이기 때문에 이전 블록이 필요하지 않다. -> previousHash값에 0을 집어넣는다. null은 너무 정이 없다.new Block(0, "01/01/2018", "Genesis Block", "0")
- getLastestBlock : 가장 최근의 블록을 불러온다
- addBlock(newBlock) : 새로운 블록을 생성해 붙인다.마이닝 과정 생략 (POW, proof of work learn it, tomorrow)중요한점 2가지 : 1. 해쉬값 계산하기 (현재 블록의 calculateHash 이용) 2. 이전 블록의 해쉬값 가지기 (블록체인의 getLastestBlock().hash 이용)
- isChainVaild: 현재 체인의 유효성 검사하기
- Check List in a loop
- 시작은 1이다. 왜? Genesis Block은 이전 해쉬값이 없기때문 -> 따로 빼서 자기 해쉬 값이 유효한지만 보자.
- 자기 properties를 이용한 해쉬값과 자기 해쉬값이 같은지 확인 (위조 방지 : blockChain[3].money = 100; 이런식 으로 위조할려고 하면 여기서 다 들통나버리고 만다)
- 현재 블록의 previousHash과 이전 블록의 hash값이 같은지 확인 (중간에 들어온 블록이 없는지 확인 : blockChain[4] = new Block(조작된 생성자 파라미터) => 여기서 들통나버림
- Good Luck, Hackers ^^
- Check List in a loop
Useage of Our BlockChain Code
let ysCoin = new BlockChain();
ysCoin.addBlock(new Block(1, "20/07/2017", { amount: 4 }));
ysCoin.addBlock(new Block(2, "20/07/2017", { amount: 8 }));
console.log('Blockchain valid? ' + savjeeCoin.isChainValid()); // => true
console.log('Changing a block...');
ysCoin.chain[1].data = { amount: 100 }; // => 위조
console.log("Blockchain valid? " + savjeeCoin.isChainValid()); // => false