사랑하애오
article thumbnail

 

 

src/block.js

1. 1. AddBlock 새로운 block 추가하는 함수 

<javascript />
// 새로운 block을 간단히 추가하는 함수 function addBlock(){ const newBlock = nextBlock(data); if(isValieNewBlock(newBlock, getLastBlock())){ Blocks.push(newBlock); return true; } return false; }

 

 

2. 2. newBlock 새로운 블록을 생성하는 함수

<javascript />
// 다음 블럭(nextBlock)의 header와 body를 만들어주는 함수 function nextBlock(data){ // 이전 block 가져오기 const prevBlock = getLastBlock(); // Header const version = getVersion(); const index = prevBlock.header.index + 1; const previousHash = createHash(prevBlock); const time = getCurrentTime(); // Mekle root를 가져오기 위해 tree 만들기 const merkleTree = merkle('sha256').sync(data) const merkleRoot = merkleTree.root() || '0'.repeat(64); const newBlockHeader = new BlockHeader(version, index, previousHash, time, merkleRoot) // header + data(body) 로 new block return return new Block(newBlockHeader, data) }

3.  

4. 3. createHash 함수 생성 - 이전 블록의 모든 header string값을 받아와 새 hash 암호화 

<javascript />
function createHash(block){ // 이전 블록을 인자로 받아와 해당 블록 header의 요소들 가져오기 const {version, index, previousHash, time, merkleRoot} = block.header; // 모든 string을 + 더하기 const blockString = version + index+previousHash+time+merkleRoot; const Hash = CryptoJs.SHA256(blockString).toString(); return Hash; }

 

 

5. 4. 새로 만든 블록 검증 -> 후에 add 

함수가 많이 나오므로 잘 구별하기.

addBlock : 새로운 블록을 추가하는 함수 

isValidNewBlock : 새로운 블록과, 이전 블록을 세트로 검증하는 함수 

isValieType : 새로운 블록의 Type 을 검증하는 함수 

<javascript />
// 새로운 block을 간단히 추가하는 함수 function addBlock(data){ const newBlock = nextBlock(data); if(isValidNewBlock(newBlock, getLastBlock())){ Blocks.push(newBlock); return true; } return false; } // 새로운 블록 검증 function isValidNewBlock(currentBlock, previousBlock){ // 1. 새로운 블록의 type 검증 isValidType(currentBlock) return true; } function isValidType(block){ console.log(block) } addBlock(['asdf']);

6.  

6.1. 1) type검증 

<javascript />
// 새로운 블록 검증 function isValidNewBlock(currentBlock, previousBlock){ // 1. 새로운 블록의 type 검증 if(!isValidType(currentBlock)){ // "" or '' or `` string 값으로 만들 때 객체는[Object Object]로 나와서 JSON.stringify 붙여주기 console.log(`inValidType is found in currentBlock = ${currentBlock}`); console.log(`inValidType is found in currentBlock = ${JSON.stringify(currentBlock)}`); return false; } return true; } // 새로운 블록 type 검증 function isValidType(block){ return ( typeof(block.header.version)=="string" && typeof(block.header.index)=="numbr" && typeof(block.header.previousHash)=="string" && typeof(block.header.time)=="number" && typeof(block.header.merkleRoot)=="string" && typeof(block.body)=="object" ) }

 

6.2. 2) index 검증 

<javascript />
// 새로운 블록 검증 function isValidNewBlock(currentBlock, previousBlock){ // 1. 새로운 블록의 type 검증 if(!isValidType(currentBlock)){ // "" or '' or `` string 값으로 만들 때 객체는[Object Object]로 나와서 JSON.stringify 붙여주기 console.log(`inValidType is found in currentBlock = ${currentBlock}`); console.log(`inValidType is found in currentBlock = ${JSON.stringify(currentBlock)}`); return false; } // 2. index 검증 if(previousBlock.header.index+1 !== currentBlock.header.index){ console.log(`invalid index found`) return false; } return true; }

 

 

6.3. 3) previous Hash 

<javascript />
// 3. previousHash check if(currentBlock.header.previousHash !== createHash(previousHash)){ console.log(`invalid previousHash found`) return false; }

 

 

6.4. 4) root 

merkle 목적 : data 위조 방지  (+ 특정 노드 효율적으로 찾기) 

<javascript />
// 4. merkleRoot check (root가 정확한지) if(currentBlock.header.merkleRoot !== merkle('sha256').sync(currentBlock.body).root()){ console.log(`invalid body found`) return false; }

 

 

6.5. 5) body

<javascript />
// 5. body check (body에 내용이 반드시 있어야함 !) if(currentBlock.body.length===0){ console.log(`invalid body found, it's empty`); return false; }

 

isValidNewBlock 함수 (새로 만들어진 블록 검증하는) 의 전체 코드 

<javascript />
// 새로운 블록 검증 function isValidNewBlock(currentBlock, previousBlock){ // 1. 새로운 블록의 type 검증 if(!isValidType(currentBlock)){ // "" or '' or `` string 값으로 만들 때 객체는[Object Object]로 나와서 JSON.stringify 붙여주기 console.log(`inValidType is found in currentBlock = ${currentBlock}`); console.log(`inValidType is found in currentBlock = ${JSON.stringify(currentBlock)}`); return false; } // 2. index 검증 if(previousBlock.header.index+1 !== currentBlock.header.index){ console.log(`invalid index found`) return false; } // 3. previousHash check if(currentBlock.header.previousHash !== createHash(previousBlock)){ console.log(`invalid previousHash found`) return false; } // 4. merkleRoot check (root가 정확한지) if(currentBlock.header.merkleRoot !== merkle('sha256').sync(currentBlock.body).root()){ console.log(`invalid body found`) return false; } // 5. body check (body에 내용이 반드시 있어야함 !) if(currentBlock.body.length===0){ console.log(`invalid body found, it's empty`); return false; } return true; }

 

 

 

6.6. 6. Blocks 안 전체 배열 검증 

1) 제네시스 블록 유효한지, 데이터가 바뀐 적이 없는지 확인

2) Blocks 배열 안의 모든 요소들을 짝으로 검사 (10개 요소라면 -> 9번 검사) 

 

 

1) 제네시스 블록 검증

JavaScript 특징 상, {} !== {} 이다. 제네시스 블록은 객체이므로 JSON.stringiyi() 로 string으로 만들어 비교를 진행해야 한다. 

<javascript />
// 제네시스 블록 검증 function isValidBlock(Blocks){ if(JSON.stringify(Blocks[0]) !== JSON.stringify(createGenesisBlock())){ console.log(`Invalie Genesis Block found`); return false; } }

 

 

 

2) Blocks 배열 요소 검증 

<javascript />
// 6. 전체 검증 (제네시스블록 & 블록을 담은 Blocks 배열 전체) function isValidBlock(Blocks){ // GENESIS BLOCK 검증 if(JSON.stringify(Blocks[0]) !== JSON.stringify(createGenesisBlock())){ console.log(`Invalie Genesis Block found`); return false; } // BLOCKS ARRAY 검증 // tempBlocks 변수에 제네시스 블록 배열로 담기 let tempBlocks = [Blocks[0]]; for(let i=1; i<Blocks.length; i++){ if(isValidNewBlock(Blocks[i], tempBlocks[i-1])){ tempBlocks.push(Blocks[i]) }else{ console.log(`invalid Block found, located at ${i} in Blocks Array`) return false; } } return true; }

 

 

 

3) 위의 isValidBlock() 함수를 addBlcok() 함수에 추가해주기 

<javascript />
// 얘는 단순히 Push만 할 것 ! 인자값에 배열을 넣어주기 (data) function addBlock(data) { // new header 만들어서 => new block(header, body) const newBlock = nextBlock(data) // return 다음 블록에 대한 객체 // newBlock과 마지막 if(isValidNewBlock(newBlock, getLastBlock()) && isValidBlocks(Blocks)){ Blocks.push(newBlock); return newBlock; //함수가 여기서 끝나버리게 } return false; }

 

 

 

 

 

전체 코드 

block.js

<html />
const fs = require('fs') 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 } // 2. StampTime 구하기 function getCurrentTime(){ console.log('TimeStamp = ', Math.ceil(new Date().getTime()/1000)) return Math.ceil(new Date().getTime()/1000) } // 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']) // 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) } // 6. 블록 생성할 때마다 -> 배열에 넣기 예정 / 마지막 블록 가져오기 let Blocks = [createGenesisBlock()] console.log('Blocks=', Blocks) function getLastBlock(){ return Blocks[Blocks.length-1] } //---------------------------------------------------------------------------------------- // 새로운 block을 간단히 추가하는 함수 function addBlock(data){ const newBlock = nextBlock(data); if(isValidNewBlock(newBlock, getLastBlock()) && isValidBlocks(Blocks)){ Blocks.push(newBlock); return true; } return false; } // 새로운 블록 검증 function isValidNewBlock(currentBlock, previousBlock){ // 1. 새로운 블록의 type 검증 if(!isValidType(currentBlock)){ // "" or '' or `` string 값으로 만들 때 객체는[Object Object]로 나와서 JSON.stringify 붙여주기 console.log(`inValidType is found in currentBlock = ${currentBlock}`); console.log(`inValidType is found in currentBlock = ${JSON.stringify(currentBlock)}`); return false; } // 2. index 검증 if(previousBlock.header.index+1 !== currentBlock.header.index){ console.log(`invalid index found`) return false; } // 3. previousHash check if(currentBlock.header.previousHash !== createHash(previousBlock)){ console.log(`invalid previousHash found`) return false; } // 4. merkleRoot check (root가 정확한지) if(currentBlock.header.merkleRoot !== merkle('sha256').sync(currentBlock.body).root()){ console.log(`invalid body found`) return false; } // 5. body check (body에 내용이 반드시 있어야함 !) if(currentBlock.body.length===0){ console.log(`invalid body found, it's empty`); return false; } return true; } // 새로운 블록 type 검증 function isValidType(block){ return ( typeof(block.header.version)=="string" && typeof(block.header.index)=="number" && typeof(block.header.previousHash)=="string" && typeof(block.header.time)=="number" && typeof(block.header.merkleRoot)=="string" && typeof(block.body)=="object" ) } // 6. 전체 검증 (제네시스블록 & 블록을 담은 Blocks 배열 전체) function isValidBlocks(Blocks){ // GENESIS BLOCK 검증 if(JSON.stringify(Blocks[0]) !== JSON.stringify(createGenesisBlock())){ console.log(`Invalie Genesis Block found`); return false; } // BLOCKS ARRAY 검증 // tempBlocks 변수에 제네시스 블록 배열로 담기 let tempBlocks = [Blocks[0]]; for(let i=1; i<Blocks.length; i++){ if(isValidNewBlock(Blocks[i], tempBlocks[i-1])){ tempBlocks.push(Blocks[i]) }else{ console.log(`invalid Block found, located at ${i} in Blocks Array`) return false; } } return true; } addBlock(['asdf']); // 다음 블럭(nextBlock)의 header와 body를 만들어주는 함수 function nextBlock(data){ // 이전 block 가져오기 const prevBlock = getLastBlock(); // Header const version = getVersion(); const index = prevBlock.header.index + 1; const previousHash = createHash(prevBlock); const time = getCurrentTime(); // Mekle root를 가져오기 위해 tree 만들기 const merkleTree = merkle('sha256').sync(data) const merkleRoot = merkleTree.root() || '0'.repeat(64); const newBlockHeader = new BlockHeader(version, index, previousHash, time, merkleRoot) // header + data(body) 로 new block return return new Block(newBlockHeader, data) } function createHash(block){ // 이전 블록을 인자로 받아와 해당 블록 header의 요소들 가져오기 const {version, index, previousHash, time, merkleRoot} = block.header; // 모든 string을 + 더하기 const blockString = version + index+previousHash+time+merkleRoot; const Hash = CryptoJs.SHA256(blockString).toString(); return Hash; }
profile

사랑하애오

@사랑하애

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!