devops

Go로 간단한 블록체인 구현하기 -2 본문

DevOps/Chain

Go로 간단한 블록체인 구현하기 -2

vataops 2022. 12. 3. 17:27
반응형

이전에는 main.go에 모든 함수를 때려넣어서 구현했지만, func의 기능도 세분화해서 만들어보려고 한다. 

main.go

# main.go

package main

import (
	"fmt"

	"github.com/test/blockchain"
)

func main() {
	chain := blockchain.GetBlockchain()
	chain.AddBlock("Second Block")
	chain.AddBlock("3 Block")
	chain.AddBlock("4 Block")
	for _, block := range chain.AllBlocks() {
		fmt.Println("Data: ", block.Data)
		fmt.Println("Hash: ", block.Hash)
		fmt.Println("PrevHash: ", block.PrevHash)
	}
}

main.go 에는 blockchain 인스턴스 chain을 선언하고, Addblock을 통해서 chain에 블록을 추가한다. 그리고 마지막 AllBlocks() 함수를 통해서 선언된 블록을 하나씩 출력해볼 수 있다.

GetBlockchain은 block이 제네시스일 경우 AddBlock을 통해서 최초의 블록을 추가하게 되고 아니면 blockchain을 리턴한다.

Blockchain.go

package blockchain

import (
	"crypto/sha256"
	"fmt"
	"sync"
)

type block struct {
	Data     string
	Hash     string
	PrevHash string
}

type blockchain struct {
	blocks []*block 	// block들의 포인트를 연결하는 array
}

func getLastHash() string {
	totalBlocks := len(GetBlockchain().blocks)
	if totalBlocks == 0 {
		return ""
	}
	return GetBlockchain().blocks[totalBlocks-1].Hash
}

// data를 파라미터로 받아서 생성된 블록을 리턴
func createBlock(data string) *block {
	newBlock := block{data, "", getLastHash()}
	newBlock.calculateHash()
	return &newBlock
}

// 패키지 내부에서만 접근 가능
var b *blockchain

// 단 한번만 실행
var once sync.Once

// hash를 생성 및 할당
func (b *block) calculateHash() {
	hash := sha256.Sum256([]byte(b.Data + b.PrevHash))
	b.Hash = fmt.Sprintf("%x", hash)
}

func GetBlockchain() *blockchain {
	if b == nil {
		once.Do(func() {
			b = &blockchain{}
			b.AddBlock("genesis_Block")
		})
	}
	return b
	// 싱글톤 패턴임
}

func (b *blockchain) AddBlock(data string) {
	b.blocks = append(b.blocks, createBlock(data))
}

func (b *blockchain) AllBlocks() []*block {
	return b.blocks
}

하나씩 살펴보자

func getLastHash() string {
	totalBlocks := len(GetBlockchain().blocks)
	if totalBlocks == 0 {
		return ""
	}
	return GetBlockchain().blocks[totalBlocks-1].Hash
}

getLastHash는 블록의 길이를 확인하여 0이 아니면, 마지막 block의 hash값을 리턴해준다. 이는 뒤에 새 블록을 추가할 때 PrevHash에 사용될 함수다.

func createBlock(data string) *block {
	newBlock := block{data, "", getLastHash()}
	newBlock.calculateHash()
	return &newBlock
}

createBlock은 data를 받아 블록을 생성하는 역할을 한다. hash는 입력된 data와 이전의 hash값을 활용해서 생성되기 때문에 data, prevHash를 먼저 할당하고 calculateHash()를 이용해서 hash값을 생성하여 할당한다.

func (b *block) calculateHash() {
	hash := sha256.Sum256([]byte(b.Data + b.PrevHash))
	b.Hash = fmt.Sprintf("%x", hash)
}

calulateHash()는 이전 해쉬값과 Data를 byte화 하고 hash값을 생성한후, 다시 16진수로 변환하여 블록에 hash를 선언해준다.

생성된 4개의 블록

반응형
Comments