ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BlockChain 만들기 - 3)Blockchain 만들기
    TYPESCRIPT 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값을 가지고 있다. 

     

     

     

     

     

     

     

Designed by Tistory.