add verification/selection a set of valid transactions

pull/5/merge
Minh Doan 6 years ago
parent 3a7f9eb46d
commit 31472956d5
  1. 90
      blockchain/utxopool.go

@ -4,6 +4,10 @@ import (
"encoding/hex"
)
const (
MaxNumberOfTransactions = 100
)
// UTXOPool stores transactions and balance associated with each address.
type UTXOPool struct {
// Mapping from address to a map of transaction id to a map of the index of output
@ -57,6 +61,80 @@ func (utxopool *UTXOPool) VerifyTransactions(transactions []*Transaction) bool {
return true
}
// VerifyOneTransactionAndUpdate verifies if a list of transactions valid.
func (utxopool *UTXOPool) VerifyOneTransaction(tx *Transaction) bool {
spentTXOs := make(map[string]map[string]map[int]bool)
txID := hex.EncodeToString(tx.ID)
inTotal := 0
// Calculate the sum of TxInput
for _, in := range tx.TxInput {
inTxID := hex.EncodeToString(in.TxID)
index := in.TxOutputIndex
// Check if the transaction with the addres is spent or not.
if val, ok := utxopool.utxo[in.Address][inTxID][index]; ok {
if spentTXOs[in.Address][inTxID][index] {
return false
}
inTotal += val
} else {
return false
}
// Mark the transactions with the address and index spent.
if _, ok := spentTXOs[in.Address]; !ok {
spentTXOs[in.Address] = make(map[string]map[int]bool)
}
if _, ok := spentTXOs[in.Address][inTxID]; !ok {
spentTXOs[in.Address][inTxID] = make(map[int]bool)
}
spentTXOs[in.Address][inTxID][index] = true
}
outTotal := 0
// Calculate the sum of TxOutput
for index, out := range tx.TxOutput {
if val, ok := spentTXOs[out.Address][txID][index]; ok {
return false
}
outTotal += out.Value
}
if inTotal != outTotal {
return false
}
return true
}
func (utxopool *UTXOPool) Update(tx* Transaction) {
if utxopool != nil {
txID := hex.EncodeToString(tx.ID)
// Remove
for _, in := range tx.TxInput {
inTxID := hex.EncodeToString(in.TxID)
delete(utxopool.utxo[in.Address][inTxID], in.TxOutputIndex)
}
// Update
for index, out := range tx.TxOutput {
if _, ok := utxopool.utxo[out.Address]; !ok {
utxopool.utxo[out.Address] = make(map[string]map[int]int)
utxopool.utxo[out.Address][txID] = make(map[int]int)
}
if _, ok := utxopool.utxo[out.Address][txID]; !ok {
utxopool.utxo[out.Address][txID] = make(map[int]int)
}
utxopool.utxo[out.Address][txID][index] = out.Value
}
}
}
func (utxopool *UTXOPool) VerifyOneTransactionAndUpdate(tx *Transaction) bool {
if utxopool.VerifyOneTransaction(tx) {
utxopool.Update(tx)
return true
}
retur false
}
// VerifyAndUpdate verifies a list of transactions and update utxoPool.
func (utxopool *UTXOPool) VerifyAndUpdate(transactions []*Transaction) bool {
if utxopool.VerifyTransactions(transactions) {
@ -111,3 +189,15 @@ func CreateUTXOPoolFromGenesisBlockChain(bc *Blockchain) *UTXOPool {
tx := bc.blocks[0].Transactions[0]
return CreateUTXOPoolFromTransaction(tx)
}
// SelectTransactionsForNewBlock returns a list of index of valid transactions for the new block.
func (utxoPool *UTXOPool) SelectTransactionsForNewBlock(transactions []*Transaction) (selected, unselected []*Transaction) {
selected, unselected = []*Transaction{}, []*Transaction{}
for id, tx := range transactions {
if len(selected) < MaxNumberOfTransactions && utxoPool.VerifyOneTransactionAndUpdate(tx) {
append(selected, tx)
} else {
append(unselected, tx)
}
}
}

Loading…
Cancel
Save