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 |
댓글