본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[122일차] 블록체인 작업증명 Proof of Work (POW)

반응형

 

오늘 작업증명 공부 예정 ! 

block.js 을 주로 수정할 예정 

-> 블럭 생성할 때 쉽게 생성하지 못하도록 만들기

-> 요청한대로 블록이 바로 생성되는게 아니라 문제를 풀어서 생성하도록 

 

작업증명이란 ? 

컴퓨터 연산을 통해 일정한 hash를 찾도록 하는 작업증명(pow)과정을 거치도록 한다. 작업증명을 통해 특정 해시값을 찾기위해 수많은 반복연산을 수행하도록 함으로써 상당한 시간과 비용이 들게 해서 결국 대량 스팸메일을 보낼 수 없도록 하는게 최초 탄생 이유 (이후 비트코인에 적용됨 by 사토시 나카모토) 

 

 

 

1. Header 기존 5가지 내용에 + 2  두 가지 추가

- 문제 난이도 설정

- 문제 몇번 풀었는지에 대한 

 

block.js

class BlockHeader { 
    constructor(version ,index ,previousHash, time, merkleRoot, difficulty, nounce){
        this.version = version 
        this.index = index  // 마지막 블럭의 index + 1 
        this.previousHash = previousHash // 마지막 블럭 -> header -> string 연결  -> SHA256
        this.time = time  //
        this.merkleRoot = merkleRoot 
        
        // 문제 어려움 정도
        this.difficulty = difficulty 
        // 풀은 횟수 
        this.nounce = nounce 
    }
}

 

 

2. GENESISBLOCK - new BlockHeader 사용한 createGenesisBlock 수정 

function createGenesisBlock(){
    // 1. header 만들기 
    // 5개의 인자값을 만들어야되여.
    const version = "1.0.0" // 1.0.0
    const index = 0
    const time = 1630907567 // 하드코딩 
    const previousHash = '0'.repeat(64)
    const body = ['hello block']

    const tree = merkle('sha256').sync(body)
    const root = tree.root() || '0'.repeat(64)

    const difficulty = 0 
    const nounce = 0 

    const header = new BlockHeader(version,index,previousHash,time,root, difficulty, nounce)
    return new Block(header,body)
}

난이도 0 / nounce 0 설정 

 

 

 

 

3. nextBlock() 함수에도 쓰인 BlockHeader  수정 

nextBlock()에서 nounce 설정 등등이 이루어질 것 ! 

 

nonce

 

-findBlock() 생성 - > 여기에서 header 생성할 것 -> new BlockHeader => 방금 만든 findBlock()으로 대체 + difficulty 일단 0 으로 추가 (먼저 nonce부터 처리하고 difficulty 처리 예정) 

// 다음블럭의 Header와 Body를 만들어주는 함수 2번
function nextBlock(data){
    // header 
    const prevBlock = getLastBlock()
    const version = getVersion()
    const index = prevBlock.header.index + 1
    const previousHash = createHash(prevBlock)
    const time = getCurrentTime()

    const difficulty = 0 

    const merkleTree = merkle("sha256").sync(data) // []
    const merkleRoot = merkleTree.root() || '0'.repeat(64)

    const header =findBlock(version,index,previousHash,time,merkleRoot,difficulty);
    return new Block(header,data)
}

function findBlock(version,index,previousHash,time,merkleRoot,difficulty){
    let nonce = 0 
	return new BlockHeader(version,index,previousHash,time,merkleRoot,difficulty, nonce)
}

이제 findBlock() 함수 안에 무한반복문을 넣고 이제 조건이 맞을 때만 return 되도록 만들기 

반복할 때마다 nonce 값 ++ 

function findBlock(version, index, previousHash, time, merkleRoot, difficulty) {
    let nonce = 0
    while (1) {
        if () {
            return new BlockHeader(version, index, previousHash, time, merkleRoot, difficulty, nonce)
        }
        nonce++; 
    }

}

if () 조건 들어가는 것 만들기 

 

 

샘플 만들기 (연습용)

src > test.js

const CryptoJs = require('crypto-js')

let a = "0000helloThere!"

console.log(a.startsWith('0000'))

console.log(CryptoJs.SHA256(a))
console.log(CryptoJs.SHA256(a).toString())
console.log(CryptoJs.SHA256(a).toString().toUpperCase())

암호화가 16진수로 나옴 

 

 

첫글자가 0000 "0"이 네개가 되었을 때 블럭을 생성할 수 있도록 작업 

- SHA256으로 16진수로 변환된 것 => 2진수로 변환할 것 

16진수 0 = 2진수 0000

즉, 2진수로 바꿨을 때 0000인 경우 (16진수일 때 첫 글자가 0000일때) 확율 1/16 

블록에 따라 0000의 개수를 가변적으로 만들면 나중에 확율이 많이 낮아져서 컴퓨터가 for문을 막 돌림! 

 

 

src > utils.js 파일 생성 

//131402EA24........

function hexToBinary(s){
    const lookup = {
        "0": "0000",
        "1": "0001",
        "2": "0010",
        "3": "0011",
        "4": "0100",
        "5": "0101",
        "6": "0110",
        "7": "0111",
        "8": "1000",
        "9": "1001",
        "A": "1010",
        "B": "1011",
        "C": "1100",
        "D": "1101",
        "E": "1110",
        "F": "1111",
    }
    console.log(s)
}

const txt = "1314042ECF8C8A7702AABA1C82D560B5A262FF3E922BB117FA81F2B002FC37B9";
hexToBinary(txt)
//131402EA24........

function hexToBinary(s){
    const lookup = {
        "0": "0000",
        "1": "0001",
        "2": "0010",
        "3": "0011",
        "4": "0100",
        "5": "0101",
        "6": "0110",
        "7": "0111",
        "8": "1000",
        "9": "1001",
        "A": "1010",
        "B": "1011",
        "C": "1100",
        "D": "1101",
        "E": "1110",
        "F": "1111",
    }
    console.log(s)
    for(let i=0; i<s.length; i++){
        console.log(lookup[s[i]])   
    }
}

const txt = "1314042ECF8C8A7702AABA1C82D560B5A262FF3E922BB117FA81F2B002FC37B9";
hexToBinary(txt)

hash에 있어서는 안되는 글자가 있으면 안됨 !! 예외처리 해주기 

 

 

//131402EA24........

function hexToBinary(s){
    const lookup = {
        "0": "0000",
        "1": "0001",
        "2": "0010",
        "3": "0011",
        "4": "0100",
        "5": "0101",
        "6": "0110",
        "7": "0111",
        "8": "1000",
        "9": "1001",
        "A": "1010",
        "B": "1011",
        "C": "1100",
        "D": "1101",
        "E": "1110",
        "F": "1111",
    }
    console.log(s)
    let rst = ""
    for(let i=0; i<s.length; i++){
        if(lookup[s[i]] === undefined) return null
        console.log(lookup[s[i]])   
        rst += lookup[s[i]]
    }    
    return rst
}

const txt = "1314042ECF8C8A7702AABA1C82D560B5A262FF3E922BB117FA81F2B002FC37B9";
let result = hexToBinary(txt)
console.log(result)
module.exports={
    hexToBinary
}

exports  해주기 

 

createHeaderHash함수 만들기 (findBlock 함수 완성위한 빌드작업) 

// 요 함수가 쓰일 때 nonce가 위에 설정되어있어서 nonce값도 넣어주기
function createHeaderHash(version, index, previousHash, time, merkleRoot, difficulty, nonce){
    let txt = version+index+previousHash+time+merkleRoot+difficulty;
    return CryptoJs.SHA256(txt).toString().toUpperCase()
}

toUpperCase 이유 : 아까 utils.js 에서 대문자로 설정함 !  맞춰주기 

 

 

function findBlock(version, index, previousHash, time, merkleRoot, difficulty) {
    let nonce = 0;
    while (1) {
        // 조건 : 우리가 만들 header의 hash값의 앞자리 0이 몇개인가 
        let hash = createHeaderHash(version, index, previousHash, time, merkleRoot, difficulty, nonce);
        // 내가 가지고있는 hash에서 그 값을 2진수로 바꾸고
        // 2진수에서 바꾼 값 중에서 첫글자가 0000인가~ 
        if () {
            return new BlockHeader(version, index, previousHash, time, merkleRoot, difficulty, nonce)
        }
        nonce++; 
    }
}

이제 if () 조건절에 가지고 있는 hash 에서 2진수로 바꾸고 그 값의 첫글자가 0000인가 를 확인할건데 또 길꺼니까 함수로 뺌 

 

16진수 -> 2진수로 바꾸는 utils.js 가져와서 적용 

const {hexToBinary} = require('./utils')
function hashMatchDifficulty(hash, difficulty){
    //difficulty 에 따라 0의 개수가 다름
    //difficulty 가 높아질 수록 의 개수가 올라가서 => 
    // 난이도가 어려워짐 
    
    // hash(16진수) => 2진수로 바꾸기 
    const hashBinary = hexToBinary(hash)
}
function hashMatchDifficulty(hash, difficulty){
    //difficulty 에 따라 0의 개수가 다름
    //difficulty 가 높아질 수록 의 개수가 올라가서 => 
    // 난이도가 어려워짐 
    
    // hash(16진수) => 2진수로 바꾸기 
    const hashBinary = hexToBinary(hash)
    // startsWith() return Boolean 
    const prefix = '0'.repeat(difficulty)
    return hashBinary.startsWith(prefix)
}

 

드디어 findBlock 완성 ㅋ..

function findBlock(version, index, previousHash, time, merkleRoot, difficulty) {
    let nonce = 0;
    while (1) {
        // 조건 : 우리가 만들 header의 hash값의 앞자리 0이 몇개인가 
        let hash = createHeaderHash(version, index, previousHash, time, merkleRoot, difficulty, nonce);
        // 내가 가지고있는 hash에서 그 값을 2진수로 바꾸고
        // 2진수에서 바꾼 값 중에서 첫글자가 0000인가~ 
        if (hashMatchDifficulty(hash,difficulty)) {
            return new BlockHeader(version, index, previousHash, time, merkleRoot, difficulty, nonce)
        }
        nonce++; 
    }
}

function hashMatchDifficulty(hash, difficulty){
    //difficulty 에 따라 0의 개수가 다름
    //difficulty 가 높아질 수록 의 개수가 올라가서 => 
    // 난이도가 어려워짐 
    
    // hash(16진수) => 2진수로 바꾸기 
    const hashBinary = hexToBinary(hash)
    // startsWith() return Boolean 
    const prefix = '0'.repeat(difficulty)
    return hashBinary.startsWith(prefix)
}

 

block.js 전체 

const fs = require('fs')
const merkle = require('merkle')
const CryptoJs = require('crypto-js')
const random = require('random')
const {hexToBinary} = require('./utils')

/* 사용법 */
// const tree = merkle("sha256").sync([]) // tree 구조 
// tree.root()

class BlockHeader {
    constructor(version, index, previousHash, time, merkleRoot, difficulty, nonce) {
        this.version = version
        this.index = index  // 마지막 블럭의 index + 1 
        this.previousHash = previousHash // 마지막 블럭 -> header -> string 연결  -> SHA256
        this.time = time  //
        this.merkleRoot = merkleRoot

        // 문제 어려움 정도
        this.difficulty = difficulty
        // 풀은 횟수 
        this.nonce = nonce
    }
}

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

let Blocks = [createGenesisBlock()]

function getBlocks() {
    return Blocks
}

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

function createGenesisBlock() {
    // 1. header 만들기 
    // 5개의 인자값을 만들어야되여.
    const version = "1.0.0" // 1.0.0
    const index = 0
    const time = 1630907567 // 하드코딩 
    const previousHash = '0'.repeat(64)
    const body = ['hello block']

    const tree = merkle('sha256').sync(body)
    const root = tree.root() || '0'.repeat(64)

    const difficulty = 0
    const nonce = 0

    const header = new BlockHeader(version, index, previousHash, time, root, difficulty, nonce)
    return new Block(header, body)
}

// 다음블럭의 Header와 Body를 만들어주는 함수 2번
function nextBlock(data) {
    // header 
    const prevBlock = getLastBlock()
    const version = getVersion()
    const index = prevBlock.header.index + 1
    const previousHash = createHash(prevBlock)
    const time = getCurrentTime()

    const difficulty = 0

    const merkleTree = merkle("sha256").sync(data) // []
    const merkleRoot = merkleTree.root() || '0'.repeat(64)

    const header = findBlock(version, index, previousHash, time, merkleRoot, difficulty);
    return new Block(header, data)
}

function findBlock(version, index, previousHash, time, merkleRoot, difficulty) {
    let nonce = 0;
    while (1) {
        // 조건 : 우리가 만들 header의 hash값의 앞자리 0이 몇개인가 
        let hash = createHeaderHash(version, index, previousHash, time, merkleRoot, difficulty, nonce);
        // 내가 가지고있는 hash에서 그 값을 2진수로 바꾸고
        // 2진수에서 바꾼 값 중에서 첫글자가 0000인가~ 
        if (hashMatchDifficulty(hash,difficulty)) {
            return new BlockHeader(version, index, previousHash, time, merkleRoot, difficulty, nonce)
        }
        nonce++; 
    }
}

function hashMatchDifficulty(hash, difficulty){
    //difficulty 에 따라 0의 개수가 다름
    //difficulty 가 높아질 수록 의 개수가 올라가서 => 
    // 난이도가 어려워짐 
    
    // hash(16진수) => 2진수로 바꾸기 
    const hashBinary = hexToBinary(hash)
    // startsWith() return Boolean 
    const prefix = '0'.repeat(difficulty)
    return hashBinary.startsWith(prefix)
}

// 요 함수가 쓰일 때 nonce가 위에 설정되어있어서 nonce값도 넣어주기
function createHeaderHash(version, index, previousHash, time, merkleRoot, difficulty, nonce){
    let txt = version+index+previousHash+time+merkleRoot+difficulty;
    return CryptoJs.SHA256(txt).toString().toUpperCase()
}

// 3번
function createHash(block) {
    const {
        version,
        index,
        previousHash,
        time,
        merkleRoot
    } = block.header
    const blockString = version + index + previousHash + time + merkleRoot;
    const Hash = CryptoJs.SHA256(blockString).toString()
    return Hash
}

// Blocks push 1번
function addBlock(newBlock) {
    // new header -> new block ( header , body)

    if (isVaildNewBlock(newBlock, getLastBlock())) {
        Blocks.push(newBlock);
        return true;
    }
    return false;
}

function mineBlock(blockData) {
    const newBlock = nextBlock(blockData) // Object Block {header, body}
    if (addBlock(newBlock)) {
        const nw = require('./network')
        nw.broadcast(nw.responseLastMsg())
        return newBlock
    } else {
        return null
    }
}

/* etc 
1: 타입검사
*/
function isVaildNewBlock(currentBlock, previousBlock) {
    // currentBlock 에대한 header , body DataType을 확인
    if (!isVaildType(currentBlock)) {
        console.log(`invaild block structrue ${JSON.stringify(currentBlock)}`)
        return false
    }
    // index값이 유효한지
    if (previousBlock.header.index + 1 !== currentBlock.header.index) {
        console.log(`invaild index`)
        return false
    }
    // previousHash 체크
    /*
        어떻게 만들었는가? 
        해당블럭의 header의 내용을 글자로 합쳐서 SHA256 활용하여 암호화한 결과물 
        previousHash         previousHash
        제네시스 블럭 기준 -> 2번째 블럭 
     */
    if (createHash(previousBlock) !== currentBlock.header.previousHash) {
        console.log(`invaild previousBlock`)
        return false
    }
    // Body check
    /*
        current.header.merkleRoot -> body [배열]
        current.body -> merkleTree root -> result !== current.header.merkleRoot
        굳이왜 ?..
        네트워크 
        body... 내용이 없으면안됩니다.
        current.body.lenght !== 0 ||  (  currnetBlock.body가지고 만든 merkleRoot !== currentBlock.header.merkleRoot )
        current.body.lenght !== 0 ||  (  merkle("sha256").sync(currentBlock.body).root() !== currentBlock.header.merkleRoot )
    */
    if (currentBlock.body.length === 0) {
        console.log(`invaild body`)
        return false
    }

    if (merkle("sha256").sync(currentBlock.body).root() !== currentBlock.header.merkleRoot) {
        console.log(`invalid merkleRoot`)
        return false
    }

    return true
}

function isVaildType(block) {
    return (
        typeof (block.header.version) === "string" &&  // stirng
        typeof (block.header.index) === "number" && // number
        typeof (block.header.previousHash) === "string" && // stirng
        typeof (block.header.time) === "number" && // number
        typeof (block.header.merkleRoot) === "string" && // string
        typeof (block.body) === "object" // object
    )

}

function replaceBlock(newBlocks) {
    // newBlocks : 내가 받은 전체 배열 => 내가 받은 전체 블록들
    //Blocks = newBlocks
    // 1. newBlocks 내용을 검증해야합니다.
    // 2. 검증을 한번만 하지않습니다. 랜덤하게 한번만할수있고, 두번할수있고, 세번할수도있게합니다. -> 조건문에 random을 사용한다.
    // 3. Blocks = newBlocks
    // 4. broadcast 날립니다.

    if (isVaildBlock(newBlocks) && newBlocks.length > Blocks.length && random.boolean()) {
        console.log(`Blocks 배열을 newBlocks 으로 교체합니다.`)
        const nw = reuqire('./network')
        Blocks = newBlocks
        nw.broadcast(nw.responseLastMsg())

    } else {
        console.log(`메시지로 부터 받은 블록배열이 맞지 않습니다.`)
    }
}


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

function getCurrentTime() {
    return Math.ceil(new Date().getTime() / 1000)
}

/*
    일단 제네시스 블럭이 유효한지 데이터가 바뀐적이 없는지.
    2번째는 
    blocks 모든 배열을 검사를 할겁니다.
*/

function isVaildBlock(Blocks) {
    if (JSON.stringify(Blocks[0]) !== JSON.stringify(createGenesisBlock())) {
        console.log(`genesis error`)
        return false
    }

    //Blocks 3개 
    // 1 < 3 
    let tempBlocks = [Blocks[0]]
    for (let i = 1; i < Blocks.length; i++) {
        if (isVaildNewBlock(Blocks[i], tempBlocks[i - 1])) {
            tempBlocks.push(Blocks[i])
        } else {
            return false
        }
    }

    return true
}

// class 
// { header body } 1차 목표는 제네시스 블럭을 만드는것 
//console.log(Blocks)

module.exports = {
    getBlocks,
    getLastBlock,
    addBlock,
    getVersion,
    mineBlock,
    createHash,
    replaceBlock,
}

 

 

window terminal 열어서 아래 명령어 실행 => 지금까지 오류가 있나 없나 쳌 (server on하고) 

curl http://localhost:3000/blocks
curl -X POST -H "Content-Type:application/json" -d "{\"data\":[\"hello\"]}" http://localhost:3000/mineBlock

 

 

 

 


 

 

 

 

난이도 만들러 가좌

Difficulty

총 코인 개수정해놓고 난이도 조절할 수도. 블록 하나 만드는 시간 설정 가능 

 

1. 시간 설정 - 마지막 블록의 시간으로 비교 

- nextBlock에서 해야함 ! GenesisBlock함수에서 잘못 difficulty 수정했다가 오류남 (genesisBlock difficulty = 0 ;) 

// 다음블럭의 Header와 Body를 만들어주는 함수 2번
function nextBlock(data) {
    // header 
    const prevBlock = getLastBlock()
    const version = getVersion()
    const index = prevBlock.header.index + 1
    const previousHash = createHash(prevBlock)
    const time = getCurrentTime()

    const difficulty = getDifficulty(getBlocks())

    const merkleTree = merkle("sha256").sync(data) // []
    const merkleRoot = merkleTree.root() || '0'.repeat(64)

    const header = findBlock(version, index, previousHash, time, merkleRoot, difficulty);
    return new Block(header, data)
}

getDifficulty() 함수 생성 - 인자값 blocks 는 전체 블록배열을 가져온 것 => 배열임

 

2. 마지막 블록 가져오기 

function getDifficulty(blocks){
    const lastBlock = blocks[blocks.length-1];
    
}

3. 상수 설정 

const fs = require('fs')
const merkle = require('merkle')
const CryptoJs = require('crypto-js')
const random = require('random')
const {hexToBinary} = require('./utils')
// 초 단위로 .. 블록 만들 때 기준점 만들기
const BLOCK_GENERATION_INTERVAL = 10; // 10초 
// 블록의 개수에 따라 난이도 조정 
// 블록이 10개째가 넘을 때마다 난이도 조정
const BLOCK_ADJUSTMENT_INTERVAL = 10;

4. 마지막 블록의 인덱스를 10으로 나눠서 딱떨어지면 (10의 배수일 때마다) 

function getDifficulty(blocks){
    const lastBlock = blocks[blocks.length-1];
    // 마지막 블록의 index 값을 10으로 나눴을 때 0 이면 10의 배수이다. 
    // (제네시스 블록 제외)
    if(lastBlock.header.index%BLOCK_ADJUSTMENT_INTERVAL===0
        && lastBlock.header.index !==0 ){
        //난이도 조정하는 코드 필요함 
    }

    return lastBlock.header.difficulty;
}

5. 난이도 조정하는 코드에 조정된 난이도를 return하는 함수 작성

function getDifficulty(blocks){
    const lastBlock = blocks[blocks.length-1];
    // 마지막 블록의 index 값을 10으로 나눴을 때 0 이면 10의 배수이다. 
    // (제네시스 블록 제외)
    if(lastBlock.header.index%BLOCK_ADJUSTMENT_INTERVAL===0
        && lastBlock.header.index !==0 ){
        //난이도 조정하는 코드 필요함 
        return getAdjustedDifficulty(lastBlock, blocks);
    }

    return lastBlock.header.difficulty;
}

6. getAdjustedDifficulty 함수 생성 

function getAdjustedDifficulty(lastBlock, blocks){
    // blocks 10개 단위로 끊는다. (게시판의paging처럼!)
    // 난이도가 증가되기 전 값 
    // 10개의 이전 블록의 난이도를 가져와서 증가시키기
    // 바로 이전 블록의 난이도를 가져오는 것보다 정확
    const prevAdjustmentBlock = blocks[blocks.length-BLOCK_ADJUSTMENT_INTERVAL];
    // ex. 총 배열이 20개다.-> 20 - 10 = 10 
    // blocks[10] 번째의 블록을 가리키게됨 
    
    // 시간 작업
    // 10개 블록이 만들어지는 시간 차이 얼마나 나는가 구할 수 있음. 
    const timeToken = lastBlock.header.time-prevAdjustmentBlock.header.time;
    
    


}

완성

function getAdjustedDifficulty(lastBlock, blocks){
    // blocks 10개 단위로 끊는다. (게시판의paging처럼!)
    // 난이도가 증가되기 전 값 
    // 10개의 이전 블록의 난이도를 가져와서 증가시키기
    // 바로 이전 블록의 난이도를 가져오는 것보다 정확
    const prevAdjustmentBlock = blocks[blocks.length-BLOCK_ADJUSTMENT_INTERVAL];
    // ex. 총 배열이 20개다.-> 20 - 10 = 10 
    // blocks[10] 번째의 블록을 가리키게됨 
    
    // 시간 작업
    // 10개 블록이 만들어지는 시간 차이 얼마나 나는가 구할 수 있음. 
    const timeToken = lastBlock.header.time-prevAdjustmentBlock.header.time;
    
    // 예상한 시간 
    const timeExpected = BLOCK_ADJUSTMENT_INTERVAL * BLOCK_GENERATION_INTERVAL;
    
    //예상 시간보다 적게 걸렸다면 (너무 빨리만들면 == 문제가 너무 쉽게 풀리면)
    // 내가 예상한 시간보다 반만큼 더 빠르면 
    if(timeToken < timeExpected/2){
        return prevAdjustmentBlock.header.difficulty +1;
    }else if(timeToken>timeExpected*2){
        return prevAdjustmentBlock.header.difficulty -1;
    }else{
        return prevAdjustmentBlock.header.difficulty;
    }
    
}

 

=> server on + 쳌쳌

 

질문

- 초를 100 으로 해도 되는지!? *1000을 안해도 되는지

=> 처음에 time 설정했을 때 애초에 /1000으로 나눠서 1= 1초가 됨 

 

 

findBlock의 hash 를 console.log찍어보기 

function findBlock(version, index, previousHash, time, merkleRoot, difficulty) {
    let nonce = 0;
    while (1) {
        // 조건 : 우리가 만들 header의 hash값의 앞자리 0이 몇개인가 
        let hash = createHeaderHash(version, index, previousHash, time, merkleRoot, difficulty, nonce);
        // 내가 가지고있는 hash에서 그 값을 2진수로 바꾸고
        // 2진수에서 바꾼 값 중에서 첫글자가 0000인가~ 
        console.log('findBlock의 hash이다.=', hash)

        
        if (hashMatchDifficulty(hash,difficulty)) {
            return new BlockHeader(version, index, previousHash, time, merkleRoot, difficulty, nonce)
        }
        nonce++; 
    }
}

-> 쭊 명령어 실행해보고 난이도 올라가는거 봐봐

(우리의 컴퓨터로는 난이도가 엄청 높으면 과부하......) 

 

교수님이 실행해본 난이도 16 

35만번 실행함 (5분정도 걸림)

 

 

다음시간 : wallet 지갑 / 인증시스템 만들어보기

반응형