상세 컨텐츠

본문 제목

[Nomad Coin] Blockchain - #4.4 Refactoring part One

Go/Blockchain

by Gopythor 2022. 7. 16. 01:53

본문

728x90
반응형

#4.4 Refactoring part One

  • 지금 만드는 프로그램은 대부분 비활성화 상태이다.
  • 프로그램을 실행하려고 하면 안 될 때가 있을 것이다. 컴파일이 제대로 안되는 것이다.
  • 위 프로그램에서도 chain이 사용되고 있지 않다.
  • Go는 선언한 것들을 전부 쓰지 않는 것을 좋아하지 않는다.

 

func GetBlockchain() *blockchain {
	if b == nil {
		b = &blockchain{}
	}
	return b
}
  • sync란 패키지에 대해 알아보자.
  • Go 언어에서 go routine을 생성하기 쉽다.
  • 프로그램이 병렬적으로 실행이 가능하다는 뜻이다.
  • sync패키지는 동기적으로 처리해야 하는 부분을 제대로 처리하게 도와준다.
  • 병렬로 실행하고 있는 프로그램이 몇개이던 간에, thread가 몇개이던, Goroutine이 몇개이던간에 이 코드를 한번만 실행시키고 싶다.
  • 이걸 위해서 sync 패키지를 사용할 것이다.
  • 구체적으로 sync의 Once를 사용할 것이다.
func GetBlockchain() *blockchain {
	if b == nil {
		once.Do(func() {
			b = &blockchain{}
		})
	}
	return b
}
  • Once는 Do라는 function을 가지고 있다.
  • Do는 정확히 단 한 번만 호출되도록 해주는 function이다.
  • once.Do를 호출해서 한 번만 실행시킬 function을 넘겨줄 것이다.
  • 이전과 똑같이 동작할 것이다.
  • 몇 천개의 Goroutine을 실행해도, 프로그램을 병렬적으로 처리해도 초기화 단계를 단 한번만 실행하도록 했다.
  • 이 blockchain이 첫 번째 block으로 초기화되야 한다는 걸 알고 있다. Genesis block 말이다. 그것이 모든 것의 시작점이다.
  • Genesis block을 생성할 것이다.
  • 즉, application을 처음 시작하고 최초로 blockchain의 block들을 보기 요청한다면, blockchain을 초기화 할 것이다.
func createBlock(data string) *block {

}

func GetBlockchain() *blockchain {
	if b == nil {
		once.Do(func() {
			b = &blockchain{}
			b.blocks = append(b.blocks,)
		})
	}
	return b
}
  • 이곳에서 첫 block인 Genesis block을 생성할 것이다.
  • 그리고 이걸 create Block이라는 function으로 정의할 것이다.
  • createBlock은 string타입의 data를 인자로 받아서 생성될 block으로의 pointer를 반환해 줄 것이다.
type blockchain struct {
	blocks []*block
}
  • blockchain은 block들의 slice다.
  • 여기에 block의 pointer들을 집어 넣을 것이다.
  • 이 blocks는 pointer의 slice가 된다.
  • blockchain이 매우 길어질 수 있기 때문에 block들을 복사하고 싶지 않다.
func GetBlockchain() *blockchain {
	if b == nil {
		once.Do(func() {
			b = &blockchain{}
			b.blocks = append(b.blocks, createBlock("Genesis Block"))
		})
	}
	return b
}
  • createBlock에서 반환된 결과를 여기에 추가할 것이다.
  • Genesis Block을 추가하여 blockchain을 초기화한다.
  • 비어있는 blockchain을 먼저 생성하고, blockchain 내부의 blocks에 하나의 block을 추가하는 것이다.
  • 첫 번째 block은 Genesis Block이다.
  • Genesis Block은 createBlock fucntion을 통해 생성된다.
func createBlock(data string) *block {
	newBlock := block{data, "", }
}
  • block 생성자를 호출해주고, data를 사용해서 block을 생성해야 한다.
  • 이 block에는 hash도 필요하지만 아직 없으니 비워둔다.
  • 마지막으로 이전 hash 값이 필요하다.
func getLastHash() string {
	totalBlocks := len(GetBlockchain().blocks)
	if totalBlocks == 0 {
		return ""
	}
	return GetBlockchain().blocks[totalBlocks - 1].hash
}
  • 이전 hash값을 불러오는 function을 만들 것이다.
  • getLastHash라는 functnion을 만든다.
  • string을 반환시키고, if-else를 구현한다.
  • 가지고 있는 block들의 길이이다.
  • GetBlockchain function을 사용한다.
  • 만약 totalBlocks가 0이라면, 아무것도 반환하지 않을 것이다. 왜냐하면 마지막 hash값이 없기 때문이다. 
  • 만약 그렇지 않다면, GetBlockchain으로 마지막 block의 hash값을 얻어낸다.
func createBlock(data string) *block {
	newBlock := block{data, "", getLastHash()}
}
  • 이 block은 엉망이다. 왜냐하면 아직 hash 값이 없다.
  • receiver function을 만들어야 한다.
  • 왜냐하면 data를 변경해야만 하기 때문이다.
func (b *block) calclulateHash() {
	hash := sha256.Sum256([]byte(b.data + b.prevHash))
	b.hash = fmt.Sprintf("%x", hash)
}
  • hash값을 계산할 calculateHash던 getHash던 원하는대로 만들어보자.
  • data값와 prevHash값을 가져와서 hash fuctnion에 넣고 string으로 변환시킬 것이다.
  • 더 모듈화된 방법으로 구현할 것이다.
  • byte의 slice, 그리고 여기에 b.data와 b.prevHash를 더한 값을 넘겨주면 byte의 배열을 반환해 줄 것이다.
  • 이걸 16진수로 포맷할 것이다.
func createBlock(data string) *block {
	newBlock := block{data, "", getLastHash()}
	newBlock.calclulateHash()
	return &newBlock
}
  • createBlock으로 돌아와서, newBlock의 calculateHash를 호출한다.
  • 여기서 block을 생성한다.
  • newBlock을 반환해준다.

 

 

  • Genesis block을 생성하는 blockchain이 있고, createBlock은 data가 들어있는 block을 생성해 줄 것이다.
  • block을 생성하기 위해 유저에게서 받아온 data가 필요하고, hash는 아직 존재하지 않는다. 그러나 이전 hash값은 가져올 수 있다.
  • getLastHash function에서는 blockchain의 길이를 알아내서 현재 blockchain의 길이가 0이라면 아무것도 반환하지 않고, 그렇지 않다면, blockchain의 마지막 block의 hash 값을 반환할 것이다.
  • blockchain의 마지막 block의 hash 값을 반환할 것이다.
  • 그리고 newBlock의 hash값을 receiver function에서 계산해주고, 이 function은 pointer를 인자 값으로 받아 온다.
  • block의 복사본이 아니고, 실제 값을 가지고 온다. 실제 block을 가지고 오기 때문에 값을 변경해 줄 수 있다.
  • calculateHash function에서 hash 값을 계산하고 계산한 hash값을 block에 넘겨준다.
  •  아직은 blockchain에서 곧바로 block을 더해주는 함수는 없다.
  • 그저 createBlock으로 생성할 뿐이다.
  • 아직 blockchain에 block을 추가할 방법을 모른다.
  • blockchain 내부의 block들을 드러내는 function도 만들지 않았다.

 

출처 : 노마드코더, 노마드코인 강의

728x90
반응형

관련글 더보기

댓글 영역