티스토리 뷰

블록체인은 여러 개의 블록이 연결된 것으로, 이전 블록에 추가하는 형태, 삭제는 불가능하다.
따라서 만들어야 할 것은 크게 다음과 같다.

  1. 추가해야 할 블록 객체
  2. 블록들이 연결된 블록체인 배열
  3. 블록을 추가할 메소드

 

전체 코드

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}`
        return crypto.createHash("sha256").update(toHash).digest("hex")
    }
}

class BlockChain {
    public blocks: Block[]
    constructor() {
        this.blocks = []
    }
    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 getBlock() {
        return [...this.blocks]
    }
}

const myBlockChain = new BlockChain
myBlockChain.addBlock("first block")
myBlockChain.addBlock("second block")
myBlockChain.addBlock("third block")

console.log(myBlockChain.getBlock())
console.log(myBlockChain.getBlock().push(new Block("ㅋㅋㅋ", 1, "해킹당하셨습니다")))

 

interface (BlockShape) 만들기

interface BlockShape {
    hash: string,
    prevHash: string,
    height: number,
    data: string
}

 

BlockShape 인터페이스를 만족하는 Block 클래스 생성하기

class Block implements BlockShape {
    // hash 변수 만듦
    public hash: string
    // 인스턴스 생성 시 3가지를 인자로 받음
    constructor (
        public prevHash: string,
        public height: number,
        public data: string
    ) {
        // 인자로 받은 3가지를 기반으로 hash 값 생성
        this.hash = Block.calculateHash(prevHash, height, data)
    }
    // hash를 만들어주는 static 함수
    static calculateHash (prevHash: string, height: number, data: string) {
    	// 3개의 인자를 하나의 문자열로 합침
        const toHash = `${prevHash}${height}${data}`
        // crypto 모듈을 이용해 문자열 생성한 후 반환
    	return crypto.createHash("sha256").update(toHash).digest("hex")
    }
}
  • 클래스 인스턴스를 생성할 때 prevHash, height, data를 인자로 받음, hash는 이를 기반으로 생성
  • crypto 모듈 이용해 hash를 만들어주는 static 함수 생성(calculateHash)
    • static 함수 : 인스턴스 없이도 호출가능 → 클래스 내에서 바로 호출 가능
    • 인스턴스 : new를 이용해 생성한 클래스의 복제본

 

블록을 추가해주는 BlockChain 클래스 생성하기

class BlockChain {
    // blocks는 Block의 배열 형태
    public blocks: Block[]
    // 처음 생성 시 블록을 담을 빈 배열 생성
    constructor() {
        this.blocks = []
    }
    // 이전 hash 값을 불러올 메서드
    private getPrevHash() {
        // blocks에 아무것도 없다면 빈 문자열 반환
        if(this.blocks.length === 0) return ""
        // 이전 블록 = blocks의 마지막 원소(length - 1)
        return this.blocks[this.blocks.length - 1].hash
    }
    // 블록을 블록체인에 추가해주는 메서드
    public addBlock(data: string) {
        // prevHash, height, data 값을 인자로 받아 새로운 블록 생성
        const newBlock = new Block(this.getPrevHash(), this.blocks.length + 1, data)
        // 생성된 새로운 블록을 블록체인 배열(blocks)에 추가
        this.blocks.push(newBlock)
    }
    // 블록체인(blocks) 조회
    public getBlock() {
        return [...this.blocks]
    }
}
  • 여러 개의 block을 담을 배열(blocks)을 만들어줌
  • block을 배열에 담을 때 필요한 것은 이전 블록의 hash 값(prevHash)
    → prevHash 값을 불러오는 getPrevHash 메서드를 생성
  • 새로운 블록을 생성해 블록체인에 추가하는 addBlock 메서드 생성
    • prevHash: 이전 hash 값 (getPrevHash 함수의 리턴 값)
    • height: 블록의 위치 (현재 배열의 길이 + 1)
    • data: 유저가 입력한 데이터 (인자로 받아옴)
  • 블록체인(blocks 배열 전체)을 조회하는 getBlock 메서드 생성
    • 이 때 새로운 배열을 반환해 줘야함 (Spread Opertor 이용)

 

테스트 해보기

const myBlockChain = new BlockChain
myBlockChain.addBlock("first block")
myBlockChain.addBlock("second block")
myBlockChain.addBlock("third block")

console.log(myBlockChain.getBlock())

 

BlockChain 클래스 내 getBlock 메서드에서 새로운 배열을 반환하는 이유 : 보안 문제!

// 새로운 배열로 반환하는 코드
public getBlock() {
    return [...this.blocks]
}

// 기존 배열 그대로 반환하는 코드
public getBlock() {
    return this.blocks
}

위 두개 코드의 차이는 새로운 배열로 반환하느냐, 기존 배열을 그대로 반환하느냐의 차이!
기존 배열을 그대로 반환하게 되면, 그 배열에 새로운 블록을 생성하여 push함으로써 조작할 수 있다.

// 바로 이런 식으로...
console.log(myBlockChain.getBlock().push(new Block("ㅋㅋㅋ", 1, "님 해킹 당함")))

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함