블록체인 블록 만들기
첫 블록, = Genesis block 은 개발자가 하드코딩을 해야함
블록의 구성 요소
A block is composed of a header and a body, where a header contains the hash of previous block, a timestamp, Nonce and the Merkle root. The Merkle root is the root hash of a Merkle tree which is stored in the block body.
Genesis Block(제네시스 블록) 만들기
1. 기본 세팅
사용할 디렉토리 안에(* 경로 주의) (src 상위 디렉토리에서 npm)
npm init
-src 디렉토리 생성 > block.js 파일 생성
2. block의 header에 들어갈 version을 package.json에서 가져오기
block.js
const fs = require('fs')
function getVersion(){
const package = fs.readFileSync('../package.json');
console.log(package)
console.log(JSON.parse(package))
console.log(JSON.parse(package).version)
return JSON.parse(package).version;
// 위와 같은 코드
// const {version} = JSON.parse(fs.readFileSync('../package.json'))
// return version
}
getVersion()
처음 그냥 가져오면 컴퓨터가 이해하는 언어 binary 형태로 가져오고,
이를 JSON.parse를 통해 우리가 이해할 수 있는 JavaScript Object로 바꿈
-> 객체 안의 key = version값을 가져옴
JSON.parse()
A common use of JSON is to exchange data to/from a web server. When receiving data from a web server, the data is always a string. Parse the data with JSON.parse() , and the data becomes a JavaScript object.
3. Timestamp (UNIX 기준일 1970년 1월 1일) 구하기
block.js
function getCurrentTime(){
console.log(Math.ceil(new Date().getTime()/1000))
return Math.ceil(new Date().getTime()/1000)
}
getCurrentTime()
1000/1초까지 시간단위가 나와서 1000으로 나누고 Math.ceil로 올림하기
4. MerkleTree, MerkleRoot
머클트리 (이진 트리) 는 블록들이 체인으로 연결되어 무수히 많아졌을 때 그 중, 하나의 특정 거래를 찾을 때 효율적으로 해싱한 경우의 수번만 찾으면 되도록 한 데이터 구조이다. 모든 노드 (거래)는 쌍으로 해싱을하게되고 또 해싱된 노드들이 또 짝을 이루어 해싱하다보면 Merkle root (최상위 노드) 로 수렴된다.
** 연습 **
src 폴더 안에 merkle.js 파일 생성
- SHA256, merkle위한 packages 설치 (경로 : src ** )
npm i merkletreejs crypo-js
- block.js 에 가져오기
const {MerkleTree} = require('merkletreejs')
const SHA256 = require('crypto-js/sha256')
- 사용해보기
console.log(SHA256('emily'))
emily라는 string을 sha256으로 암호화한 상태 여기에 toString()을 붙여보면 암호화된 string이 된다
console.log(SHA256('emily').toString())
이제 배열로 만들어서 'a', 'b', 'c'를 각각 암호화 (sha256)해서 배열에 넣어보기
const {MerkleTree} = require('merkletreejs')
const SHA256 = require('crypto-js/sha256')
const testSet = ['a','b','c'].map((v)=>SHA256(v))
console.log(testSet)
const tree = new MerkleTree(testSet, SHA256)
console.log(tree)
testSet & tree
머클 트리의 최상위 노드 (Merkle root)를 가져오기 (매서드 있음)
const testSet = ['a','b','c'].map((v)=>SHA256(v))
console.log(testSet)
const tree = new MerkleTree(testSet, SHA256)
console.log(tree)
const root = tree.getRoot().toString('hex')
console.log('root=',root)
tree.getRoot()만 하면 binary 형태로 나오고 toString('hex')를 해야 위의 string값이 나온다. 이 때 그냥 toString() 만하면 안나옴 !
merkle.js 전체 코드
const { MerkleTree } = require('merkletreejs')
const SHA256 = require('crypto-js/sha256')
// 3. merkle tree 연습
const testSet = ['a','b','c'].map((v)=>SHA256(v))
console.log(testSet)
const tree = new MerkleTree(testSet, SHA256)
console.log(tree)
const root = tree.getRoot().toString('hex')
console.log('root=',root)
const leaf = SHA256('a')
const proof = tree.getProof(leaf)
console.log(proof, tree.verify(proof,leaf,root))
hex 란? 16진수
Hexadecimal (or hex) is
a base 16 system used to simplify how binary is represented. A hex digit can be any of the following 16 digits: 0 1 2 3 4 5 6 7 8 9 A B C D E F. Each hex digit reflects a 4-bit binary sequence.
질문
tree.verify(proof, leaf, root)의 의미 -> 특정 노드 (proof) = true 인지 tree.verify() 매서드로 확인
const testSet = ['a','b','c'].map((v)=>SHA256(v))
console.log(testSet)
const tree = new MerkleTree(testSet, SHA256)
console.log(tree)
const root = tree.getRoot().toString('hex')
console.log('root=',root)
const leaf = SHA256('a')
const proof = tree.getProof(leaf)
console.log(proof, tree.verify(proof,leaf,root))
tree 연습 끝
npm i merkle
block.js
merkle & cryptoJs 가져오기
const fs = require('fs')
// const {MerkleTree} = require('merkletreejs')
// const SHA256 = require('crypto-js/sha256')
const merkle = require('merkle')
const cryptoJs = require('crypto-js')
Header
BlockHeader Class 만들기 (붕어빵 틀 만들기)
class BlockHeader {
constructor(version, index, previousHash, time, merkleRoot){
this.version = version
this.index = index
this.previousHash = previousHash
this.time = time
this.merkleRoot = merkleRoot
}
}
const header = new BlockHeader(1,2,3,4,5)
console.log(header)
이제 Block 이라는 또다른 Class를 방금 만든 BlockHeader 사용해서 만들기
const fs = require('fs')
// const {MerkleTree} = require('merkletreejs')
// const SHA256 = require('crypto-js/sha256')
const merkle = require('merkle')
const cryptoJs = require('crypto-js')
// 4. Header 만들기 by Class
class BlockHeader {
constructor(version, index, previousHash, time, merkleRoot){
this.version = version
this.index = index
this.previousHash = previousHash
this.time = time
this.merkleRoot = merkleRoot
}
}
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)
하나의 블록을 생성함
블록 안에는 크게 header, body가 있어서 block class에 인자값에 header, body가 있다 ! 그리고 넣어줄 때 header를 생성하는 classs를 (인자값 5개) 넣고 두번째 인자값으로 body값을 넣어줌
=> 이제 제대로 된 정보를 넣으면 요 것이 최초의 블록 = 제네시스 블록
제네시스 블록 만드는 함수 만들기
block.js
function createGenesisBlock(){
const version = getVersion();
const time = getCurrentTime();
const index = 0;
const previousHash = '0'.repeat(64) // 제네시스 블록 : 이전hash 없으므로 자리수만 64로 맞춰서 제공
// body는 배열 형태 ***
const body = ['hello block I am body ']
// body를 가지고 merkle tree 값을 구성하기
const tree = merkle('sha256').sync(body)
const root = tree.root() || '0'.repeat(64) // 예외처리
const header = new BlockHeader(version, index, previousHash, time, root)
console.log('header=', header)
console.log(new Block(header, body))
return new Block(header,body)
}
createGenesisBlock()
다음 사용자 / 블록이 생길 때
- 블록을 생성할 때마다 -> 배열에 넣기
- 전역변수로 배열 만들기
// 6. 블록 생성할 때마다 -> 배열에 넣기 예정 / 마지막 블록 가져오기
let Blocks = [createGenesisBlock()]
function getLastBlock(){
return Blocks[Blocks.length-1]
}
getLastBlock()
오늘 전체 코드
const fs = require('fs')
// const {MerkleTree} = require('merkletreejs')
// const SHA256 = require('crypto-js/sha256')
const merkle = require('merkle')
const cryptoJs = require('crypto-js')
// 1. version 구하기
function getVersion(){
const package = fs.readFileSync('../package.json');
// console.log(package)
// console.log(JSON.parse(package))
console.log('version=',JSON.parse(package).version)
return JSON.parse(package).version;
// 위와 같은 코드
// const {version} = JSON.parse(fs.readFileSync('../package.json'))
// return version
}
// getVersion()
// 2. StampTime 구하기
function getCurrentTime(){
console.log('TimeStamp = ', Math.ceil(new Date().getTime()/1000))
return Math.ceil(new Date().getTime()/1000)
}
// getCurrentTime()
// 3. merkle tree 연습 - > src > merkle.js 파일에 있음
// 4. Header 만들기 by Class
class BlockHeader {
constructor(version, index, previousHash, time, merkleRoot){
this.version = version
this.index = index
this.previousHash = previousHash
this.time = time
this.merkleRoot = merkleRoot
}
}
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)
// 5. 제네시스 블록 만들기
function createGenesisBlock(){
const version = getVersion();
const time = getCurrentTime();
const index = 0;
const previousHash = '0'.repeat(64) // 제네시스 블록 : 이전hash 없으므로 자리수만 64로 맞춰서 제공
// body는 배열 형태 ***
const body = ['hello block I am body ']
// body를 가지고 merkle tree 값을 구성하기
const tree = merkle('sha256').sync(body)
const root = tree.root() || '0'.repeat(64) // 예외처리
const header = new BlockHeader(version, index, previousHash, time, root)
//console.log('header=', header)
//console.log(new Block(header, body))
return new Block(header,body)
}
createGenesisBlock()
// 6. 블록 생성할 때마다 -> 배열에 넣기 예정 / 마지막 블록 가져오기
let Blocks = [createGenesisBlock()]
function getLastBlock(){
return Blocks[Blocks.length-1]
}
getLastBlock()
'BlockChain' 카테고리의 다른 글
블록체인 네트워크 웹소켓 WebSocket http ws (0) | 2021.12.31 |
---|---|
블록체인 새 블록 추가, 연결하고 검증하기 (0) | 2021.12.30 |
블록체인 블록 만들어보기 (0) | 2021.12.29 |
blockchain 맛 보기 (0) | 2021.12.27 |
PoS(Proof of Stake) 고찰 (0) | 2021.12.26 |