|
|
|
@ -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.
|
|
|
|
|