From 64f5651e5a00b1d3f2c615eddd3ca816dc3d7d38 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt <57488781+p-offtermatt@users.noreply.github.com> Date: Wed, 14 Feb 2024 12:43:27 +0100 Subject: [PATCH] test: Add driver for PSS (#1636) * Port key assignment to MBT driver * Add PSS trace generation * Add PSS trace gen to longer trace gen * Start handling top N parameter for new consumers * Finish merge * Add handling for optin/optout steps * Remove expected error from OptIn, which should not error * set top N parameter during path setup * Add comment to setup.go --- tests/mbt/driver/core.go | 28 ++++++++++++++++++ tests/mbt/driver/generate_more_traces.sh | 3 +- tests/mbt/driver/generate_traces.sh | 3 +- tests/mbt/driver/mbt_test.go | 37 +++++++++++++++++++++--- tests/mbt/driver/setup.go | 12 ++++++-- tests/mbt/model/ccv_pss_model.qnt | 3 +- 6 files changed, 76 insertions(+), 10 deletions(-) diff --git a/tests/mbt/driver/core.go b/tests/mbt/driver/core.go index 345122fa6e..0e074c6580 100644 --- a/tests/mbt/driver/core.go +++ b/tests/mbt/driver/core.go @@ -387,6 +387,34 @@ func (s *Driver) AssignKey(chain ChainId, valIndex int64, key crypto.PublicKey) return s.providerKeeper().AssignConsumerKey(s.providerCtx(), string(chain), stakingVal, key) } +// Opts the given validator into the given consumer chain on the provider. +func (s *Driver) OptIn(chain ChainId, valIndex int64) error { + stakingVal, found := s.stakingValidator(valIndex) + if !found { + return fmt.Errorf("validator with id %v not found on provider", valIndex) + } + consPubKey, err := stakingVal.ConsPubKey() + if err != nil { + return err + } + consAddr := sdk.GetConsAddress(consPubKey) + return s.providerKeeper().HandleOptIn(s.providerCtx(), string(chain), providertypes.NewProviderConsAddress(consAddr), nil) +} + +// Opts the given validator out of the given consumer chain on the provider. +func (s *Driver) OptOut(chain ChainId, valIndex int64) error { + stakingVal, found := s.stakingValidator(valIndex) + if !found { + return fmt.Errorf("validator with id %v not found on provider", valIndex) + } + consPubKey, err := stakingVal.ConsPubKey() + if err != nil { + return err + } + consAddr := sdk.GetConsAddress(consPubKey) + return s.providerKeeper().HandleOptOut(s.providerCtx(), string(chain), providertypes.NewProviderConsAddress(consAddr)) +} + // DeliverPacketToConsumer delivers a packet from the provider to the given consumer recipient. // It updates the client before delivering the packet. // Since the channel is ordered, the packet that is delivered is the first packet in the outbox. diff --git a/tests/mbt/driver/generate_more_traces.sh b/tests/mbt/driver/generate_more_traces.sh index 40589bb83b..905507a108 100755 --- a/tests/mbt/driver/generate_more_traces.sh +++ b/tests/mbt/driver/generate_more_traces.sh @@ -10,4 +10,5 @@ echo "Generating synced traces with maturations" go run ./... -modelPath=../model/ccv_sync.qnt -init initSync -step stepSync -invariant CanReceiveMaturations -traceFolder traces/sync_mat -numTraces 20 -numSteps 300 -numSamples 20 echo "Generating long synced traces without invariants" go run ./... -modelPath=../model/ccv_sync.qnt -init initSync -step stepSync -traceFolder traces/sync_noinv -numTraces 20 -numSteps 500 -numSamples 1 -go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAssignment --traceFolder traces/bound_key -numTraces 20 -numSteps 100 -numSamples 20 \ No newline at end of file +go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAssignment --traceFolder traces/bound_key -numTraces 20 -numSteps 100 -numSamples 20 +go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAndPSS --traceFolder traces/bound_pss -numTraces 20 -numSteps 100 -numSamples 20 diff --git a/tests/mbt/driver/generate_traces.sh b/tests/mbt/driver/generate_traces.sh index 9f1134fb26..f898b27e2e 100755 --- a/tests/mbt/driver/generate_traces.sh +++ b/tests/mbt/driver/generate_traces.sh @@ -10,4 +10,5 @@ echo "Generating synced traces with maturations" go run ./... -modelPath=../model/ccv_sync.qnt -init initSync -step stepSync -invariant CanReceiveMaturations -traceFolder traces/sync_mat -numTraces 1 -numSteps 300 -numSamples 20 echo "Generating long synced traces without invariants" go run ./... -modelPath=../model/ccv_sync.qnt -init initSync -step stepSync -traceFolder traces/sync_noinv -numTraces 1 -numSteps 500 -numSamples 1 -go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAssignment --traceFolder traces/bound_key -numTraces 1 -numSteps 100 -numSamples 20 \ No newline at end of file +go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAssignment --traceFolder traces/bound_key -numTraces 1 -numSteps 100 -numSamples 20 +go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAndPSS --traceFolder traces/bound_pss -numTraces 1 -numSteps 100 -numSamples 20 diff --git a/tests/mbt/driver/mbt_test.go b/tests/mbt/driver/mbt_test.go index 692cf6ee14..c31ec28359 100644 --- a/tests/mbt/driver/mbt_test.go +++ b/tests/mbt/driver/mbt_test.go @@ -314,14 +314,17 @@ func RunItfTrace(t *testing.T, path string) { driver.coordinator.CurrentTime = driver.runningTime("provider") // start consumers for _, consumer := range consumersToStart { + chainId := consumer.Value.(itf.MapExprType)["chain"].Value.(string) + topN := consumer.Value.(itf.MapExprType)["topN"].Value.(int64) driver.setupConsumer( - consumer.Value.(string), + chainId, modelParams, driver.providerChain().Vals, consumerSigners, nodes, valNames, driver.providerChain(), + topN, ) } @@ -340,7 +343,8 @@ func RunItfTrace(t *testing.T, path string) { // unless it was the last consumer to be started, in which case it already has the header // as we called driver.setupConsumer for _, consumer := range driver.runningConsumers() { - if len(consumersToStart) > 0 && consumer.ChainId == consumersToStart[len(consumersToStart)-1].Value.(string) { + if len(consumersToStart) > 0 && + consumer.ChainId == consumersToStart[len(consumersToStart)-1].Value.(itf.MapExprType)["chain"].Value.(string) { continue } @@ -415,8 +419,33 @@ func RunItfTrace(t *testing.T, path string) { protoPubKey, err := tmencoding.PubKeyToProto(assignedKey) require.NoError(t, err, "Error converting pubkey to proto") - error := driver.AssignKey(ChainId(consumerChain), int64(valIndex), protoPubKey) - require.NoError(t, error, "Error assigning key") + err = driver.AssignKey(ChainId(consumerChain), int64(valIndex), protoPubKey) + require.NoError(t, err, "Error assigning key") + case "OptIn": + consumerChain := lastAction["consumerChain"].Value.(string) + validator := lastAction["validator"].Value.(string) + t.Log("OptIn", consumerChain, validator) + + valIndex := getIndexOfString(validator, valNames) + + err := driver.OptIn(ChainId(consumerChain), int64(valIndex)) + require.NoError(t, err, "Error opting in") + + case "OptOut": + consumerChain := lastAction["consumerChain"].Value.(string) + validator := lastAction["validator"].Value.(string) + expectedError := lastAction["expectedError"].Value.(string) + t.Log("OptOut", consumerChain, validator, expectedError) + + valIndex := getIndexOfString(validator, valNames) + + err := driver.OptOut(ChainId(consumerChain), int64(valIndex)) + + if expectedError != "" { + require.Error(t, err, "Expected an error: %v", expectedError) + } else { + require.NoError(t, err, "Error opting out, but expected no error") + } default: log.Fatalf("Error loading trace file %s, step %v: do not know action type %s", diff --git a/tests/mbt/driver/setup.go b/tests/mbt/driver/setup.go index c0020a4095..6408f0e873 100644 --- a/tests/mbt/driver/setup.go +++ b/tests/mbt/driver/setup.go @@ -310,7 +310,7 @@ func newChain( // Creates a path for cross-chain validation from the consumer to the provider and configures the channel config of the endpoints // as well as the clients. // this function stops when there is an initialized, ready-to-relay channel between the provider and consumer. -func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestChain, params ModelParams) *ibctesting.Path { +func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestChain, params ModelParams, topN uint32) *ibctesting.Path { consumerChainId := ChainId(consumerChain.ChainID) path := ibctesting.NewPath(consumerChain, providerChain) @@ -382,6 +382,11 @@ func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestC consumerGenesisForProvider) require.NoError(s.t, err, "Error setting consumer genesis on provider for chain %v", consumerChain.ChainID) + // set the top N percentage + // needs to be done before the provider queues the first vsc packet to the consumer + // TODO: might be able to move this into setupConsumer, need to test once more logic is here + s.providerKeeper().SetTopN(providerChain.GetContext(), consumerChain.ChainID, topN) + // Client ID is set in InitGenesis and we treat it as a black box. So // must query it to use it with the endpoint. clientID, _ := s.consumerKeeper(consumerChainId).GetProviderClientID(s.ctx(consumerChainId)) @@ -437,9 +442,12 @@ func (s *Driver) setupConsumer( nodes []*cmttypes.Validator, // the list of nodes, even ones that have no voting power initially valNames []string, providerChain *ibctesting.TestChain, + topN int64, ) { s.t.Logf("Starting consumer %v", chain) + // TODO: reuse the partial set computation logic to compute the initial validator set + // for top N chains initValUpdates := cmttypes.TM2PB.ValidatorUpdates(valSet) // start consumer chains @@ -447,7 +455,7 @@ func (s *Driver) setupConsumer( consumerChain := newChain(s.t, params, s.coordinator, icstestingutils.ConsumerAppIniter(initValUpdates), chain, valSet, signers, nodes, valNames) s.coordinator.Chains[chain] = consumerChain - path := s.ConfigureNewPath(consumerChain, providerChain, params) + path := s.ConfigureNewPath(consumerChain, providerChain, params, uint32(topN)) s.simibcs[ChainId(chain)] = simibc.MakeRelayedPath(s.t, path) } diff --git a/tests/mbt/model/ccv_pss_model.qnt b/tests/mbt/model/ccv_pss_model.qnt index 76c4873b43..d2911a0989 100644 --- a/tests/mbt/model/ccv_pss_model.qnt +++ b/tests/mbt/model/ccv_pss_model.qnt @@ -22,8 +22,7 @@ module ccv_pss_model { ...emptyAction, kind: "OptIn", consumerChain: consumer, - validator: validator, - expectedError: res.error + validator: validator } ), params' = params,