#1에서는 누구나 블록추가할 수 있었지만 이제는 계산을 푸는 작업을 해야 블록추가할 수 있게할거야. 이 계산 푸는 거를 채굴이라고 함. 또한 퍼즐의 난이도를 통해 블록 조절할거야. 좀 있다가는 트랜잭션(거래내역)에 대해서도 다룰거야. 이걸 통해서 보상받고 거래주고받고 하는거겠지
블록에 추가할 두 가지 속성 (-> 작업증명 퍼즐(블록의 해쉬값 찾기)을 풀기 위한 값)
difficulty 난이도 (=유효한 블록의 해쉬값은 얼마나 많은 0으로 시작해야하는가, 작은값찾기임)
해쉬값을 2진수로 표현한 다음 시작부분0의 갯수세어보는 것.
난이도 difficulty 가 4이면 임계값인 nonce가 1,2,3 올라가면서 해쉬값을 찾는다. 해쉬값계산 함수를 보면
난이도가 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이 아니면
(우리는 Block에 헤더랑 바디 넣고, BlockHeader추가로 만들어서 거기에 버전이랑 인덱스 넣었음)
최초의 블록(제네시스블록)- 블록체인의 시작. 안의 값은 일일이 넣어주면 됨.
const genesisBlock
블록체인 싹 저장할 배열(javascript in memory 방식으로 저장. 컴끄면 사라짐)
const blockchain= [] //1장에서는 genesisBlock를 넣은 걸봐서 제네시스 블록 넣어서 보려나봄
필요한 함수 만들기
해쉬값계산함수
const calculateHash
다음블록만드는 함수(이전 해쉬 블록 알아야함)
const generateNextBlock
블록의 유효성 검사할 함수
그 조건임
이전 블록보다 인덱스값이 1 클 것.
previousHash값이 이전블록의 hash값일 것.
hash값이 유효한 값일 것. 다음의 코드로 이를 검사할 수 있어요.
const isValidNewBlock = (새블록, 이전블록) => {
1. 만약 이전블록인덱스가 새 블록인덱스보다 길이 더 길면
틀림 뱉어
2. 이전블록해시와 새블록이전해시가 같지 않으면
틀림뱉어
3. 새블록의 해시 계산한것이 새블록해시와 같지 않으면
틀림 뱉어
다 통과하면 맞음 뱉어
}
참고로 나 저기 들어가는 ,"새블록, 이전블록" 이렇게 써놓은 거, 파라미터(매개변수parameter)가 이름 내마음대로 지어줘도 되는건지 몰랐음.. 그래서 req, res도 막 거꾸로 써도 되더라고. 이전에 보내준 값(전달인자 argument)을 여기서 어떤 이름으로 쓸지 변수 정하고 이 함수 안에서 쓰는 것이었다!!!! 이전에 보내준 값이름이랑 이름이 달라도 상관없는 것!..ㅋㅋㅋ그동안 이름같은게 많길래 헷갈렸는데 이렇게 유동적이었다뉘
블록의 구조 검사하는 함수
const isValidBlockStructure {
블록 인덱스 타입은 숫자
블록 해시 타입은 문자열string(왜 끈, 줄이냐면 한글자씩연달아 메모리에 저장되는게 끈같아서..)