diff --git a/tests/interchain/chainsuite/chain_ics.go b/tests/interchain/chainsuite/chain_ics.go index d4c9797329..c13248f6de 100644 --- a/tests/interchain/chainsuite/chain_ics.go +++ b/tests/interchain/chainsuite/chain_ics.go @@ -12,6 +12,7 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/testutil" "github.com/tidwall/gjson" "github.com/tidwall/sjson" + "go.uber.org/multierr" "golang.org/x/mod/semver" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" @@ -219,7 +220,6 @@ func (p *Chain) DefaultConsumerChainSpec(ctx context.Context, chainID string, co } genesisOverrides := []cosmos.GenesisKV{ cosmos.NewGenesisKV("app_state.slashing.params.signed_blocks_window", strconv.Itoa(SlashingWindowConsumer)), - cosmos.NewGenesisKV("consensus_params.block.max_gas", "50000000"), } if config.TopN >= 0 { genesisOverrides = append(genesisOverrides, cosmos.NewGenesisKV("app_state.ccvconsumer.params.soft_opt_out_threshold", "0.0")) @@ -235,22 +235,30 @@ func (p *Chain) DefaultConsumerChainSpec(ctx context.Context, chainID string, co ) } - modifyGenesis := cosmos.ModifyGenesis(genesisOverrides) if chainType == strideChain { genesisOverrides = append(genesisOverrides, cosmos.NewGenesisKV("app_state.gov.params.voting_period", GovVotingPeriod.String()), ) - modifyGenesis = func(cc ibc.ChainConfig, b []byte) ([]byte, error) { - b, err := cosmos.ModifyGenesis(genesisOverrides)(cc, b) + } + modifyGenesis := func(cc ibc.ChainConfig, b []byte) ([]byte, error) { + b, err := cosmos.ModifyGenesis(genesisOverrides)(cc, b) + if err != nil { + return nil, err + } + if chainType == strideChain { + b, err = sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"day\").duration", "120s") if err != nil { return nil, err } - b, err = sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"day\").duration", "120s") + b, err = sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"stride_epoch\").duration", "30s") if err != nil { return nil, err } - return sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"stride_epoch\").duration", "30s") } + if gjson.GetBytes(b, "consensus").Exists() { + return sjson.SetBytes(b, "consensus.block.max_gas", "50000000") + } + return sjson.SetBytes(b, "consensus_params.block.max_gas", "50000000") } return &interchaintest.ChainSpec{ @@ -403,6 +411,7 @@ func (p *Chain) consumerAdditionProposal(ctx context.Context, chainID string, co HistoricalEntries: 10000, UnbondingPeriod: 1728000000000000, Deposit: strconv.Itoa(GovMinDepositAmount/2) + p.Config().Denom, + MinStake: uint64(3_999_999), } if config.TopN >= 0 { prop.TopN = uint32(config.TopN) @@ -417,7 +426,7 @@ func (p *Chain) consumerAdditionProposal(ctx context.Context, chainID string, co if err != nil { return nil, nil, err } - errCh := make(chan error) + errCh := make(chan error, 1) go func() { defer close(errCh) if err := p.WaitForProposalStatus(ctx, propTx.ProposalID, govv1.StatusDepositPeriod); err != nil { @@ -535,26 +544,55 @@ func (p *Chain) IsValoperJailed(ctx context.Context, valoper string) (bool, erro return gjson.GetBytes(out, "validator.jailed").Bool(), nil } -func (p *Chain) IsValidatorJailedForConsumerDowntime(ctx context.Context, relayer Relayer, consumer *Chain, validatorIdx int) (jailed bool, err error) { +func (p *Chain) IsValidatorJailedForConsumerDowntime(ctx context.Context, relayer *Relayer, consumer *Chain, validatorIdx int) (jailed bool, err error) { if err = consumer.Validators[validatorIdx].StopContainer(ctx); err != nil { return } defer func() { - err = consumer.Validators[validatorIdx].StartContainer(ctx) + sErr := consumer.Validators[validatorIdx].StartContainer(ctx) + if sErr != nil { + err = multierr.Append(err, sErr) + return + } + time.Sleep(10 * CommitTimeout) + if jailed && err == nil { + if _, err = p.Validators[validatorIdx].ExecTx(ctx, p.ValidatorWallets[validatorIdx].Moniker, "slashing", "unjail"); err != nil { + return + } + var stillJailed bool + if stillJailed, err = p.IsValoperJailed(ctx, p.ValidatorWallets[validatorIdx].ValoperAddress); stillJailed { + err = fmt.Errorf("validator %d is still jailed after unjailing", validatorIdx) + } + } }() - channel, err := relayer.GetChannelWithPort(ctx, consumer, p, "consumer") - if err != nil { - return - } - if err = testutil.WaitForBlocks(ctx, SlashingWindowConsumer+1, consumer); err != nil { - return - } - rs := relayer.Exec(ctx, GetRelayerExecReporter(ctx), []string{ - "hermes", "clear", "packets", "--port", "consumer", "--channel", channel.ChannelID, - "--chain", consumer.Config().ChainID, - }, nil) - if rs.Err != nil { - return false, rs.Err + if p.Config().ChainID != consumer.Config().ChainID { + var channel *ibc.ChannelOutput + channel, err = relayer.GetChannelWithPort(ctx, consumer, p, "consumer") + if err != nil { + return + } + rs := relayer.Exec(ctx, GetRelayerExecReporter(ctx), []string{ + "hermes", "clear", "packets", "--port", "consumer", "--channel", channel.ChannelID, + "--chain", consumer.Config().ChainID, + }, nil) + if rs.Err != nil { + return false, rs.Err + } + tCtx, tCancel := context.WithTimeout(ctx, (SlashingWindowConsumer+3)*CommitTimeout) + defer tCancel() + if err = testutil.WaitForBlocks(tCtx, SlashingWindowConsumer+1, consumer); err != nil { + if tCtx.Err() != nil { + err = fmt.Errorf("chain %s is stopped: %w", consumer.Config().ChainID, err) + } + return + } + rs = relayer.Exec(ctx, GetRelayerExecReporter(ctx), []string{ + "hermes", "clear", "packets", "--port", "consumer", "--channel", channel.ChannelID, + "--chain", consumer.Config().ChainID, + }, nil) + if rs.Err != nil { + return false, rs.Err + } } tCtx, tCancel := context.WithTimeout(ctx, 30*CommitTimeout) defer tCancel() diff --git a/tests/interchain/consensus_test.go b/tests/interchain/consensus_test.go new file mode 100644 index 0000000000..ff9d8f753a --- /dev/null +++ b/tests/interchain/consensus_test.go @@ -0,0 +1,138 @@ +package interchain_test + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/cosmos/gaia/v20/tests/interchain/chainsuite" + "github.com/stretchr/testify/suite" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +type ConsensusSuite struct { + *chainsuite.Suite +} + +func (s *ConsensusSuite) TestInactiveValidators() { + authority, err := s.Chain.GetGovernanceAddress(s.GetContext()) + s.Require().NoError(err) + + stakingProposal := fmt.Sprintf(`{ + "@type": "/cosmos.staking.v1beta1.MsgUpdateParams", + "authority": "%s", + "params": { + "unbonding_time": "1814400s", + "max_validators": 5, + "max_entries": 7, + "historical_entries": 10000, + "bond_denom": "%s", + "min_commission_rate": "0.050000000000000000", + "validator_bond_factor": "250.000000000000000000", + "global_liquid_staking_cap": "0.250000000000000000", + "validator_liquid_staking_cap": "0.500000000000000000" + } + }`, authority, s.Chain.Config().Denom) + + prop, err := s.Chain.BuildProposal(nil, "update staking params", "update staking params", "", chainsuite.GovDepositAmount, "", false) + s.Require().NoError(err) + prop.Messages = []json.RawMessage{json.RawMessage(stakingProposal)} + result, err := s.Chain.SubmitProposal(s.GetContext(), s.Chain.ValidatorWallets[0].Moniker, prop) + s.Require().NoError(err) + s.Require().NoError(s.Chain.PassProposal(s.GetContext(), result.ProposalID)) + s.UpgradeChain() + + stakingParams, _, err := s.Chain.GetNode().ExecQuery(s.GetContext(), "staking", "params") + s.Require().NoError(err) + s.Require().Equal(uint64(200), gjson.GetBytes(stakingParams, "params.max_validators").Uint(), string(stakingParams)) + + providerParams, _, err := s.Chain.GetNode().ExecQuery(s.GetContext(), "provider", "params") + s.Require().NoError(err) + s.Require().Equal(uint64(180), gjson.GetBytes(providerParams, "max_provider_consensus_validators").Uint(), string(providerParams)) + providerParams, err = sjson.SetBytes(providerParams, "max_provider_consensus_validators", 4) + s.Require().NoError(err) + providerProposal, err := sjson.SetRaw(fmt.Sprintf(`{ + "@type": "/interchain_security.ccv.provider.v1.MsgUpdateParams", + "authority": "%s" + }`, authority), "params", string(providerParams)) + s.Require().NoError(err) + + stakingProposal, err = sjson.Set(stakingProposal, "params.max_validators", 5) + s.Require().NoError(err) + prop, err = s.Chain.BuildProposal(nil, "update staking params", "update staking params", "", chainsuite.GovDepositAmount, "", false) + s.Require().NoError(err) + prop.Messages = append(prop.Messages, json.RawMessage(stakingProposal)) + result, err = s.Chain.SubmitProposal(s.GetContext(), s.Chain.ValidatorWallets[0].Moniker, prop) + s.Require().NoError(err) + s.Require().NoError(s.Chain.PassProposal(s.GetContext(), result.ProposalID)) + + prop, err = s.Chain.BuildProposal(nil, "update provider params", "update provider params", "", chainsuite.GovDepositAmount, "", false) + s.Require().NoError(err) + prop.Messages = []json.RawMessage{json.RawMessage(providerProposal)} + result, err = s.Chain.SubmitProposal(s.GetContext(), s.Chain.ValidatorWallets[0].Moniker, prop) + s.Require().NoError(err) + s.Require().NoError(s.Chain.PassProposal(s.GetContext(), result.ProposalID)) + + for i := 1; i < 4; i++ { + jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, s.Chain, i) + s.Require().NoError(err) + s.Assert().True(jailed, "validator %d should be jailed", i) + } + for i := 4; i < 6; i++ { + jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, s.Chain, i) + s.Require().NoError(err) + s.Assert().False(jailed, "validator %d should not be jailed", i) + } + + cfg := chainsuite.ConsumerConfig{ + ChainName: "ics-consumer", + Version: "v5.0.0", + ShouldCopyProviderKey: allProviderKeysCopied(), + Denom: chainsuite.Ucon, + TopN: 100, + } + consumer, err := s.Chain.AddConsumerChain(s.GetContext(), s.Relayer, cfg) + s.Require().NoError(err) + + vals, err := consumer.QueryJSON(s.GetContext(), "validators", "comet-validator-set") + s.Require().NoError(err) + s.Require().Equal(4, len(vals.Array()), vals) + + err = s.Chain.CheckCCV(s.GetContext(), consumer, s.Relayer, 1_000_000, 0, 1) + s.Require().NoError(err) + + vals, err = consumer.QueryJSON(s.GetContext(), "validators", "comet-validator-set") + s.Require().NoError(err) + s.Require().Equal(4, len(vals.Array()), vals) + + for i := 1; i < 4; i++ { + jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, i) + s.Require().NoError(err) + s.Assert().True(jailed, "validator %d should be jailed", i) + } + for i := 4; i < 6; i++ { + jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, i) + s.Require().NoError(err) + s.Assert().False(jailed, "validator %d should not be jailed", i) + } + + _, err = s.Chain.Validators[4].ExecTx(s.GetContext(), s.Chain.ValidatorWallets[4].Moniker, "provider", "opt-in", consumer.Config().ChainID) + s.Require().NoError(err) + jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, 4) + s.Require().NoError(err) + s.Assert().True(jailed, "validator 4 should be jailed") + + _, err = s.Chain.Validators[5].ExecTx(s.GetContext(), s.Chain.ValidatorWallets[5].Moniker, "provider", "opt-in", consumer.Config().ChainID) + s.Require().Error(err) + jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, 5) + s.Require().NoError(err) + s.Assert().False(jailed, "validator 5 should not be jailed") +} + +func TestConsensus(t *testing.T) { + s := &ConsensusSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{CreateRelayer: true}), + } + suite.Run(t, s) +} diff --git a/tests/interchain/consumer_launch_test.go b/tests/interchain/consumer_launch_test.go index 323d588342..ca59cdd62d 100644 --- a/tests/interchain/consumer_launch_test.go +++ b/tests/interchain/consumer_launch_test.go @@ -46,10 +46,10 @@ func (s *ConsumerLaunchSuite) TestChainLaunch() { s.Require().NoError(err) s.Require().NoError(chainsuite.SendSimpleIBCTx(s.GetContext(), s.Chain, consumer, s.Relayer)) - jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), *s.Relayer, consumer, 1) + jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, 1) s.Require().NoError(err) s.Require().True(jailed, "validator 1 should be jailed for downtime") - jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), *s.Relayer, consumer, 5) + jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, 5) s.Require().NoError(err) s.Require().False(jailed, "validator 5 should not be jailed for downtime") @@ -59,10 +59,10 @@ func (s *ConsumerLaunchSuite) TestChainLaunch() { s.Require().NoError(err) s.Require().NoError(chainsuite.SendSimpleIBCTx(s.GetContext(), s.Chain, consumer2, s.Relayer)) - jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), *s.Relayer, consumer2, 1) + jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer2, 1) s.Require().NoError(err) s.Require().True(jailed, "validator 1 should be jailed for downtime") - jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), *s.Relayer, consumer2, 5) + jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer2, 5) s.Require().NoError(err) s.Require().False(jailed, "validator 5 should not be jailed for downtime") } diff --git a/tests/interchain/go.mod b/tests/interchain/go.mod index be1fdfa3d9..716eed7e42 100644 --- a/tests/interchain/go.mod +++ b/tests/interchain/go.mod @@ -7,8 +7,8 @@ replace ( github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d github.com/ChainSafe/go-schnorrkel/1 => github.com/ChainSafe/go-schnorrkel v1.0.0 github.com/btcsuite/btcd/btcec/v2 => github.com/btcsuite/btcd/btcec/v2 v2.3.2 // 2.3.4 breaks api - github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.50.8 - github.com/cosmos/interchain-security/v5 => github.com/cosmos/interchain-security/v5 v5.0.1-0.20240718110115-76496d08f129 + github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.50.9-lsm + github.com/cosmos/interchain-security/v5 => github.com/cosmos/interchain-security/v5 v5.0.0-20240806104629-29327696b8e6 github.com/docker/distribution => github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/docker => github.com/docker/docker v24.0.9+incompatible github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 @@ -17,15 +17,16 @@ replace ( require ( cosmossdk.io/math v1.3.0 + github.com/cometbft/cometbft v0.38.10 github.com/cosmos/cosmos-sdk v0.50.8 - github.com/cosmos/ibc-go/v8 v8.3.2 - github.com/cosmos/interchain-security/v5 v5.1.0 + github.com/cosmos/ibc-go/v8 v8.4.0 + github.com/cosmos/interchain-security/v5 v5.1.1 github.com/docker/docker v24.0.9+incompatible github.com/google/go-github/v62 v62.0.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/strangelove-ventures/interchaintest/v8 v8.6.1 github.com/stretchr/testify v1.9.0 - github.com/tidwall/gjson v1.17.1 + github.com/tidwall/gjson v1.17.3 github.com/tidwall/sjson v1.2.5 go.uber.org/zap v1.27.0 golang.org/x/mod v0.19.0 @@ -79,7 +80,6 @@ require ( github.com/cockroachdb/pebble v1.1.1 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.38.10 // indirect github.com/cometbft/cometbft-db v0.12.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.2 // indirect diff --git a/tests/interchain/go.sum b/tests/interchain/go.sum index c8ad312dd2..be5327075c 100644 --- a/tests/interchain/go.sum +++ b/tests/interchain/go.sum @@ -373,8 +373,8 @@ github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAK github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.50.8 h1:2UJHssUaGHTl4/dFp8xyREKAnfiRU6VVfqtKG9n8w5g= -github.com/cosmos/cosmos-sdk v0.50.8/go.mod h1:Zb+DgHtiByNwgj71IlJBXwOq6dLhtyAq3AgqpXm/jHo= +github.com/cosmos/cosmos-sdk v0.50.9-lsm h1:nYQVX0YinJ3Zu3PHEee36OeZ8yAw42ctE52S2K3MleM= +github.com/cosmos/cosmos-sdk v0.50.9-lsm/go.mod h1:efdTFdUndXfLpSMkE1Kv/ra8pux9l1glcojMIhNreiA= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -387,12 +387,12 @@ github.com/cosmos/iavl v1.2.0 h1:kVxTmjTh4k0Dh1VNL046v6BXqKziqMDzxo93oh3kOfM= github.com/cosmos/iavl v1.2.0/go.mod h1:HidWWLVAtODJqFD6Hbne2Y0q3SdxByJepHUOeoH4LiI= github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= -github.com/cosmos/ibc-go/v8 v8.3.2 h1:8X1oHHKt2Bh9hcExWS89rntLaCKZp2EjFTUSxKlPhGI= -github.com/cosmos/ibc-go/v8 v8.3.2/go.mod h1:WVVIsG39jGrF9Cjggjci6LzySyWGloz194sjTxiGNIE= +github.com/cosmos/ibc-go/v8 v8.4.0 h1:K2PfX0AZ+1XKZytHGEMuSjQXG/MZshPb83RSTQt2+cE= +github.com/cosmos/ibc-go/v8 v8.4.0/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cosmos/interchain-security/v5 v5.0.1-0.20240718110115-76496d08f129 h1:DQSMnKnsfSNIVFpg4qCXwB3ZNwacMf9Q9ggaHABZII4= -github.com/cosmos/interchain-security/v5 v5.0.1-0.20240718110115-76496d08f129/go.mod h1:vmeTcTxFCl1eV0o6xpl/IRT7Basz0szVVGzbppnInMg= +github.com/cosmos/interchain-security/v5 v5.0.0-20240806104629-29327696b8e6 h1:aFwnbEdeMUaQg9ZU+Pm8fE3CzZM2gG5jSeAvYOd+hoU= +github.com/cosmos/interchain-security/v5 v5.0.0-20240806104629-29327696b8e6/go.mod h1:sT6a/OIwwkXuH9fBzt5IBa4lrlWO8etgQ+b59pIE8k4= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -1092,8 +1092,8 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= -github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94= +github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=