summaryrefslogtreecommitdiff
path: root/txnsync/emulatorCore_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'txnsync/emulatorCore_test.go')
-rw-r--r--txnsync/emulatorCore_test.go267
1 files changed, 0 insertions, 267 deletions
diff --git a/txnsync/emulatorCore_test.go b/txnsync/emulatorCore_test.go
deleted file mode 100644
index 814539827..000000000
--- a/txnsync/emulatorCore_test.go
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright (C) 2019-2021 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
-
-package txnsync
-
-import (
- "context"
- "encoding/binary"
- "sort"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
-
- "github.com/algorand/go-algorand/config"
- "github.com/algorand/go-algorand/crypto"
- "github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/data/pooldata"
- "github.com/algorand/go-algorand/data/transactions"
- "github.com/algorand/go-algorand/logging"
- "github.com/algorand/go-algorand/protocol"
- "github.com/algorand/go-algorand/util/execpool"
-)
-
-const roundDuration = 4 * time.Second
-
-type emulator struct {
- scenario scenario
- nodes []*emulatedNode
- syncers []*Service
- nodeCount int
- log logging.Logger
- currentRound basics.Round
- clock *guidedClock
- t *testing.T
- totalDuplicateTransactions uint64
- totalDuplicateTransactionSize uint64
- lastRandom uint64
- totalInitialTransactions uint64
-}
-
-type nodeTransaction struct {
- expirationRound basics.Round
- transactionSize int
-}
-
-type nodeTransactions []nodeTransaction
-
-type emulatorResult struct {
- nodes []nodeTransactions
-}
-
-func (a nodeTransactions) Len() int { return len(a) }
-func (a nodeTransactions) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a nodeTransactions) Less(i, j int) bool {
- if a[i].expirationRound < a[j].expirationRound {
- return true
- }
- if a[i].expirationRound > a[j].expirationRound {
- return false
- }
- return a[i].transactionSize < a[j].transactionSize
-}
-
-func emulateScenario(t *testing.T, scenario scenario) {
- e := &emulator{
- scenario: scenario,
- nodeCount: len(scenario.netConfig.nodes),
- log: logging.TestingLog(t),
- t: t,
- }
- e.initNodes()
- e.run()
-
- results := e.collectResult()
- for n := range scenario.expectedResults.nodes {
- sort.Stable(scenario.expectedResults.nodes[n])
- }
- for n := range results.nodes {
- sort.Stable(results.nodes[n])
- }
-
- t.Logf("Emulation Statistics:")
- t.Logf("Total duplicate transaction count: %d", e.totalDuplicateTransactions)
- t.Logf("Total duplicate transactions size: %d", e.totalDuplicateTransactionSize)
- for n := 0; n < e.nodeCount; n++ {
- t.Logf("%s transaction groups count : %d", e.nodes[n].name, len(results.nodes[n]))
- }
- for n := 0; n < e.nodeCount; n++ {
- require.Equalf(t, len(scenario.expectedResults.nodes[n]), len(results.nodes[n]), "node %d", n)
- }
-
- // calculating efficiency / overhead :
- // how many transaction need to be received ?
- // each node received all the transactions, minus the ones that it start up with.
- totalNeededSentTransactions := e.totalInitialTransactions*uint64(len(e.nodes)) - e.totalInitialTransactions
- actualReceivedTransactions := totalNeededSentTransactions + e.totalDuplicateTransactions
- t.Logf("Total transaction overhead: %d%%", (actualReceivedTransactions-totalNeededSentTransactions)*100/totalNeededSentTransactions)
-
- require.Equal(t, scenario.expectedResults, results)
- require.Equal(t, 1, 1)
-}
-
-func (e *emulator) run() {
- guidedClock := makeGuidedClock()
- lastRoundStarted := guidedClock.Since()
- e.clock = guidedClock
- e.start()
- // start the nodes
- for e.clock.Since() < e.scenario.testDuration {
- if guidedClock.Since() > lastRoundStarted+roundDuration {
- e.nextRound()
- lastRoundStarted = guidedClock.Since()
- }
- guidedClock.Advance(e.scenario.step)
- e.unblockStep()
- }
- // stop the nodes
- e.stop()
-}
-func (e *emulator) nextRound() {
- e.currentRound++
- for _, node := range e.nodes {
- node.onNewRound(e.currentRound, true)
- }
-}
-func (e *emulator) unblockStep() {
- for _, node := range e.nodes {
- // let it run through the clock advancement.
- node.unblock()
- node.waitBlocked()
-
- // make step
- node.step()
- }
-}
-func (e *emulator) start() {
- for i, node := range e.syncers {
- node.Start()
- e.nodes[i].waitBlocked()
- }
-}
-func (e *emulator) stop() {
- for i, node := range e.syncers {
- e.nodes[i].disableBlocking()
- node.Stop()
- }
-}
-
-func (e *emulator) initNodes() {
- e.nodes = make([]*emulatedNode, e.nodeCount, e.nodeCount)
- for i := 0; i < e.nodeCount; i++ {
- e.nodes[i] = makeEmulatedNode(e, i)
- syncer := MakeTransactionSyncService(
- makeNodeLogger(e.log, e.nodes[i]),
- e.nodes[i],
- e.scenario.netConfig.nodes[i].isRelay,
- "",
- crypto.Digest{},
- config.GetDefaultLocal(),
- e,
- )
- e.syncers = append(e.syncers, syncer)
- }
- randCounter := uint64(0)
- var randBuf [8]byte
- // we want to place a sender on all transaction so that they would be *somewhat* compressible.
- defaultSender := basics.Address{1, 2, 3, 4}
- const senderEncodingSize = 35
- encodingBuf := protocol.GetEncodingBuf()
- for _, initAlloc := range e.scenario.initialAlloc {
- node := e.nodes[initAlloc.node]
- for i := 0; i < initAlloc.transactionsCount; i++ {
- var group = pooldata.SignedTxGroup{}
- group.LocallyOriginated = true
- group.GroupCounter = uint64(len(node.txpoolEntries))
- group.Transactions = []transactions.SignedTxn{
- {
- Txn: transactions.Transaction{
- Type: protocol.PaymentTx,
- Header: transactions.Header{
- Note: make([]byte, initAlloc.transactionSize-senderEncodingSize, initAlloc.transactionSize-senderEncodingSize),
- LastValid: initAlloc.expirationRound,
- Sender: defaultSender,
- },
- },
- },
- }
- // fill up the note field with pseudo-random data.
- for i := 0; i < len(group.Transactions[0].Txn.Note); i += crypto.DigestSize {
- binary.LittleEndian.PutUint64(randBuf[:], randCounter)
- digest := crypto.Hash(randBuf[:])
- copy(group.Transactions[0].Txn.Note[i:], digest[:])
- randCounter++
- }
- group.GroupTransactionID = group.Transactions.ID()
- encodingBuf = encodingBuf[:0]
- group.EncodedLength = len(group.Transactions[0].MarshalMsg(encodingBuf))
- node.txpoolIds[group.Transactions[0].ID()] = true
- node.txpoolEntries = append(node.txpoolEntries, group)
- }
- node.latestLocallyOriginatedGroupCounter = uint64(len(node.txpoolEntries) - 1)
- e.totalInitialTransactions += uint64(initAlloc.transactionsCount)
- node.txpoolGroupCounter += uint64(initAlloc.transactionsCount)
- node.onNewTransactionPoolEntry()
- }
- protocol.PutEncodingBuf(encodingBuf)
-}
-
-func (e *emulator) collectResult() (result emulatorResult) {
- result.nodes = make([]nodeTransactions, len(e.nodes))
- const senderEncodingSize = 35
- for i, node := range e.nodes {
- var txns nodeTransactions
- for _, txnGroup := range node.txpoolEntries {
- size := len(txnGroup.Transactions[0].Txn.Note)
- exp := txnGroup.Transactions[0].Txn.LastValid
- txns = append(txns, nodeTransaction{expirationRound: exp, transactionSize: size + senderEncodingSize})
- }
- for _, txnGroup := range node.expiredTx {
- size := len(txnGroup.Transactions[0].Txn.Note)
- exp := txnGroup.Transactions[0].Txn.LastValid
- txns = append(txns, nodeTransaction{expirationRound: exp, transactionSize: size + senderEncodingSize})
- }
- result.nodes[i] = txns
- }
- return result
-}
-
-// Dummy implementation of execpool.BacklogPool
-func (e *emulator) EnqueueBacklog(enqueueCtx context.Context, t execpool.ExecFunc, arg interface{}, out chan interface{}) error {
- t(arg)
- return nil
-}
-
-// Dummy implementation of execpool.BacklogPool
-func (e *emulator) Enqueue(enqueueCtx context.Context, t execpool.ExecFunc, arg interface{}, i execpool.Priority, out chan interface{}) error {
- return nil
-}
-
-// Dummy implementation of execpool.BacklogPool
-func (e *emulator) GetOwner() interface{} {
- return nil
-}
-
-// Dummy implementation of execpool.BacklogPool
-func (e *emulator) Shutdown() {
-
-}
-
-// Dummy implementation of execpool.BacklogPool
-func (e *emulator) GetParallelism() int {
- return 0
-}