๐Ÿ”—
Blockchain
  • Blockchain
  • Blockchain Overview
    • Byzantine Generals Problem
    • The emergence of blockchain
    • Blockchain vs Bitcoin
    • Blockchain Structure
    • Blockchain examples
    • Blockchain Consensus
  • Bitcoin
    • Bitcoin
    • (Option) Bitcoin Whitepaper
    • Proof of Work
    • Transaction
    • Unspent Transaction Output
    • Mining
    • Wallet
    • Signature & Verification
    • Merkle Tree
    • Bitcoin Network
    • Consensus Rule Changes
    • Contracts
  • Ethereum
    • Ethereum
    • (Option) Ethereum Whitepaper
    • Web2 vs Web3
    • Smart Contract
    • Solidity
    • Ethereum Virtual Machine (EVM)
    • Accounts
    • Gas
    • (ETH2) Proof of Stake
    • (ETH2) Shard Chain
  • Ethereum Tutorials
    • Geth
    • CryptoZombies
    • Build DeFi App
    • Build Decentralized Bank
  • Ethereum Development Tools
    • Truffle
  • Golang-Blockchain
    • Go์–ธ์–ด ๋ธ”๋ก์ฒด์ธ
    • #1 Blocks and Chain
    • #2 Proof-of-Work
    • #3 Save blockchain persistently
    • #4 Transaction Basic
    • #5 Wallet
    • #6 Transaction Advanced
    • #7 UTXO management
    • #8 Merkle Tree
    • #9 Network 1
    • #10 Network 2
    • #11 p2p network
    • #12 Peer Discovery
    • #13 Console
  • Cosmos
    • Tutorials
  • Binance
    • Binance
  • DeFi
    • DeFi
    • DEX
    • Uniswap
    • Impermanent Loss
  • NFT
    • NFT
    • NFT Marketplace
    • NFT Virtual World
  • Common Algorithms
    • Hash
    • Cryptography
    • Consensus Algorithm
    • Distributed Ledger
Powered by GitBook
On this page
  • ๊ตฌํ˜„ํ•  ๊ฒƒ
  • Coinbase Transaction on New Block
  • blockchain/merkle.go
  • blockchain/block.go
  • Test
  • ๋ฏธ๊ตฌํ˜„ ์‚ฌํ•ญ

Was this helpful?

  1. Golang-Blockchain

#8 Merkle Tree

Storage size optimization

Previous#7 UTXO managementNext#9 Network 1

Last updated 4 years ago

Was this helpful?

๋น„ํŠธ์ฝ”์ธ์˜ ๋ชจ๋“  ๋ธ”๋ก์˜ ํŠธ๋žœ์žญ์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋ ค๋ฉด ํฐ space๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฒ€์ฆ์ธ๋“ค์€ ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ €์žฅํ•  ํ•„์š”๊ฐ€ ์žˆ์ง€๋งŒ, ๋น„ํŠธ์ฝ”์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋ชจ๋“  ํŠธ๋žœ์žญ์…˜ ๋ฐ์ดํ„ฐ(์ˆ˜๋ฐฑ GB)๋ฅผ ์ €์žฅํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์•„๋ฌด๋„ ๋น„ํŠธ์ฝ”์ธ ๊ฑฐ๋ž˜๋ฅผ ์ด์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

๋น„ํŠธ์ฝ”์ธ์€ ์ด๋Ÿฌํ•œ ๋น„ํšจ์œจ์„ฑ์„ ์ค„์ด๊ธฐ์œ„ํ•ด ๋ฅผ ๋„์ž…ํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋จธํดํŠธ๋ฆฌ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ๋งํฌ์—์„œ ๋จผ์ € ๊ณต๋ถ€ํ•˜์‹œ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

๊ตฌํ˜„ํ•  ๊ฒƒ

๋จธํดํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๋Š” ์•„๋ž˜ ์œ„ํ‚คํ”ผ๋””์•„์—์„œ ๊ฐ€์ ธ์˜จ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด Leaf ๋…ธ๋“œ๋ถ€ํ„ฐ ํ•ด์‹œ๋ฅผ ๊ตฌํ•˜๊ณ  2๊ฐœ์˜ ํ•ด์‹œ๋ฅผ ์ด์–ด์„œ ๋‹ค์‹œ ํ•ด์‹œ๋ฅผ ๊ตฌํ•ด ๋ถ€๋ชจ๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. Leaf ๋…ธ๋“œ๋Š” ์ง์ˆ˜๊ฐœ ์กด์žฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

ํ•ด์‹œ์˜ ํŠน์„ฑ์ƒ Leaf ์ค‘์˜ ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ(ํ•ด์‹œ๊ฐ’)๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๊ทธ ๋ฐ์ดํ„ฐ์™€ ์—ฐ๊ด€๋œ ๋ชจ๋“  ๋ถ€๋ชจ์˜ ํ•ด์‹œ๊ฐ’์ด ๋ฐ”๋€๋‹ˆ๋‹ค.

Coinbase Transaction on New Block

Merkle Tree๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ์ „์— ์ƒˆ๋กœ์šด ๋ธ”๋ก์ด ์ƒ์„ฑ๋  ๋•Œ ์ฝ”์ธ๋ฒ ์ด์Šค ํŠธ๋žœ์žญ์…˜์ด ๋ฐœ์ƒํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋‹จ transaction.goํŒŒ์ผ์„ ์—ด์–ด CoinbaseTx์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋žœ๋คํ•˜๊ฒŒ ์ƒ์„ฑ๋˜๋„๋ก ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

// miningํ•˜๋ฉด to์—๊ฒŒ ์ฝ”์ธ์„ ๋ณด์ƒ์œผ๋กœ ์ฃผ๋Š” Coinbase Transaction.
func CoinbaseTx(to, data string) *Transaction {
	if data == "" {
		randData := make([]byte, 24)
		_, err := rand.Read(randData)
		Handle(err)
		data = fmt.Sprintf("%x", randData)
	}

	txin := TxInput{[]byte{}, -1, nil, []byte(data)}
	txout := NewTXOutput(20, to)

	tx := Transaction{nil, []TxInput{txin}, []TxOutput{*txout}}
	tx.ID = tx.Hash()

	return &tx
}

send์—์„œ ๋ธ”๋ก์„ ์ถ”๊ฐ€ํ•  ๋•Œ Coinbase ํŠธ๋žœ์žญ์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ธ”๋ก์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ฃผ์†Œ์—๊ฒŒ ๋ณด์ƒ 20 ์ฝ”์ธ์„ ์ฃผ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. cli/cli.go

// {from}์—์„œ {to}๋กœ {amount}๋งŒํผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
func (cli *CommandLine) send(from, to string, amount int) {
	if !wallet.ValidateAddress(from) {
		log.Panic("Address is not Valid")
	}
	if !wallet.ValidateAddress(to) {
		log.Panic("Address is not Valid")
	}
	chain := blockchain.ContinueBlockChain("") // blockchain์„ DB๋กœ ๋ถ€ํ„ฐ ๋ฐ›์•„์˜จ๋‹ค.
	UTXOset := blockchain.UTXOSet{chain}
	defer chain.Database.Close()

	cbTx := blockchain.CoinbaseTx(from, "")  // ์ฝ”์ธ๋ฒ ์ด์Šค ํŠธ๋žœ์žญ์…˜์„ ์ƒ์„ฑํ•˜๊ณ 
	tx := blockchain.NewTransaction(from, to, amount, &UTXOset) // send ํŠธ๋žœ์žญ์…˜๋„ ์ƒ์„ฑํ•˜์—ฌ
	block := chain.AddBlock([]*blockchain.Transaction{cbTx, tx}) // ์ƒˆ๋กœ์šด ๋ธ”๋ก์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
	UTXOset.Update(block)
	fmt.Println("Success!")
}

blockchain/blockchain.goํŒŒ์ผ์„ ์—ด์–ด์„œ VerifyTransaction์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

// ํŠธ๋žœ์žญ์…˜์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
func (chain *BlockChain) VerifyTransaction(tx *Transaction) bool {
	// Coinbase ํŠธ๋žœ์žญ์…˜์€ ์œ ํšจํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.
	if tx.IsCoinbase() {
		return true
	}

	prevTXs := make(map[string]Transaction)

	for _, in := range tx.Inputs {
		prevTX, err := chain.FindTransaction(in.ID)
		Handle(err)
		prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX
	}

	// ์ด์ „ ๊ฑฐ๋ž˜ ๊ธฐ๋ก์„ ์ด์šฉํ•ด์„œ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
	return tx.Verify(prevTXs)
}

blockchain/merkle.go

Merkle Tree๋Š” ํ•ด์‹œ๋“ค์˜ ํ•ด์‹œ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌํ”„๋…ธ๋“œ(Leaf node)๋Š” ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์˜ ํ•ด์‹œ๋ฅผ ์ €์žฅํ•˜๋ฉฐ, ๋‘๊ฐœ์˜ ๋ฆฌํ”„๋…ธ๋“œ์˜ ํ•ด์‹œ๊ฐ’์„ ํ•ฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ถ€๋ชจ๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค. ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋ฃจํŠธ๋…ธ๋“œ๊นŒ์ง€ ๋งŒ๋“ค๊ณ  Merkle Tree๋Š” ์ด ๋ฃจํŠธ๋…ธ๋“œ๋ฅผ ํฌ์ธํŒ…ํ•ฉ๋‹ˆ๋‹ค.

package blockchain

import (
	"crypto/sha256"
)

// MerkleTree์˜ ๋ฃจํŠธ๋ฅผ ์ €์žฅํ•˜๋Š” ์ŠคํŠธ๋Ÿญ์ณ
type MerkleTree struct {
	RootNode *MerkleNode
}

// MerkleTree์˜ ๊ฐœ๋ณ„ ๋…ธ๋“œ
type MerkleNode struct {
	Left  *MerkleNode // ์™ผ์ชฝ ์ž์‹
	Right *MerkleNode // ์˜ค๋ฅธ์ชฝ ์ž์‹
	Data  []byte      // hash ๊ฐ’
}

// MerkleNode๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜
func NewMerkleNode(left, right *MerkleNode, data []byte) *MerkleNode {
	node := MerkleNode{}

	// {left}, {right}๊ฐ€ ์—†๋‹ค๋ฉด leaf node
	if left == nil && right == nil {
		hash := sha256.Sum256(data)
		node.Data = hash[:]
	} else {
		// ์ž์‹๋“ค์˜ ํ•ด์‹œ๋ฅผ ์ด์–ด์„œ ๋‹ค์‹œ Hash๋ฅผ ๊ตฌํ•จ
		prevHashes := append(left.Data, right.Data...)
		hash := sha256.Sum256(prevHashes)
		node.Data = hash[:]
	}

	// ์ž์‹ ์—ฐ๊ฒฐ
	node.Left = left
	node.Right = right

	return &node
}

// MerkleTree๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •
func NewMerkleTree(data [][]byte) *MerkleTree {
	var nodes []MerkleNode

	// ์ž์‹ ๋…ธ๋“œ์˜ ์ˆ˜๋ฅผ ์ง์ˆ˜๋กœ ๋งŒ๋“ค์–ด์•ผํ•จ
	// ๋งˆ์ง€๋ง‰ ์ž์‹์„ ๋ณต์‚ฌํ•œ๋‹ค.
	if len(data)%2 != 0 {
		data = append(data, data[len(data)-1])
	}

	// Leaf node๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •
	for _, dat := range data {
		node := NewMerkleNode(nil, nil, dat)
		nodes = append(nodes, *node)
	}

	// Tree height ๋งŒํผ ์ˆœํšŒ
	for i := len(data); i > 1; i /= 2 {
		var level []MerkleNode

		// ์ˆœ์„œ๋Œ€๋กœ 2๊ฐœ์”ฉ ํ•ฉ์ณ์„œ ๋…ธ๋“œ ์ƒ์„ฑ
		for j := 0; j < len(nodes); j += 2 {
			node := NewMerkleNode(&nodes[j], &nodes[j+1], nil)
			level = append(level, *node)
		}
		// ๋‹ค์Œ iteration์€ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง„ ๋…ธ๋“œ๋“ค๋กœ ์ง„ํ–‰
		nodes = level
	}

	// Root ๋…ธ๋“œ ๋ฐ˜ํ™˜
	tree := MerkleTree{&nodes[0]}

	return &tree
}

blockchain/block.go

HashTransactions ์ฝ”๋“œ๋ฅผ ๋ฐ”๊พธ์–ด ๋จธํดํŠธ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๋ฃจํŠธ์˜ Hash๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

// Block์˜ Transaction๋“ค์„ ํ•ฉ์ณ์„œ ํ•˜๋‚˜์˜ ํ•ด์‹œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
// Merkle Tree๋ฅผ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค.
func (b *Block) HashTransactions() []byte {
	var txHashes [][]byte

	for _, tx := range b.Transactions {
		txHashes = append(txHashes, tx.Serialize())
	}
	tree := NewMerkleTree(txHashes)

	// merkle tree๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๋ฃจํŠธ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ๊ฐ’์ด ์ตœ์ข… ํ•ด์‹œ๊ฐ’
	return tree.RootNode.Data
}

Test

Send ์‹œ์— ๋ธ”๋ก์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”์ธ๋ฒ ์ด์Šค ํŠธ๋žœ์žญ์…˜์ด ๋ฐœ์ƒํ•˜์—ฌ 20์ฝ”์ธ์ด ๋” ์ฃผ์–ด์ง„๋‹ค.

printchain ์œผ๋กœ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ๋ณด๋ฉด,

2๋ฒˆ์งธ ๋ธ”๋ก (ํ”„๋ฆฐํŠธ ์ƒ์—์„œ๋Š” ์œ„์—์„œ ์ฒซ๋ฒˆ์งธ)์— 2๊ฐœ์˜ transaction์ด ์ ํ˜€์žˆ๊ณ , ๊ทธ ์ค‘ ์ฒซ๋ฒˆ์งธ ํŠธ๋žœ์žญ์…˜์€ Coinbase ํŠธ๋žœ์žญ์…˜์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๋ฏธ๊ตฌํ˜„ ์‚ฌํ•ญ

ํ’€ ๋…ธ๋“œ์™€ ๋ผ์ดํŠธ ๋…ธ๋“œ ๊ฐœ๋…์ด ์—†์ด, ์ผ๋‹จ ํ•˜๋‚˜์˜ ๋…ธ๋“œ๊ฐ€ ๋ชจ๋“  ๋ธ”๋ก์ฒด์ธ ์ •๋ณด๋ฅผ ๋‹ค ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋จธํดํŠธ๋ฆฌ์˜ ์žฅ์ ์€ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

Last updated: May 8, 2021

์ฝ”๋“œ๋Š” ์˜ step8 ๋ธŒ๋žœ์น˜์— ์žˆ์Šต๋‹ˆ๋‹ค .

https://github.com/siisee11/golang-blockchain
Merkle Tree
Merkle Tree from Wikipidia