TypeScript) 블록체인 만들기

송민경's avatar
Sep 13, 2024
TypeScript) 블록체인 만들기

1. 블록체인

  • 데이터 블록들이 서로 연결되어 체인 형태를 이루는 구조
  • 각 블록은 이전 블록의 해시 값을 포함하여 데이터의 무결성을 보장
 

2. 디자인하기

  • 인터페이스 사용
    • 블록이 가져야 할 속성을 정의
    • 클래스가 이 인터페이스를 구현하도록 하여 일관된 구조를 유지하도록 강제함
    • interface BlockShape { hash: string; prevHash:string; height: number; data: string; } class Block implements BlockShape { constructor( public prevHash:string, public height: number, public data:string ) {} }
      notion image
 

3. 해시

  • 데이터의 고유한 서명을 생성
  • 데이터가 변경되면 해시 값도 변경되어 데이터 무결성 보장
 
  • 초기화가 필요함
interface BlockShape { hash: string; prevHash:string; height: number; data: string; } class Block implements BlockShape { public hash: string; constructor( public prevHash:string, public height: number, public data:string ) {} }
notion image
 

4. crypto 모듈 사용하기

  • ‘crypto’ import 하는 방법
    • - * as
      import * as crypto from "crypto"; interface BlockShape { hash: string; prevHash:string; height: number; data: string; } class Block implements BlockShape { public hash: string; constructor( public prevHash:string, public height: number, public data:string ) { this.hash = Block.calculateHash(prevHash, height, data); } static calculateHash(prevHash:string, height: number, data:string) { const toHash = `${prevHash}${height}${data}`; } }
    • CommonJS 모듈을 ECMAScript 모듈처럼 다룰 수 있게 되어 두 시스템 간의 호환성이 향상됨
      • { "include": ["src", "src/myPackage.js"], "compilerOptions": { "outDir": "build", "target": "ES6", "lib": ["ES6"], "strict": true, "esModuleInterop": true, "module": "CommonJS" // 브라우저 앱 -> umd } }
        import crypto from "crypto";
 

5. 타입 정의 패키지 설치

  • Node.js 및 기타 패키지의 타입 정의를 설치하여 TypeScript에서 정확한 타입 검사를 지원
 
  • Node.js의 내장 모듈들에 대한 TypeScript 타입 정의를 제공
    • Node.js에서 제공하는 다양한 기능(예: cryptofshttp, 등)에 대해 TypeScript가 타입 검사를 수행할 수 있도록 해줌
    • npm i -D @types/node
      notion image
  • Axon이라는 패키지의 TypeScript 타입 정의를 제공
    • 이 패키지의 타입 정보를 TypeScript에 제공하여 코드의 타입 안정성을 높임
    • Axon 패키지를 사용하는 코드에서 TypeScript의 타입 검사를 활성화하여 코드 품질을 향상시킴
    • npm i -D @types/axon
      notion image
  • Express.js 프레임워크의 TypeScript 타입 정의를 제공
    • Express.js를 사용하는 서버 애플리케이션에서 TypeScript가 올바른 타입 검사를 수행할 수 있게 해줌
    • xpress의 라우터, 미들웨어, 요청 및 응답 객체에 대한 타입 정보를 제공하여 개발자가 타입 관련 오류를 미리 방지할 수 있음
    • npm i -D @types/express
      notion image
 
 

6. 블록 생성과 해시 값 계산

  • 블록을 생성하면서 데이터의 해시 값을 계산하고 블록의 hash에 저장
import crypto from "crypto"; // Node.js의 crypto 모듈을 임포트하여 해시를 생성 // 블록의 구조를 정의하는 인터페이스 interface BlockShape { hash: string; // 블록의 해시 값 prevHash: string; // 이전 블록의 해시 값 height: number; // 블록의 높이 (블록체인에서의 위치) data: string; // 블록에 저장된 데이터 } // BlockShape 인터페이스를 구현하며 블록을 정의 class Block implements BlockShape { public hash: string; // 블록의 해시 값을 저장하는 속성 // 블록을 생성할 때 호출되며, 블록의 속성을 초기화 constructor( public prevHash: string, // 이전 블록의 해시 값 public height: number, // 블록의 높이 public data: string // 블록에 저장된 데이터 ) { // 블록 생성 시 해시 값을 계산하여 설정 this.hash = Block.calculateHash(prevHash, height, data); } // 정적 메서드: 블록의 해시 값을 계산(클래스 인스턴스와 무관하게 사용) static calculateHash(prevHash: string, height: number, data: string) { // 블록의 해시를 생성하기 위한 문자열 생성 const toHash = `${prevHash}${height}${data}`; // SHA-256 해시를 계산하고, 결과를 16진수 문자열로 반환 return crypto.createHash("sha256").update(toHash).digest("hex"); } }
 
import crypto from "crypto"; // Node.js의 crypto 모듈을 임포트하여 해시를 생성 // 블록의 구조를 정의하는 인터페이스 interface BlockShape { hash: string; // 블록의 해시 값 prevHash: string; // 이전 블록의 해시 값 height: number; // 블록의 높이 (블록체인에서의 위치) data: string; // 블록에 저장된 데이터 } // BlockShape 인터페이스를 구현하며 블록을 정의 class Block implements BlockShape { public hash: string; // 블록의 해시 값을 저장하는 속성 // 블록을 생성할 때 호출되며, 블록의 속성을 초기화 constructor( public prevHash: string, // 이전 블록의 해시 값 public height: number, // 블록의 높이 public data: string // 블록에 저장된 데이터 ) { // 블록 생성 시 해시 값을 계산하여 설정 this.hash = Block.calculateHash(prevHash, height, data); } // 정적 메서드: 블록의 해시 값을 계산(클래스 인스턴스와 무관하게 사용) static calculateHash(prevHash: string, height: number, data: string) { // 블록의 해시를 생성하기 위한 문자열 생성 const toHash = `${prevHash}${height}${data}`; // SHA-256 해시를 계산하고, 결과를 16진수 문자열로 반환 return crypto.createHash("sha256").update(toHash).digest("hex"); } } // 블록체인을 정의하는 클래스 class Blockchain { private blocks: Block[]; // 블록체인에 포함된 블록들을 저장하는 배열 // 블록체인 인스턴스 생성 constructor() { this.blocks = []; // 초기에는 블록이 없는 빈 배열 // 첫 번째 블록(제네시스 블록)을 추가할 수 있음 this.addBlock("제네시스 블록"); } // 가장 최근 블록의 해시 값을 반환 private getPrevHash() { if (this.blocks.length === 0) return ""; // 블록이 없으면 빈 문자열 반환 return this.blocks[this.blocks.length - 1].hash; // 마지막 블록의 해시 반환 } // 블록체인에 새 블록을 추가 public addBlock(data: string) { // 새로운 블록 생성: 이전 블록의 해시, 현재 블록의 높이, 데이터를 인자로 전달 const newBlock = new Block(this.getPrevHash(), this.blocks.length + 1, data); this.blocks.push(newBlock); // 새 블록을 블록체인 배열에 추가 } // 블록체인에 포함된 모든 블록을 반환 public getBlocks() { return this.blocks; } } // 블록체인 인스턴스 생성 const blockchain = new Blockchain(); // 블록 추가 blockchain.addBlock("첫 번째 블록 데이터"); blockchain.addBlock("두 번째 블록 데이터"); blockchain.addBlock("세 번째 블록 데이터"); // 블록체인에 포함된 블록 출력 console.log(blockchain.getBlocks());
notion image
 

7. 보안 문제

  • 블록을 추가할 때 아무런 권한 검증이 없기에 누구든지 블록을 추가할 수 있음
  • 블록을 리턴할 때 this.blocks를 리턴하기에 getBlocks()로 배열에 접근이 가능함
  • 새로운 블록을 배열에 추가하거나 기존 해시값이나 높이, 데이터를 조작할 수 있음
 
  • this.blocks 리턴 대신 새로운 배열을 리턴 하기
import crypto from "crypto"; // Node.js의 crypto 모듈을 임포트하여 해시를 생성 // 블록의 구조를 정의하는 인터페이스 interface BlockShape { hash: string; // 블록의 해시 값 prevHash: string; // 이전 블록의 해시 값 height: number; // 블록의 높이 (블록체인에서의 위치) data: string; // 블록에 저장된 데이터 } // BlockShape 인터페이스를 구현하며 블록을 정의 class Block implements BlockShape { public hash: string; // 블록의 해시 값을 저장하는 속성 // 블록을 생성할 때 호출되며, 블록의 속성을 초기화 constructor( public prevHash: string, // 이전 블록의 해시 값 public height: number, // 블록의 높이 public data: string // 블록에 저장된 데이터 ) { // 블록 생성 시 해시 값을 계산하여 설정 this.hash = Block.calculateHash(prevHash, height, data); } // 정적 메서드: 블록의 해시 값을 계산(클래스 인스턴스와 무관하게 사용) static calculateHash(prevHash: string, height: number, data: string) { // 블록의 해시를 생성하기 위한 문자열 생성 const toHash = `${prevHash}${height}${data}`; // SHA-256 해시를 계산하고, 결과를 16진수 문자열로 반환 return crypto.createHash("sha256").update(toHash).digest("hex"); } } // 블록체인을 정의하는 클래스 class Blockchain { private blocks: Block[]; // 블록체인에 포함된 블록들을 저장하는 배열 // 블록체인 인스턴스 생성 constructor() { this.blocks = []; // 초기에는 블록이 없는 빈 배열 // 첫 번째 블록(제네시스 블록)을 추가할 수 있음 this.addBlock("제네시스 블록"); } // 가장 최근 블록의 해시 값을 반환 private getPrevHash() { if (this.blocks.length === 0) return ""; // 블록이 없으면 빈 문자열 반환 return this.blocks[this.blocks.length - 1].hash; // 마지막 블록의 해시 반환 } // 블록체인에 새 블록을 추가 public addBlock(data: string) { // 새로운 블록 생성: 이전 블록의 해시, 현재 블록의 높이, 데이터를 인자로 전달 const newBlock = new Block(this.getPrevHash(), this.blocks.length + 1, data); this.blocks.push(newBlock); // 새 블록을 블록체인 배열에 추가 } // 블록체인에 포함된 모든 블록을 새 배열로 반환 public getBlocks() { return [...this.blocks]; } } // 블록체인 인스턴스 생성 const blockchain = new Blockchain(); // 블록 추가 blockchain.addBlock("첫 번째 블록 데이터"); blockchain.addBlock("두 번째 블록 데이터"); blockchain.addBlock("세 번째 블록 데이터"); blockchain.getBlocks().push(new Block("xxxx", 1111, "hacking???")); // 블록체인에 포함된 블록 출력 console.log(blockchain.getBlocks());
notion image
 
Share article

vosw1