Skip to content

Commit

Permalink
feat: add upgrade sequence to tx sim (#3890)
Browse files Browse the repository at this point in the history
Adds the ability to use txsim to upgrade a network
  • Loading branch information
cmwaters authored Sep 24, 2024
1 parent 27dc26f commit 418ddbf
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
52 changes: 52 additions & 0 deletions test/txsim/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ import (

"github.com/celestiaorg/celestia-app/v3/app"
"github.com/celestiaorg/celestia-app/v3/app/encoding"
v2 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v2"
v3 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v3"
"github.com/celestiaorg/celestia-app/v3/test/txsim"
"github.com/celestiaorg/celestia-app/v3/test/util/testnode"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

blob "github.com/celestiaorg/celestia-app/v3/x/blob/types"
signaltypes "github.com/celestiaorg/celestia-app/v3/x/signal/types"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
distribution "github.com/cosmos/cosmos-sdk/x/distribution/types"
staking "github.com/cosmos/cosmos-sdk/x/staking/types"
Expand Down Expand Up @@ -152,3 +157,50 @@ func Setup(t testing.TB) (keyring.Keyring, string, string) {

return cctx.Keyring, rpcAddr, grpcAddr
}

func TestTxSimUpgrade(t *testing.T) {
if testing.Short() {
t.Skip("skipping TestTxSimUpgrade in short mode.")
}
cp := app.DefaultConsensusParams()
cp.Version.AppVersion = v2.Version
cfg := testnode.DefaultConfig().
WithTimeoutCommit(300 * time.Millisecond).
WithConsensusParams(cp).
WithFundedAccounts("txsim-master")
cctx, _, grpcAddr := testnode.NewNetwork(t, cfg)

// updrade to v3 at height 20
sequences := []txsim.Sequence{
txsim.NewUpgradeSequence(v3.Version, 20),
}

opts := txsim.DefaultOptions().
// SuppressLogs().
WithPollTime(time.Millisecond * 100)

err := txsim.Run(
cctx.GoContext(),
grpcAddr,
cctx.Keyring,
encoding.MakeConfig(app.ModuleEncodingRegisters...),
opts,
sequences...,
)
require.NoError(t, err)

conn, err := grpc.NewClient(grpcAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
defer conn.Close()

querier := signaltypes.NewQueryClient(conn)

// We can't check that the upgrade was successful because the upgrade height is thousands of blocks away
// and even at 300 millisecond block times, it would take too long. Instead we just want to assert
// that the upgrade is ready to be performed
require.Eventually(t, func() bool {
upgradePlan, err := querier.GetUpgrade(cctx.GoContext(), &signaltypes.QueryGetUpgradeRequest{})
require.NoError(t, err)
return upgradePlan.Upgrade != nil && upgradePlan.Upgrade.AppVersion == v3.Version
}, time.Second*20, time.Millisecond*100)
}
82 changes: 82 additions & 0 deletions test/txsim/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package txsim

import (
"context"
"errors"
"math/rand"

signaltypes "github.com/celestiaorg/celestia-app/v3/x/signal/types"
"github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/gogo/protobuf/grpc"
)

var _ Sequence = &UpgradeSequence{}

const fundsForUpgrade = 100_000

// UpgradeSequence simulates an upgrade proposal and voting process
type UpgradeSequence struct {
voted map[string]bool
height int64
version uint64
account types.AccAddress
hasUpgraded bool
}

func NewUpgradeSequence(version uint64, height int64) *UpgradeSequence {
return &UpgradeSequence{version: version, height: height, voted: make(map[string]bool)}
}

func (s *UpgradeSequence) Clone(_ int) []Sequence {
panic("cloning not supported for upgrade sequence. Only a single sequence is needed")
}

// this is a no-op for the upgrade sequence
func (s *UpgradeSequence) Init(_ context.Context, _ grpc.ClientConn, allocateAccounts AccountAllocator, _ *rand.Rand, _ bool) {
s.account = allocateAccounts(1, fundsForUpgrade)[0]
}

func (s *UpgradeSequence) Next(ctx context.Context, querier grpc.ClientConn, _ *rand.Rand) (Operation, error) {
if s.hasUpgraded {
return Operation{}, ErrEndOfSequence
}

stakingQuerier := stakingtypes.NewQueryClient(querier)
validatorsResp, err := stakingQuerier.Validators(ctx, &stakingtypes.QueryValidatorsRequest{})
if err != nil {
return Operation{}, err
}

if len(validatorsResp.Validators) == 0 {
return Operation{}, errors.New("no validators found")
}

// Choose a random validator to be the authority
var msg types.Msg
for _, validator := range validatorsResp.Validators {
if !s.voted[validator.OperatorAddress] {
msg = &signaltypes.MsgSignalVersion{
ValidatorAddress: validator.OperatorAddress,
Version: s.version,
}
s.voted[validator.OperatorAddress] = true
}
}
// if all validators have voted, we can now try to upgrade.
if msg == nil {
msg = signaltypes.NewMsgTryUpgrade(s.account)
s.hasUpgraded = true
}

delay := uint64(0)
// apply a delay to the first sequence only
if len(s.voted) == 0 {
delay = uint64(s.height)
}

return Operation{
Msgs: []types.Msg{msg},
Delay: delay,
}, nil
}

0 comments on commit 418ddbf

Please sign in to comment.