add CreateBlockchain

pull/2/head
Minh Doan 7 years ago
parent 32d1f71ac1
commit 3d5c33ee14
  1. 44
      block.go
  2. 14
      blockchain.go
  3. 65
      transaction.go

@ -16,6 +16,28 @@ type Block struct {
Hash []byte
}
// Serialize serializes the block
func (b *Block) Serialize() []byte {
var result bytes.Buffer
encoder := gob.NewEncoder(&result)
err := encoder.Encode(b)
if err != nil {
log.Panic(err)
}
return result.Bytes()
}
// DeserializeBlock deserializes a block
func DeserializeBlock(d []byte) *Block {
var block Block
decoder := gob.NewDecoder(bytes.NewReader(d))
err := decoder.Decode(&block)
if err != nil {
log.Panic(err)
}
return &block
}
// HashTransactions returns a hash of the transactions in the block
func (b *Block) HashTransactions() []byte {
var txHashes [][]byte
@ -28,17 +50,6 @@ func (b *Block) HashTransactions() []byte {
return txHash[:]
}
// Serialize serializes the block
func (b *Block) Serialize() []byte {
var result bytes.Buffer
encoder := gob.NewEncoder(&result)
err := encoder.Encode(b)
if err != nil {
log.Panic(err)
}
return result.Bytes()
}
// NewBlock creates and returns Block.
func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block {
block := &Block{time.Now().Unix(), transactions, prevBlockHash, []byte{}, 0}
@ -50,14 +61,3 @@ func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block {
func NewGenesisBlock(coinbase *Transaction) *Block {
return NewBlock([]*Transaction{coinbase}, []byte{})
}
// DeserializeBlock deserializes a block
func DeserializeBlock(d []byte) *Block {
var block Block
decoder := gob.NewDecoder(bytes.NewReader(d))
err := decoder.Decode(&block)
if err != nil {
log.Panic(err)
}
return &block
}

@ -9,6 +9,8 @@ type Blockchain struct {
blocks []*Block
}
const genesisCoinbaseData = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
// NewBlockchain creates a new Blockchain with genesis Block
func NewBlockchain(address string) *Blockchain {
return &Blockchain{[]*Block{NewGenesisBlock()}}
@ -87,3 +89,15 @@ Work:
return accumulated, unspentOutputs
}
// CreateBlockchain creates a new blockchain DB
func CreateBlockchain(address string) *Blockchain {
// 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.
cbtx := NewCoinbaseTX(address, genesisCoinbaseData)
genesis := NewGenesisBlock(cbtx)
bc := Blockchain{[]*Block{genesis}}
return &bc
}

@ -4,6 +4,8 @@ import (
"bytes"
"crypto/sha256"
"encoding/gob"
"encoding/hex"
"fmt"
"log"
)
@ -14,19 +16,24 @@ type Transaction struct {
txOutput []TXOutput
}
// TXOutput is the struct of transaction output in a transaction.
type TXOutput struct {
address string
value int
address string
}
// TXInput is the struct of transaction input in a transaction.
type TXInput struct {
txId []byte
txID []byte
txOutputIndex int
address string
}
// defaultCoinbaseValue is the default value of coinbase transaction.
const defaultCoinbaseValue = 10
// SetID sets ID of a transaction
func (tx *Transaction) SetId() {
func (tx *Transaction) SetID() {
var encoded bytes.Buffer
var hash [32]byte
@ -36,5 +43,55 @@ func (tx *Transaction) SetId() {
log.Panic(err)
}
hash = sha256.Sum256(encoded.Bytes())
tx.ID = hash[:]
tx.id = hash[:]
}
// NewCoinbaseTX creates a new coinbase transaction
func NewCoinbaseTX(to, data string) *Transaction {
if data == "" {
data = fmt.Sprintf("Reward to '%s'", to)
}
txin := TXInput{[]byte{}, -1, data}
txout := TXOutput{defaultCoinbaseValue, to}
tx := Transaction{nil, []TXInput{txin}, []TXOutput{txout}}
tx.SetID()
return &tx
}
// NewUTXOTransaction creates a new transaction
func NewUTXOTransaction(from, to string, amount int, bc *Blockchain) *Transaction {
var inputs []TXInput
var outputs []TXOutput
acc, validOutputs := bc.FindSpendableOutputs(from, amount)
if acc < amount {
log.Panic("ERROR: Not enough funds")
}
// Build a list of inputs
for txid, outs := range validOutputs {
txID, err := hex.DecodeString(txid)
if err != nil {
log.Panic(err)
}
for _, out := range outs {
input := TXInput{txID, out, from}
inputs = append(inputs, input)
}
}
// Build a list of outputs
outputs = append(outputs, TXOutput{amount, to})
if acc > amount {
outputs = append(outputs, TXOutput{acc - amount, from}) // a change
}
tx := Transaction{nil, inputs, outputs}
tx.SetID()
return &tx
}

Loading…
Cancel
Save