github.com/annchain/OG@v0.0.9/benchmark/auto/auto_client.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package auto 15 16 import ( 17 "encoding/json" 18 "fmt" 19 "github.com/annchain/OG/arefactor/common/goroutine" 20 "github.com/annchain/OG/common/crypto" 21 "github.com/annchain/OG/consensus/campaign" 22 "github.com/annchain/OG/node" 23 "github.com/annchain/OG/og/types" 24 "github.com/annchain/OG/og/types/archive" 25 core2 "github.com/annchain/OG/ogcore/ledger" 26 "math/rand" 27 "sync" 28 "time" 29 30 "github.com/spf13/viper" 31 32 "github.com/annchain/OG/account" 33 "github.com/annchain/OG/common/math" 34 "github.com/annchain/OG/types" 35 "github.com/sirupsen/logrus" 36 ) 37 38 const ( 39 IntervalModeConstantInterval = "constant" 40 IntervalModeRandom = "random" 41 ) 42 43 type AutoClient struct { 44 SampleAccounts []*account.Account 45 MyIndex int //only for debug 46 MyAccount *account.Account //if MyAccount is 47 SequencerIntervalUs int 48 TxIntervalUs int 49 ArchiveInterValUs int 50 IntervalMode string 51 NonceSelfDiscipline bool 52 AutoSequencerEnabled bool 53 CampainEnable bool 54 AutoTxEnabled bool 55 AutoArchiveEnabled bool 56 57 Delegate *node.Delegate 58 59 ManualChan chan types.TxBaseType 60 quit chan bool 61 62 pause bool 63 64 wg sync.WaitGroup 65 66 nonceLock sync.RWMutex 67 txLock sync.RWMutex 68 archiveLock sync.RWMutex 69 NewRawTx chan types.Txi 70 TpsTest bool 71 TpsTestInit bool 72 TestInsertPool bool 73 TestDagPush bool 74 TestSyncBuffer bool 75 TestSigNature bool 76 TestSeal bool 77 } 78 79 func (c *AutoClient) Init() { 80 c.quit = make(chan bool) 81 c.ManualChan = make(chan types.TxBaseType) 82 c.NewRawTx = make(chan types.Txi) 83 } 84 85 func (c *AutoClient) SetTxIntervalUs(i int) { 86 c.TxIntervalUs = i 87 } 88 89 func (c *AutoClient) nextArchiveSleepDuraiton() time.Duration { 90 // tx duration selection 91 var sleepDuration time.Duration 92 switch c.IntervalMode { 93 case IntervalModeConstantInterval: 94 sleepDuration = time.Microsecond * time.Duration(c.ArchiveInterValUs) 95 case IntervalModeRandom: 96 sleepDuration = time.Microsecond * (time.Duration(rand.Intn(c.ArchiveInterValUs-1) + 1)) 97 default: 98 panic(fmt.Sprintf("unkown IntervalMode : %s ", c.IntervalMode)) 99 } 100 return sleepDuration 101 } 102 103 func (c *AutoClient) nextSleepDuraiton() time.Duration { 104 // tx duration selection 105 var sleepDuration time.Duration 106 switch c.IntervalMode { 107 case IntervalModeConstantInterval: 108 sleepDuration = time.Microsecond * time.Duration(c.TxIntervalUs) 109 case IntervalModeRandom: 110 sleepDuration = time.Microsecond * (time.Duration(rand.Intn(c.TxIntervalUs-1) + 1)) 111 default: 112 panic(fmt.Sprintf("unkown IntervalMode : %s ", c.IntervalMode)) 113 } 114 return sleepDuration 115 } 116 117 func (c *AutoClient) fireManualTx(txType types.TxBaseType, force bool) { 118 switch txType { 119 case types.TxBaseTypeTx: 120 c.doSampleTx(force) 121 case types.TxBaseTypeSequencer: 122 c.doSampleSequencer(force) 123 default: 124 logrus.WithField("type", txType).Warn("Unknown TxBaseType") 125 } 126 } 127 128 func (c *AutoClient) loop() { 129 c.pause = true 130 c.wg.Add(1) 131 defer c.wg.Done() 132 133 timerTx := time.NewTimer(c.nextSleepDuraiton()) 134 timerArchive := time.NewTimer(c.nextArchiveSleepDuraiton()) 135 tickerSeq := time.NewTicker(time.Microsecond * time.Duration(c.SequencerIntervalUs)) 136 logrus.Debug(c.SequencerIntervalUs, " seq duration") 137 if !c.AutoTxEnabled { 138 timerTx.Stop() 139 } 140 if !c.AutoSequencerEnabled { 141 tickerSeq.Stop() 142 } 143 if !c.AutoArchiveEnabled { 144 timerArchive.Stop() 145 } 146 for { 147 if c.pause { 148 logrus.Trace("client paused") 149 select { 150 case <-time.After(time.Second): 151 continue 152 case <-c.quit: 153 logrus.Debug("got quit signal") 154 return 155 case txType := <-c.ManualChan: 156 c.fireManualTx(txType, true) 157 } 158 } 159 logrus.Trace("client is working") 160 select { 161 case <-c.quit: 162 c.pause = true 163 logrus.Debug("got quit signal") 164 return 165 case txType := <-c.ManualChan: 166 c.fireManualTx(txType, true) 167 case <-timerTx.C: 168 logrus.Debug("timer sample tx") 169 if node.TooMoreTx() { 170 timerTx.Stop() 171 logrus.Warn("auto tx stopped") 172 continue 173 } 174 c.doSampleTx(false) 175 if c.TpsTestInit { 176 timerTx.Stop() 177 logrus.Warn("auto tx stopped tps test init done") 178 continue 179 } 180 timerTx.Reset(c.nextSleepDuraiton()) 181 case tx := <-c.NewRawTx: 182 c.doRawTx(tx) 183 case <-timerArchive.C: 184 logrus.Debug("timer sample archive") 185 if node.TooMoreTx() { 186 timerArchive.Stop() 187 logrus.Warn("auto archive stopped") 188 continue 189 } 190 c.doSampleArchive(false) 191 timerArchive.Reset(c.nextArchiveSleepDuraiton()) 192 case <-tickerSeq.C: 193 if c.TpsTest && !c.TestSeal { 194 timerTx.Stop() 195 continue 196 } 197 logrus.Debug("timer sample seq") 198 c.doSampleSequencer(false) 199 } 200 201 } 202 } 203 204 func (c *AutoClient) Start() { 205 goroutine.New(c.loop) 206 } 207 208 func (c *AutoClient) Stop() { 209 close(c.quit) 210 c.Delegate.TxCreator.Stop() 211 c.wg.Wait() 212 } 213 214 func (c *AutoClient) Pause() { 215 c.pause = true 216 } 217 218 func (c *AutoClient) Resume() { 219 c.pause = false 220 } 221 222 func (c *AutoClient) judgeNonce() uint64 { 223 c.nonceLock.Lock() 224 defer c.nonceLock.Unlock() 225 226 var n uint64 227 me := c.MyAccount 228 if c.NonceSelfDiscipline { 229 n, err := me.ConsumeNonce() 230 if err == nil { 231 return n 232 } 233 } 234 235 // fetch from db every time 236 n, err := node.GetLatestAccountNonce(me.Address) 237 me.SetNonce(n) 238 if err != nil { 239 // not exists, set to 0 240 return 1 241 } else { 242 n, _ = me.ConsumeNonce() 243 return n 244 } 245 } 246 247 func (c *AutoClient) fireTxs() bool { 248 m := viper.GetInt("auto_client.tx.interval_us") 249 if m == 0 { 250 m = 1000 251 } 252 c.TestSigNature = viper.GetBool("auto_client.tx.test_sig") 253 c.TpsTestInit = true 254 logrus.WithField("micro", m).Info("sent interval") 255 for i := uint64(1); i < 1000000000; i++ { 256 if c.pause { 257 logrus.Info("tx generate stopped") 258 return true 259 } 260 txis, seq := c.Delegate.Dag.GetTestTxisByNumber(i) 261 if seq == nil { 262 logrus.WithField("seq", seq).Error("seq is nil") 263 return true 264 } 265 if c.TestSigNature { 266 f := func() { 267 for _, tx := range txis { 268 ok := c.Delegate.TxCreator.TxFormatVerifier.VerifySignature(tx) 269 if !ok { 270 logrus.Error(tx, ok) 271 } 272 } 273 cf := types.ConfirmTime{ 274 SeqHeight: seq.Height, 275 TxNum: uint64(len(txis)), 276 ConfirmTime: time.Now().Format(time.RFC3339Nano), 277 } 278 err := c.Delegate.Dag.TestWriteConfirmTIme(&cf) 279 if err != nil { 280 logrus.WithField("seq ", seq).WithError(err).Error("dag push err") 281 } 282 } 283 goroutine.New(f) 284 continue 285 286 } 287 if c.TestDagPush { 288 batch := &core2.ConfirmBatch{seq, txis} 289 err := c.Delegate.Dag.Push(batch) 290 if err != nil { 291 logrus.WithField("seq ", seq).WithError(err).Error("dag push err") 292 } 293 continue 294 } else if c.TestSyncBuffer { 295 err := node.InsertSyncBuffer(seq, txis) 296 if err != nil { 297 logrus.WithField("seq ", seq).WithError(err).Error("syncbuffer add err") 298 } 299 } else { 300 if c.TestSeal { 301 for k := 0; k < len(txis); { 302 //time.Sleep(time.Duration(m) * time.Microsecond) 303 if c.pause { 304 return true 305 } 306 ok := c.Delegate.TxCreator.SealTx(txis[k], nil) 307 if !ok { 308 logrus.WithField("tx ", txis[k]).Warn("seal tx err") 309 } 310 k++ 311 } 312 } 313 var j int 314 for k := 0; k < len(txis); { 315 //time.Sleep(time.Duration(m) * time.Microsecond) 316 if c.pause { 317 return true 318 } 319 if c.TestInsertPool { 320 tx := txis[k] 321 err := c.Delegate.TxPool.AddRemoteTx(tx, true) 322 if err != nil { 323 logrus.WithField("tx ", tx).WithError(err).Warn("add tx err") 324 } 325 k++ 326 } else { 327 //tx := txis[k] 328 //c.Delegate.Announce(tx) 329 ////if err != nil { 330 //// logrus.WithField("tx ", tx).WithError(err).Warn("add tx err") 331 ////} 332 //k++ 333 //_=j 334 335 j = k + 150 336 if j >= len(txis) { 337 node.ReceivedNewTxsChan <- txis[k:] 338 } else { 339 node.ReceivedNewTxsChan <- txis[k:j] 340 } 341 k = j 342 } 343 } 344 } 345 if c.pause { 346 return true 347 } 348 if c.TestInsertPool { 349 err := c.Delegate.TxPool.AddRemoteTx(seq, true) 350 if err != nil { 351 logrus.WithField("tx ", seq).WithError(err).Warn("add tx err") 352 } 353 } else if !c.TestSeal { 354 node.ReceivedNewTxsChan <- types.Txis{seq} 355 //c.Delegate.Announce(seq) 356 } 357 } 358 return true 359 } 360 361 func (c *AutoClient) doSampleTx(force bool) bool { 362 if !force && !c.AutoTxEnabled { 363 return false 364 } 365 366 me := c.MyAccount 367 if c.TpsTest { 368 logrus.Info("get start test tps") 369 c.AutoTxEnabled = false 370 if !c.TestSeal { 371 c.AutoSequencerEnabled = false 372 } 373 return c.fireTxs() 374 //logrus.WithField("txi", txi).Info("tps test mode, txi not found, enter normal mode") 375 } 376 c.txLock.RLock() 377 defer c.txLock.RUnlock() 378 379 tx, err := node.GenerateTx(node.TxRequest{ 380 AddrFrom: me.Address, 381 AddrTo: c.SampleAccounts[rand.Intn(len(c.SampleAccounts))].Address, 382 Nonce: c.judgeNonce(), 383 Value: math.NewBigInt(0), 384 PrivateKey: me.PrivateKey, 385 }) 386 if err != nil { 387 logrus.WithError(err).Error("failed to auto generate tx") 388 return false 389 } 390 logrus.WithField("tx", tx).WithField("nonce", tx.GetNonce()). 391 WithField("id", c.MyIndex).Trace("Generated tx") 392 tx.SetVerified(archive.VerifiedFormat) 393 node.Announce(tx) 394 return true 395 } 396 397 type randomArchive struct { 398 Name string `json:"name"` 399 RandInt uint64 `json:"rand_int"` 400 Num int `json:"num"` 401 From []byte `json:"from"` 402 } 403 404 var archiveNum int 405 406 func (c *AutoClient) doSampleArchive(force bool) bool { 407 if !force && !c.AutoArchiveEnabled { 408 return false 409 } 410 c.archiveLock.RLock() 411 defer c.archiveLock.RUnlock() 412 ran := rand.Uint64() 413 r := randomArchive{ 414 Name: fmt.Sprintf("%d", ran), 415 RandInt: ran, 416 Num: archiveNum, 417 From: c.MyAccount.Address.ToBytes()[:5], 418 } 419 archiveNum++ 420 data, _ := json.Marshal(&r) 421 tx, err := node.GenerateArchive(data) 422 if err != nil { 423 logrus.WithError(err).Error("failed to auto generate tx") 424 return false 425 } 426 logrus.WithField("tx", tx).WithField("nonce", tx.GetNonce()). 427 WithField("id", c.MyIndex).Trace("Generated tx") 428 node.Announce(tx) 429 return true 430 } 431 432 func (c *AutoClient) doRawTx(txi types.Txi) bool { 433 if !c.CampainEnable { 434 return false 435 } 436 me := c.MyAccount 437 txi.GetBase().PublicKey = me.PublicKey.KeyBytes 438 txi.GetBase().AccountNonce = c.judgeNonce() 439 if txi.GetType() == types.TxBaseTypeCampaign { 440 cp := txi.(*campaign.Campaign) 441 cp.Issuer = &me.Address 442 } else if txi.GetType() == types.TxBaseTypeTermChange { 443 cp := txi.(*campaign.TermChange) 444 cp.Issuer = &me.Address 445 } 446 s := crypto.NewSigner(me.PublicKey.Type) 447 txi.GetBase().Signature = s.Sign(me.PrivateKey, txi.SignatureTargets()).SignatureBytes 448 if ok := c.Delegate.TxCreator.SealTx(txi, &me.PrivateKey); !ok { 449 logrus.Warn("delegate failed to seal tx") 450 return false 451 } 452 453 logrus.WithField("tx", txi).WithField("nonce", txi.GetNonce()). 454 WithField("id", c.MyIndex).Trace("Generated txi") 455 txi.SetVerified(archive.VerifiedFormat) 456 node.Announce(txi) 457 return true 458 } 459 460 func (c *AutoClient) doSampleSequencer(force bool) bool { 461 if !force && !c.AutoSequencerEnabled { 462 return false 463 } 464 me := c.MyAccount 465 466 seq, err := node.GenerateSequencer(node.SeqRequest{ 467 Issuer: me.Address, 468 Height: c.Delegate.GetLatestDagSequencer().Height + 1, 469 Nonce: c.judgeNonce(), 470 PrivateKey: me.PrivateKey, 471 }) 472 if err != nil { 473 logrus.WithError(err).Error("failed to auto generate seq") 474 return false 475 } 476 logrus.WithField("seq", seq).WithField("nonce", seq.GetNonce()). 477 WithField("id", c.MyIndex).WithField("dump ", seq.Dump()).Debug("Generated seq") 478 seq.SetVerified(archive.VerifiedFormat) 479 node.Announce(seq) 480 return true 481 }