상세 컨텐츠

본문 제목

[Nomad Coin] Blockchain - #4.2 Our First Blockchain

Go/Blockchain

by Gopythor 2022. 7. 14. 04:23

본문

728x90
반응형

#4.2 Our First Blockchain

  • Hash하는 방법을 배웠다. 기존에 작성했던 코드에는 문제가 있다. 우리가 block을 복제할 수 없다. 두 번째 block을 만들 때 번거롭다.
func main() {
	genesisBlock := block{"Genesis Block", "", ""}
	hash := sha256.Sum256([]byte(genesisBlock.data + genesisBlock.prevHash))
	hexHash := fmt.Sprintf("%x", hash)
	genesisBlock.hash = hexHash
	secondBlocks := block{"Second blocks", "", genesisBlock.hash}
}
  • 이전 hash가 있으니 넘겨준다.
  • 예제는 어떻게 두 번째 block을 만들건지 나와있다.
  • block들은 이전 block들의 hash를 가지고 있다.
  • block들의 배열과 block chain의 차이점이다.
  • 각 block이 이전 block의 hash를 가리키고 있다.
  • 이 두 번째 block은 "Second blocks"라는 data를 가지고 있고, hash는 아직 비어있고, genesisBlock.hash가 이 두 번째 block의 이전 hash이다.
type blockchain struct{
	blocks []block
}

func main() {
	chain := blockchain{}
}

func main() {
	chain := blockchain{}
	chain.addBlock("Genesis Block")
	chain.addBlock("Second Block")
	chain.addBlock("Third Block")
	chain.listblocks()
}
  • blockchain에 대한 struct를 구현할 것이다.
  • 이 block chain은 block들의 slice를 가지고 있다고 정의할 것이다.
  • 여기에 빈 blockcain의 chain을 생성할 것이다.
  • addBlock이라는 function을 통해 Genesis Block을 생성하고, 이걸 세 번 반복해서, 두 번째, 세 번째 블록을 생성하는 것이다. 
  • 그리고 마지막에는 listBlocks라는 function도 구현하길 원한다.

  • 이 function들은 chain struct의 메소드(내부 함수)들이다.
  • receiver function을 생성해줘야 된다.
func (b *blockchain) addBlock(data string) {

}

func (b *blockchain) listBlocks() {
	
}
  • 복사본을 원하지 않으니 *를 넣어야 한다.
  • addblock은 string인 data을 받아서 구현할 것이다.
  • 여기에 또 다른 listBlocks function도 만들 것이다.
  • 이 함수는 아무런 인자도 받지 않고, 반환도 하지 않을 것이다.
  • 이 함수는 그저 block들을 콘솔에 출력만 할 것이다.
func (b *blockchain) addBlock(data string) {
	newBlock := block{data, "", ""}
	if len(b.blocks) > 0 {
		newBlock.prevHash = b.blocks[len(b.blocks)-1].hash
	}
}
  • addBlock에서는 block을 생성해줘야 한다.
  • data를 얻었으니 넘겨줘야 한다.
  • hash는 없으니 넘겨주지 않는다.
  • 이전 hash도 없다.
  • 하지만 이전 hash 값을 찾아와야 한다.
  • 첫 block을 제외한 모든 block들은 이전 hash값이 존재해야 한다.
  • blockchain의 길이가 0인지 확인을 해야 한다.
  • 길이가 0이라면 생성되는 block의 이전 hash 값은 없는 것이다.
  • 만약 blockchain의 길이가 0보다 크다면, 그 다음에 생성되는 block은 이전 hash값이 존재해야 한다.
  • newBlock에는 prevHash가 존재해야 한다.
  • 이 이전 hash값은 blockchain의 마지막 block의 hash값과 동일하다.
  • 찾는 방법은 배열을 탐색하는 방법과 비슷하다. 
  • blockchain의 가장 끝 부분을 찾으면 된다. 그리고 .hash를 더해주면 된다.
  • 배열에서 가장 마지막 item을 가지고 오고 싶다면, 배열의 길이에서 1을 뺀 값을 가져오면 마지막 item을 가져올 수 있다.
  • 만약에 배열에 10개의 item들이 들어있고 마지막 item을 가져오고 싶다면, 10에서 1을 뺀 값으로 조회하면 된다.
  • 왜냐하면 컴퓨터는 0부터 갯수를 센다.
func (b *blockchain) getLastHash() string{
	if len(b.blocks) > 0 {
		return b.blocks[len(b.blocks)-1].hash
	}
	return ""
}
  • 분리된 다른 function으로 옮기는 게 좋을 것 같다.
  • receiver function에 if가 들어가는 걸 원하지 않는다.
  • 그리고 이건 string을 반환해줄거야.
  • 여기로 옮겨준다.
  • return 하고 rese return은 아무것도 하지 않을거야
func (b *blockchain) addBlock(data string) {
	newBlock := block{data, "", b.getLastHash()}
    
}
  • 이제 이 newBlock의 prevHash부분에서 b.getLastHash()를 호출해준다.
  • 하나의 작업을 수행하기 위해서 function을 나눴다.
  • getLastHash는 마지막 block의 hash를 불러오는 것이다.
  • addBlock function의 작업은 block을 추가하는 것이다.
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)
}
  • byte의 slice가 필요하다.
  • 여기서 newBlock의 data와 prevHash를 hash해 줄 것이다.
  • hash는 16진수의 값이 필요하다. 따라서 Sprint에 "%x" 를 넣는다.
  • 새로운 block이 생겼고 이 새로운 block은 hash도 생성했다.
  • block도 hash를 가진다.
  • 우리가 이제 해줘야 할 것은 이 block을 blockchain.blocks에 추가해주기만 하면 된다.
  • 이건 복사본이 아니다. append를 이용해서 b.blocks에 newBlock을 추가할 수 있다.
  • append는 추가하고 싶은 element와 함께 새로운 slice를 반환한다.
  • append는 기존 slice와 추가하고 싶은 element를 인자로 받아서 기존 slice에다가 추가하고 싶은 element를 담아서 반환해준다.
  • 결과물을 어딘가에다가 저장해야 한다. 그저 b.block를 교체해주면 된다.
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)
	}
}
  • 인덱스를 신경쓰지 않고 block만 신경쓸 것이다.
  • block의 data를 출력해보고 hash 값과 이전 hash값 또한 출력해볼 것이다.
Data: Genesis Block
Hash: 89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3
Prev Hash:
Data: Second Block
Hash: ec6f43cf27c78760cc38a4855b36e83a7f054f5205a751628591d3f505599c08
Prev Hash: 89eb0ac031a63d2421cd05a2fbe41f3ea35f5c3712ca839cbf6b85c4ee07b7a3
Data: Third Block
Hash: d90e93ce55d3ef3b137b01112c8aad9f304efde1f970c41035c9c7658ad5e8dd
Prev Hash: ec6f43cf27c78760cc38a4855b36e83a7f054f5205a751628591d3f505599c08
  • 하나의 function이 하나의 일을 맡아서 하고 있다.
  • block을 생성하고, block을 hash하고, block을 append하지
  • 아마도 분리할 수 있다.

https://go.dev/play/p/8as9Eg1xftJ

 
728x90
반응형

관련글 더보기

댓글 영역