add outpoint

pull/54/head
Richard Liu 6 years ago
parent 762b6ec219
commit 09286bb82a
  1. 18
      blockchain/blockchain.go
  2. 49
      blockchain/transaction.go
  3. 40
      blockchain/utxopool.go
  4. 4
      client/btctxgen/main.go
  5. 10
      client/txgen/main.go

@ -51,8 +51,8 @@ func (bc *Blockchain) FindUnspentTransactions(address string) []Transaction {
for _, txInput := range tx.TxInput {
if address == txInput.Address {
ID := hex.EncodeToString(txInput.TxID[:])
spentTXOs[ID] = append(spentTXOs[ID], txInput.TxOutputIndex)
ID := hex.EncodeToString(txInput.PreviousOutPoint.Hash[:])
spentTXOs[ID] = append(spentTXOs[ID], txInput.PreviousOutPoint.Index)
}
}
}
@ -103,7 +103,7 @@ Work:
}
// NewUTXOTransaction creates a new transaction
func (bc *Blockchain) NewUTXOTransaction(from, to string, amount int, shardId uint32) *Transaction {
func (bc *Blockchain) NewUTXOTransaction(from, to string, amount int, shardID uint32) *Transaction {
var inputs []TXInput
var outputs []TXOutput
@ -120,18 +120,18 @@ func (bc *Blockchain) NewUTXOTransaction(from, to string, amount int, shardId ui
return nil
}
txId := [32]byte{}
copy(txId[:], id[:])
txID := Hash{}
copy(txID[:], id[:])
for _, out := range outs {
input := TXInput{txId, out, from, shardId}
inputs = append(inputs, input)
input := NewTXInput(NewOutPoint(&txID, out), from, shardID)
inputs = append(inputs, *input)
}
}
// Build a list of outputs
outputs = append(outputs, TXOutput{amount, to, shardId})
outputs = append(outputs, TXOutput{amount, to, shardID})
if acc > amount {
outputs = append(outputs, TXOutput{acc - amount, from, shardId}) // a change
outputs = append(outputs, TXOutput{acc - amount, from, shardID}) // a change
}
tx := Transaction{[32]byte{}, inputs, outputs, nil}

@ -25,12 +25,41 @@ type TXOutput struct {
ShardId uint32 // The Id of the shard where this UTXO belongs
}
type Hash = [32]byte
// Output defines a data type that is used to track previous
// transaction outputs.
// Hash is the transaction id
// Index is the index of the transaction ouput in the previous transaction
type OutPoint struct {
Hash Hash
Index int
}
// NewOutPoint returns a new transaction outpoint point with the
// provided hash and index.
func NewOutPoint(hash *Hash, index int) *OutPoint {
return &OutPoint{
Hash: *hash,
Index: index,
}
}
// TXInput is the struct of transaction input (a UTXO) in a transaction.
type TXInput struct {
TxID [32]byte
TxOutputIndex int
PreviousOutPoint OutPoint
Address string
ShardId uint32 // The Id of the shard where this UTXO belongs
ShardID uint32 // The Id of the shard where this UTXO belongs
}
// NewTXInput returns a new transaction input with the provided
// previous outpoint point, output address and shardID
func NewTXInput(prevOut *OutPoint, address string, shardID uint32) *TXInput {
return &TXInput{
PreviousOutPoint: *prevOut,
Address: address,
ShardID: shardID,
}
}
// The proof of accept or reject in the cross shard transaction locking phase.
@ -68,24 +97,24 @@ func (tx *Transaction) SetID() {
}
// NewCoinbaseTX creates a new coinbase transaction
func NewCoinbaseTX(to, data string, shardId uint32) *Transaction {
func NewCoinbaseTX(to, data string, shardID uint32) *Transaction {
if data == "" {
data = fmt.Sprintf("Reward to '%s'", to)
}
txin := TXInput{[32]byte{}, -1, data, shardId}
txout := TXOutput{DefaultCoinbaseValue, to, shardId}
tx := Transaction{[32]byte{}, []TXInput{txin}, []TXOutput{txout}, nil}
txin := NewTXInput(nil, to, shardID)
txout := TXOutput{DefaultCoinbaseValue, to, shardID}
tx := Transaction{[32]byte{}, []TXInput{*txin}, []TXOutput{txout}, nil}
tx.SetID()
return &tx
}
// Used for debuging.
func (txInput *TXInput) String() string {
res := fmt.Sprintf("TxID: %v, ", hex.EncodeToString(txInput.TxID[:]))
res += fmt.Sprintf("TxOutputIndex: %v, ", txInput.TxOutputIndex)
res := fmt.Sprintf("TxID: %v, ", hex.EncodeToString(txInput.PreviousOutPoint.Hash[:]))
res += fmt.Sprintf("TxOutputIndex: %v, ", txInput.PreviousOutPoint.Index)
res += fmt.Sprintf("Address: %v, ", txInput.Address)
res += fmt.Sprintf("Shard Id: %v", txInput.ShardId)
res += fmt.Sprintf("Shard Id: %v", txInput.ShardID)
return res
}

@ -57,13 +57,13 @@ func (utxoPool *UTXOPool) VerifyOneTransaction(tx *Transaction, spentTXOs *map[s
// Calculate the sum of TxInput
for _, in := range tx.TxInput {
// Only check the input for my own shard.
if in.ShardId != utxoPool.ShardId {
if in.ShardID != utxoPool.ShardId {
crossShard = true
continue
}
inTxID := hex.EncodeToString(in.TxID[:])
index := in.TxOutputIndex
inTxID := hex.EncodeToString(in.PreviousOutPoint.Hash[:])
index := in.PreviousOutPoint.Index
// Check if the transaction with the addres is spent or not.
if val, ok := (*spentTXOs)[in.Address][inTxID][index]; ok {
if val {
@ -150,7 +150,7 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
isCrossShard := false
// check whether it's a cross shard tx.
for _, in := range tx.TxInput {
if in.ShardId != utxoPool.ShardId {
if in.ShardID != utxoPool.ShardId {
isCrossShard = true
break
}
@ -161,11 +161,11 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
// Check whether for this shard this cross transaction is valid or not.
for _, in := range tx.TxInput {
// Only check the input for my own shard.
if in.ShardId != utxoPool.ShardId {
if in.ShardID != utxoPool.ShardId {
continue
}
inTxID := hex.EncodeToString(in.TxID[:])
if _, ok := utxoPool.UtxoMap[in.Address][inTxID][in.TxOutputIndex]; !ok {
inTxID := hex.EncodeToString(in.PreviousOutPoint.Hash[:])
if _, ok := utxoPool.UtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index]; !ok {
isValidCrossShard = false
}
}
@ -181,17 +181,17 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
if isValidCrossShard {
for _, in := range tx.TxInput {
// Only check the input for my own shard.
if in.ShardId != utxoPool.ShardId {
if in.ShardID != utxoPool.ShardId {
continue
}
// NOTE: for the locking phase of cross tx, the utxo is simply removed from the pool.
inTxID := hex.EncodeToString(in.TxID[:])
value := utxoPool.UtxoMap[in.Address][inTxID][in.TxOutputIndex]
utxoPool.DeleteOneUtxo(in.Address, inTxID, in.TxOutputIndex)
inTxID := hex.EncodeToString(in.PreviousOutPoint.Hash[:])
value := utxoPool.UtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index]
utxoPool.DeleteOneUtxo(in.Address, inTxID, in.PreviousOutPoint.Index)
if isCrossShard {
// put the delete (locked) utxo into a separate locked utxo pool
inTxID := hex.EncodeToString(in.TxID[:])
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)
@ -199,7 +199,7 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
if _, ok := utxoPool.LockedUtxoMap[in.Address][inTxID]; !ok {
utxoPool.LockedUtxoMap[in.Address][inTxID] = make(map[int]int)
}
utxoPool.LockedUtxoMap[in.Address][inTxID][in.TxOutputIndex] = value
utxoPool.LockedUtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index] = value
}
}
}
@ -212,12 +212,12 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
// unlock-to-abort, bring back (unlock) the utxo input
for _, in := range tx.TxInput {
// Only unlock the input for my own shard.
if in.ShardId != utxoPool.ShardId {
if in.ShardID != utxoPool.ShardId {
continue
}
// Simply bring back the locked (removed) utxo
inTxID := hex.EncodeToString(in.TxID[:])
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)
@ -225,10 +225,10 @@ func (utxoPool *UTXOPool) UpdateOneTransaction(tx *Transaction) {
if _, ok := utxoPool.UtxoMap[in.Address][inTxID]; !ok {
utxoPool.UtxoMap[in.Address][inTxID] = make(map[int]int)
}
value := utxoPool.LockedUtxoMap[in.Address][inTxID][in.TxOutputIndex]
utxoPool.UtxoMap[in.Address][inTxID][in.TxOutputIndex] = value
value := utxoPool.LockedUtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index]
utxoPool.UtxoMap[in.Address][inTxID][in.PreviousOutPoint.Index] = value
utxoPool.DeleteOneLockedUtxo(in.Address, inTxID, in.TxOutputIndex)
utxoPool.DeleteOneLockedUtxo(in.Address, inTxID, in.PreviousOutPoint.Index)
}
}
} else {
@ -319,10 +319,10 @@ func (utxoPool *UTXOPool) SelectTransactionsForNewBlock(transactions []*Transact
return selected, unselected, crossShardTxs
}
func getShardTxInput(transaction *Transaction, shardId uint32) []TXInput {
func getShardTxInput(transaction *Transaction, shardID uint32) []TXInput {
result := []TXInput{}
for _, txInput := range transaction.TxInput {
if txInput.ShardId == shardId {
if txInput.ShardID == shardID {
result = append(result, txInput)
}
}

@ -78,7 +78,7 @@ LOOP:
isCrossShardTx := false
if btcTx.IsCoinBase() {
// TODO: merge txID with txIndex in TxInput
tx.TxInput = []blockchain.TXInput{blockchain.TXInput{[32]byte{}, -1, "", nodeShardID}}
tx.TxInput = []blockchain.TXInput{*blockchain.NewTXInput(nil, "", 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.TXInput{txRef.txID, int(btcTXI.Input.Vout), "", txRef.shardID})
tx.TxInput = append(tx.TxInput, *blockchain.NewTXInput(blockchain.NewOutPoint(&txRef.txID, int(btcTXI.Input.Vout)), "", txRef.shardID))
}
}

@ -145,7 +145,7 @@ func generateCrossShardTx(txInfo *TxInfo) {
for crossShardIndex, crossShardValue := range crossShardUtxos {
crossUtxoValue = crossShardValue
crossTxin = &blockchain.TXInput{crossTxId, crossShardIndex, txInfo.address, uint32(crossShardId)}
crossTxin = blockchain.NewTXInput(blockchain.NewOutPoint(&crossTxId, crossShardIndex), txInfo.address, uint32(crossShardId))
break
}
if crossTxin != nil {
@ -154,8 +154,8 @@ func generateCrossShardTx(txInfo *TxInfo) {
}
// Add the utxo from current shard
txin := blockchain.TXInput{txInfo.id, txInfo.index, txInfo.address, nodeShardID}
txInputs := []blockchain.TXInput{txin}
txIn := blockchain.NewTXInput(blockchain.NewOutPoint(&txInfo.id, txInfo.index), txInfo.address, nodeShardID)
txInputs := []blockchain.TXInput{*txIn}
// Add the utxo from the other shard, if any
if crossTxin != nil { // This means the ratio of cross shard tx could be lower than 1/3
@ -183,11 +183,11 @@ func generateCrossShardTx(txInfo *TxInfo) {
func generateSingleShardTx(txInfo *TxInfo) {
nodeShardID := txInfo.dataNodes[txInfo.shardID].Consensus.ShardID
// Add the utxo as new tx input
txin := blockchain.TXInput{txInfo.id, txInfo.index, txInfo.address, nodeShardID}
txin := blockchain.NewTXInput(blockchain.NewOutPoint(&txInfo.id, txInfo.index), txInfo.address, nodeShardID)
// Spend the utxo to a random address in [0 - N)
txout := blockchain.TXOutput{txInfo.value, strconv.Itoa(rand.Intn(setting.numOfAddress)), nodeShardID}
tx := blockchain.Transaction{[32]byte{}, []blockchain.TXInput{txin}, []blockchain.TXOutput{txout}, nil}
tx := blockchain.Transaction{[32]byte{}, []blockchain.TXInput{*txin}, []blockchain.TXOutput{txout}, nil}
tx.SetID()
txInfo.txs = append(txInfo.txs, &tx)

Loading…
Cancel
Save