블록체인 구현해 보기 (1) - 블록 생성 (feat. JavaScript)

최현석·2021년 12월 30일
0

블록체인

목록 보기
3/5

필요한 모듈

  • crypto-js
  • fs
  • merkle

모듈 불러오기 및 선언

// chainedBlock.js

// 모듈 불러오기
const cryptojs = require('crypto-js')
const fs = require('fs')
const merkle = require('merkle')

블럭 클래스 생성

// 블록 클래스 생성
class Block{
	constructor(header, body){
		this.header = header
		this.body = body
	}
}

// 블록 헤더 클래스 생성
class BlockHeader{
    constructor(version, index, previousHash,timestamp,merkleRoot,bit,nonce){
		this.version = version
		this.index = index
		this.previousHash = previousHash
		this.timestamp = timestamp
		this.merkleRoot = merkleRoot
		this.bit = bit
		this.nonce = nonce
    }
}

앞선 포스트에서 말했듯이 블록은 header와 body로 나뉘어져 있습니다.

먼저 Block 클래스에서 header와 body를 초기화해주고

다음 BlockHeader 클래스에서 header에 들어갈 인스턴스 객체들을 초기화 해주었습니다. ( 아마 이 BlockHeaderBlock의 header에 들어가겠죠?)


초기 블록을 만들어 보자

// 제네시스 블록 만들기 ( 제일 초기의 블록 )
function createGenesisBlock() {
    const version = getVersion(); // 해당 코인의 현재 버전
    const index = 0; // 현재 블록의 인덱스
    const previousHash = "0".repeat(64); // 이전 블록의 Hash값 ( 초기의 블록이기 때문에 0000...00)
    const timestamp = parseInt(Date.now() / 1000); // 현재 시간 ( 초 단위 )
    const body = ["genesis block!"]; // 블록의 body부분
    const tree = merkle("sha256").sync(body); // body부분을 트리로 변경
    const merkleRoot = tree.root() || "0".repeat(64); // tree의 root hash값. 없으면 기본 0 x 64개
    const bit = 0; // 초기 0 bit
    const nonce = 0; // 초기 nonce 0
}

function getVersion() {
    const package = fs.readFileSync("package.json"); // package.json 파일 불러오기
    return JSON.parse(package).version; // JSON 파싱해서 package에 들어있는 key중 version이라는 key의 값 반환
}

getVersion() 함수를 만들어서 version 값을 넣어줬습니다!

let Blocks = [createGenesisBlock()]

이후 Blocks배열을 만들어서 해당 배열에 첫 블록을 넣어주었습니다.

get 접근자 함수를 만들어서 return 해주겠습니다.

function getBlocks(){
	return Blocks
}

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

다음 블록 만들기


  • 다음 블록을 만들기 위해서는 현재 블록의 해시 값을 구해야 합니다.
  • 현재 블록의 해시 값은 version, index, previousHash, timeStamp, merkleRoot, bit, nonce의 값을 모두 더해서 구한 다고 하였습니다.
function createHash(data){
	const {version,index, previousHash, timestamp, merkleRoot, bit, nonce} = data.header // 헤더의 데이터를 가져와서
	const blockString = version + index + previousHash + timestamp + merkleRoot + bit + nonce // 모두 더한다
	const hash = cryptojs.SHA256(blockString).toString() // 해시화
	return hash // 리턴
}
  • 해시 값을 리턴 해주므로 이제 다음 블록을 만드는 함수를 만들어 보도록 하겠습니다.
function nextBlock(bodyData){
	const prevBlock = getLastBlock() // 다음 블록은 마지막 블록 뒤에 이어지므로 

	const version = getVersion() // 버전 가져오기 
	const index = prevBlock.header.index + 1 // 이전 블록 인덱스 + 1
	const previousHash = createHash(prevBlock) // 이전 블록 해시
	const timestamp = parseInt(Date.now() / 1000) // 초 단위 타임스탬프
	const tree = merkle('sha256').sync(bodyData) // 트리 생성
	const merkleRoot = tree.root() || '0'.repeat(64) // 머클 트리 루트 값 
	const bit = 0 // 비트
	const nonce = 0 // 논스

	const header = new BlockHeader(version, index, previousHash, timestamp, merkleRoot, bit, nonce) 
	// BlockHeader header 블록에 상단 정보들 넣어주기

	return new Block(header, bodyData)
    // Block 반환
}

// 매개변수로 body 값 넣어서 Block 배열에 push
function addBlock(bodyData){ 
	const newBlock = nextBlock(bodyData)
	Blocks.push(newBlock)
}


전체코드

const cryptojs = require('crypto-js')
const fs = require('fs')
const merkle = require('merkle')

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

class BlockHeader {
	constructor (version, index, previousHash, timestamp, merkleRoot, bit, nonce){
		this.version = version
		this.index = index
		this.previousHash = previousHash
		this.timestamp = timestamp
		this.merkleRoot = merkleRoot
		this.bit = bit
		this.nonce = nonce
	}
}

function getVersion() {
	const package = fs.readFileSync("package.json")
	return JSON.parse(package).version
}

function createGenesisBlock() {
	const version = getVersion()
	const previousHash = '0'.repeat(64)
	const timestamp = parseInt(Date.now()/1000)
	const body = ['hello block']
	const tree = merkle('sha256').sync(body)
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0
	const index = 0

	const header = new BlockHeader(version, index, previousHash, timestamp, merkleRoot, bit, nonce)
	
	return new Block(header, body)
}

let Blocks = [createGenesisBlock()]

function getBlocks(){
	return Blocks
}

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

function createHash(data){
	const {version,index, previousHash, timestamp, merkleRoot, bit, nonce} = data.header
	const blockString = version + index + previousHash + timestamp + merkleRoot + bit + nonce
	const hash = cryptojs.SHA256(blockString).toString()
	return hash
}

function nextBlock(bodyData){
	const prevBlock = getLastBlock()

	const version = getVersion()
	const index = prevBlock.header.index + 1 
	const previousHash = createHash(prevBlock)
	const timestamp = parseInt(Date.now() / 1000)
	const tree = merkle('sha256').sync(bodyData)
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

	const header = new BlockHeader(version, index, previousHash, timestamp, merkleRoot, bit, nonce)
	
	return new Block(header, bodyData)
}

function addBlock(bodyData){
	const newBlock = nextBlock(bodyData)
	Blocks.push(newBlock)
}
addBlock(['transaction'])

const blockChain = getBlocks()
console.log(blockChain)
profile
개발자 꿈나무 https://github.com/Tozinoo

0개의 댓글