@ -60,14 +60,14 @@ func printVersion(me string) {
// processing.
// processing.
var (
var (
ip = flag . String ( "ip" , "127.0.0.1" , "IP of the node" )
ip = flag . String ( "ip" , "127.0.0.1" , "IP of the node" )
port = flag . String ( "port" , "9999" , "port of the node." )
port = flag . String ( "port" , "9999" , "port of the node." )
maxNumTxsPerBatch = flag . Int ( "max_num_txs_per_batch" , 200 00 , "number of transactions to send per message" )
numTxns = flag . Int ( "numTxns" , 1 00 , "number of transactions to send per message" )
logFolder = flag . String ( "log_folder" , "latest" , "the folder collecting the logs of this execution" )
logFolder = flag . String ( "log_folder" , "latest" , "the folder collecting the logs of this execution" )
duration = flag . Int ( "duration" , 30 , "duration of the tx generation in second. If it's negative, the experiment runs forever." )
duration = flag . Int ( "duration" , 30 , "duration of the tx generation in second. If it's negative, the experiment runs forever." )
versionFlag = flag . Bool ( "version" , false , "Output version info" )
versionFlag = flag . Bool ( "version" , false , "Output version info" )
crossShardRatio = flag . Int ( "cross_shard_ratio" , 30 , "The percentage of cross shard transactions." ) //Keeping this for backward compatibility
crossShardRatio = flag . Int ( "cross_shard_ratio" , 30 , "The percentage of cross shard transactions." ) //Keeping this for backward compatibility
shardIDFlag = flag . Int ( "shardID" , 0 , "The shardID the node belongs to." )
shardIDFlag = flag . Int ( "shardID" , 0 , "The shardID the node belongs to." )
// Key file to store the private key
// Key file to store the private key
keyFile = flag . String ( "key" , "./.txgenkey" , "the private key file of the txgen" )
keyFile = flag . String ( "key" , "./.txgenkey" , "the private key file of the txgen" )
// logging verbosity
// logging verbosity
@ -117,9 +117,15 @@ func setUpTXGen() *node.Node {
consensusObj . PublicKeys = append ( consensusObj . PublicKeys , secretKey . GetPublicKey ( ) )
consensusObj . PublicKeys = append ( consensusObj . PublicKeys , secretKey . GetPublicKey ( ) )
}
}
txGen . NodeConfig . SetRole ( nodeconfig . ClientNode )
txGen . NodeConfig . SetRole ( nodeconfig . ClientNode )
txGen . NodeConfig . SetIsBeacon ( true )
if shardID == 0 {
txGen . NodeConfig . SetIsBeacon ( true )
txGen . NodeConfig . SetShardGroupID ( p2p . GroupIDBeacon )
} else {
txGen . NodeConfig . SetShardGroupID ( p2p . NewGroupIDByShardID ( p2p . ShardID ( shardID ) ) )
}
txGen . NodeConfig . SetIsClient ( true )
txGen . NodeConfig . SetIsClient ( true )
txGen . NodeConfig . SetShardGroupID ( p2p . GroupIDBeacon )
return txGen
return txGen
}
}
func main ( ) {
func main ( ) {
@ -143,8 +149,9 @@ func main() {
// Init with LibP2P enabled, FIXME: (leochen) right now we support only one shard
// Init with LibP2P enabled, FIXME: (leochen) right now we support only one shard
setting := Settings {
setting := Settings {
NumOfAddress : 10000 ,
NumOfAddress : 10000 ,
MaxNumTxsPerBatch : * maxNumTxsPerBatch ,
MaxNumTxsPerBatch : * numTxns ,
}
}
shardID := * shardIDFlag
utils . GetLogInstance ( ) . Debug ( "Cross Shard Ratio Is Set But not used" , "cx ratio" , * crossShardRatio )
utils . GetLogInstance ( ) . Debug ( "Cross Shard Ratio Is Set But not used" , "cx ratio" , * crossShardRatio )
// TODO(Richard): refactor this chuck to a single method
// TODO(Richard): refactor this chuck to a single method
@ -158,7 +165,6 @@ func main() {
txGen := setUpTXGen ( )
txGen := setUpTXGen ( )
txGen . ServiceManagerSetup ( )
txGen . ServiceManagerSetup ( )
txGen . RunServices ( )
txGen . RunServices ( )
time . Sleep ( 20 * time . Second )
start := time . Now ( )
start := time . Now ( )
totalTime := float64 ( * duration )
totalTime := float64 ( * duration )
utils . GetLogInstance ( ) . Debug ( "Total Duration" , "totalTime" , totalTime , "RunForever" , isDurationForever ( totalTime ) )
utils . GetLogInstance ( ) . Debug ( "Total Duration" , "totalTime" , totalTime , "RunForever" , isDurationForever ( totalTime ) )
@ -187,12 +193,14 @@ syncLoop:
for _ , block := range blocks {
for _ , block := range blocks {
shardID := block . ShardID ( )
shardID := block . ShardID ( )
if txGen . Consensus . ShardID == shardID {
if txGen . Consensus . ShardID == shardID {
utils . GetLogInstance ( ) . Info ( "Adding block from leader" , "txNum" , len ( block . Transactions ( ) ) , "shardID" , shardID , "preHash" , block . ParentHash ( ) . Hex ( ) , "currentBlock" , txGen . Blockchain ( ) . CurrentBlock ( ) . NumberU64 ( ) , "incoming block" , block . NumberU64 ( ) )
utils . GetLogInstance ( ) . Info ( "Got block from leader" , "txNum" , len ( block . Transactions ( ) ) , "shardID" , shardID , "preHash" , block . ParentHash ( ) . Hex ( ) , "currentBlock" , txGen . Blockchain ( ) . CurrentBlock ( ) . NumberU64 ( ) , "incoming block" , block . NumberU64 ( ) )
txGen . AddNewBlock ( block )
if block . NumberU64 ( ) - txGen . Blockchain ( ) . CurrentBlock ( ) . NumberU64 ( ) == 1 {
stateMutex . Lock ( )
txGen . AddNewBlock ( block )
txGen . Worker . UpdateCurrent ( )
stateMutex . Lock ( )
stateMutex . Unlock ( )
txGen . Worker . UpdateCurrent ( )
readySignal <- shardID
stateMutex . Unlock ( )
readySignal <- shardID
}
} else {
} else {
continue
continue
}
}
@ -203,8 +211,8 @@ syncLoop:
go func ( ) {
go func ( ) {
// wait for 3 seconds for client to send ping message to leader
// wait for 3 seconds for client to send ping message to leader
// FIXME (leo) the readySignal should be set once we really sent ping message to leader
// FIXME (leo) the readySignal should be set once we really sent ping message to leader
time . Sleep ( 3 * time . Second ) // wait for nodes to be ready
time . Sleep ( 1 * time . Second ) // wait for nodes to be ready
readySignal <- uint32 ( 0 )
readySignal <- uint32 ( shardID )
} ( )
} ( )
pushLoop :
pushLoop :
for {
for {
@ -214,6 +222,17 @@ pushLoop:
utils . GetLogInstance ( ) . Debug ( "Generator timer ended." , "duration" , ( int ( t . Sub ( start ) ) ) , "startTime" , start , "totalTime" , totalTime )
utils . GetLogInstance ( ) . Debug ( "Generator timer ended." , "duration" , ( int ( t . Sub ( start ) ) ) , "startTime" , start , "totalTime" , totalTime )
break pushLoop
break pushLoop
}
}
if shardID != 0 {
if otherHeight , flag := txGen . IsSameHeight ( ) ; flag {
if otherHeight >= 1 {
go func ( ) {
readySignal <- uint32 ( shardID )
utils . GetLogInstance ( ) . Debug ( "Same blockchain height so readySignal generated" )
time . Sleep ( 3 * time . Second ) // wait for nodes to be ready
} ( )
}
}
}
select {
select {
case shardID := <- readySignal :
case shardID := <- readySignal :
lock := sync . Mutex { }
lock := sync . Mutex { }
@ -223,7 +242,7 @@ pushLoop:
utils . GetLogInstance ( ) . Debug ( "Error in Generating Txns" , "Err" , err )
utils . GetLogInstance ( ) . Debug ( "Error in Generating Txns" , "Err" , err )
}
}
lock . Lock ( )
lock . Lock ( )
SendTxsToShard ( txGen , txs )
SendTxsToShard ( txGen , txs , uint32 ( shardID ) )
lock . Unlock ( )
lock . Unlock ( )
case <- time . After ( 10 * time . Second ) :
case <- time . After ( 10 * time . Second ) :
utils . GetLogInstance ( ) . Warn ( "No new block is received so far" )
utils . GetLogInstance ( ) . Warn ( "No new block is received so far" )
@ -232,9 +251,15 @@ pushLoop:
}
}
// SendTxsToShard sends txs to shard, currently just to beacon shard
// SendTxsToShard sends txs to shard, currently just to beacon shard
func SendTxsToShard ( clientNode * node . Node , txs types . Transactions ) {
func SendTxsToShard ( clientNode * node . Node , txs types . Transactions , shardID uint32 ) {
msg := proto_node . ConstructTransactionListMessageAccount ( txs )
msg := proto_node . ConstructTransactionListMessageAccount ( txs )
err := clientNode . GetHost ( ) . SendMessageToGroups ( [ ] p2p . GroupID { p2p . GroupIDBeaconClient } , p2p_host . ConstructP2pMessage ( byte ( 0 ) , msg ) )
var err error
if shardID == 0 {
err = clientNode . GetHost ( ) . SendMessageToGroups ( [ ] p2p . GroupID { p2p . GroupIDBeaconClient } , p2p_host . ConstructP2pMessage ( byte ( 0 ) , msg ) )
} else {
clientGroup := p2p . NewClientGroupIDByShardID ( p2p . ShardID ( shardID ) )
err = clientNode . GetHost ( ) . SendMessageToGroups ( [ ] p2p . GroupID { clientGroup } , p2p_host . ConstructP2pMessage ( byte ( 0 ) , msg ) )
}
if err != nil {
if err != nil {
utils . GetLogInstance ( ) . Debug ( "Error in Sending Txns" , "Err" , err )
utils . GetLogInstance ( ) . Debug ( "Error in Sending Txns" , "Err" , err )
}
}
@ -242,14 +267,24 @@ func SendTxsToShard(clientNode *node.Node, txs types.Transactions) {
// GenerateSimulatedTransactionsAccount generates simulated transaction for account model.
// GenerateSimulatedTransactionsAccount generates simulated transaction for account model.
func GenerateSimulatedTransactionsAccount ( shardID uint32 , node * node . Node , setting Settings ) ( types . Transactions , error ) {
func GenerateSimulatedTransactionsAccount ( shardID uint32 , node * node . Node , setting Settings ) ( types . Transactions , error ) {
_ = setting // TODO: make use of settings
TxnsToGenerate := setting . MaxNumTxsPerBatch // TODO: make use of settings
txs := make ( [ ] * types . Transaction , 100 )
txs := make ( [ ] * types . Transaction , TxnsToGenerate )
rounds := ( TxnsToGenerate / 100 )
remainder := TxnsToGenerate % 100
for i := 0 ; i < 100 ; i ++ {
for i := 0 ; i < 100 ; i ++ {
baseNonce := node . Worker . GetCurrentState ( ) . GetNonce ( crypto . PubkeyToAddress ( node . TestBankKeys [ i ] . PublicKey ) )
baseNonce := node . Worker . GetCurrentState ( ) . GetNonce ( crypto . PubkeyToAddress ( node . TestBankKeys [ i ] . PublicKey ) )
randomUserAddress := crypto . PubkeyToAddress ( node . TestBankKeys [ rand . Intn ( 100 ) ] . PublicKey )
for j := 0 ; j < rounds ; j ++ {
randAmount := rand . Float32 ( )
randomUserAddress := crypto . PubkeyToAddress ( node . TestBankKeys [ rand . Intn ( 100 ) ] . PublicKey )
tx , _ := types . SignTx ( types . NewTransaction ( baseNonce + uint64 ( 0 ) , randomUserAddress , shardID , big . NewInt ( int64 ( params . Ether * randAmount ) ) , params . TxGas , nil , nil ) , types . HomesteadSigner { } , node . TestBankKeys [ i ] )
randAmount := rand . Float32 ( )
txs [ i ] = tx
tx , _ := types . SignTx ( types . NewTransaction ( baseNonce + uint64 ( j ) , randomUserAddress , shardID , big . NewInt ( int64 ( params . Ether * randAmount ) ) , params . TxGas , nil , nil ) , types . HomesteadSigner { } , node . TestBankKeys [ i ] )
txs [ 100 * j + i ] = tx
}
if i < remainder {
randomUserAddress := crypto . PubkeyToAddress ( node . TestBankKeys [ rand . Intn ( 100 ) ] . PublicKey )
randAmount := rand . Float32 ( )
tx , _ := types . SignTx ( types . NewTransaction ( baseNonce + uint64 ( rounds ) , randomUserAddress , shardID , big . NewInt ( int64 ( params . Ether * randAmount ) ) , params . TxGas , nil , nil ) , types . HomesteadSigner { } , node . TestBankKeys [ i ] )
txs [ 100 * rounds + i ] = tx
}
}
}
return txs , nil
return txs , nil
}
}