fixed null outpoint issue; make outpoint.index uint32.

pull/54/head
Richard Liu 6 years ago
parent 09286bb82a
commit 5ad778781e
  1. 10
      blockchain/blockchain.go
  2. 15
      blockchain/transaction.go
  3. 50
      blockchain/utxopool.go
  4. 6
      client/btctxgen/main.go
  5. 2
      client/txgen/main.go

@ -23,7 +23,7 @@ func (bc *Blockchain) GetLatestBlock() *Block {
// FindUnspentTransactions returns a list of transactions containing unspent outputs
func (bc *Blockchain) FindUnspentTransactions(address string) []Transaction {
var unspentTXs []Transaction
spentTXOs := make(map[string][]int)
spentTXOs := make(map[string][]uint32)
for index := len(bc.Blocks) - 1; index >= 0; index-- {
block := bc.Blocks[index]
@ -37,7 +37,7 @@ func (bc *Blockchain) FindUnspentTransactions(address string) []Transaction {
idx = 0
}
for outIdx, txOutput := range tx.TxOutput {
if idx >= 0 && spentTXOs[txID][idx] == outIdx {
if idx >= 0 && spentTXOs[txID][idx] == uint32(outIdx) {
idx++
continue
}
@ -78,8 +78,8 @@ func (bc *Blockchain) FindUTXO(address string) []TXOutput {
}
// 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)
func (bc *Blockchain) FindSpendableOutputs(address string, amount int) (int, map[string][]uint32) {
unspentOutputs := make(map[string][]uint32)
unspentTXs := bc.FindUnspentTransactions(address)
accumulated := 0
@ -90,7 +90,7 @@ Work:
for outIdx, txOutput := range tx.TxOutput {
if txOutput.Address == address && accumulated < amount {
accumulated += txOutput.Value
unspentOutputs[txID] = append(unspentOutputs[txID], outIdx)
unspentOutputs[txID] = append(unspentOutputs[txID], uint32(outIdx))
if accumulated >= amount {
break Work

@ -7,9 +7,16 @@ import (
"encoding/hex"
"fmt"
"log"
"math"
)
var (
// zeroHash is the zero value for a Hash and is defined as
// a package level variable to avoid the need to create a new instance
// every time a check is needed.
zeroHash Hash
)
// Transaction represents a Bitcoin transaction
type Transaction struct {
ID [32]byte // 32 byte hash
TxInput []TXInput
@ -33,12 +40,12 @@ type Hash = [32]byte
// Index is the index of the transaction ouput in the previous transaction
type OutPoint struct {
Hash Hash
Index int
Index uint32
}
// NewOutPoint returns a new transaction outpoint point with the
// provided hash and index.
func NewOutPoint(hash *Hash, index int) *OutPoint {
func NewOutPoint(hash *Hash, index uint32) *OutPoint {
return &OutPoint{
Hash: *hash,
Index: index,
@ -102,7 +109,7 @@ func NewCoinbaseTX(to, data string, shardID uint32) *Transaction {
data = fmt.Sprintf("Reward to '%s'", to)
}
txin := NewTXInput(nil, to, shardID)
txin := NewTXInput(NewOutPoint(&Hash{}, math.MaxUint32), to, shardID)
txout := TXOutput{DefaultCoinbaseValue, to, shardID}
tx := Transaction{[32]byte{}, []TXInput{*txin}, []TXOutput{txout}, nil}
tx.SetID()

@ -25,15 +25,15 @@ type UTXOPool struct {
]
]
*/
UtxoMap map[string]map[string]map[int]int
LockedUtxoMap map[string]map[string]map[int]int
UtxoMap map[string]map[string]map[uint32]int
LockedUtxoMap map[string]map[string]map[uint32]int
ShardId uint32
mutex sync.Mutex
}
// VerifyTransactions verifies if a list of transactions valid for this shard.
func (utxoPool *UTXOPool) VerifyTransactions(transactions []*Transaction) bool {
spentTXOs := make(map[string]map[string]map[int]bool)
spentTXOs := make(map[string]map[string]map[uint32]bool)
if utxoPool != nil {
for _, tx := range transactions {
if valid, crossShard := utxoPool.VerifyOneTransaction(tx, &spentTXOs); !crossShard && !valid {
@ -45,13 +45,13 @@ func (utxoPool *UTXOPool) VerifyTransactions(transactions []*Transaction) bool {
}
// VerifyOneTransaction verifies if a list of transactions valid.
func (utxoPool *UTXOPool) VerifyOneTransaction(tx *Transaction, spentTXOs *map[string]map[string]map[int]bool) (valid, crossShard bool) {
func (utxoPool *UTXOPool) VerifyOneTransaction(tx *Transaction, spentTXOs *map[string]map[string]map[uint32]bool) (valid, crossShard bool) {
if len(tx.Proofs) != 0 {
return utxoPool.VerifyUnlockTransaction(tx)
}
if spentTXOs == nil {
spentTXOs = &map[string]map[string]map[int]bool{}
spentTXOs = &map[string]map[string]map[uint32]bool{}
}
inTotal := 0
// Calculate the sum of TxInput
@ -72,10 +72,10 @@ func (utxoPool *UTXOPool) VerifyOneTransaction(tx *Transaction, spentTXOs *map[s
}
// Mark the transactions with the address and index spent.
if _, ok := (*spentTXOs)[in.Address]; !ok {
(*spentTXOs)[in.Address] = make(map[string]map[int]bool)
(*spentTXOs)[in.Address] = make(map[string]map[uint32]bool)
}
if _, ok := (*spentTXOs)[in.Address][inTxID]; !ok {
(*spentTXOs)[in.Address][inTxID] = make(map[int]bool)
(*spentTXOs)[in.Address][inTxID] = make(map[uint32]bool)
}
(*spentTXOs)[in.Address][inTxID][index] = true
@ -193,11 +193,11 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
// put the delete (locked) utxo into a separate locked utxo pool
inTxID := hex.EncodeToString(in.PreviousOutPoint.Hash[:])
if _, ok := utxoPool.LockedUtxoMap[in.Address]; !ok {
utxoPool.LockedUtxoMap[in.Address] = make(map[string]map[int]int)
utxoPool.LockedUtxoMap[in.Address][inTxID] = make(map[int]int)
utxoPool.LockedUtxoMap[in.Address] = make(map[string]map[uint32]int)
utxoPool.LockedUtxoMap[in.Address][inTxID] = make(map[uint32]int)
}
if _, ok := utxoPool.LockedUtxoMap[in.Address][inTxID]; !ok {
utxoPool.LockedUtxoMap[in.Address][inTxID] = make(map[int]int)
utxoPool.LockedUtxoMap[in.Address][inTxID] = make(map[uint32]int)
}
utxoPool.LockedUtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index] = value
}
@ -219,11 +219,11 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
// Simply bring back the locked (removed) utxo
inTxID := hex.EncodeToString(in.PreviousOutPoint.Hash[:])
if _, ok := utxoPool.UtxoMap[in.Address]; !ok {
utxoPool.UtxoMap[in.Address] = make(map[string]map[int]int)
utxoPool.UtxoMap[in.Address][inTxID] = make(map[int]int)
utxoPool.UtxoMap[in.Address] = make(map[string]map[uint32]int)
utxoPool.UtxoMap[in.Address][inTxID] = make(map[uint32]int)
}
if _, ok := utxoPool.UtxoMap[in.Address][inTxID]; !ok {
utxoPool.UtxoMap[in.Address][inTxID] = make(map[int]int)
utxoPool.UtxoMap[in.Address][inTxID] = make(map[uint32]int)
}
value := utxoPool.LockedUtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index]
utxoPool.UtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index] = value
@ -239,13 +239,13 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
continue
}
if _, ok := utxoPool.UtxoMap[out.Address]; !ok {
utxoPool.UtxoMap[out.Address] = make(map[string]map[int]int)
utxoPool.UtxoMap[out.Address][txID] = make(map[int]int)
utxoPool.UtxoMap[out.Address] = make(map[string]map[uint32]int)
utxoPool.UtxoMap[out.Address][txID] = make(map[uint32]int)
}
if _, ok := utxoPool.UtxoMap[out.Address][txID]; !ok {
utxoPool.UtxoMap[out.Address][txID] = make(map[int]int)
utxoPool.UtxoMap[out.Address][txID] = make(map[uint32]int)
}
utxoPool.UtxoMap[out.Address][txID][index] = out.Value
utxoPool.UtxoMap[out.Address][txID][uint32(index)] = out.Value
}
}
} // If it's a cross shard locking Tx, then don't update so the input UTXOs are locked (removed), and the money is not spendable until unlock-to-commit or unlock-to-abort
@ -275,12 +275,12 @@ func (utxoPool *UTXOPool) VerifyAndUpdate(transactions []*Transaction) bool {
func CreateUTXOPoolFromTransaction(tx *Transaction, shardId uint32) *UTXOPool {
var utxoPool UTXOPool
txID := hex.EncodeToString(tx.ID[:])
utxoPool.UtxoMap = make(map[string]map[string]map[int]int)
utxoPool.LockedUtxoMap = make(map[string]map[string]map[int]int)
utxoPool.UtxoMap = make(map[string]map[string]map[uint32]int)
utxoPool.LockedUtxoMap = make(map[string]map[string]map[uint32]int)
for index, out := range tx.TxOutput {
utxoPool.UtxoMap[out.Address] = make(map[string]map[int]int)
utxoPool.UtxoMap[out.Address][txID] = make(map[int]int)
utxoPool.UtxoMap[out.Address][txID][index] = out.Value
utxoPool.UtxoMap[out.Address] = make(map[string]map[uint32]int)
utxoPool.UtxoMap[out.Address][txID] = make(map[uint32]int)
utxoPool.UtxoMap[out.Address][txID][uint32(index)] = out.Value
}
utxoPool.ShardId = shardId
return &utxoPool
@ -296,7 +296,7 @@ func CreateUTXOPoolFromGenesisBlockChain(bc *Blockchain) *UTXOPool {
// SelectTransactionsForNewBlock returns a list of index of valid transactions for the new block.
func (utxoPool *UTXOPool) SelectTransactionsForNewBlock(transactions []*Transaction, maxNumTxs int) ([]*Transaction, []*Transaction, []*CrossShardTxAndProof) {
selected, unselected, crossShardTxs := []*Transaction{}, []*Transaction{}, []*CrossShardTxAndProof{}
spentTXOs := make(map[string]map[string]map[int]bool)
spentTXOs := make(map[string]map[string]map[uint32]bool)
for _, tx := range transactions {
valid, crossShard := utxoPool.VerifyOneTransaction(tx, &spentTXOs)
@ -330,7 +330,7 @@ func getShardTxInput(transaction *Transaction, shardID uint32) []TXInput {
}
// DeleteOneBalanceItem deletes one balance item of UTXOPool and clean up if possible.
func (utxoPool *UTXOPool) DeleteOneUtxo(address, txID string, index int) {
func (utxoPool *UTXOPool) DeleteOneUtxo(address, txID string, index uint32) {
delete(utxoPool.UtxoMap[address][txID], index)
if len(utxoPool.UtxoMap[address][txID]) == 0 {
delete(utxoPool.UtxoMap[address], txID)
@ -341,7 +341,7 @@ func (utxoPool *UTXOPool) DeleteOneUtxo(address, txID string, index int) {
}
// DeleteOneBalanceItem deletes one balance item of UTXOPool and clean up if possible.
func (utxoPool *UTXOPool) DeleteOneLockedUtxo(address, txID string, index int) {
func (utxoPool *UTXOPool) DeleteOneLockedUtxo(address, txID string, index uint32) {
delete(utxoPool.LockedUtxoMap[address][txID], index)
if len(utxoPool.LockedUtxoMap[address][txID]) == 0 {
delete(utxoPool.LockedUtxoMap[address], txID)

@ -12,6 +12,7 @@ import (
"harmony-benchmark/node"
"harmony-benchmark/p2p"
proto_node "harmony-benchmark/proto/node"
"math"
"sync"
"time"
@ -77,8 +78,7 @@ LOOP:
tx := blockchain.Transaction{}
isCrossShardTx := false
if btcTx.IsCoinBase() {
// TODO: merge txID with txIndex in TxInput
tx.TxInput = []blockchain.TXInput{*blockchain.NewTXInput(nil, "", nodeShardID)}
tx.TxInput = []blockchain.TXInput{*blockchain.NewTXInput(blockchain.NewOutPoint(&blockchain.Hash{}, math.MaxUint32), "", nodeShardID)}
} else {
for _, btcTXI := range btcTx.TxIn {
btcTXIDStr := btc.NewUint256(btcTXI.Input.Hash[:]).String()
@ -86,7 +86,7 @@ LOOP:
if txRef.shardID != nodeShardID {
isCrossShardTx = true
}
tx.TxInput = append(tx.TxInput, *blockchain.NewTXInput(blockchain.NewOutPoint(&txRef.txID, int(btcTXI.Input.Vout)), "", txRef.shardID))
tx.TxInput = append(tx.TxInput, *blockchain.NewTXInput(blockchain.NewOutPoint(&txRef.txID, btcTXI.Input.Vout), "", txRef.shardID))
}
}

@ -35,7 +35,7 @@ type TxInfo struct {
dataNodes []*node.Node
// Temp Input
id [32]byte
index int
index uint32
value int
address string
// Output

Loading…
Cancel
Save