블록체인(Blockchain)의 기본 개념, 제네시스 블록(Genesis Block) 만들기

2021. 10. 18. 16:09Blockchain/Blockchain

기본 개념

  • 네트워크 : http, socket
  • 분산원장 : 데이터를 저장하는 코드(블록)
    Hash sha256 -> JWT
    단방향 암호화 -> 자리수 고정 // a -> 64암호화
  • 머클(Merkle)
    너무 많은 노드(블록)들을 찾기에(완전 탐색) 리소스의 낭비가 커 효율이 낮아 연결 된 데이터 중 찾고자하는 데이터를 효율적으로 찾기 위해 사용
  • 작업증명(PoW, Proof of Work) = 마이닝(Mining)

제네시스 블록 만들기

- 제네시스 블록의 구조

 

  1. npm init
  2. src 폴더 생성
  3. cd src
  4. block.js 파일 생성 후 코드 작성
  5. version 가져오기
    const fs = require('fs'); // file system package
    
    function getVersion() {
        const { version } = JSON.parse(fs.readFileSync("../package.json"));
        // console.log(package.toString('utf8'));
        // console.log(JSON.parse(package));
        // console.log(JSON.parse(package).version);
        console.log(version);
        return version;
    }
    
    getVersion();
    console.log(version);
  6. timestamp 가져오기
    function getCurrentTime(){
        console.log(new Date());
        // getTime 메서드로 변환 후 ceil()로 소수점 올림 처리
        console.log(Math.ceil(new Date().getTime()/1000));
        return Math.ceil(new Date().getTime()/1000);
    }
    
    getCurrentTime();
    console.log(new Date()), console.log(Math.ceil(new Date().getTime()/1000));
  7. 새 패키지 설치
    npm install merkle
    npm install merkletreejs
    npm install crypto-js

  8. merkle.js 파일 생성 후 코드 작성
  9. merkle 가져오기
    // 변수명 색에 따라 데이터 타입 확인 가능
    // 초록색 == Class, 노란색 == 함수
    const { MerkleTree } = require('merkletreejs');
    const SHA256 = require('crypto-js/sha256');
    
    console.log('SHA256 check : ', SHA256('check').toString() );
    
    const testSet = ['a','b','c'].map(v => SHA256(v));
    console.log('testSet : ', testSet);
    
    const tree = new MerkleTree(testSet, SHA256);
    console.log('tree : ', tree);
    
    const root = tree.getRoot().toString('hex'); // utf8 안됨
    console.log('root : ', root);
    
    const testRoot = 'a';
    const leaf = SHA256(testRoot);
    const proof = tree.getProof(leaf);
    console.log('tree.verify : ', tree.verify(proof, leaf, root) ); // 비교
    console.log('tree.toString : ', tree.toString() );​
    text로 만들기 // console.log(SHA256 check);
    a, b, c를 배열에 담아 암호화 // console.log(testSet);
    배열을 머클에 적용 // console.log(tree);
    getRoot() : 최상위 노드 가져오는 메서드 // console.log(root);
    coinsole.log(tree.verify(proof, leaf, root));
    console.log(tree.toString());
  10. 헤더 만들기
    const fs = require('fs'); // file system package
    const merkle = require('merkle');
    const CryptoJs = require('crypto-js');
    
    /*
        사용법, sync 배열만 가능
        const tree =
        merkle("sha256")    // 인자값 : 암호화 방법
        .sync([]);          // tree 구조로 변환
        tree.root();        // root를 가져옴
    */
    
    // 붕어빵 틀
    class BlockHeader{
        constructor(version, index, previousHash, time, merkleRoot, difficulty, nonce){ // Header를 만들 인자값 5개
            this.version = version;             // 1 { version : 1 }
            this.index = index;                 // 2 { version : 1, index : 2}
            this.previousHash = previousHash;   // 3 { version : 1, index : 2, previousHash : 3}
            this.time = time;                   // ...
            this.merkleRoot = merkleRoot;       // ......
        }
        // 안에서 함수 선언도 가능, React에서 했던 Render 등..
        // render(){}
    }
    
    // 헤더 블록 확인
    const header = new BlockHeader(1,2,3,4,5);
    console.log(header);
    
    class Block{
        constructor(header, body){
            this.header = header;
            this.body = body;
        }
    }
    
    // // 단일 블록 확인
    const blockchain = new Block(new BlockHeader(1,2,3,4,5), ['hello']);
    console.log(blockchain);
    console.log(header);
    console.log(blockchain); // 이 안에 제대로 된 정보만 넣으면 최초의 제네시스 블록
  11. 제네시스 블록을 생성하는 함수
    // file system package 
    const fs = require('fs')
    const merkle = require('merkle')
    const cryptoJs = require('crypto-js')
    
    /*
        사용법
        const tree =
        merkle("sha256")    // 인자값 : 암호화 방법
        .sync([]);          // tree 구조로 변환
        tree.root();        // root를 가져옴
    */
    
    // 붕어빵 틀
    class BlockHeader {
        constructor(version, index, previousHash, time, merkleRoot, difficulty, nonce) { // Header를 만들 인자값 5개
            this.version = version;             // 1 { version : 1 }
            this.index = index;                 // 2 { version : 1, index : 2}
            this.previousHash = previousHash;   // 3 { version : 1, index : 2, previousHash : 3}
            this.time = time;                   // ...
            this.merkleRoot = merkleRoot;       // ......
    
            this.difficulty = difficulty;
            this.nonce = nonce;
        }
        // 안에서 함수 선언도 가능, React에서 했던 Render 등..
        // render(){}
    }
    
    // 헤더 블록 확인
    // const header = new BlockHeader(1,2,3,4,5);
    // console.log(header);
    
    class Block {
        constructor(header, body) {
            this.header = header;
            this.body = body;
        }
    }
    
    // 단일 블록 확인
    // const blockchain = new Block(new BlockHeader(1,2,3,4,5), ['hello']);
    // console.log(blockchain);
    
    function createGenesisBlock() {
        // header 생성 : 5개의 인자값 필요
        const version = getVersion();           // 1.0.0
        const index = 0;                        // 최초의 블록이므로 index 0으로 하드코딩
        const previousHash = '0'.repeat(64);    // 이전 hash가 없으므로 자리수만 0으로
        const time = getCurrentTime();
        const body = ['hello block'];
    
        const tree = merkle('sha256').sync(body);
        const root = tree.root() || '0'.repeat(64);
    
        // header 완성시키기 
        const header = new BlockHeader(version, index, previousHash, time, root);
        
        return new Block(header, body);
    }
    
    let Blocks = createGenesisBlock();
    console.log(Blocks);
    
    function getVersion() {
        const { version } = JSON.parse(fs.readFileSync("../package.json"));
        // console.log(package.toString('utf8'));
        // console.log(JSON.parse(package));
        // console.log(JSON.parse(package).version);
        // console.log(version);
        return version;
    }
    
    function getCurrentTime(){
        // console.log(new Date());
        // getTime 메서드로 변환 후 ceil()로 소수점 올림 처리
        // console.log(Math.ceil(new Date().getTime()/1000));
        return Math.ceil(new Date().getTime()/1000);
    }
    console.log(Blocks);
  12. 현재 블록과 마지막 블록 가져오기
    let Blocks = [createGenesisBlock()];
    
    function getBlocks(){
        return Blocks;
    }
    
    function getLastBlock(){
        return Blocks[Blocks.length - 1];
    }​

전체 코드

// file system package 
const fs = require('fs')
const merkle = require('merkle')
const cryptoJs = require('crypto-js')

/*
    사용법
    const tree =
    merkle("sha256")    // 인자값 : 암호화 방법
    .sync([]);          // tree 구조로 변환
    tree.root();        // root를 가져옴
*/

// 붕어빵 틀
class BlockHeader {
    constructor(version, index, previousHash, time, merkleRoot, difficulty, nonce) { // Header를 만들 인자값 5개
        this.version = version;             // 1 { version : 1 }
        this.index = index;                 // 2 { version : 1, index : 2}
        this.previousHash = previousHash;   // 3 { version : 1, index : 2, previousHash : 3}
        this.time = time;                   // ...
        this.merkleRoot = merkleRoot;       // ......

        this.difficulty = difficulty;
        this.nonce = nonce;
    }
    // 안에서 함수 선언도 가능, React에서 했던 Render 등..
    // render(){}
}

// 헤더 블록 확인
// const header = new BlockHeader(1,2,3,4,5);
// console.log(header);

class Block {
    constructor(header, body) {
        this.header = header;
        this.body = body;
    }
}

// 단일 블록 확인
// const blockchain = new Block(new BlockHeader(1,2,3,4,5), ['hello']);
// console.log(blockchain);

function createGenesisBlock() {
    // header 생성 : 5개의 인자값 필요
    const version = getVersion();           // 1.0.0
    const index = 0;                        // 최초의 블록이므로 index 0으로 하드코딩
    const previousHash = '0'.repeat(64);    // 이전 hash가 없으므로 자리수만 0으로
    const time = getCurrentTime();
    const body = ['hello block'];

    const tree = merkle('sha256').sync(body);
    const root = tree.root() || '0'.repeat(64);

    // header 완성시키기 
    const header = new BlockHeader(version, index, previousHash, time, root);
    
    return new Block(header, body);
}

let Blocks = createGenesisBlock();
console.log(Blocks);

function getVersion() {
    const { version } = JSON.parse(fs.readFileSync("../package.json"));
    // console.log(package.toString('utf8'));
    // console.log(JSON.parse(package));
    // console.log(JSON.parse(package).version);
    // console.log(version);
    return version;
}

function getCurrentTime(){
    // console.log(new Date());
    // getTime 메서드로 변환 후 ceil()로 소수점 올림 처리
    // console.log(Math.ceil(new Date().getTime()/1000));
    return Math.ceil(new Date().getTime()/1000);
}

let Blocks = [createGenesisBlock()];

function getBlocks(){
    return Blocks;
}

function getLastBlock(){
    return Blocks[Blocks.length - 1];
}