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  }