From 10bbf568b560f9697066382bd2f4730ba8a3f458 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 8 Feb 2024 11:23:57 +0100 Subject: [PATCH 1/9] Port key assignment to MBT driver --- tests/mbt/driver/core.go | 15 ++- tests/mbt/driver/generate_more_traces.sh | 3 +- tests/mbt/driver/generate_traces.sh | 3 +- tests/mbt/driver/mbt_test.go | 125 ++++++++++++++++++----- tests/mbt/driver/stats.go | 2 + 5 files changed, 118 insertions(+), 30 deletions(-) diff --git a/tests/mbt/driver/core.go b/tests/mbt/driver/core.go index f9f1e12e05..b9a4293df1 100644 --- a/tests/mbt/driver/core.go +++ b/tests/mbt/driver/core.go @@ -20,6 +20,7 @@ import ( abcitypes "github.com/cometbft/cometbft/abci/types" cmttypes "github.com/cometbft/cometbft/types" + "github.com/cometbft/cometbft/proto/tendermint/crypto" appConsumer "github.com/cosmos/interchain-security/v4/app/consumer" appProvider "github.com/cosmos/interchain-security/v4/app/provider" simibc "github.com/cosmos/interchain-security/v4/testutil/simibc" @@ -123,9 +124,13 @@ func (s *Driver) consumerPower(i int64, chain ChainId) (int64, error) { return v.Power, nil } +func (s *Driver) stakingValidator(i int64) (stakingtypes.Validator, bool) { + return s.providerStakingKeeper().GetValidator(s.ctx(PROVIDER), s.validator(i)) +} + // providerPower returns the power(=number of bonded tokens) of the i-th validator on the provider. func (s *Driver) providerPower(i int64) (int64, error) { - v, found := s.providerStakingKeeper().GetValidator(s.ctx(PROVIDER), s.validator(i)) + v, found := s.stakingValidator(i) if !found { return 0, fmt.Errorf("validator with id %v not found on provider", i) } else { @@ -370,6 +375,14 @@ func (s *Driver) setTime(chain ChainId, newTime time.Time) { testChain.App.BeginBlock(abcitypes.RequestBeginBlock{Header: testChain.CurrentHeader}) } +func (s *Driver) AssignKey(chain ChainId, valIndex int64, value crypto.PublicKey) error { + stakingVal, found := s.stakingValidator(valIndex) + if !found { + return fmt.Errorf("validator with id %v not found on provider", valIndex) + } + return s.providerKeeper().AssignConsumerKey(s.providerCtx(), string(chain), stakingVal, value) +} + // 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 9af4da82e9..40589bb83b 100755 --- a/tests/mbt/driver/generate_more_traces.sh +++ b/tests/mbt/driver/generate_more_traces.sh @@ -9,4 +9,5 @@ go run ./... -modelPath=../model/ccv_boundeddrift.qnt -step stepBoundedDrift -in 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 \ No newline at end of file +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 diff --git a/tests/mbt/driver/generate_traces.sh b/tests/mbt/driver/generate_traces.sh index ca0a6ba973..9f1134fb26 100755 --- a/tests/mbt/driver/generate_traces.sh +++ b/tests/mbt/driver/generate_traces.sh @@ -9,4 +9,5 @@ go run ./... -modelPath=../model/ccv_boundeddrift.qnt -step stepBoundedDrift -in 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 \ No newline at end of file +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 diff --git a/tests/mbt/driver/mbt_test.go b/tests/mbt/driver/mbt_test.go index 78f9e7910f..a55d870dda 100644 --- a/tests/mbt/driver/mbt_test.go +++ b/tests/mbt/driver/mbt_test.go @@ -15,10 +15,13 @@ import ( "github.com/kylelemons/godebug/pretty" "github.com/stretchr/testify/require" - sdktypes "github.com/cosmos/cosmos-sdk/types" - cmttypes "github.com/cometbft/cometbft/types" + tmencoding "github.com/cometbft/cometbft/crypto/encoding" + "github.com/cosmos/interchain-security/v4/testutil/integration" + + sdktypes "github.com/cosmos/cosmos-sdk/types" + providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" ) @@ -69,6 +72,7 @@ func TestMBT(t *testing.T) { t.Logf("Number of sent packets: %v", stats.numSentPackets) t.Logf("Number of blocks: %v", stats.numBlocks) t.Logf("Number of transactions: %v", stats.numTxs) + t.Logf("Number of key assignments: %v", stats.numKeyAssignments) t.Logf("Average summed block time delta passed per trace: %v", stats.totalBlockTimePassedPerTrace/time.Duration(numTraces)) } @@ -117,6 +121,21 @@ func RunItfTrace(t *testing.T, path string) { t.Log("Chains are: ", chains) + // generate keys that can be assigned on consumers, according to the ConsumerAddresses in the trace + consumerAddressesExpr := params["ConsumerAddresses"].Value.(itf.ListExprType) + + _, _, consumerPrivVals, err := integration.CreateValidators(len(consumerAddressesExpr)) + require.NoError(t, err, "Error creating consumer signers") + + consumerAddrNamesToPrivVals := make(map[string]cmttypes.PrivValidator, len(consumerAddressesExpr)) + realAddrsToModelConsAddrs := make(map[string]string, len(consumerAddressesExpr)) + i := 0 + for address, privVal := range consumerPrivVals { + consumerAddrNamesToPrivVals[consumerAddressesExpr[i].Value.(string)] = privVal + realAddrsToModelConsAddrs[address] = consumerAddressesExpr[i].Value.(string) + i++ + } + // create params struct vscTimeout := time.Duration(params["VscTimeout"].Value.(int64)) * time.Second @@ -145,6 +164,15 @@ func RunItfTrace(t *testing.T, path string) { valSet, addressMap, signers, err := CreateValSet(initialValSet) require.NoError(t, err, "Error creating validator set") + // get the set of signers for consumers: the validator signers, plus signers for the assignable addresses + consumerSigners := make(map[string]cmttypes.PrivValidator, 0) + for consAddr, consPrivVal := range consumerPrivVals { + consumerSigners[consAddr] = consPrivVal + } + for consAddr, signer := range signers { + consumerSigners[consAddr] = signer + } + // get a slice of validators in the right order nodes := make([]*cmttypes.Validator, len(valNames)) for i, valName := range valNames { @@ -211,6 +239,10 @@ func RunItfTrace(t *testing.T, path string) { // and then increment the rest of the time runningConsumersBefore := driver.runningConsumers() driver.endAndBeginBlock("provider", 1*time.Nanosecond) + for _, consumer := range driver.runningConsumers() { + UpdateProviderClientOnConsumer(t, driver, consumer.ChainId) + } + driver.endAndBeginBlock("provider", time.Duration(timeAdvancement)*time.Second-1*time.Nanosecond) runningConsumersAfter := driver.runningConsumers() @@ -243,7 +275,7 @@ func RunItfTrace(t *testing.T, path string) { consumer.Value.(string), modelParams, driver.providerChain().Vals, - signers, + consumerSigners, nodes, valNames, driver.providerChain(), @@ -268,11 +300,8 @@ func RunItfTrace(t *testing.T, path string) { if len(consumersToStart) > 0 && consumer.ChainId == consumersToStart[len(consumersToStart)-1].Value.(string) { continue } - consumerChainId := consumer.ChainId - driver.path(ChainId(consumerChainId)).AddClientHeader(PROVIDER, driver.providerHeader()) - err := driver.path(ChainId(consumerChainId)).UpdateClient(consumerChainId, false) - require.True(t, err == nil, "Error updating client from %v on provider: %v", consumerChainId, err) + UpdateProviderClientOnConsumer(t, driver, consumer.ChainId) } case "EndAndBeginBlockForConsumer": @@ -286,13 +315,12 @@ func RunItfTrace(t *testing.T, path string) { _ = headerBefore driver.endAndBeginBlock(ChainId(consumerChain), 1*time.Nanosecond) + UpdateConsumerClientOnProvider(t, driver, consumerChain) + driver.endAndBeginBlock(ChainId(consumerChain), time.Duration(timeAdvancement)*time.Second-1*time.Nanosecond) // update the client on the provider - consumerHeader := driver.chain(ChainId(consumerChain)).LastHeader - driver.path(ChainId(consumerChain)).AddClientHeader(consumerChain, consumerHeader) - err := driver.path(ChainId(consumerChain)).UpdateClient(PROVIDER, false) - require.True(t, err == nil, "Error updating client from %v on provider: %v", consumerChain, err) + UpdateConsumerClientOnProvider(t, driver, consumerChain) case "DeliverVscPacket": consumerChain := lastAction["consumerChain"].Value.(string) @@ -328,8 +356,26 @@ func RunItfTrace(t *testing.T, path string) { expectError = false driver.DeliverPacketFromConsumer(ChainId(consumerChain), expectError) } - default: + case "KeyAssignment": + consumerChain := lastAction["consumerChain"].Value.(string) + node := lastAction["validator"].Value.(string) + consumerAddr := lastAction["consumerAddr"].Value.(string) + + t.Log("KeyAssignment", consumerChain, node, consumerAddr) + stats.numKeyAssignments++ + valIndex := getIndexOfString(node, valNames) + assignedPrivVal := consumerAddrNamesToPrivVals[consumerAddr] + assignedKey, err := assignedPrivVal.GetPubKey() + require.NoError(t, err, "Error getting pubkey") + + 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") + + default: log.Fatalf("Error loading trace file %s, step %v: do not know action type %s", path, index, actionKind) } @@ -364,7 +410,7 @@ func RunItfTrace(t *testing.T, path string) { require.Equal(t, modelRunningConsumers, actualRunningConsumers, "Running consumers do not match") // check validator sets - provider current validator set should be the one from the staking keeper - CompareValidatorSets(t, driver, currentModelState, actualRunningConsumers) + CompareValidatorSets(t, driver, currentModelState, actualRunningConsumers, realAddrsToModelConsAddrs) // check times - sanity check that the block times match the ones from the model CompareTimes(driver, actualRunningConsumers, currentModelState, timeOffset) @@ -383,7 +429,27 @@ func RunItfTrace(t *testing.T, path string) { t.Log("🟢 Trace is ok!") } -func CompareValidatorSets(t *testing.T, driver *Driver, currentModelState map[string]itf.Expr, consumers []string) { +func UpdateProviderClientOnConsumer(t *testing.T, driver *Driver, consumerChainId string) { + driver.path(ChainId(consumerChainId)).AddClientHeader(PROVIDER, driver.providerHeader()) + err := driver.path(ChainId(consumerChainId)).UpdateClient(consumerChainId, false) + require.True(t, err == nil, "Error updating client from %v on provider: %v", consumerChainId, err) +} + +func UpdateConsumerClientOnProvider(t *testing.T, driver *Driver, consumerChain string) { + consumerHeader := driver.chain(ChainId(consumerChain)).LastHeader + driver.path(ChainId(consumerChain)).AddClientHeader(consumerChain, consumerHeader) + err := driver.path(ChainId(consumerChain)).UpdateClient(PROVIDER, false) + require.True(t, err == nil, "Error updating client from %v on provider: %v", consumerChain, err) +} + +func CompareValidatorSets( + t *testing.T, + driver *Driver, + currentModelState map[string]itf.Expr, + consumers []string, + // a map from real addresses to the names of those consumer addresses in the model + keyAddrsToModelConsAddrName map[string]string, +) { t.Helper() modelValSet := ValidatorSet(currentModelState, "provider") @@ -407,23 +473,28 @@ func CompareValidatorSets(t *testing.T, driver *Driver, currentModelState map[st pubkey, err := val.ConsPubKey() require.NoError(t, err, "Error getting pubkey") - consAddr := providertypes.NewConsumerConsAddress(sdktypes.ConsAddress(pubkey.Address().Bytes())) + consAddrModelName, ok := keyAddrsToModelConsAddrName[pubkey.Address().String()] + if ok { // the node has a key assigned, use the name of the consumer address in the model + consumerCurValSet[consAddrModelName] = val.Power + } else { // the node doesn't have a key assigned yet, get the validator moniker + consAddr := providertypes.NewConsumerConsAddress(sdktypes.ConsAddress(pubkey.Address().Bytes())) - // the consumer vals right now are CrossChainValidators, for which we don't know their mnemonic - // so we need to find the mnemonic of the consumer val now to enter it by name in the map + // the consumer vals right now are CrossChainValidators, for which we don't know their mnemonic + // so we need to find the mnemonic of the consumer val now to enter it by name in the map - // get the address on the provider that corresponds to the consumer address - providerConsAddr, found := driver.providerKeeper().GetValidatorByConsumerAddr(driver.providerCtx(), consumer, consAddr) - if !found { - providerConsAddr = providertypes.NewProviderConsAddress(consAddr.Address) - } + // get the address on the provider that corresponds to the consumer address + providerConsAddr, found := driver.providerKeeper().GetValidatorByConsumerAddr(driver.providerCtx(), consumer, consAddr) + if !found { + providerConsAddr = providertypes.NewProviderConsAddress(consAddr.Address) + } - // get the validator for that address on the provider - providerVal, found := driver.providerStakingKeeper().GetValidatorByConsAddr(driver.providerCtx(), providerConsAddr.Address) - require.True(t, found, "Error getting provider validator") + // get the validator for that address on the provider + providerVal, found := driver.providerStakingKeeper().GetValidatorByConsAddr(driver.providerCtx(), providerConsAddr.Address) + require.True(t, found, "Error getting provider validator") - // use the moniker of that validator - consumerCurValSet[providerVal.GetMoniker()] = val.Power + // use the moniker of that validator + consumerCurValSet[providerVal.GetMoniker()] = val.Power + } } require.NoError(t, CompareValSet(modelValSet, consumerCurValSet), "Validator sets do not match for consumer %v", consumer) } diff --git a/tests/mbt/driver/stats.go b/tests/mbt/driver/stats.go index 0d397571be..8b4c95a3dd 100644 --- a/tests/mbt/driver/stats.go +++ b/tests/mbt/driver/stats.go @@ -16,4 +16,6 @@ type Stats struct { numTxs int totalBlockTimePassedPerTrace time.Duration + + numKeyAssignments int } From a58c7fa1c524a162d8b43019caf39a0fb1da742f Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 8 Feb 2024 13:35:41 +0100 Subject: [PATCH 2/9] Add PSS trace generation --- tests/mbt/driver/generate_traces.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mbt/driver/generate_traces.sh b/tests/mbt/driver/generate_traces.sh index 9f1134fb26..df54b3f17c 100755 --- a/tests/mbt/driver/generate_traces.sh +++ b/tests/mbt/driver/generate_traces.sh @@ -10,4 +10,4 @@ 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 stepBoundedDriftKeyAndPSS --traceFolder traces/bound_pss -numTraces 1 -numSteps 100 -numSamples 20 \ No newline at end of file From 46fc809d428dc597fbb4aed5ad1db186ea58332b Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 8 Feb 2024 13:39:29 +0100 Subject: [PATCH 3/9] Add PSS trace gen to longer trace gen --- tests/mbt/driver/generate_more_traces.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mbt/driver/generate_more_traces.sh b/tests/mbt/driver/generate_more_traces.sh index 40589bb83b..c97b194d27 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 \ No newline at end of file From 91d54a415ed156f33c2e4633d9ada89a6611fb4f Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Thu, 8 Feb 2024 13:56:37 +0100 Subject: [PATCH 4/9] Start handling top N parameter for new consumers --- tests/mbt/driver/mbt_test.go | 5 ++++- tests/mbt/driver/setup.go | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/mbt/driver/mbt_test.go b/tests/mbt/driver/mbt_test.go index a55d870dda..bc6221282d 100644 --- a/tests/mbt/driver/mbt_test.go +++ b/tests/mbt/driver/mbt_test.go @@ -271,14 +271,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, ) } diff --git a/tests/mbt/driver/setup.go b/tests/mbt/driver/setup.go index 83fa6e0669..160ee0f4ce 100644 --- a/tests/mbt/driver/setup.go +++ b/tests/mbt/driver/setup.go @@ -433,6 +433,7 @@ 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) From c809296790d6d35d83dfa3061ba0b0de30780660 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 9 Feb 2024 12:46:23 +0100 Subject: [PATCH 5/9] Finish merge --- tests/mbt/driver/core.go | 8 -------- tests/mbt/driver/generate_more_traces.sh | 4 ---- 2 files changed, 12 deletions(-) diff --git a/tests/mbt/driver/core.go b/tests/mbt/driver/core.go index 4da1daeb2d..66413bafe9 100644 --- a/tests/mbt/driver/core.go +++ b/tests/mbt/driver/core.go @@ -375,20 +375,12 @@ func (s *Driver) setTime(chain ChainId, newTime time.Time) { testChain.App.BeginBlock(abcitypes.RequestBeginBlock{Header: testChain.CurrentHeader}) } -<<<<<<< HEAD -func (s *Driver) AssignKey(chain ChainId, valIndex int64, value crypto.PublicKey) error { -======= func (s *Driver) AssignKey(chain ChainId, valIndex int64, key crypto.PublicKey) error { ->>>>>>> feat/partial-set-security stakingVal, found := s.stakingValidator(valIndex) if !found { return fmt.Errorf("validator with id %v not found on provider", valIndex) } -<<<<<<< HEAD - return s.providerKeeper().AssignConsumerKey(s.providerCtx(), string(chain), stakingVal, value) -======= return s.providerKeeper().AssignConsumerKey(s.providerCtx(), string(chain), stakingVal, key) ->>>>>>> feat/partial-set-security } // DeliverPacketToConsumer delivers a packet from the provider to the given consumer recipient. diff --git a/tests/mbt/driver/generate_more_traces.sh b/tests/mbt/driver/generate_more_traces.sh index ef99e525b9..905507a108 100755 --- a/tests/mbt/driver/generate_more_traces.sh +++ b/tests/mbt/driver/generate_more_traces.sh @@ -10,9 +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 -<<<<<<< HEAD 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 -======= -go run ./... -modelPath=../model/ccv_boundeddrift.qnt --step stepBoundedDriftKeyAssignment --traceFolder traces/bound_key -numTraces 20 -numSteps 100 -numSamples 20 ->>>>>>> feat/partial-set-security From 42b11d2508d302c12e3f4713cf985a2e17fee0c8 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 9 Feb 2024 15:06:07 +0100 Subject: [PATCH 6/9] Add handling for optin/optout steps --- tests/mbt/driver/core.go | 28 ++++++++++++++++++++++++++++ tests/mbt/driver/mbt_test.go | 32 +++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/tests/mbt/driver/core.go b/tests/mbt/driver/core.go index 66413bafe9..2a01d45bfc 100644 --- a/tests/mbt/driver/core.go +++ b/tests/mbt/driver/core.go @@ -383,6 +383,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/mbt_test.go b/tests/mbt/driver/mbt_test.go index c399a47585..54135c575d 100644 --- a/tests/mbt/driver/mbt_test.go +++ b/tests/mbt/driver/mbt_test.go @@ -304,7 +304,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 } @@ -379,8 +380,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", From 50522f726c92358457d66d1c584566d3e072aa7c Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 9 Feb 2024 15:10:33 +0100 Subject: [PATCH 7/9] Remove expected error from OptIn, which should not error --- tests/mbt/model/ccv_pss_model.qnt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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, From 6935373c5f839bcf910acbaa5ec5bc72c1c61e3e Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 9 Feb 2024 15:22:21 +0100 Subject: [PATCH 8/9] set top N parameter during path setup --- tests/mbt/driver/setup.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/mbt/driver/setup.go b/tests/mbt/driver/setup.go index 160ee0f4ce..5fc7097404 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) @@ -362,6 +362,9 @@ 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 + 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,6 +440,8 @@ func (s *Driver) setupConsumer( ) { 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 @@ -444,7 +449,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) } From b0152dd86c3fb25b1977965a1eb633e51cbcef19 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 9 Feb 2024 15:23:48 +0100 Subject: [PATCH 9/9] Add comment to setup.go --- tests/mbt/driver/setup.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/mbt/driver/setup.go b/tests/mbt/driver/setup.go index 5fc7097404..ada9bddca3 100644 --- a/tests/mbt/driver/setup.go +++ b/tests/mbt/driver/setup.go @@ -363,6 +363,8 @@ func (s *Driver) ConfigureNewPath(consumerChain, providerChain *ibctesting.TestC 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