728x90

다음과 같은 조건을 거쳐야함.

 

1. 블록구조가 유효한지

2. 현재 블록의 인덱스가 이전 블록의 인덱스보다 1만큼 큰지

3. 이전블록의 해시값과 현재 블록의 이전해시가 같은지

4. 데이터 필드로부터 계산한 머클루트와 블록헤더의 머클루트가 동일한지 

 

이 조건 다 맞으면 올바른 구조체이다.

 

 

1.블록구조가 유효한가

//블록의 각각 타입체크 블록구조 유효한지 체크하는 함수
function isValidBlockStructure(block) {
    return typeof(block.blockheader.version) === 'string'
    && typeof(block.header.index) === 'number'
    && typeof(block.header.previousHash) === 'string'
    && typeof(block.header.timestamp) === 'number'
    && typeof(block.header.merkleRoot) === 'string'
    && typeof(block.body) === 'object'
}
//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
    }
    return true;
}

 

2. 현재 블록의 인덱스가 이전 블록의 인덱스보다 1만큼 큰지

 

//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
        //현재블록이 이전 블록보다 1크지 않으면 false
    } else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
    }
    return true;
}

3. 이전블록의 해시값과 현재 블록의 이전해시가 같은지

 

나는 새로 만들어서 하는중이라

blockcopy.js 에 블록생성block, 다음블록연결chainedBlock까지 해놨음

여기서 createHash 내보내주기 

 

//이전블록 해시값과 현재 블록해시값의 이전해시가 같은지
//보려고 내보내줘야함 
module.exports = { 
	createHash,
}

이제 현재 코드,

비교해볼 코드에 createHash 가져와야돼

 

(수업때는 checkValidBlock.js 라고 이름지은걸 걍 다시 하면서 checkedBlock.js라고 했닿 )

const {createHash} = require('./blockcopy');

 

//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
    } else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
        //이전블록해시랑 현재블록의 이전해시가 다르면 false
    } else if (createHash(previousBlock)!==newBlock.header.previousHash) {
        console.log('Invalid previousHash');
        return false;
    }
    return true;
}

4. 데이터 필드로부터 계산한 머클루트와 블록헤더의 머클루트가 동일한지 

 

merkle쓰려면 설치해야돼

 

npm i merkle
const merkle = require("merkle")

....

//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock) === false) {
        console.log('Invalid Block Structure')
        return false;
    } else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
    } else if (createHash(previousBlock)!==newBlock.header.previousHash) {
        console.log('Invalid previousHash');
        return false;
    } else if (newBlock.body.length === 0 && ('0'.repeat(64) !== newBlock.header.merkleRoot) 
    || newBlock.body.length !== 0 && (merkle("sha256").sync(newBlock.body).root() !==newBlock.header.merkleRoot))
    {
        console.log('Invalid merkleRoot')
        return false
    }
    return true;
}

새블록 body의 길이가 0일 경우 && 머클루트는 '0'.repeat(64)이 아니면

또는 

 

새블록바디 길이가 0이 아닐경우 && 머클루트에있는 정보와  새블록 바디의 루트 정보들이 같지 않으면

false

 

 

5. 새블록추가

chainedBlock.js 하단에 추가

 

나는 blockcopy.js에 추가함요

module.exports = {
	Blocks,
	getLastBlock,
	createHash,
}

checkValidBlock.js 상단에 불러오기

 

나는 checkBlock.js에 넣음

 

const {createHash,Blocks, createHash} = require('./blockcopy');

 

 

 

 

 

 

 

 

검증과정을 마친 블록

 

//검증마친 블록들은 chainedBlock.js의 Blocks배열에 추가한다
function addBlock(newBlock){
    if(isValidNewBlock(newBlock,getLastBlock())){
        Blocks.push(newBlock)
        return true;
    }
    return false;
}

const block = nextBlock(['transaction1'])
addBlock(block)

console.log(block)

 

 

 

blockcopy.js에서의 nextBlock함수 이용해서 

블록생성하고 출력해보기 

 

 

근데 결과에 

 

계속 이게 나와서 

이 콘솔임

 

코드비교해보니까 

blockcopy.js (chainedBlock.js) 에 

index순서 바꾸니까 안뜨네 뭐냐...

blockcopy.js (chained.js)

결과

 

 

 

코드 전체

blockcopy.js

(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(index, version, previousHash, timestamp, merkleRoot, bit, nonce) {
	  this.index = index
	  this.version = version
	  this.previousHash = previousHash
	  this.timestamp = timestamp
	  this.merkleRoot = merkleRoot
	  this.bit = bit
	  this.nonce = nonce
	}
  }
  

//버전계산하는 함수 
function getVersion(){
	const package = fs.readFileSync("package.json")
	// console.log(JSON.parse(package).version)
	return JSON.parse(package).version

}


//getVersion()

function createGenesisBlock() {
  const index = 0
  const version = getVersion()
  const previousHash = '0'.repeat(64) // 0을 64번 반복
  const timestamp = parseInt(Date.now() / 1000) // 1000 나눈 이유 : 초 단위로 환산하기 위해
  const body = ['Hello block!']
  const tree = merkle('sha256').sync(body)
  const merkleRoot = tree.root() || '0'.repeat(64)
  const bit = 0
  const nonce = 0

  // console.log("version : %s, timestamp : %d, body: %s", version, timestamp, body);
  // console.log("previousHash : %d", previousHash);
  // console.log(tree);
  // console.log("merkleRoot: %s", merkleRoot);

  const header = new BlockHeader(index, version, 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,previousHash,timestamp, merkleRoot, bit, nonce}= data.header
	const blockString = version +previousHash +timestamp+ merkleRoot+ bit+ nonce
	const hash = cryptojs.SHA256(blockString).toString()
	return hash
}



// const block = createGenesisBlock()
// const testHash = createHash(block)
// console.log(testHash)

//다음블록 생성하기 
function nextBlock(bodyData) {
	const prevBlock = getLastBlock()
	const version = getVersion()
	//다음순서니까 하나 추가됨
	const index = prevBlock.header.index + 1
	//createHash함수에 이전블록 정보를 넣어 블록해시값을 구해넣는다.
	const previousHash = createHash(prevBlock)
	const timestamp = parseInt(Date.now() / 1000)
	//블록body부분에 저장될 트랜잭션(거래정보)인 bodyData를
	//merkle몯ㄹ을 사용하여 트랜잭션들의 해시트리를 만들어 tree에 넣어
	const tree = merkle('sha256').sync(bodyData)
	//여기서 최종적으로 구해진 해시값인 머클루트 해시값을 merkleRoot변수에 넣어
	const merkleRoot = tree.root() || '0'.repeat(64)
	const bit = 0
	const nonce = 0

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

}
//다음블록생성 출력하기
// const block1 = nextBlock(["tranjaction1"])
// console.log(block1)

//addblock함수를 통해 순차적으로 트랜잭션값 전달해 블록생성하고
function addBlock(bodyData) {
	const newBlock = nextBlock([bodyData])
	Blocks.push(newBlock)
  
  }

// addBlock(['transaction1'])
// addBlock(['transaction2'])
// addBlock(['transaction3'])
// addBlock(['transaction4'])
// addBlock(['transaction5'])

// console.log(Blocks);

//이전블록 해시값과 현재 블록해시값의 이전해시가 같은지
//보려고 내보내줘야함 
module.exports = { nextBlock, getLastBlock, createHash, Blocks, getVersion, getBlocks }


// function addBlock(newBlock){

// 	if(isValidNewBlock(newBlock,getLastBlock())){

// 		Blocks.push(newBlock)
// 		return true;
// 	} return false;
// }

 

checkedBlock.js

더보기
const merkle = require("merkle")
const {Blocks, createHash, getLastBlock,nextBlock} = require('./blockcopy');
// const { nextBlock } = require("./chainedBlock");


//블록구조 유효한지
//blockcopy.js에서 만든 블록체인

//블록의 각각 타입체크 블록구조 유효한지 체크하는 함수
function isValidBlockStructure(block) {
  return typeof (block.header.version) === 'string'
    && typeof (block.header.index) === 'number'
    && typeof (block.header.previousHash) === 'string'
    && typeof (block.header.timestamp) === 'number'
    && typeof (block.header.merkleRoot) === 'string'
    && typeof (block.body) === 'object'
}
//위 함수를 통해 블록구조의 유효성 검사
function isValidNewBlock(newBlock, previousBlock) {
    if (isValidBlockStructure(newBlock)===false){
		console.log('Invalid Block Structure');
		return false;
	} else if (newBlock.header.index !== previousBlock.header.index +1 ){
        console.log('Invalid Index')
        return false;
    } else if (createHash(previousBlock)!==newBlock.header.previousHash) {
        console.log('Invalid previousHash');
        return false;
        //블록길이가 0일경우
    } else if (newBlock.body.length === 0 
        //머클루트는길이가 
        && ('0'.repeat(64) !== newBlock.header.merkleRoot) 
    || newBlock.body.length !== 0 && (merkle("sha256").sync(newBlock.body).root() !==newBlock.header.merkleRoot))
    {
        console.log('Invalid merkleRoot')
        return false
    }
    return true;
}

//검증마친 블록들은 chainedBlock.js의 Blocks배열에 추가한다
function addBlock(newBlock){
    if(isValidNewBlock(newBlock,getLastBlock())){
        Blocks.push(newBlock)
        return true;
    }
    return false;
}

const block = nextBlock(['transaction1'])
addBlock(block)

console.log(block)
728x90
728x90

이론 출처: https://steemit.com/kr/@yahweh87/3

코드설명:https://berrypjh.tistory.com/50

 

블록체인에서 사용되는 '블록' 일정 시간마다(비트코인의 기준으로 10분에 한 번씩 생성됩니다.)

 여러 건의 거래내역을 하나의 블록으로 묶어 기존에 생성된 블록에 체인처럼 계속적으로 연결하는 데이터 구조를 의미합니다. 

 

 

블록은 블록체인의 원소 개념으로, 다수의 거래 정보의 묶음을 의미합니다.

블록에는 블록의 이름이 있는데 Height(높이)라는 용어로 표현되고 있습니다.

한 칸 한 칸 쌓아나가 탑의 형태로 구성된다고 생각하여 Height(높이)라는 말을 쓴다고 합니다.(깊이라고 이해해도 될듯)

하지만 이 높이는 정확한 블록의 이름이 아닙니다. 

블록의 정확한 이름은 TXID라 불리는 블록의 해시값입니다. 이 블록의 해시값은 블록의 헤더 정보(블록의 버전, 이전블록해시,머클루트,타임,bits,논스 정보)를 모두 합산한 후 SHA256으로 변환된 값입니다.

bits : 난이도 해시 목표값을 의미하는 지표

nonce: 블록을 만드는 과정에서 해시값을 구할 때 필요한 재료 역할을 수행한다.

블록의 구성요소

여러 요소들이 있지만

크게 블록 헤더블록 바디로 나눌 수 있다.

블록 하나 만들기

(리눅스 우분투에서 코드 작성중)

<block.js>

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

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

	}
}

header와 body가 들어간 block클래스를 만들고 블록의 header class도 만들어준다.

npm init

버전과 모듈설치확인 위해서 package.json 파일 만들고 fs불러서 버전표시해보자

const fs = require('fs')

//버전계산하는 함수 
function getVersion(){
	const package = fs.readFileSync("package.json")
	console.log(JSON.parse(package).version)
	return JSON.parse(package).version

}

 

 

# node block.js

 

첫번째 block값 대입한다

function createGenesisBlock(){
	const version = getVersion()
	const previousHash = '0'.repeat(64)
	const timestamp = parseInt(Date.now()/1000)

}

 

version은 getVersion에서 나온 값을 대입한다.

previousHash는 이전 블록이 없는 첫번째 블록이므로 64비트 '0'을 대입

timestamp는 Date써서 현재 시간 넣어두기

 

머클리루트 값을 넣기 위해 설치

 

npm i merkle

 

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

	console.log("version : %s, timestamp: %d, body : %s",version,timestamp,body)
	console.log("previousHash : %d", previousHash);
	console.log("tree :")
	// console.log(tree)
	console.log("merkleRoot : %s", merkleRoot);
	console.log("merkleRoot : %s", merkleRoot.toString('hex'));

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

}

해당 모듈 설치 후 body에 들어갈 트랜잭션(거래내역)인 첫 번째 데이터로 hello block을 넣음

나머지는 0대입하고 만들어보고 실행해보기

 

node block.js

하면

(아까는 merkleRoot 안나왔는데 %d 여서 그랬음 %s 이게 string값 불러오는건가보다 둘이 똑같이 뜨네)

 

 

첫번째 블록 생성하기

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

	console.log("version : %s, timestamp: %d, body : %s",version,timestamp,body)
	console.log("previousHash : %d", previousHash);
	console.log("tree :")
	// console.log(tree)
	console.log("merkleRoot : %s", merkleRoot);
	console.log("merkleRoot : %s", merkleRoot.toString('hex'));
     
	//헤더에 대입
	const header = new BlockHeader(version, previousHash, timestamp, merkleRoot, bit,nonce)
    return new Block(header, body)

}
//값넣어서 블록생성
const block = createGenesisBlock()
console.log(block)

위에 대입한 결과를 BlockHeader class로 정보를 전달하고 

블록헤더와 바디를 Block class에 전달하여 첫번째 블록을 생성하였다.

 

node block.js  로 실행결과보기

 

block.js 전체코드는 이와같다.

더보기
const fs = require('fs')
const merkle = require('merkle')

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

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

	}
}

//버전계산하는 함수 
function getVersion(){
	const package = fs.readFileSync("package.json")
	console.log(JSON.parse(package).version)
	return JSON.parse(package).version

}


//getVersion()

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

	console.log("version : %s, timestamp: %d, body : %s",version,timestamp,body)
	console.log("previousHash : %d", previousHash);
	console.log("tree :")
	// console.log(tree)
	console.log("merkleRoot : %s", merkleRoot);
	console.log("merkleRoot : %s", merkleRoot.toString('hex'));
     
	//헤더에 대입
	const header = new BlockHeader(version, previousHash, timestamp, merkleRoot, bit,nonce)
    return new Block(header, body)

}
//값넣어서 블록생성
const block = createGenesisBlock()
console.log(block)

 

 

 

 

 

728x90

+ Recent posts