본문 바로가기
언어/Go

genesis Block 생성

by gun_poo 2022. 7. 21.
package main

import (
	"crypto/sha256"
	"fmt"
)

type block struct {
	data string
	hash string
	prevHash string
}

	func main() {
		genesisBlock := block{"Genesis Block", "", ""}
		hash := sha256.Sum256([]byte(genesisBlock.data + genesisBlock.prevHash))
		hexHash := fmt.Sprintf("%x", hash)
		genesisBlock.hash = hexHash
		fmt.Println(genesisBlock)
	}

블럭 구조체 설정하고

제네시스 블럭에는 데이터, 해쉬값, 직전 해쉬값이 들어가는데 제네시스이기에 직전 해쉬가 없다.

제네시스 블럭에 해쉬값을 설정해주는 함수를 세팅하고 실행! 

 

다음은 자동화 과정을 진행한다

package main

import (
	"crypto/sha256"
	"fmt"
)

type block struct {
	data string
	hash string
	prevHash string
}

type blockchain struct {
	blocks []block
}

func (b * blockchain) getLastHash() string {
	if len(b.blocks) > 0 {
		return b.blocks[len(b.blocks) -1].hash
	}
	return ""
	//블록의 길이가 0인지 아닌지 확인한다. 0이 아니라면 newblock에는 직전해쉬값이 존재하여아한다.
	//그리고 직전 해쉬값은 블록체인의 마지막 블록의 해쉬값과 동일하다. (배열을 찾는 방법과 동일, 블록체인의 가장 끝부분 찾으면된다. 배열의 길이에서 -1, 0부터 갯수를 세기 때문에)
}
func (b * blockchain) addBlock(data string) {
	newBlock := block{data, "", b.getLastHash()}
	hash := sha256.Sum256([]byte(newBlock.data + newBlock.prevHash))
	newBlock.hash = fmt.Sprintf("%x", hash)
	b.blocks = append(b.blocks, newBlock)
	//append로 b.blocks에 newBlock 을 추가 해준다. append는 추가해주고 싶은 element와 new slice를 반환한다. 
}

func (b * blockchain) listBlocks() {
	for _, block := range b.blocks{
		fmt.Printf("Data: %s\n", block.data)
		fmt.Printf("Hash: %s\n", block.hash)
		fmt.Printf("Prev Hash: %s\n", block.prevHash)
	}
}
func main() {
		chain := blockchain{}
		chain.addBlock("Genesis Block")
		chain.addBlock("Second Block")
		chain.addBlock("Third Block")
		chain.listBlocks()
}

리팩토링

blockchain/blockchain.go

package blockchain

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

type block struct {
	Data string
	Hash string
	PrevHash string
}

type blockchain struct {
	blocks []*block
}

var b * blockchain
//singleton의 의미는 이 변수의 instance를 직접 공유하지 않고 대신
//이 변수의 instance를 우릴 대신해서 드러내주는 function 생성
var once sync.Once
// 단 한번만 함수가 실행되게 해주는 함수
func (b * block) calculateHash(){
	hash := sha256.Sum256([]byte(b.Data + b.PrevHash))
	b.Hash = fmt.Sprintf("%x", hash)
	//16진수로 포맷
	// 5)
}

func getLastHash() string {
	totalBlocks := len(GetBlockchain().blocks)
	if totalBlocks == 0 {
		return ""
	}
	return GetBlockchain().blocks[totalBlocks -1].Hash
	// 3)
	// 4)
}
func createBlock(data string) *block {
	newBlock := block{data, "", getLastHash()}
	newBlock.calculateHash()
	return &newBlock
	// 2)
}
func (b*blockchain) AddBlock(data string) {
	b.blocks = append(b.blocks, createBlock(data))
		// 1)
		//append를 이용해 블록체인 내부에 블록 추가 첫 블럭은 제네시스 블럭, 제네시스 블럭은
		//크리에이트 블럭을 통해 생성된다. 이 함수는 블럭을 반환해준다.
		//b.blocks는 block을 append한 값이다. 
}
func GetBlockchain() *blockchain {
	if b == nil {
		once.Do(func(){
			b = &blockchain{}
			//비어있는 블록체인 생성
			b.AddBlock("Genesis Block")
		})
	}
	return b
}
//이 초기화 단계는 단 한번만 실행된다.
func (b * blockchain) AllBlock() []*block {
	return b.blocks
}
//1. 제네시스블록을 생성해주는 블록체인이 있고 
//2. createBlock은 data가 들어있는 블럭을 생성해준다
//3. 직전 해쉬값이 필요하고 getLastHash 함수를 통해 가져온다. 
//4. 이 함수를 통해 블록체인의 길이를 알아내고 블록체인의 길이가 0이라면 아무것도 반환하지않고
// 그렇지 않다면 블록체인의 마지막 블록의 해쉬값을 반환한다.
//5. 그리고 newBlock의 새로운 해쉬값을 계산해준다. 이 함수는 pointer를 인자값으로 받아온다.
// 이 해쉬값을 블록에 넘겨준다.

main.go

package main

import (
	"fmt"
	"goBlock/blockchain"
)

func main() {
		chain := blockchain.GetBlockchain()
		chain.AddBlock("second block")
		chain.AddBlock("third block")
		chain.AddBlock("fourth block")
		for _, block := range chain.AllBlock(){
			fmt.Printf("Data: %s\n", block.Data)
			fmt.Printf("Hash: %s\n", block.Hash)
			fmt.Printf("Prev Hash: %s\n", block.PrevHash)
		}
}

 

'언어 > Go' 카테고리의 다른 글

go test sample study  (0) 2022.07.21
If with a Twist  (0) 2022.02.13
for, range, ...args  (0) 2022.02.13
Functions part Two  (0) 2022.02.13
Functions part One  (0) 2022.02.13

댓글