특정 토이 프로젝트를 진행하기 보다는 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()
}
}