github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/abci/example/dummyapp/app/dummyapp.go (about)

     1  // Package dummy extends the kvstore.Application to include random data.
     2  // The random data is generated via the PreprocessTxs abci method.
     3  //
     4  // The name is inspired by:
     5  // https://github.com/lazyledger/lazyledger-prototype/blob/2aeca6f55ad389b9d68034a0a7038f80a8d2982e/app_dummy.go#L7
     6  package dummy
     7  
     8  import (
     9  	"bytes"
    10  	"math/rand"
    11  	"sort"
    12  	"time"
    13  
    14  	"github.com/lazyledger/lazyledger-core/abci/example/kvstore"
    15  	"github.com/lazyledger/lazyledger-core/abci/types"
    16  	tmproto "github.com/lazyledger/lazyledger-core/proto/tendermint/types"
    17  	"github.com/lazyledger/lazyledger-core/types/consts"
    18  )
    19  
    20  type Application struct {
    21  	*kvstore.Application
    22  
    23  	// PreprocessTxs will create random messages according to these numbers:
    24  	randTxs  uint32
    25  	txSize   uint32
    26  	msgSize  uint32
    27  	randMsgs uint32
    28  	sleep    time.Duration
    29  }
    30  
    31  type Option func(app *Application)
    32  
    33  // RandMessagesOnPreprocess will indicate to generate a given number of
    34  // random messages and transactions on PreprocessTxs.
    35  func RandMessagesOnPreprocess(numTx, txSize, numMsgs, msgSize uint32) Option {
    36  	return func(app *Application) {
    37  		app.randTxs = numTx
    38  		app.txSize = txSize
    39  		app.randMsgs = numMsgs
    40  		app.msgSize = msgSize
    41  	}
    42  }
    43  
    44  // SleepDuration simulates latency (e.g. incurred by execution or other computation)
    45  // during PreprocessTxs.
    46  func SleepDuration(sleep time.Duration) Option {
    47  	return func(app *Application) {
    48  		app.sleep = sleep
    49  	}
    50  }
    51  
    52  func NewApplication(opts ...Option) *Application {
    53  	app := &Application{Application: kvstore.NewApplication()}
    54  	for _, opt := range opts {
    55  		opt(app)
    56  	}
    57  
    58  	return app
    59  }
    60  
    61  func (app *Application) PreprocessTxs(req types.RequestPreprocessTxs) types.ResponsePreprocessTxs {
    62  	time.Sleep(app.sleep)
    63  	if app.randTxs > 0 || app.randMsgs > 0 {
    64  		randMsgs := generateRandNamespacedRawData(app.randMsgs, consts.NamespaceSize, app.msgSize)
    65  		randMessages := toMessageSlice(randMsgs)
    66  		// yeah, we misuse same function as above to generate Txs
    67  		// as they will still be app.txSize large ¯\_(ツ)_/¯
    68  		randTxs := generateRandNamespacedRawData(app.randTxs, app.txSize, 0)
    69  
    70  		return types.ResponsePreprocessTxs{
    71  			Txs: append(append(
    72  				make([][]byte, len(req.Txs)+len(randTxs)),
    73  				req.Txs...), randTxs...),
    74  			Messages: &tmproto.Messages{MessagesList: randMessages},
    75  		}
    76  	}
    77  	return types.ResponsePreprocessTxs{Txs: req.Txs}
    78  }
    79  
    80  func toMessageSlice(msgs [][]byte) []*tmproto.Message {
    81  	res := make([]*tmproto.Message, len(msgs))
    82  	for i := 0; i < len(msgs); i++ {
    83  		res[i] = &tmproto.Message{NamespaceId: msgs[i][:consts.NamespaceSize], Data: msgs[i][consts.NamespaceSize:]}
    84  	}
    85  	return res
    86  }
    87  
    88  // nolint:gosec // G404: Use of weak random number generator
    89  func generateRandNamespacedRawData(total, nidSize, leafSize uint32) [][]byte {
    90  	data := make([][]byte, total)
    91  	for i := uint32(0); i < total; i++ {
    92  		nid := make([]byte, nidSize)
    93  		rand.Read(nid)
    94  		data[i] = nid
    95  	}
    96  	sortByteArrays(data)
    97  	for i := uint32(0); i < total; i++ {
    98  		d := make([]byte, leafSize)
    99  		rand.Read(d)
   100  		data[i] = append(data[i], d...)
   101  	}
   102  
   103  	return data
   104  }
   105  
   106  func sortByteArrays(src [][]byte) {
   107  	sort.Slice(src, func(i, j int) bool { return bytes.Compare(src[i], src[j]) < 0 })
   108  }