code.vegaprotocol.io/vega@v0.79.0/core/governance/market_cp_restore_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 governance_test
    17  
    18  import (
    19  	"context"
    20  	"encoding/base64"
    21  	"encoding/json"
    22  	"testing"
    23  	"time"
    24  
    25  	"code.vegaprotocol.io/vega/core/assets"
    26  	amocks "code.vegaprotocol.io/vega/core/assets/mocks"
    27  	bmocks "code.vegaprotocol.io/vega/core/broker/mocks"
    28  	"code.vegaprotocol.io/vega/core/checkpoint"
    29  	"code.vegaprotocol.io/vega/core/collateral"
    30  	"code.vegaprotocol.io/vega/core/execution"
    31  	"code.vegaprotocol.io/vega/core/execution/common"
    32  	emocks "code.vegaprotocol.io/vega/core/execution/common/mocks"
    33  	fmocks "code.vegaprotocol.io/vega/core/fee/mocks"
    34  	"code.vegaprotocol.io/vega/core/governance"
    35  	"code.vegaprotocol.io/vega/core/governance/mocks"
    36  	"code.vegaprotocol.io/vega/core/netparams"
    37  	"code.vegaprotocol.io/vega/core/nodewallets"
    38  	"code.vegaprotocol.io/vega/core/types"
    39  	"code.vegaprotocol.io/vega/libs/num"
    40  	"code.vegaprotocol.io/vega/libs/proto"
    41  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    42  	vgtesting "code.vegaprotocol.io/vega/libs/testing"
    43  	"code.vegaprotocol.io/vega/logging"
    44  	"code.vegaprotocol.io/vega/paths"
    45  	checkpointpb "code.vegaprotocol.io/vega/protos/vega/checkpoint/v1"
    46  
    47  	"github.com/golang/mock/gomock"
    48  	"github.com/pkg/errors"
    49  	"github.com/stretchr/testify/require"
    50  
    51  	_ "embed"
    52  )
    53  
    54  //go:embed testcp/checkpoint.cp
    55  var cpFile []byte
    56  
    57  //go:embed testcp/scp.cp
    58  var cpSuccessorFile []byte
    59  
    60  // Disable 'TestMarketRestoreFromCheckpoint' for now. 'testcp/checkpoint.cp' needs to be regenerated for the new data sourcing types.
    61  // Rest of functions disabled because linter complains.
    62  
    63  func TestMarketRestoreFromCheckpoint(t *testing.T) {
    64  	t.Skipf("Skipping test as need to regenerate testcp/checkpoint.cp with appropriate values for LP - Zohar to fix")
    65  	now := time.Now()
    66  	ex, gov, cpEng := createExecutionEngine(t, now)
    67  	genesis := &checkpoint.GenesisState{
    68  		CheckpointHash:  "b60aa26b5b167ecf72620778b481a65d029367c1a56bd280b55614b5586f3e8c",
    69  		CheckpointState: base64.StdEncoding.EncodeToString(cpFile),
    70  	}
    71  	gd := &struct {
    72  		Checkpoint *checkpoint.GenesisState `json:"checkpoint"`
    73  	}{}
    74  
    75  	gd.Checkpoint = genesis
    76  	gdBytes, _ := json.Marshal(gd)
    77  
    78  	require.NoError(t, cpEng.UponGenesis(context.Background(), gdBytes))
    79  
    80  	expectedMarkets := []string{
    81  		"86948f946a64e14bb2e284f825cd46879d1cb581ce405cc62e4f74fcded190d3",
    82  		"3fed7242cce2cbe7df8cc3a2808969fc6e108f2047838c4af323c10430dfe041",
    83  		"5ed56476934d952229c0d796e143be4d1a96871d1607f9188dfa3727bdd6f7a0",
    84  		"2bf3cab7a239f34f40145a0700f8f12bc504bd2ec3a65d5915c4e58881dfcb52",
    85  		"eda61c9948ae97182c344b6a900e960a6c85271a4db1926eb26c82d847d9ba78",
    86  		"954410d873a6d1a419b8a11e7e3a5178f65b976f3140bb78fc97d21daf08877f",
    87  		"14719259af09239e479c107c6a69dbdae05dbde619ad06632af27a2fc2c9a9c7",
    88  		"3201812426fed4cc6d5cfbacdaa54e738791deb9f72743f8b18d3e9f6a3e222c",
    89  	}
    90  	govProposalsCP, _ := gov.Checkpoint()
    91  	proposals := &checkpointpb.Proposals{}
    92  	err := proto.Unmarshal(govProposalsCP, proposals)
    93  	require.NoError(t, err)
    94  	require.Equal(t, len(expectedMarkets), len(proposals.Proposals))
    95  
    96  	for i, expectedMarket := range expectedMarkets {
    97  		m, exists := ex.GetMarket(expectedMarket, false)
    98  		require.True(t, exists)
    99  		require.Equal(t, types.MarketTradingModeOpeningAuction, m.TradingMode)
   100  		require.Equal(t, types.MarketStatePending, m.State)
   101  		require.Equal(t, expectedMarket, proposals.Proposals[i].Id)
   102  	}
   103  }
   104  
   105  // Disable 'TestMarketRestoreFromCheckpoint' for now. 'testcp/scp.cp' needs to be regenerated for the new data sourcing types.
   106  func TestMarketRestoreFromCheckpointWithEmptySuccessor(t *testing.T) {
   107  	t.Skipf("Skipping test as need to regenerate testcp/scp.cp with appropriate values for LP - Zohar to fix")
   108  
   109  	now := time.Now()
   110  	ex, gov, cpEng := createExecutionEngine(t, now)
   111  	genesis := &checkpoint.GenesisState{
   112  		CheckpointHash:  "45ff656ab5f434ceb47329d109874a8d81c7f987d1e08f913f22265a809da766",
   113  		CheckpointState: base64.StdEncoding.EncodeToString(cpSuccessorFile),
   114  	}
   115  	gd := &struct {
   116  		Checkpoint *checkpoint.GenesisState `json:"checkpoint"`
   117  	}{}
   118  
   119  	gd.Checkpoint = genesis
   120  	gdBytes, _ := json.Marshal(gd)
   121  
   122  	require.NoError(t, cpEng.UponGenesis(context.Background(), gdBytes))
   123  
   124  	expectedMarkets := []string{
   125  		"2dca7baa5f7269b08d053668bca03f97f72e9a162327eebd941c54f1f9fb8f80",
   126  	}
   127  	govProposalsCP, _ := gov.Checkpoint()
   128  	proposals := &checkpointpb.Proposals{}
   129  	err := proto.Unmarshal(govProposalsCP, proposals)
   130  	require.NoError(t, err)
   131  	proposedMarkets := []string{}
   132  	marketPropIDs := map[string]struct{}{}
   133  	for _, proposal := range proposals.Proposals {
   134  		if nm := proposal.Terms.GetNewMarket(); nm != nil {
   135  			proposedMarkets = append(proposedMarkets, proposal.Id)
   136  			marketPropIDs[proposal.Id] = struct{}{}
   137  		}
   138  	}
   139  	require.Equal(t, len(expectedMarkets), len(proposedMarkets))
   140  	// this is a real cp file, we expect asset proposals etc... to be included, so
   141  	// the total number of proposals must be > just the market proposals
   142  	require.Less(t, len(expectedMarkets), len(proposals.Proposals))
   143  
   144  	for _, expectedMarket := range expectedMarkets {
   145  		m, exists := ex.GetMarket(expectedMarket, false)
   146  		require.True(t, exists)
   147  		require.Equal(t, types.MarketTradingModeOpeningAuction, m.TradingMode)
   148  		require.Equal(t, types.MarketStatePending, m.State)
   149  		_, ok := marketPropIDs[expectedMarket]
   150  		require.True(t, ok)
   151  	}
   152  }
   153  
   154  func getNodeWallet() *nodewallets.NodeWallets {
   155  	vegaPaths, cleanupFn := vgtesting.NewVegaPaths()
   156  	defer cleanupFn()
   157  	registryPass := vgrand.RandomStr(10)
   158  	walletsPass := vgrand.RandomStr(10)
   159  	config := nodewallets.NewDefaultConfig()
   160  	createTestNodeWallets(vegaPaths, registryPass, walletsPass)
   161  	nw, _ := nodewallets.GetNodeWallets(config, vegaPaths, registryPass)
   162  	return nw
   163  }
   164  
   165  func createTestNodeWallets(vegaPaths paths.Paths, registryPass, walletPass string) {
   166  	if _, err := nodewallets.GenerateEthereumWallet(vegaPaths, registryPass, walletPass, "", false); err != nil {
   167  		panic("couldn't generate Ethereum node wallet for tests")
   168  	}
   169  
   170  	if _, err := nodewallets.GenerateVegaWallet(vegaPaths, registryPass, walletPass, false); err != nil {
   171  		panic("couldn't generate Vega node wallet for tests")
   172  	}
   173  }
   174  
   175  func createExecutionEngine(t *testing.T, tm time.Time) (*execution.Engine, *governance.Engine, *checkpoint.Engine) {
   176  	t.Helper()
   177  	ctrl := gomock.NewController(t)
   178  	log := logging.NewTestLogger()
   179  	executionConfig := execution.NewDefaultConfig()
   180  	broker := bmocks.NewMockBroker(ctrl)
   181  	broker.EXPECT().Send(gomock.Any()).AnyTimes()
   182  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
   183  	timeService := mocks.NewMockTimeService(ctrl)
   184  	timeService.EXPECT().GetTimeNow().Return(tm).AnyTimes()
   185  
   186  	collateralService := collateral.New(log, collateral.NewDefaultConfig(), timeService, broker)
   187  	oracleService := emocks.NewMockOracleEngine(ctrl)
   188  	oracleService.EXPECT().Subscribe(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
   189  
   190  	statevar := emocks.NewMockStateVarEngine(ctrl)
   191  	statevar.EXPECT().RegisterStateVariable(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
   192  	statevar.EXPECT().NewEvent(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
   193  
   194  	epochEngine := emocks.NewMockEpochEngine(ctrl)
   195  	epochEngine.EXPECT().NotifyOnEpoch(gomock.Any(), gomock.Any()).Times(1)
   196  
   197  	primaryBridgeView := amocks.NewMockERC20BridgeView(ctrl)
   198  	secondaryBridgeView := amocks.NewMockERC20BridgeView(ctrl)
   199  	notary := amocks.NewMockNotary(ctrl)
   200  
   201  	asset, _ := assets.New(context.Background(), log, assets.NewDefaultConfig(), getNodeWallet().Ethereum, nil, nil, broker, primaryBridgeView, secondaryBridgeView, notary, false)
   202  	teams := emocks.NewMockTeams(ctrl)
   203  	bc := emocks.NewMockAccountBalanceChecker(ctrl)
   204  	marketTracker := common.NewMarketActivityTracker(log, teams, bc, broker, collateralService)
   205  	epochEngine.NotifyOnEpoch(marketTracker.OnEpochEvent, marketTracker.OnEpochRestore)
   206  	referralDiscountReward := fmocks.NewMockReferralDiscountRewardService(ctrl)
   207  	volumeDiscount := fmocks.NewMockVolumeDiscountService(ctrl)
   208  	volumeRebateService := fmocks.NewMockVolumeRebateService(ctrl)
   209  	referralDiscountReward.EXPECT().GetReferrer(gomock.Any()).Return(types.PartyID(""), errors.New("no referrer")).AnyTimes()
   210  	referralDiscountReward.EXPECT().ReferralDiscountFactorsForParty(gomock.Any()).Return(types.EmptyFactors).AnyTimes()
   211  	referralDiscountReward.EXPECT().RewardsFactorsMultiplierAppliedForParty(gomock.Any()).Return(types.EmptyFactors).AnyTimes()
   212  	volumeDiscount.EXPECT().VolumeDiscountFactorForParty(gomock.Any()).Return(num.DecimalZero()).AnyTimes()
   213  	execBanking := emocks.NewMockBanking(ctrl)
   214  	parties := emocks.NewMockParties(ctrl)
   215  	delayTarget := emocks.NewMockDelayTransactionsTarget(ctrl)
   216  	delayTarget.EXPECT().MarketDelayRequiredUpdated(gomock.Any(), gomock.Any()).AnyTimes()
   217  	exec := execution.NewEngine(log, executionConfig, timeService, collateralService, oracleService, broker, statevar, marketTracker, asset, referralDiscountReward, volumeDiscount, volumeRebateService, execBanking, parties, delayTarget)
   218  	accounts := mocks.NewMockStakingAccounts(ctrl)
   219  
   220  	witness := mocks.NewMockWitness(ctrl)
   221  	netp := netparams.New(log, netparams.NewDefaultConfig(), broker)
   222  
   223  	govBanking := mocks.NewMockBanking(ctrl)
   224  	gov := governance.NewEngine(log, governance.NewDefaultConfig(), accounts, timeService, broker, asset, witness, exec, netp, govBanking)
   225  	valFake := fakeCPComponent{
   226  		name: types.ValidatorsCheckpoint,
   227  	}
   228  	epochFake := fakeCPComponent{
   229  		name: types.EpochCheckpoint,
   230  	}
   231  	msFake := fakeCPComponent{
   232  		name: types.MultisigControlCheckpoint,
   233  	}
   234  	stakeFake := fakeCPComponent{
   235  		name: types.StakingCheckpoint,
   236  	}
   237  	delFake := fakeCPComponent{
   238  		name: types.DelegationCheckpoint,
   239  	}
   240  	prFake := fakeCPComponent{
   241  		name: types.PendingRewardsCheckpoint,
   242  	}
   243  	bankFake := fakeCPComponent{
   244  		name: types.BankingCheckpoint,
   245  	}
   246  	cpEngine, _ := checkpoint.New(log, checkpoint.NewDefaultConfig(), gov, netp, asset, collateralService, marketTracker, exec, valFake, epochFake, msFake, stakeFake, delFake, prFake, bankFake)
   247  
   248  	return exec, gov, cpEngine
   249  }
   250  
   251  type fakeCPComponent struct {
   252  	name types.CheckpointName
   253  }
   254  
   255  func (f fakeCPComponent) Name() types.CheckpointName {
   256  	return f.name
   257  }
   258  
   259  func (fakeCPComponent) Load(_ context.Context, _ []byte) error {
   260  	return nil
   261  }
   262  
   263  func (fakeCPComponent) Checkpoint() ([]byte, error) {
   264  	return []byte{}, nil
   265  }