2023-09-21 21:13:12

 

Chain

전 시간에는 블록체인에서 "블록"을 알아 봤다면 이번에는 "체인"에 대해 알아 보겠습니다.

블록체인은 말그대로 블록들이 체인처럼 연결되어 있는 분산 원장을 말하는데 실습을 통해 블록들이 어떤식으로 체인을 이루어 알아보겠습니다.

 

롱기스트 체인 룰

롱기스트 체인 룰이란 블록체인 네트워크에서 사용되는 규칙으로 네트워크 참여자들에게 가장 긴 체인을 주 체인으로 추가하도록 하는 규칙입니다. 

만약 동시간대에 생성된 블록이라면 모든 네트워크 참여자에게 전파되기 전 1번 체인에는 3개의 블록이 2번 체인에는 4개의 블록이 있다면  주 체인은 2번 체인이 됩니다.

롱기스트 체인 룰은 블록체인의 기본적인 합의 메커니즘 중 하나로 블록체인의 무결성과 보안을 보장하는데 중요한 역할을 합니다.

 

주요 특징

가장 긴 체인 선택 : 블록체인 네트워크의 참여자들은 항상 가장 긴 체인을 유효한 체인으로 간주합니다. 여기서 가장 긴 체인은 가장 많은 블록을 가진 체인을 뜻합니다.

포크 해결 : 블록이 계속 추가됨에 따라 여러개의 체인이 만들어 질 수 있습니다. 하지만 롱기스트 체인 룰에 의해 네트워크 참여자들은 항상 가장 긴 체인을 선택하기 때문에 시간이 지나도 하나의 일관된 상태로 수렴하게 됩니다.

보안 측면 : 악의적인 참여자가 특정 트랜잭션을 무효화 하려면 해당 참여자는 네트워크의 나머지 부분보다 더 빠르게 블록을 추가하여 가장 긴 체인을 만들어야 하는데 이때 엄청난 계산 능력을 필요로 하기 떄문에 실질적으로 불가능하다 볼 수 있습니다.

 

채굴 난이도

채굴 난이도는 PoW 기반 블록체인에서 새로운 블록을 생성하기 위해 필요한 작업의 난이도를 나타내는 지표로 블록이 생성되는 시간에 따라 조정됩니다.

 

주요 특징

블록 생성 시간 조정 : 비트코인의 경우 약 10분만다 하나의 블록이 생성되도록 설계되었으나 네트워크 전체 해시파워가 증가하면 블록 생성 속도도 빨라질 수 있으므로 이를 방지하고자 생성 속도가 빨라지면 난이도를 증가하며 해시파워가 감소하면 난이도도 감소합니다.

동적 조정 : 비트코인을 예로 들어 비트코인에서는 2016개의 블록이 생성된 후 난이도가 조정되는데 이 기간동안 생성된 블록이 이전에 생성된 시간보다 빠를경우 난이도를 상향 조정, 생성 속도가 느릴 경우 하향 조정 됩니다.

 

 

https://dbdj.tistory.com/50

 

[BlockChain] BlockChain 구조 알아보기(1)

BlockChain 구조 알아보기 실제는 훨씬 더 복잡한 구조를 가지겠지만 간단한 Genesis block을 만들고 chain으로 만들기 까지의 과정을 실습을 통해 알아보자 프로젝트 구조 설치 모듈 정보 // npm init -y : p

dbdj.tistory.com

기본 구조는 전편의 구조와 같고 block.test.ts 내용 추가 및 chain.js가 추가 되었습니다.

 

chain/chain.ts

블록들을 이어주는 역활을 하며 이전의 블록이 정상적인 블록인지에 대한 검증 및 상대방의 체인과 본인의 체인을 비교하여 어떤 체인이 더 긴지(롱기스트 체인 룰)를 비교하여 블록 등록

실습에서는 10개의 블록 생성시간을 비교하여 난이도를 조절

import Block from "@core/block/block";
import { GENESIS } from "@core/config";
import { Failable } from "@core/interface/failable.interface";

class Chain {
  private chain: Block[] = [GENESIS];
  private readonly INTERVAL = 10;

  // 현재 체인을 반환하는 함수
  get() {
    return this.chain;
  }

  // 길이를 반환하는 함수
  length() {
    return this.chain.length;
  }

  // 체인에 마지막 블록 반환 함수
  lastestBlock() {
    return this.chain[this.length() - 1];
  }

  // 블록 추가 메소드
  addToChain(receivedBlock: Block) {
    this.chain.push(receivedBlock);
    return this.lastestBlock();
  }

  // 블록 조회 메소드
  getBlock(callbackFn: (block: Block) => boolean) {
    const findBlock = this.chain.find(callbackFn);
    if (!findBlock) throw new Error("block not find");
    return findBlock;
  }

  // 블록의 높이로 블록을 조회
  getBlockByHeight(height: number) {
    return this.getBlock((block: Block) => block.height === height);
  }

  // 블록의 해시로 찾는 함수
  getBlockByHash(hash: string) {
    return this.getBlock((block: Block) => block.hash === hash);
  }

  // 현재 위치에서 10번째 블록들을 찾는 함수
  getAdjustBlock() {
    const { height } = this.lastestBlock();
    const findHeight =
      height < this.INTERVAL
        ? 1
        : Math.floor(height / this.INTERVAL) * this.INTERVAL;
    // 10번 블록의 높이 조회해서 반환
    return this.getBlockByHeight(findHeight);
  }

  // 다른 네트워크로 체인을 보냄
  serialze() {
    return JSON.stringify(this.chain);
  }

  // 다른 네트워크에서 체인을 받음
  deserialize(chunk: string) {
    return JSON.parse(chunk);
  }

  // 상대방 체인과 본인의 체인을 비교
  replaceChain(receivedChain: Block[]): Failable<undefined, string> {
    // 본인의 체인과 상대방의 체인을 검사하는 로직
    // 체인의 길이를 비교하는 로직 구현 (롱기스트 체인 룰)
    // 실제 네트워크에서는 더 복잡한 로직 사용

    // 상대방 체인의 마지막 블록
    const lastestReceivedBlock: Block = receivedChain[receivedChain.length - 1];

    // 본인의 마지막 블록
    const lastestBlock: Block = this.lastestBlock();

    // 상대방 체인의 마지막 블록과 본인의 마지막 블록의 길이가 같을 경우
    if (lastestReceivedBlock.height === 0)
      return {
        isError: true,
        value: "The last block of the other network chain is the first block",
      };

    // 상대방 체인의 마지막 블록이 본인의 마지막 블록의 길이보다 크거나 같을 경우
    if (lastestReceivedBlock.height <= lastestBlock.height)
      return {
        isError: true,
        value: "The last block of the other network chain is large or the same",
      };

    // 상대방의 체인이 본인의 체인보다 길면 본인의 체인을 업데이트
    this.chain = receivedChain;

    return { isError: false, value: undefined };
  }

  // 현재 블록 생성 시점에서 이전 10번째 블록 구하기
  // 현재 높이값 < 10 : 최초블록을 반환
  // 현재 높이 > 10 : -10번째 블록을 반환
  // 이전 10번째 블록의 생성 시간의 차이를 구하여 그 차이가 블록 생성 주기 보다 빠르면 난이도 증가
  // 생성 주기가 느리면 난이도 하락
  // 비트코인 기준으로 블록의 생성 시간은 10분
  getAdjustmentBlock() {
    const currentLength = this.length();
    const adjustmentBlock: Block =
      this.length() < this.INTERVAL
        ? GENESIS
        : this.chain[currentLength - this.INTERVAL];
    // 반환값은 최초블록 아니면 -10번째 블록
    return adjustmentBlock;
  }
}

export default Chain;

 

_test/block.test.ts

블록을 체인에 추가하는 테스트 코드 및 난이도 조정 코드 작성 (실습에서는 10개 단위로 난이도 조정)

import Block from "@core/block/block";
import Chain from "@core/chain/chain";
import { GENESIS } from "@core/config";

describe("block verify", () => {
  let newBlock: Block;
  let newChain: Chain;
  let newChain2: Chain;
  it("add block", () => {
    const data = ["Block 1"];
    newBlock = Block.generateBlock(GENESIS, data);
  });

  it("block validation", () => {
    console.log("newBlock : ", newBlock);
    const isValidNewBlock = Block.isValidNewBlock(newBlock, GENESIS);
    if (isValidNewBlock.isError) return expect(true).toBe(false);
    expect(isValidNewBlock.isError).toBe(false);
  });

  // 블록 체인 추가
  it("Add Block chain", () => {
    newChain = new Chain();
    newChain.addToChain(newBlock);

    console.log(newChain.get());

    console.log(newChain.getBlockByHash(newBlock.hash));
  });

  //
  it("Longest Chain Rule", () => {
    newChain2 = new Chain();
    newChain2.replaceChain(newChain.get());
    console.log(newChain2);
  });

  // 블록 생성 주기를 계산해서 정해 놓은 생명 주기보다 빠른지 느린지 판단
  it("before 10 block or genesis block", () => {
    for (let i = 0; i < 20; i++) {
      let block = new Block(newChain.lastestBlock(), ["block"]);
      newChain.addToChain(block);
    }
    console.log(newChain.getAdjustmentBlock());
  });
});

 

결과

20개의 코인을 생성 후 10번째 인덱스의 있는 블록의 값을 가져오는 거까지 성공 난이도를 동적으로 조절하는 건 다음 실습에서 진행 예정

728x90