code.vegaprotocol.io/vega@v0.79.0/core/processor/abci_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package processor_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"strconv"
    22  	"sync"
    23  	"testing"
    24  	"time"
    25  
    26  	"code.vegaprotocol.io/vega/core/blockchain/abci"
    27  	"code.vegaprotocol.io/vega/core/events"
    28  	"code.vegaprotocol.io/vega/core/genesis"
    29  	"code.vegaprotocol.io/vega/core/netparams"
    30  	"code.vegaprotocol.io/vega/core/processor"
    31  	"code.vegaprotocol.io/vega/core/processor/mocks"
    32  	"code.vegaprotocol.io/vega/logging"
    33  	"code.vegaprotocol.io/vega/paths"
    34  	proto "code.vegaprotocol.io/vega/protos/vega"
    35  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    36  
    37  	tmtypes "github.com/cometbft/cometbft/abci/types"
    38  	"github.com/golang/mock/gomock"
    39  	"github.com/pkg/errors"
    40  	"github.com/stretchr/testify/require"
    41  	gproto "google.golang.org/protobuf/proto"
    42  )
    43  
    44  func TestListSnapshots(t *testing.T) {
    45  	ctx, cfunc := context.WithCancel(context.Background())
    46  	app := getTestApp(t, cfunc, stopDummy, true, true)
    47  	defer app.ctrl.Finish()
    48  
    49  	app.snap.EXPECT().ListLatestSnapshots().Times(1).Return([]*tmtypes.Snapshot{
    50  		{
    51  			Height:   123,
    52  			Format:   1,
    53  			Chunks:   3,
    54  			Hash:     []byte("0xDEADBEEF"),
    55  			Metadata: []byte("test"),
    56  		},
    57  	}, nil)
    58  	resp, err := app.ListSnapshots(ctx, nil)
    59  	require.NoError(t, err)
    60  	require.NotNil(t, resp)
    61  	require.Equal(t, 1, len(resp.GetSnapshots()))
    62  }
    63  
    64  func TestAppInfo(t *testing.T) {
    65  	ctx, cfunc := context.WithCancel(context.Background())
    66  	app := getTestApp(t, cfunc, stopDummy, true, true)
    67  	defer app.ctrl.Finish()
    68  	// first, the broker streaming stuff
    69  	app.broker.EXPECT().SetStreaming(false).Times(1).Return(true)
    70  	app.broker.EXPECT().SetStreaming(true).Times(1).Return(true)
    71  	// snapshot engine
    72  	app.snap.EXPECT().HasSnapshots().Times(1).Return(true, nil)
    73  	// hash, height, chainID := app.snapshotEngine.Info()
    74  	app.snap.EXPECT().Info().Times(1).Return([]byte("43f86066fe13743448442022c099c48abbd7e9c5eac1c2558fdac1fbf549e867"), int64(123), fmt.Sprintf("%d", app.pChainID))
    75  	info, err := app.Info(ctx, nil)
    76  	require.NoError(t, err)
    77  	require.NotNil(t, info)
    78  }
    79  
    80  func getTransaction(t *testing.T, inputData *commandspb.InputData) *commandspb.Transaction {
    81  	t.Helper()
    82  	rawInputData, err := gproto.Marshal(inputData)
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  	return &commandspb.Transaction{
    87  		InputData: rawInputData,
    88  		Signature: &commandspb.Signature{
    89  			Algo:    "vega/ed25519",
    90  			Value:   "876e46defc40030391b5feb2c9bb0b6b68b2d95a6b5fd17a730a46ea73f3b1808420c8c609be6f1c6156e472ecbcd09202f750da000dee41429947a4b7eca00b",
    91  			Version: 1,
    92  		},
    93  		From: &commandspb.Transaction_PubKey{
    94  			PubKey: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
    95  		},
    96  		Version: 2,
    97  	}
    98  }
    99  
   100  // A batch transaction including only cancellations and/or post-only limit orders is executed at
   101  // the top of the block alongside standalone post-only limit orders and cancellations (0093-TRTO-001).
   102  func TestBatchOnlyCancelsAndPostOnly(t *testing.T) {
   103  	_, cfunc := context.WithCancel(context.Background())
   104  	app := getTestApp(t, cfunc, stopDummy, false, false)
   105  	defer app.ctrl.Finish()
   106  
   107  	// setup some order as the first tx
   108  	tx1InputData := &commandspb.InputData{
   109  		Nonce:       123456789,
   110  		BlockHeight: 1789,
   111  		Command: &commandspb.InputData_OrderSubmission{
   112  			OrderSubmission: &commandspb.OrderSubmission{
   113  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   114  				Side:        proto.Side_SIDE_BUY,
   115  				Size:        1,
   116  				TimeInForce: proto.Order_TIME_IN_FORCE_FOK,
   117  				Type:        proto.Order_TYPE_LIMIT,
   118  				Price:       "123",
   119  			},
   120  		},
   121  	}
   122  	tx1 := getTransaction(t, tx1InputData)
   123  	marshalledTx1, err := gproto.Marshal(tx1)
   124  	require.NoError(t, err)
   125  
   126  	// setup a batch transaction with cancellation and post only
   127  	tx2InputData := &commandspb.InputData{
   128  		Nonce:       123456789,
   129  		BlockHeight: 1789,
   130  		Command: &commandspb.InputData_BatchMarketInstructions{
   131  			BatchMarketInstructions: &commandspb.BatchMarketInstructions{
   132  				Cancellations: []*commandspb.OrderCancellation{
   133  					{
   134  						OrderId:  "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   135  						MarketId: "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   136  					},
   137  				},
   138  				Submissions: []*commandspb.OrderSubmission{
   139  					{
   140  						MarketId:    "926df3b689a5440fe21cad7069ebcedc46f75b2b23ce11002a1ee2254e339f23",
   141  						TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   142  						PostOnly:    true,
   143  					},
   144  				},
   145  			},
   146  		},
   147  	}
   148  	tx2 := getTransaction(t, tx2InputData)
   149  	marshalledTx2, err := gproto.Marshal(tx2)
   150  	require.NoError(t, err)
   151  
   152  	rawTxs := [][]byte{marshalledTx1, marshalledTx2}
   153  	txs := []abci.Tx{}
   154  	for _, tx := range rawTxs {
   155  		decodedTx, err := app.codec.Decode(tx, "1")
   156  		require.NoError(t, err)
   157  		txs = append(txs, decodedTx)
   158  	}
   159  
   160  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return(nil).Times(1)
   161  	app.txCache.EXPECT().IsDelayRequired(gomock.Any()).Return(true).AnyTimes()
   162  	app.txCache.EXPECT().NewDelayedTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("123")).Times(1)
   163  	app.limits.EXPECT().CanTrade().Return(true).AnyTimes()
   164  	blockTxs := app.Abci().OnPrepareProposal(100, txs, rawTxs)
   165  	require.Equal(t, 2, len(blockTxs))
   166  	require.Equal(t, rawTxs[1], blockTxs[0])
   167  	require.Equal(t, []byte("123"), blockTxs[1])
   168  }
   169  
   170  // A batch transaction including either a non-post-only order or an amendment is delayed by one block
   171  // and then executed after the expedited transactions in that later block (0093-TRTO-002).
   172  func TestBatchDelayed(t *testing.T) {
   173  	_, cfunc := context.WithCancel(context.Background())
   174  	app := getTestApp(t, cfunc, stopDummy, false, false)
   175  	defer app.ctrl.Finish()
   176  
   177  	// setup some order as the first tx that doesn't get delayed
   178  	tx1InputData := &commandspb.InputData{
   179  		Nonce:       123456789,
   180  		BlockHeight: 1789,
   181  		Command: &commandspb.InputData_OrderSubmission{
   182  			OrderSubmission: &commandspb.OrderSubmission{
   183  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   184  				Side:        proto.Side_SIDE_BUY,
   185  				Size:        1,
   186  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   187  				Type:        proto.Order_TYPE_LIMIT,
   188  				Price:       "123",
   189  				PostOnly:    true,
   190  			},
   191  		},
   192  	}
   193  	tx1 := getTransaction(t, tx1InputData)
   194  	marshalledTx1, err := gproto.Marshal(tx1)
   195  	require.NoError(t, err)
   196  
   197  	// setup a cancellation
   198  	tx2InputData := &commandspb.InputData{
   199  		Nonce:       123456789,
   200  		BlockHeight: 1789,
   201  		Command: &commandspb.InputData_OrderCancellation{
   202  			OrderCancellation: &commandspb.OrderCancellation{
   203  				MarketId: "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   204  			},
   205  		},
   206  	}
   207  	tx2 := getTransaction(t, tx2InputData)
   208  	marshalledTx2, err := gproto.Marshal(tx2)
   209  	require.NoError(t, err)
   210  
   211  	// now get a batch transaction with submission such that will get it delayed by 1 block
   212  	// setup a batch transaction with cancellation and post only
   213  	tx3InputData := &commandspb.InputData{
   214  		Nonce:       123456789,
   215  		BlockHeight: 1789,
   216  		Command: &commandspb.InputData_BatchMarketInstructions{
   217  			BatchMarketInstructions: &commandspb.BatchMarketInstructions{
   218  				Submissions: []*commandspb.OrderSubmission{
   219  					{
   220  						MarketId:    "926df3b689a5440fe21cad7069ebcedc46f75b2b23ce11002a1ee2254e339f23",
   221  						Side:        proto.Side_SIDE_BUY,
   222  						Size:        1,
   223  						TimeInForce: proto.Order_TIME_IN_FORCE_FOK,
   224  						Type:        proto.Order_TYPE_LIMIT,
   225  						Price:       "123",
   226  					},
   227  					{
   228  						MarketId:    "926df3b689a5440fe21cad7069ebcedc46f75b2b23ce11002a1ee2254e339f23",
   229  						Side:        proto.Side_SIDE_BUY,
   230  						Size:        2,
   231  						TimeInForce: proto.Order_TIME_IN_FORCE_FOK,
   232  						Type:        proto.Order_TYPE_LIMIT,
   233  						Price:       "234",
   234  					},
   235  				},
   236  			},
   237  		},
   238  	}
   239  	tx3 := getTransaction(t, tx3InputData)
   240  	marshalledTx3, err := gproto.Marshal(tx3)
   241  	require.NoError(t, err)
   242  
   243  	rawTxs := [][]byte{marshalledTx1, marshalledTx2, marshalledTx3}
   244  	txs := []abci.Tx{}
   245  	for _, tx := range rawTxs {
   246  		decodedTx, err := app.codec.Decode(tx, "1")
   247  		require.NoError(t, err)
   248  		txs = append(txs, decodedTx)
   249  	}
   250  
   251  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return(nil).Times(1)
   252  	app.txCache.EXPECT().IsDelayRequired(gomock.Any()).Return(true).AnyTimes()
   253  	app.txCache.EXPECT().NewDelayedTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("123")).Times(1)
   254  	app.limits.EXPECT().CanTrade().Return(true).AnyTimes()
   255  	blockTxs := app.Abci().OnPrepareProposal(100, txs, rawTxs)
   256  	// the first two transactions and the delayed wrapped transaction
   257  	require.Equal(t, 3, len(blockTxs))
   258  	require.Equal(t, rawTxs[1], blockTxs[0])
   259  	require.Equal(t, rawTxs[0], blockTxs[1])
   260  	require.Equal(t, []byte("123"), blockTxs[2])
   261  
   262  	// setup a cancellation
   263  	tx4InputData := &commandspb.InputData{
   264  		Nonce:       123456789,
   265  		BlockHeight: 1789,
   266  		Command: &commandspb.InputData_OrderCancellation{
   267  			OrderCancellation: &commandspb.OrderCancellation{
   268  				MarketId: "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   269  			},
   270  		},
   271  	}
   272  	tx4 := getTransaction(t, tx4InputData)
   273  	marshalledTx4, err := gproto.Marshal(tx4)
   274  	require.NoError(t, err)
   275  
   276  	rawTxs = [][]byte{marshalledTx4}
   277  	txs = []abci.Tx{}
   278  	for _, tx := range rawTxs {
   279  		decodedTx, err := app.codec.Decode(tx, "1")
   280  		require.NoError(t, err)
   281  		txs = append(txs, decodedTx)
   282  	}
   283  	// now lets go to the next block and have the postponed transactions executed after the
   284  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return([][]byte{marshalledTx3}).Times(1)
   285  	blockTxs = app.Abci().OnPrepareProposal(101, txs, rawTxs)
   286  	require.Equal(t, 2, len(blockTxs))
   287  	require.Equal(t, marshalledTx4, blockTxs[0])
   288  	// the delayed transaction gets in execution order after the expedited
   289  	require.Equal(t, marshalledTx3, blockTxs[1])
   290  }
   291  
   292  // Cancellation transactions always occur before:
   293  // Market orders (0093-TRTO-003)
   294  // Non post-only limit orders (0093-TRTO-004)
   295  // Order Amends (0093-TRTO-005)
   296  // post-only limit orders (0093-TRTO-013).
   297  func TestCancelledOrdersGoFirst(t *testing.T) {
   298  	_, cfunc := context.WithCancel(context.Background())
   299  	app := getTestApp(t, cfunc, stopDummy, false, false)
   300  	defer app.ctrl.Finish()
   301  
   302  	// cancel 1
   303  	// setup a cancellation
   304  	cancel1 := &commandspb.InputData{
   305  		Nonce:       123456789,
   306  		BlockHeight: 1789,
   307  		Command: &commandspb.InputData_OrderCancellation{
   308  			OrderCancellation: &commandspb.OrderCancellation{
   309  				MarketId: "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   310  			},
   311  		},
   312  	}
   313  	cancel1Tx := getTransaction(t, cancel1)
   314  	marshalledCancel1Tx, err := gproto.Marshal(cancel1Tx)
   315  	require.NoError(t, err)
   316  
   317  	// cancel 2
   318  	cancel2 := &commandspb.InputData{
   319  		Nonce:       123456789,
   320  		BlockHeight: 1789,
   321  		Command: &commandspb.InputData_OrderCancellation{
   322  			OrderCancellation: &commandspb.OrderCancellation{
   323  				MarketId: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   324  			},
   325  		},
   326  	}
   327  	cancel2Tx := getTransaction(t, cancel2)
   328  	marshalledCancel2Tx, err := gproto.Marshal(cancel2Tx)
   329  	require.NoError(t, err)
   330  
   331  	// now lets set up one order of each of the desired types
   332  	marketOrder := &commandspb.InputData{
   333  		Nonce:       123456789,
   334  		BlockHeight: 1789,
   335  		Command: &commandspb.InputData_OrderSubmission{
   336  			OrderSubmission: &commandspb.OrderSubmission{
   337  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   338  				Side:        proto.Side_SIDE_BUY,
   339  				Size:        1,
   340  				TimeInForce: proto.Order_TIME_IN_FORCE_FOK,
   341  				Type:        proto.Order_TYPE_MARKET,
   342  			},
   343  		},
   344  	}
   345  	marketOrderTx := getTransaction(t, marketOrder)
   346  	marshalledMarketOrderTx, err := gproto.Marshal(marketOrderTx)
   347  	require.NoError(t, err)
   348  
   349  	limitOrder := &commandspb.InputData{
   350  		Nonce:       123456789,
   351  		BlockHeight: 1789,
   352  		Command: &commandspb.InputData_OrderSubmission{
   353  			OrderSubmission: &commandspb.OrderSubmission{
   354  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   355  				Side:        proto.Side_SIDE_BUY,
   356  				Size:        1,
   357  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   358  				Type:        proto.Order_TYPE_LIMIT,
   359  				Price:       "123",
   360  			},
   361  		},
   362  	}
   363  	limitOrderTx := getTransaction(t, limitOrder)
   364  	marshalledLimitOrderTx, err := gproto.Marshal(limitOrderTx)
   365  	require.NoError(t, err)
   366  
   367  	amend := &commandspb.InputData{
   368  		Nonce:       123456789,
   369  		BlockHeight: 1789,
   370  		Command: &commandspb.InputData_OrderAmendment{
   371  			OrderAmendment: &commandspb.OrderAmendment{
   372  				MarketId:  "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   373  				OrderId:   "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   374  				SizeDelta: 5,
   375  			},
   376  		},
   377  	}
   378  	amendTx := getTransaction(t, amend)
   379  	marshalledAmendTx, err := gproto.Marshal(amendTx)
   380  	require.NoError(t, err)
   381  
   382  	postOnly := &commandspb.InputData{
   383  		Nonce:       123456789,
   384  		BlockHeight: 1789,
   385  		Command: &commandspb.InputData_OrderSubmission{
   386  			OrderSubmission: &commandspb.OrderSubmission{
   387  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   388  				Side:        proto.Side_SIDE_BUY,
   389  				Size:        1,
   390  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   391  				Type:        proto.Order_TYPE_LIMIT,
   392  				Price:       "123",
   393  				PostOnly:    true,
   394  			},
   395  		},
   396  	}
   397  	postOnlyTx := getTransaction(t, postOnly)
   398  	marshalledPostOnlyTx, err := gproto.Marshal(postOnlyTx)
   399  	require.NoError(t, err)
   400  
   401  	rawTxs := [][]byte{marshalledCancel1Tx, marshalledCancel2Tx, marshalledAmendTx, marshalledMarketOrderTx, marshalledLimitOrderTx, marshalledPostOnlyTx}
   402  	txs := []abci.Tx{}
   403  	for _, tx := range rawTxs {
   404  		decodedTx, err := app.codec.Decode(tx, "1")
   405  		require.NoError(t, err)
   406  		txs = append(txs, decodedTx)
   407  	}
   408  
   409  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return(nil).Times(1)
   410  	app.txCache.EXPECT().IsDelayRequired(gomock.Any()).Return(true).AnyTimes()
   411  	app.txCache.EXPECT().NewDelayedTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("123")).Times(1)
   412  	app.limits.EXPECT().CanTrade().Return(true).AnyTimes()
   413  	blockTxs := app.Abci().OnPrepareProposal(100, txs, rawTxs)
   414  	// cancel 1, then cancel 2, then post only, then wrapped delayed
   415  	require.Equal(t, 4, len(blockTxs))
   416  	require.Equal(t, marshalledCancel1Tx, blockTxs[0])
   417  	require.Equal(t, marshalledCancel2Tx, blockTxs[1])
   418  	require.Equal(t, marshalledPostOnlyTx, blockTxs[2])
   419  	require.Equal(t, []byte("123"), blockTxs[3])
   420  
   421  	// now, in the following block we expect the delayed transactions to be executed, still after expedited transactions
   422  	// cancel 3
   423  	cancel3 := &commandspb.InputData{
   424  		Nonce:       123456789,
   425  		BlockHeight: 1789,
   426  		Command: &commandspb.InputData_OrderCancellation{
   427  			OrderCancellation: &commandspb.OrderCancellation{
   428  				MarketId: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   429  			},
   430  		},
   431  	}
   432  	cancel3Tx := getTransaction(t, cancel3)
   433  	marshalledCancel3Tx, err := gproto.Marshal(cancel3Tx)
   434  	require.NoError(t, err)
   435  
   436  	rawTxs = [][]byte{marshalledCancel3Tx}
   437  	txs = []abci.Tx{}
   438  	for _, tx := range rawTxs {
   439  		decodedTx, err := app.codec.Decode(tx, "1")
   440  		require.NoError(t, err)
   441  		txs = append(txs, decodedTx)
   442  	}
   443  	// now lets go to the next block and have the postponed transactions executed after the
   444  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return([][]byte{marshalledAmendTx, marshalledMarketOrderTx, marshalledLimitOrderTx}).Times(1)
   445  	blockTxs = app.Abci().OnPrepareProposal(101, txs, rawTxs)
   446  	require.Equal(t, 4, len(blockTxs))
   447  	require.Equal(t, marshalledCancel3Tx, blockTxs[0])
   448  	require.Equal(t, marshalledAmendTx, blockTxs[1])
   449  	require.Equal(t, marshalledMarketOrderTx, blockTxs[2])
   450  	require.Equal(t, marshalledLimitOrderTx, blockTxs[3])
   451  }
   452  
   453  // Post-only transactions always occur before:
   454  // Market orders (0093-TRTO-006)
   455  // Non post-only limit orders (0093-TRTO-007)
   456  // Order Amends (0093-TRTO-008).
   457  // Potentially aggressive orders take effect on the market exactly one block after they are included
   458  // in a block (i.e for an order which is included in block N it hits the market in block N+1). This is true for:
   459  // Market orders (0093-TRTO-009)
   460  // Non post-only limit orders (0093-TRTO-010)
   461  // Order Amends (0093-TRTO-011).
   462  func TestPostOnlyGoBeforeAggressive(t *testing.T) {
   463  	_, cfunc := context.WithCancel(context.Background())
   464  	app := getTestApp(t, cfunc, stopDummy, false, false)
   465  	defer app.ctrl.Finish()
   466  
   467  	postOnly1 := &commandspb.InputData{
   468  		Nonce:       123456789,
   469  		BlockHeight: 1789,
   470  		Command: &commandspb.InputData_OrderSubmission{
   471  			OrderSubmission: &commandspb.OrderSubmission{
   472  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   473  				Side:        proto.Side_SIDE_BUY,
   474  				Size:        1,
   475  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   476  				Type:        proto.Order_TYPE_LIMIT,
   477  				Price:       "123",
   478  				PostOnly:    true,
   479  			},
   480  		},
   481  	}
   482  	postOnly1Tx := getTransaction(t, postOnly1)
   483  	marshalledPostOnly1Tx, err := gproto.Marshal(postOnly1Tx)
   484  	require.NoError(t, err)
   485  
   486  	postOnly2 := &commandspb.InputData{
   487  		Nonce:       123456789,
   488  		BlockHeight: 1789,
   489  		Command: &commandspb.InputData_OrderSubmission{
   490  			OrderSubmission: &commandspb.OrderSubmission{
   491  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   492  				Side:        proto.Side_SIDE_BUY,
   493  				Size:        1,
   494  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   495  				Type:        proto.Order_TYPE_LIMIT,
   496  				Price:       "123",
   497  				PostOnly:    true,
   498  			},
   499  		},
   500  	}
   501  	postOnly2Tx := getTransaction(t, postOnly2)
   502  	marshalledPostOnly2Tx, err := gproto.Marshal(postOnly2Tx)
   503  	require.NoError(t, err)
   504  
   505  	// cancel 1
   506  	cancel1 := &commandspb.InputData{
   507  		Nonce:       123456789,
   508  		BlockHeight: 1789,
   509  		Command: &commandspb.InputData_OrderCancellation{
   510  			OrderCancellation: &commandspb.OrderCancellation{
   511  				MarketId: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   512  			},
   513  		},
   514  	}
   515  	cancel1Tx := getTransaction(t, cancel1)
   516  	marshalledCancel1Tx, err := gproto.Marshal(cancel1Tx)
   517  	require.NoError(t, err)
   518  
   519  	// now lets set up one order of each of the desired types
   520  	marketOrder := &commandspb.InputData{
   521  		Nonce:       123456789,
   522  		BlockHeight: 1789,
   523  		Command: &commandspb.InputData_OrderSubmission{
   524  			OrderSubmission: &commandspb.OrderSubmission{
   525  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   526  				Side:        proto.Side_SIDE_BUY,
   527  				Size:        1,
   528  				TimeInForce: proto.Order_TIME_IN_FORCE_FOK,
   529  				Type:        proto.Order_TYPE_MARKET,
   530  			},
   531  		},
   532  	}
   533  	marketOrderTx := getTransaction(t, marketOrder)
   534  	marshalledMarketOrderTx, err := gproto.Marshal(marketOrderTx)
   535  	require.NoError(t, err)
   536  
   537  	limitOrder := &commandspb.InputData{
   538  		Nonce:       123456789,
   539  		BlockHeight: 1789,
   540  		Command: &commandspb.InputData_OrderSubmission{
   541  			OrderSubmission: &commandspb.OrderSubmission{
   542  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   543  				Side:        proto.Side_SIDE_BUY,
   544  				Size:        1,
   545  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   546  				Type:        proto.Order_TYPE_LIMIT,
   547  				Price:       "123",
   548  			},
   549  		},
   550  	}
   551  	limitOrderTx := getTransaction(t, limitOrder)
   552  	marshalledLimitOrderTx, err := gproto.Marshal(limitOrderTx)
   553  	require.NoError(t, err)
   554  
   555  	amend := &commandspb.InputData{
   556  		Nonce:       123456789,
   557  		BlockHeight: 1789,
   558  		Command: &commandspb.InputData_OrderAmendment{
   559  			OrderAmendment: &commandspb.OrderAmendment{
   560  				MarketId:  "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   561  				OrderId:   "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   562  				SizeDelta: 5,
   563  			},
   564  		},
   565  	}
   566  	amendTx := getTransaction(t, amend)
   567  	marshalledAmendTx, err := gproto.Marshal(amendTx)
   568  	require.NoError(t, err)
   569  
   570  	rawTxs := [][]byte{marshalledAmendTx, marshalledMarketOrderTx, marshalledLimitOrderTx, marshalledPostOnly1Tx, marshalledCancel1Tx, marshalledPostOnly2Tx}
   571  	txs := []abci.Tx{}
   572  	for _, tx := range rawTxs {
   573  		decodedTx, err := app.codec.Decode(tx, "1")
   574  		require.NoError(t, err)
   575  		txs = append(txs, decodedTx)
   576  	}
   577  
   578  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return(nil).Times(1)
   579  	app.txCache.EXPECT().IsDelayRequired(gomock.Any()).Return(true).AnyTimes()
   580  	app.txCache.EXPECT().NewDelayedTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("123")).Times(1)
   581  	app.limits.EXPECT().CanTrade().Return(true).AnyTimes()
   582  	blockTxs := app.Abci().OnPrepareProposal(100, txs, rawTxs)
   583  	// cancel, then post only 1, then post only 2, then wrapped delayed
   584  	require.Equal(t, 4, len(blockTxs))
   585  	require.Equal(t, marshalledCancel1Tx, blockTxs[0])
   586  	require.Equal(t, marshalledPostOnly1Tx, blockTxs[1])
   587  	require.Equal(t, marshalledPostOnly2Tx, blockTxs[2])
   588  	require.Equal(t, []byte("123"), blockTxs[3])
   589  
   590  	// now, in the following block we expect the delayed transactions to be executed, still after expedited transactions
   591  	// cancel 3
   592  	cancel3 := &commandspb.InputData{
   593  		Nonce:       123456789,
   594  		BlockHeight: 1789,
   595  		Command: &commandspb.InputData_OrderCancellation{
   596  			OrderCancellation: &commandspb.OrderCancellation{
   597  				MarketId: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   598  			},
   599  		},
   600  	}
   601  	cancel3Tx := getTransaction(t, cancel3)
   602  	marshalledCancel3Tx, err := gproto.Marshal(cancel3Tx)
   603  	require.NoError(t, err)
   604  
   605  	postOnly3 := &commandspb.InputData{
   606  		Nonce:       123456789,
   607  		BlockHeight: 1789,
   608  		Command: &commandspb.InputData_OrderSubmission{
   609  			OrderSubmission: &commandspb.OrderSubmission{
   610  				MarketId:    "47076f002ddd9bfeb7f4679fc75b4686f64446d5a5afcb84584e7c7166d13efa",
   611  				Side:        proto.Side_SIDE_BUY,
   612  				Size:        1,
   613  				TimeInForce: proto.Order_TIME_IN_FORCE_GTC,
   614  				Type:        proto.Order_TYPE_LIMIT,
   615  				Price:       "123",
   616  				PostOnly:    true,
   617  			},
   618  		},
   619  	}
   620  	postOnly3Tx := getTransaction(t, postOnly3)
   621  	marshalledPostOnly3Tx, err := gproto.Marshal(postOnly3Tx)
   622  	require.NoError(t, err)
   623  
   624  	amend2 := &commandspb.InputData{
   625  		Nonce:       123456789,
   626  		BlockHeight: 1789,
   627  		Command: &commandspb.InputData_OrderAmendment{
   628  			OrderAmendment: &commandspb.OrderAmendment{
   629  				MarketId:  "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   630  				OrderId:   "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   631  				SizeDelta: 5,
   632  			},
   633  		},
   634  	}
   635  	amend2Tx := getTransaction(t, amend2)
   636  	marshalledAmend2Tx, err := gproto.Marshal(amend2Tx)
   637  	require.NoError(t, err)
   638  
   639  	rawTxs = [][]byte{marshalledPostOnly3Tx, marshalledAmend2Tx, marshalledCancel3Tx}
   640  	txs = []abci.Tx{}
   641  	for _, tx := range rawTxs {
   642  		decodedTx, err := app.codec.Decode(tx, "1")
   643  		require.NoError(t, err)
   644  		txs = append(txs, decodedTx)
   645  	}
   646  	// now lets go to the next block and have the postponed transactions executed after the new cancellation and post only from this block
   647  	// plus throw in another amend this block that gets delayed to the next block
   648  	app.txCache.EXPECT().GetRawTxs(gomock.Any()).Return([][]byte{marshalledAmendTx, marshalledMarketOrderTx, marshalledLimitOrderTx}).Times(1)
   649  	app.txCache.EXPECT().NewDelayedTransaction(gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("456")).Times(1)
   650  	blockTxs = app.Abci().OnPrepareProposal(101, txs, rawTxs)
   651  	require.Equal(t, 6, len(blockTxs))
   652  	require.Equal(t, marshalledCancel3Tx, blockTxs[0])
   653  	require.Equal(t, marshalledPostOnly3Tx, blockTxs[1])
   654  	require.Equal(t, marshalledAmendTx, blockTxs[2])
   655  	require.Equal(t, marshalledMarketOrderTx, blockTxs[3])
   656  	require.Equal(t, marshalledLimitOrderTx, blockTxs[4])
   657  	require.Equal(t, []byte("456"), blockTxs[5])
   658  }
   659  
   660  type tstApp struct {
   661  	*processor.App
   662  	ctrl               *gomock.Controller
   663  	timeSvc            *mocks.MockTimeService
   664  	epochSvc           *mocks.MockEpochService
   665  	delegation         *mocks.MockDelegationEngine
   666  	exec               *mocks.MockExecutionEngine
   667  	gov                *mocks.MockGovernanceEngine
   668  	stats              *mocks.MockStats
   669  	assets             *mocks.MockAssets
   670  	validator          *mocks.MockValidatorTopology
   671  	notary             *mocks.MockNotary
   672  	evtForwarder       *mocks.MockEvtForwarder
   673  	witness            *mocks.MockWitness
   674  	banking            *mocks.MockBanking
   675  	netParams          *mocks.MockNetworkParameters
   676  	oracleEngine       *mocks.MockOraclesEngine
   677  	oracleAdaptors     *mocks.MockOracleAdaptors
   678  	l1Verifier         *mocks.MockEthereumOracleVerifier
   679  	l2Verifier         *mocks.MockEthereumOracleVerifier
   680  	limits             *mocks.MockLimits
   681  	stakeVerifier      *mocks.MockStakeVerifier
   682  	stakingAccs        *mocks.MockStakingAccounts
   683  	primaryERC20       *mocks.MockERC20MultiSigTopology
   684  	secondaryERC20     *mocks.MockERC20MultiSigTopology
   685  	cp                 *mocks.MockCheckpoint
   686  	broker             *mocks.MockBroker
   687  	evtForwarderHB     *mocks.MockEvtForwarderHeartbeat
   688  	spam               *mocks.MockSpamEngine
   689  	pow                *mocks.MockPoWEngine
   690  	snap               *mocks.MockSnapshotEngine
   691  	stateVar           *mocks.MockStateVarEngine
   692  	teams              *mocks.MockTeamsEngine
   693  	referral           *mocks.MockReferralProgram
   694  	volDiscount        *mocks.MockVolumeDiscountProgram
   695  	volRebate          *mocks.MockVolumeRebateProgram
   696  	bClient            *mocks.MockBlockchainClient
   697  	puSvc              *mocks.MockProtocolUpgradeService
   698  	ethCallEng         *mocks.MockEthCallEngine
   699  	balance            *mocks.MockBalanceChecker
   700  	parties            *mocks.MockPartiesEngine
   701  	txCache            *mocks.MockTxCache
   702  	codec              processor.NullBlockchainTxCodec
   703  	onTickCB           []func(context.Context, time.Time)
   704  	pChainID, sChainID uint64
   705  }
   706  
   707  func TestProtocolUpgradeFailedBrokerStreamError(t *testing.T) {
   708  	streamClient := newBrokerClient(0)
   709  	wg := sync.WaitGroup{}
   710  	wg.Add(1)
   711  	stop := func() error {
   712  		wg.Done()
   713  		return nil
   714  	}
   715  	ctx, cfunc := context.WithCancel(context.Background())
   716  	app := getTestAppWithInit(t, cfunc, stop, false, false)
   717  	defer func() {
   718  		wg.Wait()
   719  		streamClient.finish()
   720  		app.ctrl.Finish()
   721  	}()
   722  
   723  	// vars
   724  	blockHeight := uint64(123)
   725  	blockHash := "0xDEADBEEF"
   726  	proposer := "0xCAFECAFE1"
   727  	updateTime := time.Now()
   728  	brokerErr := errors.Errorf("pretend something went wrong")
   729  
   730  	// let's make this look like a protocol upgrade
   731  	app.txCache.EXPECT().SetRawTxs(nil, blockHeight).Times(1)
   732  
   733  	// These are the calls made in the startProtocolUpgrade func:
   734  	app.puSvc.EXPECT().CoreReadyForUpgrade().Times(1).Return(true)
   735  	// broker streaming is enabled, so let's set up the channels and push some data
   736  	app.broker.EXPECT().StreamingEnabled().Times(1).Return(true)
   737  	app.broker.EXPECT().SocketClient().Times(1).Return(streamClient)
   738  	// we expect the protocol upgraded started event to be sent once at least.
   739  	app.broker.EXPECT().Send(gomock.Any()).Times(1)
   740  	// as part of the event data sent here, we call stats to get the height:
   741  	app.stats.EXPECT().Height().Times(1).Return(blockHeight - 1)
   742  	// now we set the upgrade service as ready:
   743  	app.puSvc.EXPECT().SetReadyForUpgrade().Times(0)
   744  
   745  	// start stream client routine, throw some events on the channels
   746  	go func() {
   747  		// this event should be read, but not have any effect on the logic.
   748  		streamClient.evtCh <- events.NewTime(ctx, updateTime)
   749  		require.True(t, blockHeight > 0) // just check we reach this part
   750  		streamClient.errCh <- brokerErr
   751  	}()
   752  
   753  	// see if we can recover here?
   754  	defer func() {
   755  		if r := recover(); r != nil {
   756  			expect := "failed to wait for data node to get ready for upgrade"
   757  			msg := fmt.Sprintf("Test likely passed, recovered: %v\n", r)
   758  			require.Contains(t, msg, expect, msg)
   759  		}
   760  	}()
   761  
   762  	// start upgrade
   763  	_ = app.OnBeginBlock(blockHeight, blockHash, updateTime, proposer, nil)
   764  }
   765  
   766  func TestOnBeginBlock(t *testing.T) {
   767  	// keeping the test for reference, as it can be used for reference with regular OnBeginBlock calls
   768  	// or error cases with for protocol upgrade stuff.
   769  	// set up stop call, so we can ensure the chain is stopped as part of protocol upgrade.
   770  	_, cfunc := context.WithCancel(context.Background())
   771  	app := getTestAppWithInit(t, cfunc, stopDummy, true, true)
   772  	defer app.ctrl.Finish()
   773  
   774  	// vars
   775  	blockHeight := uint64(123)
   776  	blockHash := "0xDEADBEEF"
   777  	proposer := "0xCAFECAFE1"
   778  	updateTime := time.Now()
   779  	prevTime := updateTime.Add(-1 * time.Second)
   780  
   781  	// let's make this look like a protocol upgrade
   782  	app.txCache.EXPECT().SetRawTxs(nil, blockHeight).Times(1)
   783  
   784  	// check for upgrade
   785  	app.puSvc.EXPECT().CoreReadyForUpgrade().Times(1).Return(false)
   786  
   787  	// now we're back to the OnBeginBlock call, set mocks for the remainder of that func:
   788  	app.broker.EXPECT().Send(gomock.Any()).Times(1)
   789  	// we're not passing any transactions ATM, so no setTxStats to worry about
   790  	// now PoW
   791  	app.pow.EXPECT().BeginBlock(blockHeight, blockHash, nil).Times(1)
   792  	// spam:
   793  	app.spam.EXPECT().BeginBlock(nil).Times(1)
   794  	// now do stats:
   795  	app.stats.EXPECT().SetHash(blockHash).Times(1)
   796  	app.stats.EXPECT().SetHeight(blockHeight).Times(1)
   797  	// now the calls to time service:
   798  	app.timeSvc.EXPECT().SetTimeNow(gomock.Any(), updateTime).Times(1)
   799  	app.timeSvc.EXPECT().GetTimeNow().Times(1).Return(updateTime)
   800  	app.timeSvc.EXPECT().GetTimeLastBatch().Times(1).Return(prevTime)
   801  	// begin upgrade:
   802  	app.puSvc.EXPECT().BeginBlock(gomock.Any(), blockHeight).Times(1)
   803  	// topology:
   804  	app.validator.EXPECT().BeginBlock(gomock.Any(), blockHeight, proposer).Times(1)
   805  	// balance checker:
   806  	app.balance.EXPECT().BeginBlock(gomock.Any()).Times(1)
   807  	// exec engine:
   808  	app.exec.EXPECT().BeginBlock(gomock.Any(), updateTime.Sub(prevTime)).Times(1)
   809  
   810  	// actually make the call now:
   811  	ctx := app.OnBeginBlock(blockHeight, blockHash, updateTime, proposer, nil)
   812  	// we should get a context back, this just checks the call returned.
   813  	require.NotNil(t, ctx)
   814  }
   815  
   816  func stopDummy() error {
   817  	return nil
   818  }
   819  
   820  func getTestApp(t *testing.T, cfunc func(), stop func() error, PoW, Spam bool) *tstApp {
   821  	t.Helper()
   822  	pChain := "1"
   823  	sChain := "2"
   824  	gHandler := genesis.New(
   825  		logging.NewTestLogger(),
   826  		genesis.NewDefaultConfig(),
   827  	)
   828  	pChainID, err := strconv.ParseUint(pChain, 10, 64)
   829  	if err != nil {
   830  		t.Fatalf("Could not get test app instance, chain ID parse error: %v", err)
   831  	}
   832  	sChainID, err := strconv.ParseUint(sChain, 10, 64)
   833  	if err != nil {
   834  		t.Fatalf("Could not get test app instance, chain ID parse error: %v", err)
   835  	}
   836  	ctrl := gomock.NewController(t)
   837  	broker := mocks.NewMockBroker(ctrl)
   838  	timeSvc := mocks.NewMockTimeService(ctrl)
   839  	epochSvc := mocks.NewMockEpochService(ctrl)
   840  	delegation := mocks.NewMockDelegationEngine(ctrl)
   841  	exec := mocks.NewMockExecutionEngine(ctrl)
   842  	gov := mocks.NewMockGovernanceEngine(ctrl)
   843  	stats := mocks.NewMockStats(ctrl)
   844  	assets := mocks.NewMockAssets(ctrl)
   845  	validator := mocks.NewMockValidatorTopology(ctrl)
   846  	notary := mocks.NewMockNotary(ctrl)
   847  	evtForwarder := mocks.NewMockEvtForwarder(ctrl)
   848  	evtForwarderHB := mocks.NewMockEvtForwarderHeartbeat(ctrl)
   849  	witness := mocks.NewMockWitness(ctrl)
   850  	banking := mocks.NewMockBanking(ctrl)
   851  	netParams := mocks.NewMockNetworkParameters(ctrl)
   852  	oracleEngine := mocks.NewMockOraclesEngine(ctrl)
   853  	oracleAdaptors := mocks.NewMockOracleAdaptors(ctrl)
   854  	l1Verifier := mocks.NewMockEthereumOracleVerifier(ctrl)
   855  	l2Verifier := mocks.NewMockEthereumOracleVerifier(ctrl)
   856  	limits := mocks.NewMockLimits(ctrl)
   857  	stakeVerifier := mocks.NewMockStakeVerifier(ctrl)
   858  	stakingAccs := mocks.NewMockStakingAccounts(ctrl)
   859  	pERC20 := mocks.NewMockERC20MultiSigTopology(ctrl)
   860  	sERC20 := mocks.NewMockERC20MultiSigTopology(ctrl)
   861  	cp := mocks.NewMockCheckpoint(ctrl)
   862  	var (
   863  		spam *mocks.MockSpamEngine
   864  		pow  *mocks.MockPoWEngine
   865  	)
   866  	if Spam {
   867  		spam = mocks.NewMockSpamEngine(ctrl)
   868  	}
   869  	if PoW {
   870  		pow = mocks.NewMockPoWEngine(ctrl)
   871  	}
   872  	snap := mocks.NewMockSnapshotEngine(ctrl)
   873  	stateVar := mocks.NewMockStateVarEngine(ctrl)
   874  	teams := mocks.NewMockTeamsEngine(ctrl)
   875  	referral := mocks.NewMockReferralProgram(ctrl)
   876  	volDiscount := mocks.NewMockVolumeDiscountProgram(ctrl)
   877  	volRebate := mocks.NewMockVolumeRebateProgram(ctrl)
   878  	bClient := mocks.NewMockBlockchainClient(ctrl)
   879  	puSvc := mocks.NewMockProtocolUpgradeService(ctrl)
   880  	ethCallEng := mocks.NewMockEthCallEngine(ctrl)
   881  	balance := mocks.NewMockBalanceChecker(ctrl)
   882  	parties := mocks.NewMockPartiesEngine(ctrl)
   883  	txCache := mocks.NewMockTxCache(ctrl)
   884  	codec := processor.NullBlockchainTxCodec{}
   885  	// paths, config, gastimator, ...
   886  	vp := paths.New("/tmp")
   887  	conf := processor.NewDefaultConfig()
   888  	gastimator := processor.NewGastimator(exec)
   889  	// test wrapper
   890  	tstApp := &tstApp{
   891  		ctrl:           ctrl,
   892  		broker:         broker,
   893  		timeSvc:        timeSvc,
   894  		epochSvc:       epochSvc,
   895  		delegation:     delegation,
   896  		exec:           exec,
   897  		gov:            gov,
   898  		stats:          stats,
   899  		assets:         assets,
   900  		validator:      validator,
   901  		notary:         notary,
   902  		evtForwarder:   evtForwarder,
   903  		evtForwarderHB: evtForwarderHB,
   904  		witness:        witness,
   905  		banking:        banking,
   906  		netParams:      netParams,
   907  		oracleEngine:   oracleEngine,
   908  		oracleAdaptors: oracleAdaptors,
   909  		l1Verifier:     l1Verifier,
   910  		l2Verifier:     l2Verifier,
   911  		limits:         limits,
   912  		stakeVerifier:  stakeVerifier,
   913  		stakingAccs:    stakingAccs,
   914  		primaryERC20:   pERC20,
   915  		secondaryERC20: sERC20,
   916  		cp:             cp,
   917  		spam:           spam,
   918  		pow:            pow,
   919  		snap:           snap,
   920  		stateVar:       stateVar,
   921  		teams:          teams,
   922  		referral:       referral,
   923  		volDiscount:    volDiscount,
   924  		volRebate:      volRebate,
   925  		bClient:        bClient,
   926  		puSvc:          puSvc,
   927  		ethCallEng:     ethCallEng,
   928  		balance:        balance,
   929  		parties:        parties,
   930  		txCache:        txCache,
   931  		codec:          codec,
   932  		onTickCB:       []func(context.Context, time.Time){},
   933  		pChainID:       pChainID,
   934  		sChainID:       sChainID,
   935  	}
   936  	// timeSvc will be set up to the onTick callback
   937  	timeSvc.EXPECT().NotifyOnTick(gomock.Any()).AnyTimes().Do(func(cbs ...func(context.Context, time.Time)) {
   938  		if cbs == nil {
   939  			return
   940  		}
   941  		tstApp.onTickCB = append(tstApp.onTickCB, cbs...)
   942  	})
   943  	// ensureConfig calls netparams
   944  	netParams.EXPECT().GetJSONStruct(netparams.BlockchainsPrimaryEthereumConfig, gomock.Any()).Times(1).DoAndReturn(func(_ string, v netparams.Reset) error {
   945  		vt, ok := v.(*proto.EthereumConfig)
   946  		if !ok {
   947  			return errors.Errorf("invalid type %t", v)
   948  		}
   949  		vt.ChainId = pChain
   950  		return nil
   951  	})
   952  	netParams.EXPECT().GetJSONStruct(netparams.BlockchainsEVMBridgeConfigs, gomock.Any()).Times(1).DoAndReturn(func(_ string, v netparams.Reset) error {
   953  		vt, ok := v.(*proto.EVMBridgeConfigs)
   954  		if !ok {
   955  			return errors.Errorf("invalid type %t", v)
   956  		}
   957  		if vt.Configs == nil {
   958  			vt.Configs = []*proto.EVMBridgeConfig{}
   959  		}
   960  		vt.Configs = append(vt.Configs, &proto.EVMBridgeConfig{
   961  			ChainId: sChain,
   962  		})
   963  		return nil
   964  	})
   965  	// set primary chain ID
   966  	exec.EXPECT().OnChainIDUpdate(pChainID).Times(1).Return(nil)
   967  	gov.EXPECT().OnChainIDUpdate(pChainID).Times(1).Return(nil)
   968  	app := processor.NewApp(
   969  		logging.NewTestLogger(),
   970  		vp,
   971  		conf,
   972  		cfunc,
   973  		stop,
   974  		assets,
   975  		banking,
   976  		broker,
   977  		witness,
   978  		evtForwarder,
   979  		evtForwarderHB,
   980  		exec,
   981  		gHandler,
   982  		gov,
   983  		notary,
   984  		stats,
   985  		timeSvc,
   986  		epochSvc,
   987  		validator,
   988  		netParams,
   989  		&processor.Oracle{
   990  			Engine:                    oracleEngine,
   991  			Adaptors:                  oracleAdaptors,
   992  			EthereumOraclesVerifier:   l1Verifier,
   993  			EthereumL2OraclesVerifier: l2Verifier,
   994  		},
   995  		delegation,
   996  		limits,
   997  		stakeVerifier,
   998  		cp,
   999  		spam,
  1000  		pow,
  1001  		stakingAccs,
  1002  		snap,
  1003  		stateVar,
  1004  		teams,
  1005  		referral,
  1006  		volDiscount,
  1007  		volRebate,
  1008  		bClient,
  1009  		pERC20,
  1010  		sERC20,
  1011  		"0",
  1012  		puSvc,
  1013  		&codec,
  1014  		gastimator,
  1015  		ethCallEng,
  1016  		balance,
  1017  		parties,
  1018  		txCache,
  1019  	)
  1020  
  1021  	// embed the app
  1022  	tstApp.App = app
  1023  	// return wrapper
  1024  	return tstApp
  1025  }
  1026  
  1027  func getTestAppWithInit(t *testing.T, cfunc func(), stop func() error, PoW, Spam bool) *tstApp {
  1028  	t.Helper()
  1029  	tstApp := getTestApp(t, cfunc, stop, PoW, Spam)
  1030  	// now set up the OnInitChain stuff
  1031  	req := &tmtypes.RequestInitChain{
  1032  		ChainId:       "1",
  1033  		InitialHeight: 0,
  1034  		Time:          time.Now().Add(-1 * time.Hour), // some time in the past
  1035  	}
  1036  	// set up mock calls:
  1037  	tstApp.broker.EXPECT().Send(gomock.Any()).Times(2) // once before, and once after gHandler is called
  1038  	tstApp.ethCallEng.EXPECT().Start().Times(1)
  1039  	tstApp.validator.EXPECT().GetValidatorPowerUpdates().Times(1).Return(nil)
  1040  	resp, err := tstApp.OnInitChain(req)
  1041  	require.NoError(t, err)
  1042  	require.NotNil(t, resp)
  1043  	return tstApp
  1044  }
  1045  
  1046  // fake socket client.
  1047  type brokerClient struct {
  1048  	errCh chan error
  1049  	evtCh chan events.Event
  1050  }
  1051  
  1052  func newBrokerClient(buf int) *brokerClient {
  1053  	return &brokerClient{
  1054  		errCh: make(chan error, buf),
  1055  		evtCh: make(chan events.Event, buf),
  1056  	}
  1057  }
  1058  
  1059  func (b *brokerClient) finish() {
  1060  	if b.errCh != nil {
  1061  		close(b.errCh)
  1062  		b.errCh = nil
  1063  	}
  1064  	if b.evtCh != nil {
  1065  		close(b.evtCh)
  1066  		b.evtCh = nil
  1067  	}
  1068  }
  1069  
  1070  func (b *brokerClient) SendBatch(events []events.Event) error {
  1071  	return nil
  1072  }
  1073  
  1074  func (b *brokerClient) Receive(ctx context.Context) (<-chan events.Event, <-chan error) {
  1075  	return b.evtCh, b.errCh
  1076  }