diff options
Diffstat (limited to 'txnsync/emulatorCore_test.go')
-rw-r--r-- | txnsync/emulatorCore_test.go | 267 |
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 -} |