728x90

작업(을 통한)증명 Proof of Work

https://newpouy.github.io/jekyll/update/2018/03/20/naivecoin-kr-translate-2.html

 

Naivecoin Korean Translate Version #2

navie코인 번역 원문: lhartikk.github.io

newpouy.github.io

 

#1에서는 누구나 블록추가할 수 있었지만 이제는 계산을 푸는 작업을 해야 블록추가할 수 있게할거야. 이 계산 푸는 거를 채굴이라고 함. 또한 퍼즐의 난이도를 통해 블록 조절할거야. 좀 있다가는 트랜잭션(거래내역)에 대해서도 다룰거야. 이걸 통해서 보상받고 거래주고받고 하는거겠지

 

 

블록에 추가할 두 가지 속성 (-> 작업증명 퍼즐(블록의 해쉬값 찾기)을 풀기 위한 값)

  • difficulty 난이도  (=유효한 블록의 해쉬값은 얼마나 많은 0으로 시작해야하는가, 작은값찾기임)

해쉬값을 2진수로 표현한 다음 시작부분0의 갯수세어보는 것.

난이도 difficulty 가 4이면 임계값인 nonce가 1,2,3 올라가면서 해쉬값을 찾는다. 해쉬값계산 함수를 보면 

전체값을 합쳐서 hash화한걸 볼 수 있어 

 //다합쳐서 해시로 만들고 리턴
  const hash = cryptojs.SHA256(blockString).toString();
  return hash;

참고로 우리 코드에서도 다음블록찾는 nextBlock함수안에 findBlock함수가 있는데 거기서 nonce++로 수 올리고 있음.

 

 

 

블록의 해시값이 난이도를 만족하는지 

  • nonce 난이도를 만족하는 해시값을 찾기위해 반복한 값

 

//naive코드와 우리 팀플코드의 차이점

naive - 난이도를 만족하는지 확인하는 코드에서 hexToBinary 함수를 썼음 

function hexToBinary(s) {
  //헤더부분을 sha256 암호화한 결과
  //16진수 64자리를 2진수로 변환하기
  const lookupTable = {
    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",
  };

상단의 이미지로 예시를 들면 

난이도가 4일 때 hash:08f3... 이거를 binaryHash 2진수로 변환한거임 0: "0000", 8:"1000", f:"1111",3:"0011"

(숫자형태아니고 문자열 string형태라서 옆에 붙는다)

우리는 hexToBinary 함수를 안썼어. 그래서 nonce추가되는걸로 난이도 따라 해시값찾는걸로 나와. naive는 binaryHash기준으로 난이도 비교적 쉽게 통과되고 우리는 hash대로. 그니까 난이도 8일때 hash값 지금 0027..나오면 우린 안돼 더 돌려서 hash값 앞에 0이 최소한 8개여야 통과되는 거임. 

 

 

 

 

아무튼 다시 naive코드로 와서

 

블록의 해시값이 난이도 difficulty를 만족하는지 확인하는 코드

const hashMatchesDifficulty=(hash, difficulty)=>{

해시값을 이진수화해.

난이도만큼 0을 반복해.

이진수화한 거가. 지정한문자로 시작하는지 확인. 0이 8개인 문자로. 

}

 

난이도를 만족하는 해시값찾기 위해 같은 블록에서 여러번 계산해줘야한다. 이때 nonce값을 쓰는데 sha256라는 해시함수를 쓴다. 채굴이 바로 매번 다른 nonce값을 시도해보는 과정을 뜻한다. 

 

블록구조, 최초의 블록 구조에 difficulty와 nonce추가

class Block{

난이도 추가

넌스값 추가

}

 

 

블록찾기 

nonce값은 언제 증가시키는 findBlock 함수. 해시값을 찾을 때까지 반복문 돌릴거임.

const findBlock{

초기넌스값은 0

hash를 해시계산함수 안에 블록애들 넣어서 찾아.

만약에 난이도 확인하는 함수에 (해시랑, 난이도)보내서 통과되면

블록을 뱉어내(블록내용들을 담아서)

}

 

그렇게 블록이 채굴되면 네트워크통해서 발송(broadcast)되겠지

 

 

 

난이도(difficulty)를 어떻게 결정할건가

 

난이도값을 계산하는 로직필요해서 상수를 몇 개 정의하면서 만들었어. 하드코딩한거임. 물론 naive에서..ㅋㅋ

  • BLOCK_GENERATION_INTERVAL: 블록은 얼마나 자주 채굴되는가(Bitcoin의 경우 10분 간격이죠.)
  • DIFFICULTY_ADJUSTMENT_INTERVAL: 난이도difficulty는 얼마나 자주 조정되는가(Bitcoin은 2016블록마다 조정돼요.)
// in seconds
const BLOCK_GENERATION_INTERVAL: number = 10;

// in blocks
const DIFFICULTY_ADJUSTMENT_INTERVAL: number = 10;

신기한게 여기서는 그냥 임의로 지정한 숫자 10을 넣었는데 이게 어떻게 10초, 10블록으로 인식하나 싶었거든. 이게 같이 비교되는 애들따라서 인식을 하는거래.  코드를 보자

 

난이도가져오는함수

const getDifficulty=(블록체인)={

가장 마지막 블록= 블록체인.길이-1

만약에

마지막블록.index % BLOCK_GENERATION_INTERVAL(10블록으로 인식됨) 이 0이면 그리고 마지막블록.index가 0이 아니면

난이도 조절함수로 (마지막블록, 블록체인) 보내

 

아니면, 마지막블록의 난이도 뱉어내.

}

 

 

난이도 조절함수 

const getAdjustedDifficulty=(마지막블록,블록체인)=>{

이전조절블록 = 블록체인.길이- BLOCK_GENERATION_INTERVAL(10블록으로 인식됨)

예상시간= BLOCK_GENERATION_INTERVAL(10) 곱하기 DIFFICULTY_ADJUSTMENT_INTERVAL(10) //100이라는 숫자

걸린시간 = 마지막블록.timestamp -이전조절블록.timestamp     //그니까 10블록 생성될동안 걸린시간

 

만약 (걸린시간이 < 100 /2 ){

이전조절블록.난이도 +1  

아니면, (걸린시간 > 100* 2) {

이전조절블록.난이도 -1}

아니면, {

이전조절블록. 난이도 그대로 뱉어내

}

}

 

 

timestamp 

이전에는 아무 역할도 안해서 무슨값이든 상관없었는데 이제 난이도 조절하면서 블록 유효성 검증되는지 사용할거야.

 

유효한 타임스탬프인지 확인하는 함수

const isValidTimestamp = (새블록, 이전블록)=>{

이전블록.생성시간 - 60 < 새 블록.생성시간 그리고 새블록.생성시간 - 60 < 현재타임스탬프함수getCurrentTimestamp()

면 true

}

 

//현재 타임스템프 찍어주는 함수
function getCurrentTimestamp() {
  //Math.round 반올림함수
  return Math.round(new Date().getTime() / 1000);
}
 
new Date().getTime() / 1000이게 1970 년 1 월 1 일 자정 이후의 초를 알려준다고 함.

 

 

 

누적난이도

#1에서는 가장 긴 체인이 옳은 체인이라고 했지만 사실 

difficulty 난이도가 가장 많이 누적된 체인이 옳은 체인이야. 

 

작업증명에서 가장 중요한 건 그 과정이 풀기는 어렵지만 증명하기는 쉬워야한다는 것! 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

Hash

sha256

단방향 암호화, 자리수 64자리로 고정됨

 

해시함수 설명:

더보기

해시함수를 이용한다면 어떤 길이의 입력값이라도 256비트의 고정된 결과값을 출력할 것이고

입력값의 아주 일부만 변경되어도 전혀 다른 값이 출력되는 특징 때문에 데이터가 변경되었는지 쉽게 확인할 수 있습니다.

추가적으로 해시함수는 입력된 값이 같을 경우 항상 같은 결과 값을 출력해야합니다.

https://steemit.com/kr/@yahweh87/2)

 

머클트리 Merkle tree, 머클 루트 Merkle root

데이터가 위변조 되었는지 효율적으로 확인하기 위한 용도로 사용됨

자바스크립트에서 merkletreejs를 이용해 사용할 수 있다.

https://blockone.tistory.com/11 -Merkle tree

더보기

출처 : https://blockone.tistory.com/11

머클트리 Merkle tree

해시트리 라고도 한다. 여러 블록으로 나뉘어 있는 데이터를 전송할 때 데이터가 변조되지 않았음  보증하는 용도로 쓰인다. 특히 p2p네트워크에서 전송받는 데이터에 오류가 있거나 외부로부터 조작이 있었는지 검증하는 용로도로 쓰인다.

블록체인에서는 블록에 포함된 거래 데이터를 요약해 트리 형태로 만들게 되는데 해시함수를 활용해 두개의 거래 데이터를 하나의 데이터로 묶음으로써 용량을 절약할 수 있다.

머클 루트 

블록에 들어있는 모든 거래내역을 요약한 데이터로 최소한의 정보로 인증할 수 있도록 도와준다.

개별 거래에 대한 트랜잭션을 검증하는 기능을 수행하는 노드(라이트노드)에 대해서는 중요한 데이터만 갖고 있게 한다. 외부에서 다른 블록의 거래내역을 조작하면 머클루트를 대조하여 비교하게 된다. 가장 밑단에 있는 거래를 제외한 나머지내역을 두개씩 짝지어 해시값을 얻고 또 그 해시끼리 짝지어 암호화하는 식이다. 이렇게 모든 거래 내역에 해시값을 얻는 과정을 거듭하여 나무 모형으로 만들면 머클트리가 된다. 결국 머클트리 그 자체가 해시로 이루어져 있다. 하나의 트랜잭션이 변조되면 머클루트까지 모든 값이 바뀌게 되는 쇄도효과가 일어난다.

 

 

합의 알고리즘

-작업증명Proof of Work

-지분증명 Proof of Stake

728x90

+ Recent posts