|
|
|
@ -19,7 +19,16 @@ import ( |
|
|
|
|
"time" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var utxoPoolMutex sync.Mutex |
|
|
|
|
type txGenSettings struct { |
|
|
|
|
numOfAddress int |
|
|
|
|
crossShard bool |
|
|
|
|
maxNumTxsPerBatch int |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
utxoPoolMutex sync.Mutex |
|
|
|
|
setting txGenSettings |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
@ -35,12 +44,10 @@ var utxoPoolMutex sync.Mutex |
|
|
|
|
// Params:
|
|
|
|
|
// shardId - the shardId for current shard
|
|
|
|
|
// dataNodes - nodes containing utxopools of all shards
|
|
|
|
|
// maxNumTxs - the max number of txs to generate
|
|
|
|
|
// crossShard - whether to generate cross shard txs
|
|
|
|
|
// Returns:
|
|
|
|
|
// all single-shard txs
|
|
|
|
|
// all cross-shard txs
|
|
|
|
|
func generateSimulatedTransactions(shardId int, dataNodes []*node.Node, maxNumTxs int, crossShard bool) ([]*blockchain.Transaction, []*blockchain.Transaction) { |
|
|
|
|
func generateSimulatedTransactions(shardId int, dataNodes []*node.Node) ([]*blockchain.Transaction, []*blockchain.Transaction) { |
|
|
|
|
/* |
|
|
|
|
UTXO map structure: |
|
|
|
|
address - [ |
|
|
|
@ -75,80 +82,81 @@ UTXOLOOP: |
|
|
|
|
|
|
|
|
|
// Loop over all utxos for the txId
|
|
|
|
|
for index, value := range utxoMap { |
|
|
|
|
if txsCount >= maxNumTxs { |
|
|
|
|
if txsCount >= setting.maxNumTxsPerBatch { |
|
|
|
|
break UTXOLOOP |
|
|
|
|
} |
|
|
|
|
randNum := rand.Intn(100) |
|
|
|
|
|
|
|
|
|
// 30% sample rate to select UTXO to use for new transactions
|
|
|
|
|
if randNum < 30 { |
|
|
|
|
if crossShard && randNum < 10 { // 30% 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 |
|
|
|
|
} |
|
|
|
|
if randNum >= 30 { |
|
|
|
|
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[:]) |
|
|
|
|
|
|
|
|
|
// Add the utxo from current shard
|
|
|
|
|
txin := blockchain.TXInput{txId, index, address, dataNodes[shardId].Consensus.ShardID} |
|
|
|
|
txInputs := []blockchain.TXInput{txin} |
|
|
|
|
|
|
|
|
|
// Add the utxo from the other shard, if any
|
|
|
|
|
if crossTxin != nil { |
|
|
|
|
txInputs = append(txInputs, *crossTxin) |
|
|
|
|
for crossShardIndex, crossShardValue := range crossShardUtxos { |
|
|
|
|
crossUtxoValue = crossShardValue |
|
|
|
|
crossTxin = &blockchain.TXInput{crossTxId, crossShardIndex, address, uint32(crossShardId)} |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Spend the utxo from the current shard to a random address in [0 - N)
|
|
|
|
|
txout := blockchain.TXOutput{value, strconv.Itoa(rand.Intn(10000)), dataNodes[shardId].Consensus.ShardID} |
|
|
|
|
txOutputs := []blockchain.TXOutput{txout} |
|
|
|
|
|
|
|
|
|
// 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(10000)), uint32(crossShardId)} |
|
|
|
|
txOutputs = append(txOutputs, crossTxout) |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Construct the new transaction
|
|
|
|
|
tx := blockchain.Transaction{[32]byte{}, txInputs, txOutputs, nil} |
|
|
|
|
tx.SetID() |
|
|
|
|
// Add the utxo from current shard
|
|
|
|
|
txin := blockchain.TXInput{txId, index, address, dataNodes[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(10000)), 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{value, strconv.Itoa(rand.Intn(setting.numOfAddress)), dataNodes[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) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Construct the new transaction
|
|
|
|
|
tx := blockchain.Transaction{[32]byte{}, txInputs, txOutputs, nil} |
|
|
|
|
tx.SetID() |
|
|
|
|
|
|
|
|
|
crossTxs = append(crossTxs, &tx) |
|
|
|
|
txsCount++ |
|
|
|
|
} else { |
|
|
|
|
// Add the utxo as new tx input
|
|
|
|
|
txin := blockchain.TXInput{txId, index, address, dataNodes[shardId].Consensus.ShardID} |
|
|
|
|
|
|
|
|
|
// 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() |
|
|
|
|
|
|
|
|
|
txs = append(txs, &tx) |
|
|
|
|
txsCount++ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -250,8 +258,10 @@ func main() { |
|
|
|
|
config := readConfigFile(*configFile) |
|
|
|
|
leaders, shardIds := getLeadersAndShardIds(&config) |
|
|
|
|
|
|
|
|
|
setting.numOfAddress = 10000 |
|
|
|
|
// Do cross shard tx if there are more than one shard
|
|
|
|
|
crossShard := len(shardIds) > 1 |
|
|
|
|
setting.crossShard = len(shardIds) > 1 |
|
|
|
|
setting.maxNumTxsPerBatch = *maxNumTxsPerBatch |
|
|
|
|
|
|
|
|
|
// TODO(Richard): refactor this chuck to a single method
|
|
|
|
|
// Setup a logger to stdout and log file.
|
|
|
|
@ -267,8 +277,8 @@ func main() { |
|
|
|
|
nodes := []*node.Node{} |
|
|
|
|
for _, shardId := range shardIds { |
|
|
|
|
node := node.New(&consensus.Consensus{ShardID: shardId}) |
|
|
|
|
// Assign many fake addresses so we have enough address to place with at first
|
|
|
|
|
node.AddTestingAddresses(10000) |
|
|
|
|
// Assign many fake addresses so we have enough address to play with at first
|
|
|
|
|
node.AddTestingAddresses(setting.numOfAddress) |
|
|
|
|
nodes = append(nodes, node) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -321,7 +331,7 @@ func main() { |
|
|
|
|
allCrossTxs := []*blockchain.Transaction{} |
|
|
|
|
// Generate simulated transactions
|
|
|
|
|
for i, leader := range leaders { |
|
|
|
|
txs, crossTxs := generateSimulatedTransactions(i, nodes, *maxNumTxsPerBatch, crossShard) |
|
|
|
|
txs, crossTxs := generateSimulatedTransactions(i, nodes) |
|
|
|
|
allCrossTxs = append(allCrossTxs, crossTxs...) |
|
|
|
|
|
|
|
|
|
log.Debug("[Generator] Sending single-shard txs ...", "leader", leader, "numTxs", len(txs), "numCrossTxs", len(crossTxs)) |
|
|
|
|