TYPESCRIPT
BlockChain 만들기 - 3)Blockchain 만들기
dodop
2021. 5. 18. 16:36
이제 타입스크립트로 블록체인을 만들어보자 .
index.ts를 다음과 같이 바꿔주자.
타입스크립은 다음과 같이 타입자체를 설정할 수 있다.
class Block {//블록 구조를 만든다.
public index: number;
public hash: string;
public previousHash : string;
public data: string;
public timestamp : number;
constructor(index:number, hash:string, previousHash:string, data:string, timestamp:number){
this.index = index;
this.hash = hash;
this.previousHash = previousHash;
this.data = data;
this.timestamp = timestamp;
}
}
//첫번째 블록을 만들자.(여기서 :Block은 타입이 블록이라는 뜻이다.)
const genesisBlock:Block = new Block(0, "202020202020", "", "Hello", 123456)
//블록으로 이루어진 배열에 첫번째 블록을 넣는다.
let blockchain: [Block] = [genesisBlock];
console.log(blockchain);
export {};//타입스크립트의 방식(이걸 해야 선언이 가능하다)
콘솔창에 뜨는 것을 확인할 수 있다.
이제 해시를 계산해서 생산해내는 기능을 만들어 블럭을 만들어보자 .
crypto-js를 기능을 사용할 것이다.
yarn add crypto-js
설치하고 나서 다음과 같이 import해준다. (자바스크립트의 방식과는 다르다)
import * as CryptoJS from "crypto-js";
자바스크립트에서 블록체인을 만들때는 클래스 밖에 생성했지만,
타입스크립트는 클래스 안에 생성해준다.
이는 블록클래스 안에서 항상 사용할 수 있는 method라는 의미다.
즉, 블록을 생성했을 때에만 (블록타입일때만)사용이 가능한 함수라는 의미다. (여기서 static을 써야 Block.~의 형태로 사용이 가능하다)
import * as CryptoJS from "crypto-js";
class Block {//블록 구조를 만든다.
public index: number;
public hash: string;
public previousHash : string;
public data: string;
public timestamp : number;
static calculateBlockHash = (index:number, previousHash:string, timestamp:number, data:string ):string=>CryptoJS.SHA256(index+previousHash+timestamp+data).toString();
constructor(index:number, hash:string, previousHash:string, data:string, timestamp:number){
this.index = index;
this.hash = hash;
this.previousHash = previousHash;
this.data = data;
this.timestamp = timestamp;
}
}
여러가지 함수를 추가해서 만들어보자.
import * as CryptoJS from "crypto-js";
class Block {//블록 구조를 만든다.
public index: number;
public hash: string;
public previousHash : string;
public data: string;
public timestamp : number;
static calculateBlockHash = (index:number, previousHash:string, timestamp:number, data:string ):string=> CryptoJS.SHA256(index+previousHash+timestamp+data).toString();
constructor(index:number, hash:string, previousHash:string, data:string, timestamp:number){
this.index = index;
this.hash = hash;
this.previousHash = previousHash;
this.data = data;
this.timestamp = timestamp;
}
}
//첫번째 블록을 만들자.(여기서 :Block은 타입이 블록이라는 뜻이다.)
const genesisBlock:Block = new Block(0, "202020202020", "", "Hello", 123456)
//블록으로 이루어진 배열에 첫번째 블록을 넣는다.
let blockchain: Block[] = [genesisBlock];
console.log(blockchain);
//블록들을 가지고 오는 함수
const getBlockchain = () :Block[] => blockchain;
//가장 마지막 블록을 가지고 오는 함수 (최근것)
const getLatestBlock = () :Block => blockchain[blockchain.length-1];
//새로운 시간을 가지고 오는 함수(현재)
const getNewTimeStamp = ():number=> Math.round(new Date().getTime()/1000);
새로운 블록을 만드는 함수를 생성하고 결과를 보자 .
//새로운 블록을 만드는 함수
const createNewBlock = (data:string) : Block =>{
const previousBlock :Block = getLatestBlock();
const newIndex :number = previousBlock.index +1;
const newTimestamp:number = getNewTimeStamp();
const newHash :string = Block.calculateBlockHash(newIndex, previousBlock.hash, newTimestamp, data);
const newBlock:Block = new Block(newIndex, newHash, previousBlock.hash, data,newTimestamp );
return newBlock;
};
console.log(createNewBlock("hello"), createNewBlock("bye bye"));
여기서 인덱스가 계속 1인 이유는 블록 배열안에 원래 블록인 genesisblock만을 가지고 있기 때문이다.
이번엔 만든 것들이 validate한지 확인하자.
import * as CryptoJS from "crypto-js";
class Block {//블록 구조를 만든다.
//블록의 구조가 맞는지 확인하는 static함수
static validateStructure = (aBlock:Block) : boolean =>
typeof aBlock.index ==="number" &&
typeof aBlock.hash ==="string" &&
typeof aBlock.previousHash==="string" &&
typeof aBlock.timestamp ==="number" &&
typeof aBlock.data ==="string";
}
//두개의 block을 비교해서 타당한지 확인
const isBlockValid = (candidateBlock:Block, previousBlock:Block):boolean =>{
if(!Block.validateStructure(candidateBlock)){
return false;
}else if(previousBlock.index+1 !== candidateBlock.index){
return false;
} else if(previousBlock.hash!== candidateBlock.previousHash){
return false;
} //여기는 따로 해쉬를 계산해서 들어온 블록의 해쉬가 실제로 있는지 확인한다.
else if()
}
블록의 해쉬를 가져오는함수를 따로 작성해준다.
const getHashforBlock = (aBlock:Block):string =>Block.calculateBlockHash(aBlock.index,aBlock.previousHash, aBlock.timestamp, aBlock.data )
//두개의 block을 비교해서 타당한지 확인
const isBlockValid = (candidateBlock:Block, previousBlock:Block):boolean =>{
if(!Block.validateStructure(candidateBlock)){
return false;
}else if(previousBlock.index+1 !== candidateBlock.index){
return false;
} else if(previousBlock.hash!== candidateBlock.previousHash){
return false;
} //여기는 따로 해쉬를 계산해서 들어온 블록의 해쉬가 실제로 있는지 확인한다.
else if(getHashforBlock(candidateBlock)!== candidateBlock.hash){
return false;
}else{
return true;
}
};
이제 블록을 추가하자.
//블록을 추가하자.
const addBlock = (candidateBlock:Block):void=>{
if(isBlockValid(candidateBlock, getLatestBlock())){
blockchain.push(candidateBlock);
}
}
createNewBlock함수에 addBlock함수를 추가하자.
//새로운 블록을 만드는 함수
const createNewBlock = (data:string) : Block =>{
const previousBlock :Block = getLatestBlock();
const newIndex :number = previousBlock.index +1;
const newTimestamp:number = getNewTimeStamp();
const newHash :string = Block.calculateBlockHash(newIndex, previousBlock.hash, newTimestamp, data);
const newBlock:Block = new Block(newIndex, newHash, previousBlock.hash, data,newTimestamp );
addBlock(newBlock);
return newBlock;
};
다음과 같이 실행해보면,
createNewBlock("second block");
createNewBlock("third block");
createNewBlock("fourth block");
console.log(blockchain);
올바르게 생성됐음을 확인할 수 있다.
모두 previousHash값을 가지고 있다.