이전 포스트에서 내가 만든 블록들에 대해서 검증을 해보자.
// checkValidBlock.js
const merkle = require('merkle')
const {Blocks,getLastBlock,createHash} = require('./chainedBlock')
이전 코드에서 module.exports={Blocks,getLastBlock,createHash, nextBlock}
로 모듈들을 가져와서 선언 해준다.
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'
}
매개변수로 블록을 받고
해당 블록이 유효하면 true
, 유효하지 않다면 false
를 반환해준다.
function isValidNewBlock(newBlock, previousBlock){
// 새로운 블록 구조 유효성 검사를 실패 하였을 때 return false
if (!isValidBlockStructure(newBlock)){
console.log('Invalid Block Structure');
return false;
}
// 새로운 블록의 인덱스가 이전 블록의 인덱스보다 1만큼 큰지. 아닐 시 return false
else if (newBlock.header.index !== previousBlock.header.index +1){
console.log('Invalid Index');
return false;
}
// 새로운 블록의 이전 해시값이 이전 블록의 해시 값이 아닐 때 return false
else if (newBlock.header.previousHash !== createHash(previousBlock)){
console.log('Invalid previousHash');
return false;
}
// 데이터 필드로부터 계산한 머클루트와 블록 헤더의 머클루트가 동일하지 않으면 return false
else if (
// 새로운 블록안의 body 데이터가 없을 때 머클 루트 비교
(newBlock.body.length === 0 && ('0'.repeat(64) !== newBlock.header.merkleRoot))
||
// 새로운 블록안의 body 데이터가 있을 때 해당 데이터의 머클 루트 비교
(newBlock.body.length !== 0 && (merkle('sha256').sync(newBlock.body).root() !== newBlock.header.merkleRoot))
) {
console.log('Invalid merkleRoot');
return false;
}
// 해당 블록 검증 완료
return true
}
매개변수로 newBlock
(새로 생성되는 블록)과 previousBlock
(이전 블록)을 넣어준다.
해당 함수로 새로 생성되는 블록을 검증 할 수 있다.
add 함수를 만들어서 잘 실행 되는지 실험해보자
function addBlock(newBlock){
// addBlock으로 새로운 블록을 받아오고, isValidNewBlock 매개변수로 새로운 블록, 마지막 블록을 넣어준다
// 정상 작동 시
if(isValidNewBlock(newBlock, getLastBlock())){
console.log('valid block!!')
Blocks.push(newBlock)
return true;
}
// 정상 작동 실패 시
return false
}
// newBlock 생성
const newBlock = nextBlock(['new Transaction']) // 변수로 nextBlock을 써주고 싶은데 이미 함수로 만들어져 있어서 newBlock으로 만듬 ㅠ
addBlock(newBlock)
console.log(newBlock)
검증을 마치고 Blocks
배열에 잘 들어간 것을 확인할 수 있다!!
const merkle = require('merkle')
const {Blocks,getLastBlock,createHash,nextBlock} = require('./chainedBlock')
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){
// 새로운 블록 구조 유효성 검사를 실패 하였을 때 return false
if (!isValidBlockStructure(newBlock)){
console.log('Invalid Block Structure');
return false;
}
// 새로운 블록의 인덱스가 이전 블록의 인덱스보다 1만큼 큰지. 아닐 시 return false
else if (newBlock.header.index !== previousBlock.header.index +1){
console.log('Invalid Index');
return false;
}
// 새로운 블록의 이전 해시값이 이전 블록의 해시 값이 아닐 때 return false
else if (newBlock.header.previousHash !== createHash(previousBlock)){
console.log('Invalid previousHash');
return false;
}
// 데이터 필드로부터 계산한 머클루트와 블록 헤더의 머클루트가 동일하지 않으면 return false
else if (
// 새로운 블록안의 body 데이터가 없을 때 머클 루트 비교
(newBlock.body.length === 0 && ('0'.repeat(64) !== newBlock.header.merkleRoot))
||
// 새로운 블록안의 body 데이터가 있을 때 해당 데이터의 머클 루트 비교
(newBlock.body.length !== 0 && (merkle('sha256').sync(newBlock.body).root() !== newBlock.header.merkleRoot))
) {
console.log('Invalid merkleRoot');
return false;
}
// 해당 블록 검증 완료
return true
}
function addBlock(newBlock){
if(isValidNewBlock(newBlock, getLastBlock())){
console.log('valid block!!')
Blocks.push(newBlock)
return true;
}
return false
}
const afterBlock = nextBlock(['new Transaction'])
addBlock(afterBlock)
console.log(Blocks)