diff --git a/.travis.yml b/.travis.yml index 120c9a6a6..6cefeb9fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,13 @@ language: go go: - master -install: | - export GOPATH=$HOME/gopath - mkdir -p $HOME/gopath/src/harmony-benchmark - rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/harmony-benchmark/ - export TRAVIS_BUILD_DIR=$HOME/gopath/src/harmony-benchmark - cd $HOME/gopath/src/harmony-benchmark +install: + - export GOPATH=$HOME/gopath + - mkdir -p $HOME/gopath/src/harmony-benchmark + - rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/harmony-benchmark/ + - export TRAVIS_BUILD_DIR=$HOME/gopath/src/harmony-benchmark + - cd $HOME/gopath/src/harmony-benchmark + - go build notifications: slack: secure: RPB3ThYIGuDUidvaWfOA7Hc9x1bDfd5+Y10r7xwY+NGCN3zW86s/GNLpLutI0MWTV9e2CJupHvz5clp8Ktle/tVjLhs6jHQnNV7U8PTWKkL5By6IFVAHN12unMQn/m0RPwqMfdubajXoV51XhbFA/iow/0fqwsd61VdPIuBrlQjy9z7kyVnRLNoGvYjDqKEkJfYVb3qFNFLzD0F7Y2AgxnezIRjsTLgHzR4owLJYqVMhvTYIV9/vSf1w4UUPzhHyZRESl6bri+a1+g7GxE32OtNwq68xxVeeJcrO/MbjAHHW9V6BW1MjJfYzD5T+7JHIfZOjV2WgzJ7uCkVYztfq+02yOCSWsLNxFVojIDhVFEhhJ6Vd2Zf1otolS7j0svK/qNmShID9q9NAasaI105GsQgtaSPAUGd88J/vyX2ndG1nDOvxmgOo10tZFOnPHW7JnWMybk3PLza8o1ujA7X3JFdvDA8BPP9h6MVP4N7doCQ/n4Crts53HvEWlvcv5sBNu61WYlSTBzf1qNwBKMyN2E0rNubsxKmW8B6jLdWYdlx57nyTRPraNKGE1fnUW5nWRZGax3F1tQRwEfpQMk22qgeUK0RYWsPgHFaPciKCA3dJX7t1k/ib9pyR4nc9SZnYw54KMhkAXPIVQ0iy0EpTAH1DNYV6v8zXCwjl+BdkhlY= diff --git a/blockchain/utxopool.go b/blockchain/utxopool.go index 036585059..cac48da40 100644 --- a/blockchain/utxopool.go +++ b/blockchain/utxopool.go @@ -5,6 +5,7 @@ import ( ) const ( + // MaxNumberOfTransactions is the max number of transaction per a block. MaxNumberOfTransactions = 100 ) @@ -16,9 +17,9 @@ type UTXOPool struct { } // VerifyTransactions verifies if a list of transactions valid. -func (utxopool *UTXOPool) VerifyTransactions(transactions []*Transaction) bool { +func (utxoPool *UTXOPool) VerifyTransactions(transactions []*Transaction) bool { spentTXOs := make(map[string]map[string]map[int]bool) - if utxopool != nil { + if utxoPool != nil { for _, tx := range transactions { inTotal := 0 // Calculate the sum of TxInput @@ -41,7 +42,7 @@ func (utxopool *UTXOPool) VerifyTransactions(transactions []*Transaction) bool { spentTXOs[in.Address][inTxID][index] = true // Sum the balance up to the inTotal. - if val, ok := utxopool.utxo[in.Address][inTxID][index]; ok { + if val, ok := utxoPool.utxo[in.Address][inTxID][index]; ok { inTotal += val } else { return false @@ -61,111 +62,114 @@ 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 - } +// VerifyOneTransaction 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 _, 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 - } - } +// UpdateOneTransaction updates utxoPool in respect to the new Transaction. +func (utxoPool *UTXOPool) UpdateOneTransaction(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 - } - return false +// VerifyOneTransactionAndUpdate verifies and update a valid transaction. +// Return false if the transaction is not valid. +func (utxoPool *UTXOPool) VerifyOneTransactionAndUpdate(tx *Transaction) bool { + if utxoPool.VerifyOneTransaction(tx) { + utxoPool.UpdateOneTransaction(tx) + return true + } + return false } // VerifyAndUpdate verifies a list of transactions and update utxoPool. -func (utxopool *UTXOPool) VerifyAndUpdate(transactions []*Transaction) bool { - if utxopool.VerifyTransactions(transactions) { - utxopool.Update(transactions) +func (utxoPool *UTXOPool) VerifyAndUpdate(transactions []*Transaction) bool { + if utxoPool.VerifyTransactions(transactions) { + utxoPool.Update(transactions) return true } return false } // Update utxo balances with a list of new transactions. -func (utxopool *UTXOPool) Update(transactions []*Transaction) { - if utxopool != nil { +func (utxoPool *UTXOPool) Update(transactions []*Transaction) { + if utxoPool != nil { for _, tx := range transactions { curTxID := hex.EncodeToString(tx.ID) // Remove for _, in := range tx.TxInput { inTxID := hex.EncodeToString(in.TxID) - delete(utxopool.utxo[in.Address][inTxID], in.TxOutputIndex) + 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][curTxID] = make(map[int]int) + if _, ok := utxoPool.utxo[out.Address]; !ok { + utxoPool.utxo[out.Address] = make(map[string]map[int]int) + utxoPool.utxo[out.Address][curTxID] = make(map[int]int) } - if _, ok := utxopool.utxo[out.Address][curTxID]; !ok { - utxopool.utxo[out.Address][curTxID] = make(map[int]int) + if _, ok := utxoPool.utxo[out.Address][curTxID]; !ok { + utxoPool.utxo[out.Address][curTxID] = make(map[int]int) } - utxopool.utxo[out.Address][curTxID][index] = out.Value + utxoPool.utxo[out.Address][curTxID][index] = out.Value } } } @@ -191,13 +195,14 @@ func CreateUTXOPoolFromGenesisBlockChain(bc *Blockchain) *UTXOPool { } // 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) - } +func (utxoPool *UTXOPool) SelectTransactionsForNewBlock(transactions []*Transaction) ([]*Transaction, []*Transaction) { + selected, unselected := []*Transaction{}, []*Transaction{} + for _, tx := range transactions { + if len(selected) < MaxNumberOfTransactions && utxoPool.VerifyOneTransactionAndUpdate(tx) { + selected = append(selected, tx) + } else { + unselected = append(unselected, tx) + } } + return selected, unselected } diff --git a/blockchain/utxopool_test.go b/blockchain/utxopool_test.go index 4e76f322e..c47fb4b24 100644 --- a/blockchain/utxopool_test.go +++ b/blockchain/utxopool_test.go @@ -4,8 +4,20 @@ import ( "testing" ) -func TestVerifyTransactions(t *testing.T) { - if cbtx := NewCoinbaseTX("minh", genesisCoinbaseData); cbtx == nil { - t.Errorf("failed to create a coinbase transaction.") +func TestVerifyOneTransactionAndUpdate(t *testing.T) { + bc := CreateBlockchain("minh") + utxoPool := CreateUTXOPoolFromGenesisBlockChain(bc) + + bc.AddNewUserTransfer(utxoPool, "minh", "alok", 3) + bc.AddNewUserTransfer(utxoPool, "minh", "rj", 100) + + tx := bc.NewUTXOTransaction("minh", "mark", 10) + if tx == nil { + t.Error("failed to create a new transaction.") } + + // if utxoPool.VerifyOneTransaction(tx) { + // t.Error("failed to verify a valid transaction.") + // } + }