refactor transaction and add logic of FindUTXO and FindSpendableOutputs and FindUnspentTransactions

pull/2/head
Minh Doan 7 years ago
parent 5ad2c3e3f8
commit 37ac634c0a
  1. 79
      blockchain.go
  2. 18
      transaction.go

@ -1,5 +1,9 @@
package main
import (
"encoding/hex"
)
// Blockchain keeps a sequence of Blocks
type Blockchain struct {
blocks []*Block
@ -17,4 +21,77 @@ func (bc *Blockchain) AddBlock(data string) {
// NewBlockchain creates a new Blockchain with genesis Block
func NewBlockchain() *Blockchain {
return &Blockchain{[]*Block{NewGenesisBlock()}}
}
}
// FindUnspentTransactions returns a list of transactions containing unspent outputs
func (bc *Blockchain) FindUnspentTransactions(address string) []Transaction {
var unspentTXs []Transaction
spentTXOs := make(map[string][]int)
for index := len(bc.blocks); index >= 0; index-- {
block := bc.blocks[index];
BreakTransaction:
for _, tx := range block.Transactions {
txId := hex.EncodeToString(tx.Id)
idx := -1
if spentTXOs[txId] != nil {
idx = 0
}
for outIdx, txOutput := range tx.txOutput {
if idx >= 0 spentTXOs[txId][idx] == outIdx {
continue
}
if txOutput.address == address {
unspentTXs = append(unspentTXs, *tx)
continue BreakTransaction
}
}
}
}
return unspentTXs
}
// FindUTXO finds and returns all unspent transaction outputs
func (bc *Blockchain) FindUTXO(address string) []TXOutput {
var UTXOs []TXOutput
unspentTXs := bc.FindUnspentTransactions(address)
for _, tx := range unspentTXs {
for _, txOutput := range tx.txOutput {
if txOutput.address == address {
UTXOs = append(UTXOs, txOutput)
break
}
}
}
return UTXOs
}
// FindSpendableOutputs finds and returns unspent outputs to reference in inputs
func (bc *Blockchain) FindSpendableOutputs(address string, amount int) (int, map[string][]int) {
unspentOutputs := make(map[string][]int)
unspentTXs := bc.FindUnspentTransactions(address)
accumulated := 0
Work:
for _, tx := range unspentTXs {
txID := hex.EncodeToString(tx.ID)
for outIdx, txOutput := range tx.txOutput {
if txOutput.address == address && accumulated < amount {
accumulated += txOutput.value
unspentOutputs[txID] = append(unspentOutputs[txID], outIdx)
if accumulated >= amount {
break Work
}
}
}
}
return accumulated, unspentOutputs
}

@ -9,24 +9,24 @@ import (
// Transaction represents a Bitcoin transaction
type Transaction struct {
ID []byte
Vin []TXInput
Vout []TXOutput
id []byte
txInput []TXInput
txOutput []TXOutput
}
type TXOutput struct {
Addresss string
Value int
address string
value int
}
type TXInput struct {
Txid []byte
outIndex int
Address string
txId []byte
txOutputIndex int
address string
}
// SetID sets ID of a transaction
func (tx *Transaction) SetID() {
func (tx *Transaction) SetId() {
var encoded bytes.Buffer
var hash [32]byte

Loading…
Cancel
Save