decouple CreateBlockchain and UTXOPool into different methods

pull/5/merge
Minh Doan 7 years ago
parent c45ed9439f
commit 6a48a4d810
  1. 4
      blockchain/block_test.go
  2. 6
      blockchain/blockchain.go
  3. 13
      blockchain/blockchain_test.go
  4. 11
      blockchain/transaction.go
  5. 2
      blockchain/transaction_test.go
  6. 31
      blockchain/utxopool.go
  7. 2
      blockchain/utxopool_test.go

@ -6,8 +6,8 @@ import (
) )
func TestBlockSerialize(t *testing.T) { func TestBlockSerialize(t *testing.T) {
cbtx, utxoPool := NewCoinbaseTX("minh", genesisCoinbaseData) cbtx := NewCoinbaseTX("minh", genesisCoinbaseData)
if cbtx == nil || utxoPool == nil { if cbtx == nil {
t.Errorf("Failed to create a coinbase transaction.") t.Errorf("Failed to create a coinbase transaction.")
} }
block := NewGenesisBlock(cbtx) block := NewGenesisBlock(cbtx)

@ -161,13 +161,13 @@ func (bc *Blockchain) VerifyNewBlockAndUpdate(utxopool *UTXOPool, block *Block)
} }
// CreateBlockchain creates a new blockchain DB // CreateBlockchain creates a new blockchain DB
func CreateBlockchain(address string) (*Blockchain, *UTXOPool) { func CreateBlockchain(address string) *Blockchain {
// TODO: We assume we have not created any blockchain before. // TODO: We assume we have not created any blockchain before.
// In current bitcoin, we can check if we created a blockchain before accessing local db. // In current bitcoin, we can check if we created a blockchain before accessing local db.
cbtx, utxoPool := NewCoinbaseTX(address, genesisCoinbaseData) cbtx := NewCoinbaseTX(address, genesisCoinbaseData)
genesis := NewGenesisBlock(cbtx) genesis := NewGenesisBlock(cbtx)
bc := Blockchain{[]*Block{genesis}} bc := Blockchain{[]*Block{genesis}}
return &bc, utxoPool return &bc
} }

@ -5,14 +5,14 @@ import (
) )
func TestCreateBlockchain(t *testing.T) { func TestCreateBlockchain(t *testing.T) {
if bc, _ := CreateBlockchain("minh"); bc == nil { if bc := CreateBlockchain("minh"); bc == nil {
t.Errorf("failed to create a blockchain") t.Errorf("failed to create a blockchain")
} }
} }
func TestFindSpendableOutputs(t *testing.T) { func TestFindSpendableOutputs(t *testing.T) {
requestAmount := 3 requestAmount := 3
bc, _ := CreateBlockchain("minh") bc := CreateBlockchain("minh")
accumulated, unspentOutputs := bc.FindSpendableOutputs("minh", requestAmount) accumulated, unspentOutputs := bc.FindSpendableOutputs("minh", requestAmount)
if accumulated < DefaultCoinbaseValue { if accumulated < DefaultCoinbaseValue {
t.Error("Failed to find enough unspent ouptuts") t.Error("Failed to find enough unspent ouptuts")
@ -24,7 +24,7 @@ func TestFindSpendableOutputs(t *testing.T) {
} }
func TestFindUTXO(t *testing.T) { func TestFindUTXO(t *testing.T) {
bc, _ := CreateBlockchain("minh") bc := CreateBlockchain("minh")
utxo := bc.FindUTXO("minh") utxo := bc.FindUTXO("minh")
total := 0 total := 0
@ -41,7 +41,8 @@ func TestFindUTXO(t *testing.T) {
} }
func TestAddNewUserTransfer(t *testing.T) { func TestAddNewUserTransfer(t *testing.T) {
bc, utxoPool := CreateBlockchain("minh") bc := CreateBlockchain("minh")
utxoPool := CreateUTXOPoolFromGenesisBlockChain(bc)
if !bc.AddNewUserTransfer(utxoPool, "minh", "alok", 3) { if !bc.AddNewUserTransfer(utxoPool, "minh", "alok", 3) {
t.Error("Failed to add new transfer to alok.") t.Error("Failed to add new transfer to alok.")
@ -57,7 +58,9 @@ func TestAddNewUserTransfer(t *testing.T) {
} }
func TestVerifyNewBlock(t *testing.T) { func TestVerifyNewBlock(t *testing.T) {
bc, utxoPool := CreateBlockchain("minh") bc := CreateBlockchain("minh")
utxoPool := CreateUTXOPoolFromGenesisBlockChain(bc)
bc.AddNewUserTransfer(utxoPool, "minh", "alok", 3) bc.AddNewUserTransfer(utxoPool, "minh", "alok", 3)
bc.AddNewUserTransfer(utxoPool, "minh", "rj", 100) bc.AddNewUserTransfer(utxoPool, "minh", "rj", 100)

@ -47,7 +47,7 @@ func (tx *Transaction) SetID() {
} }
// NewCoinbaseTX creates a new coinbase transaction // NewCoinbaseTX creates a new coinbase transaction
func NewCoinbaseTX(to, data string) (*Transaction, *UTXOPool) { func NewCoinbaseTX(to, data string) *Transaction {
if data == "" { if data == "" {
data = fmt.Sprintf("Reward to '%s'", to) data = fmt.Sprintf("Reward to '%s'", to)
} }
@ -56,14 +56,7 @@ func NewCoinbaseTX(to, data string) (*Transaction, *UTXOPool) {
txout := TXOutput{DefaultCoinbaseValue, to} txout := TXOutput{DefaultCoinbaseValue, to}
tx := Transaction{nil, []TXInput{txin}, []TXOutput{txout}} tx := Transaction{nil, []TXInput{txin}, []TXOutput{txout}}
tx.SetID() tx.SetID()
txID := hex.EncodeToString(tx.ID) return &tx
var utxoPool UTXOPool
utxoPool.utxo = make(map[string]map[string]int)
utxoPool.utxo[to] = make(map[string]int)
utxoPool.utxo[to][txID] = DefaultCoinbaseValue
return &tx, &utxoPool
} }
// Used for debuging. // Used for debuging.

@ -5,7 +5,7 @@ import (
) )
func TestNewCoinbaseTX(t *testing.T) { func TestNewCoinbaseTX(t *testing.T) {
if cbtx, utxoPool := NewCoinbaseTX("minh", genesisCoinbaseData); cbtx == nil || utxoPool == nil { if cbtx := NewCoinbaseTX("minh", genesisCoinbaseData); cbtx == nil {
t.Errorf("failed to create a coinbase transaction.") t.Errorf("failed to create a coinbase transaction.")
} }
} }

@ -6,9 +6,9 @@ import (
// UTXOPool stores transactions and balance associated with each address. // UTXOPool stores transactions and balance associated with each address.
type UTXOPool struct { type UTXOPool struct {
// Mapping from address to a map of transaction id to that balance. // Mapping from address to a map of transaction id to a map of the index of output
// The assumption here is that one address only appears once output array in a transaction. // array in that transaction to that balance.
utxo map[string]map[string]map[int]int utxo map[string]map[string]int
} }
// VerifyTransactions verifies if a list of transactions valid. // VerifyTransactions verifies if a list of transactions valid.
@ -88,3 +88,28 @@ func (utxopool *UTXOPool) Update(transactions []*Transaction) {
} }
} }
} }
// CreateUTXOPoolFromTransaction a utxo pool from a genesis transaction.
func CreateUTXOPoolFromTransaction(tx *Transaction) *UTXOPool {
var utxoPool UTXOPool
txID := hex.EncodeToString(tx.ID)
utxoPool.utxo = make(map[string]map[string]int)
for _, out := range tx.TxOutput {
utxoPool.utxo[out.Address] = make(map[string]int)
utxoPool.utxo[out.Address][txID] = DefaultCoinbaseValue
}
return &utxoPool
}
// CreateUTXOPoolFromGenesisBlockChain a utxo pool from a genesis blockchain.
func CreateUTXOPoolFromGenesisBlockChain(bc *Blockchain) *UTXOPool {
tx := bc.blocks[0].Transactions[0]
var utxoPool UTXOPool
txID := hex.EncodeToString(tx.ID)
utxoPool.utxo = make(map[string]map[string]int)
for _, out := range tx.TxOutput {
utxoPool.utxo[out.Address] = make(map[string]int)
utxoPool.utxo[out.Address][txID] = DefaultCoinbaseValue
}
return &utxoPool
}

@ -5,7 +5,7 @@ import (
) )
func TestVerifyTransactions(t *testing.T) { func TestVerifyTransactions(t *testing.T) {
if cbtx, utxoPool := NewCoinbaseTX("minh", genesisCoinbaseData); cbtx == nil || utxoPool == nil { if cbtx := NewCoinbaseTX("minh", genesisCoinbaseData); cbtx == nil {
t.Errorf("failed to create a coinbase transaction.") t.Errorf("failed to create a coinbase transaction.")
} }
} }

Loading…
Cancel
Save