diff --git a/client/txgen/main.go b/client/txgen/main.go index f3b344c36..bc15124f6 100644 --- a/client/txgen/main.go +++ b/client/txgen/main.go @@ -28,6 +28,21 @@ var ( setting txGenSettings ) +type TxInfo struct { + // Global Input + shardID int + dataNodes []*node.Node + // Temp Input + id [32]byte + index int + value int + address string + // Output + txs []*blockchain.Transaction + crossTxs []*blockchain.Transaction + txCount int +} + // Generates at most "maxNumTxs" number of simulated transactions based on the current UtxoPools of all shards. // The transactions are generated by going through the existing utxos and // randomly select a subset of them as the input for each new transaction. The output @@ -59,11 +74,12 @@ func generateSimulatedTransactions(shardId int, dataNodes []*node.Node) ([]*bloc ] ] */ - var txs []*blockchain.Transaction - var crossTxs []*blockchain.Transaction - txsCount := 0 utxoPoolMutex.Lock() + txInfo := TxInfo{} + txInfo.shardID = shardId + txInfo.dataNodes = dataNodes + txInfo.txCount = 0 UTXOLOOP: // Loop over all addresses @@ -75,12 +91,14 @@ UTXOLOOP: if err != nil { continue } - txId := [32]byte{} - copy(txId[:], id[:]) + copy(txInfo.id[:], id[:]) + txInfo.address = address // Loop over all utxos for the txId for index, value := range utxoMap { - if txsCount >= setting.maxNumTxsPerBatch { + txInfo.index = index + txInfo.value = value + if txInfo.txCount >= setting.maxNumTxsPerBatch { break UTXOLOOP } randNum := rand.Intn(100) @@ -90,78 +108,86 @@ UTXOLOOP: continue } if setting.crossShard && randNum < 10 { // 1/3 cross shard transactions: add another txinput from another shard - // shard with neighboring Id - crossShardId := (int(dataNodes[shardId].Consensus.ShardID) + 1) % len(dataNodes) - - crossShardNode := dataNodes[crossShardId] - crossShardUtxosMap := crossShardNode.UtxoPool.UtxoMap[address] - - // Get the cross shard utxo from another shard - var crossTxin *blockchain.TXInput - crossUtxoValue := 0 - // Loop over utxos for the same address from the other shard and use the first utxo as the second cross tx input - for crossTxIdStr, crossShardUtxos := range crossShardUtxosMap { - // Parse TxId - id, err := hex.DecodeString(crossTxIdStr) - if err != nil { - continue - } - crossTxId := [32]byte{} - copy(crossTxId[:], id[:]) - - for crossShardIndex, crossShardValue := range crossShardUtxos { - crossUtxoValue = crossShardValue - crossTxin = &blockchain.TXInput{crossTxId, crossShardIndex, address, uint32(crossShardId)} - break - } - if crossTxin != nil { - break - } - } - - // Add the utxo from current shard - txin := blockchain.TXInput{txId, index, address, dataNodes[shardId].Consensus.ShardID} - txInputs := []blockchain.TXInput{txin} + generateCrossShardTx(txInfo) + } else { + generateSingleShardTx(txInfo) + } + } + } + } + utxoPoolMutex.Unlock() - // Add the utxo from the other shard, if any - if crossTxin != nil { - txInputs = append(txInputs, *crossTxin) - } + return txInfo.txs, txInfo.crossTxs +} - // Spend the utxo from the current shard to a random address in [0 - N) - txout := blockchain.TXOutput{value, strconv.Itoa(rand.Intn(setting.numOfAddress)), dataNodes[shardId].Consensus.ShardID} - txOutputs := []blockchain.TXOutput{txout} +func generateCrossShardTx(txInfo TxInfo) { + // shard with neighboring Id + crossShardId := (int(txInfo.dataNodes[txInfo.shardID].Consensus.ShardID) + 1) % len(txInfo.dataNodes) + + crossShardNode := txInfo.dataNodes[crossShardId] + crossShardUtxosMap := crossShardNode.UtxoPool.UtxoMap[txInfo.address] + + // Get the cross shard utxo from another shard + var crossTxin *blockchain.TXInput + crossUtxoValue := 0 + // Loop over utxos for the same address from the other shard and use the first utxo as the second cross tx input + for crossTxIdStr, crossShardUtxos := range crossShardUtxosMap { + // Parse TxId + id, err := hex.DecodeString(crossTxIdStr) + if err != nil { + continue + } + crossTxId := [32]byte{} + copy(crossTxId[:], id[:]) - // Spend the utxo from the other shard, if any, to a random address in [0 - N) - if crossTxin != nil { - crossTxout := blockchain.TXOutput{crossUtxoValue, strconv.Itoa(rand.Intn(setting.numOfAddress)), uint32(crossShardId)} - txOutputs = append(txOutputs, crossTxout) - } + for crossShardIndex, crossShardValue := range crossShardUtxos { + crossUtxoValue = crossShardValue + crossTxin = &blockchain.TXInput{crossTxId, crossShardIndex, txInfo.address, uint32(crossShardId)} + break + } + if crossTxin != nil { + break + } + } - // Construct the new transaction - tx := blockchain.Transaction{[32]byte{}, txInputs, txOutputs, nil} - tx.SetID() + // Add the utxo from current shard + txin := blockchain.TXInput{txInfo.id, txInfo.index, txInfo.address, txInfo.dataNodes[txInfo.shardID].Consensus.ShardID} + txInputs := []blockchain.TXInput{txin} - crossTxs = append(crossTxs, &tx) - txsCount++ - } else { - // Add the utxo as new tx input - txin := blockchain.TXInput{txId, index, address, dataNodes[shardId].Consensus.ShardID} + // Add the utxo from the other shard, if any + if crossTxin != nil { + txInputs = append(txInputs, *crossTxin) + } - // Spend the utxo to a random address in [0 - N) - txout := blockchain.TXOutput{value, strconv.Itoa(rand.Intn(setting.numOfAddress)), dataNodes[shardId].Consensus.ShardID} - tx := blockchain.Transaction{[32]byte{}, []blockchain.TXInput{txin}, []blockchain.TXOutput{txout}, nil} - tx.SetID() + // Spend the utxo from the current shard to a random address in [0 - N) + txout := blockchain.TXOutput{txInfo.value, strconv.Itoa(rand.Intn(setting.numOfAddress)), txInfo.dataNodes[txInfo.shardID].Consensus.ShardID} + txOutputs := []blockchain.TXOutput{txout} - txs = append(txs, &tx) - txsCount++ - } - } - } + // Spend the utxo from the other shard, if any, to a random address in [0 - N) + if crossTxin != nil { + crossTxout := blockchain.TXOutput{crossUtxoValue, strconv.Itoa(rand.Intn(setting.numOfAddress)), uint32(crossShardId)} + txOutputs = append(txOutputs, crossTxout) } - utxoPoolMutex.Unlock() - return txs, crossTxs + // Construct the new transaction + tx := blockchain.Transaction{[32]byte{}, txInputs, txOutputs, nil} + tx.SetID() + + txInfo.crossTxs = append(txInfo.crossTxs, &tx) + txInfo.txCount++ +} + +func generateSingleShardTx(txInfo TxInfo) { + // Add the utxo as new tx input + txin := blockchain.TXInput{txInfo.id, txInfo.index, txInfo.address, txInfo.dataNodes[txInfo.shardID].Consensus.ShardID} + + // Spend the utxo to a random address in [0 - N) + txout := blockchain.TXOutput{txInfo.value, strconv.Itoa(rand.Intn(setting.numOfAddress)), txInfo.dataNodes[txInfo.shardID].Consensus.ShardID} + tx := blockchain.Transaction{[32]byte{}, []blockchain.TXInput{txin}, []blockchain.TXOutput{txout}, nil} + tx.SetID() + + txInfo.txs = append(txInfo.txs, &tx) + txInfo.txCount++ } // A utility func that counts the total number of utxos in a pool.