Integrate transactions into the blockchain
This commit is contained in:
parent
2ba0f1bfdd
commit
08a211be41
10
block.go
10
block.go
|
@ -10,7 +10,7 @@ import (
|
||||||
// Block keeps block headers
|
// Block keeps block headers
|
||||||
type Block struct {
|
type Block struct {
|
||||||
Timestamp int64
|
Timestamp int64
|
||||||
Data []byte
|
Transactions []*Transaction
|
||||||
PrevBlockHash []byte
|
PrevBlockHash []byte
|
||||||
Hash []byte
|
Hash []byte
|
||||||
Nonce int
|
Nonce int
|
||||||
|
@ -30,8 +30,8 @@ func (b *Block) Serialize() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlock creates and returns Block
|
// NewBlock creates and returns Block
|
||||||
func NewBlock(data string, prevBlockHash []byte) *Block {
|
func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block {
|
||||||
block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}, 0}
|
block := &Block{time.Now().Unix(), transactions, prevBlockHash, []byte{}, 0}
|
||||||
pow := NewProofOfWork(block)
|
pow := NewProofOfWork(block)
|
||||||
nonce, hash := pow.Run()
|
nonce, hash := pow.Run()
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ func NewBlock(data string, prevBlockHash []byte) *Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGenesisBlock creates and returns genesis Block
|
// NewGenesisBlock creates and returns genesis Block
|
||||||
func NewGenesisBlock() *Block {
|
func NewGenesisBlock(coinbase *Transaction) *Block {
|
||||||
return NewBlock("Genesis Block", []byte{})
|
return NewBlock([]*Transaction{coinbase}, []byte{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeserializeBlock deserializes a block
|
// DeserializeBlock deserializes a block
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
const dbFile = "blockchain.db"
|
const dbFile = "blockchain.db"
|
||||||
const blocksBucket = "blocks"
|
const blocksBucket = "blocks"
|
||||||
|
const genesisCoinbase = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
|
||||||
|
|
||||||
// Blockchain keeps a sequence of Blocks
|
// Blockchain keeps a sequence of Blocks
|
||||||
type Blockchain struct {
|
type Blockchain struct {
|
||||||
|
@ -86,7 +87,7 @@ func (i *BlockchainIterator) Next() *Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockchain creates a new Blockchain with genesis Block
|
// NewBlockchain creates a new Blockchain with genesis Block
|
||||||
func NewBlockchain() *Blockchain {
|
func NewBlockchain(address string) *Blockchain {
|
||||||
var tip []byte
|
var tip []byte
|
||||||
db, err := bolt.Open(dbFile, 0600, nil)
|
db, err := bolt.Open(dbFile, 0600, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -98,7 +99,8 @@ func NewBlockchain() *Blockchain {
|
||||||
|
|
||||||
if b == nil {
|
if b == nil {
|
||||||
fmt.Println("No existing blockchain found. Creating a new one...")
|
fmt.Println("No existing blockchain found. Creating a new one...")
|
||||||
genesis := NewGenesisBlock()
|
cbtx := NewCoinbaseTX(address, genesisCoinbase)
|
||||||
|
genesis := NewGenesisBlock(cbtx)
|
||||||
|
|
||||||
b, err := tx.CreateBucket([]byte(blocksBucket))
|
b, err := tx.CreateBucket([]byte(blocksBucket))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -31,10 +31,18 @@ func NewProofOfWork(b *Block) *ProofOfWork {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pow *ProofOfWork) prepareData(nonce int) []byte {
|
func (pow *ProofOfWork) prepareData(nonce int) []byte {
|
||||||
|
var txHashes [][]byte
|
||||||
|
var txHash [32]byte
|
||||||
|
|
||||||
|
for _, tx := range pow.block.Transactions {
|
||||||
|
txHashes = append(txHashes, tx.GetHash())
|
||||||
|
}
|
||||||
|
txHash = sha256.Sum256(bytes.Join(txHashes, []byte{}))
|
||||||
|
|
||||||
data := bytes.Join(
|
data := bytes.Join(
|
||||||
[][]byte{
|
[][]byte{
|
||||||
pow.block.PrevBlockHash,
|
pow.block.PrevBlockHash,
|
||||||
pow.block.Data,
|
txHash[:],
|
||||||
IntToHex(pow.block.Timestamp),
|
IntToHex(pow.block.Timestamp),
|
||||||
IntToHex(int64(targetBits)),
|
IntToHex(int64(targetBits)),
|
||||||
IntToHex(int64(nonce)),
|
IntToHex(int64(nonce)),
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "log"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/gob"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
const subsidy = 10
|
const subsidy = 10
|
||||||
|
|
||||||
|
@ -15,6 +20,21 @@ func (tx Transaction) IsCoinbase() bool {
|
||||||
return len(tx.Vin) == 1 && tx.Vin[0].Txid == -1 && tx.Vin[0].Vout == -1
|
return len(tx.Vin) == 1 && tx.Vin[0].Txid == -1 && tx.Vin[0].Vout == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHash hashes the transaction and returns the hash
|
||||||
|
func (tx Transaction) GetHash() []byte {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
var hash [32]byte
|
||||||
|
|
||||||
|
enc := gob.NewEncoder(&encoded)
|
||||||
|
err := enc.Encode(tx)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
hash = sha256.Sum256(encoded.Bytes())
|
||||||
|
|
||||||
|
return hash[:]
|
||||||
|
}
|
||||||
|
|
||||||
// TXInput represents a transaction input
|
// TXInput represents a transaction input
|
||||||
type TXInput struct {
|
type TXInput struct {
|
||||||
Txid int
|
Txid int
|
||||||
|
@ -34,8 +54,12 @@ func (out *TXOutput) Unlock(unlockingData string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCoinbaseTX creates a new coinbase transaction
|
// NewCoinbaseTX creates a new coinbase transaction
|
||||||
func NewCoinbaseTX(to string) *Transaction {
|
func NewCoinbaseTX(to, data string) *Transaction {
|
||||||
txin := TXInput{-1, -1, "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"}
|
if data == "" {
|
||||||
|
data = "Coinbase"
|
||||||
|
}
|
||||||
|
|
||||||
|
txin := TXInput{-1, -1, data}
|
||||||
txout := TXOutput{subsidy, to}
|
txout := TXOutput{subsidy, to}
|
||||||
tx := Transaction{[]TXInput{txin}, []TXOutput{txout}}
|
tx := Transaction{[]TXInput{txin}, []TXOutput{txout}}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue