Golang - Go로 구현하는 블록체인 : 기본 구조 - 1

Lumi·2022년 2월 21일
0

Golang

목록 보기
31/38
post-thumbnail

🔥 개요

특정 토이 프로젝트를 진행하기 보다는 Go를 사용한다면 어떤방향으로 블록체인 네트워크를 구성하는지가 궁금하여 google을 통해서 학습을 해 보았습니다.

🔨 기본 구조 설정 - 블록

블록체인은 기본적으로 블록+체인으로 이루어져 있기 떄문에 일단 블록의 구조를 먼저 구성해 보았습니다.

type Block struct {
	Timestamp     int64
	Data          []byte
	PrevBlockHash []byte
	Hash          []byte
}

기본적인 block의 구조 입니다.

많은 구조를 가지고 있지는 않고 시간, 데이터, 이전 블록값, 해시값을 담고 있습니다.

🔨 블록 해시값 설정

그후 저희는 hash값을 설정해주는 함수가 필요합니다.

func (b *Block) SetHash() {
	timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
	// 정수를 문자열로 변환
	// b.Timestamp를 10진수로 변환
    
	headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
	// byte 슬라이스를 만드는 함수이다.
    
	hash := sha256.Sum256(headers)
	b.Hash = hash[:]
}

기본적으로 timeStamp값이 필요합니다.

  • strconv.FormatInt를 통하여 10진수로 변환시킨후 byte형태로 바꾸어 줍니다.

그후 byte슬라이스를 만들게 됩니다.

해당 로직은 새로운 byte를 만드는 역할을 합니다.

func main() {
	s := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")}
	fmt.Printf("%s", bytes.Join(s, []byte(", ")))
}
  • 이와같은 코드를 실행시키게 된다면 어떤방향으로 작동을 하는지 확인해 볼수 있습니다.

이후 해시값을 만들어 주고 해당 해시값을 블록의 해시값으로 할당해 줌으로써 작동합니다.

🔨 블록 생성 함수

다음으로는 간단한 블록생성 함수가 필요합니다.

func NewBlock(data string, prevBlockHash []byte) *Block {
	block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}
	block.SetHash()
	return block
}

이와 같이 작성을 하여 새로운 블록을 생성하게 되고

해당 블록의 해시값을 위해서 앞서 예시를 보여주었던 해시함수를 실행 시킵니다.

🔨 체인 구성

새로운 블록을 생성하는 함수까지 완성을 하였으니 이제 블록을 이어줄 체인이 필요합니다.

type BlockChain struct {
	blocks []*Block
}

체인 역할을 할 하나의 구조체 입니다.

말 그대로 Block타입을 배열로 담고 있게 됩니다.

그후 블록을 추가해 주는 함수가 필요합니다.

func (bc *BlockChain) AddBlock(data string) {
	prevBlock := bc.blocks[len(bc.blocks)-1]
	// 이전의 블록값을 가져오는 코드
	newBlock := NewBlock(data, prevBlock.Hash)
	// 새로운 블록을 만들어 주고
	bc.blocks = append(bc.blocks, newBlock)
	// 해당 블록을 연결해 준다.
}

블록체인이라고 하면 이전 블록을 가르키는 값이 필요하기 떄문에 이전 값을 가져오게 됩니다.

  • prevBlock

그후 새로운 블록을 만들어 주고 해당 블록을 체인에 더해주게 됩니다.

  • append

이러한 과정을 거치면 자연스럽게 체인이 연결이 됩니다.

하지만 초기에는 아무런 블록이 없기 떄문에 저희는 초기 블록을 만들어 주어야 합니다.

func NewGenesisBlock() *Block {
	// 최초 블록을 말합니다.
	return NewBlock("Genesis Block", []byte{})
}

func NewBlockchain() *BlockChain {
	// 이후 최초 블록을 만들어 줍니다.
	return &BlockChain{[]*Block{NewGenesisBlock()}}
}

이와 같이 최초 블록을 만들어 주는 함수를 추가 해 줍니다.

그후 테스트를 돌려보겠습니다.

func main() {
	bc := NewBlockchain()

	bc.AddBlock("send 1coin!!")
	bc.AddBlock("send 2coin!!")

	for _, block := range bc.blocks {
		fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)
		fmt.Printf("Data: %s\n", block.Data)
		fmt.Printf("Hash: %x\n", block.Hash)
		fmt.Println()
	}
}
  • 해당 테스트 영상과 코드에 대한 설명은 youtube에 정리를 해 두었습니다.
profile
[기술 블로그가 아닌 하루하루 기록용 블로그]

0개의 댓글