From e49371a6876f650fc908ee376337606b2f57f3b5 Mon Sep 17 00:00:00 2001 From: Hard-Nett <123711748+hard-nett@users.noreply.github.com> Date: Fri, 27 Dec 2024 15:48:25 +0000 Subject: [PATCH] Upgrade: V0.20.2 (#252) * add stargate queries to wasmOpts * log upgrade * move govPropHandlers to modules file, rename AppModuleBasic type, only include impacted delegators in upgrade, ugrade go simulation test layout * remove printing log file * e2e localbitsong without state * add upgrade test for v020 * bump * clean e2e repo format --------- Co-authored-by: hard-nett Co-authored-by: simi --- app/app.go | 36 +---- app/config.go | 2 +- app/encoding.go | 4 +- app/genesis.go | 44 +++++- app/modules.go | 18 ++- app/test_helper.go | 68 ++++---- app/testing/test_suite.go | 70 ++++++++- app/upgrades/v020/upgrade_test.go | 118 ++++++++++++++ app/upgrades/v020/upgrades.go | 135 ++++++++-------- cmd/bitsongd/cmd/root.go | 10 +- docker-compose.yml | 67 -------- e2e/{cw-orchestrator => cw-orch}/Cargo.lock | 0 e2e/{cw-orchestrator => cw-orch}/Cargo.toml | 0 e2e/{cw-orchestrator => cw-orch}/README.md | 0 .../src/bin/grpc.rs | 0 .../src/bin/iba.rs | 1 - .../src/bin/slashing.rs | 0 e2e/{cw-orchestrator => cw-orch}/src/lib.rs | 0 e2e/{ => ict}/basic_start_test.go | 0 e2e/{ => ict}/basic_upgrade_test.go | 9 +- e2e/{ => ict}/ci.go | 0 e2e/{ => ict}/conformance/cosmwasm.go | 0 e2e/{ => ict}/contracts/cw_template.wasm | Bin .../contracts/polytone_listener.wasm | Bin e2e/{ => ict}/contracts/polytone_note.wasm | Bin e2e/{ => ict}/contracts/polytone_proxy.wasm | Bin e2e/{ => ict}/contracts/polytone_tester.wasm | Bin e2e/{ => ict}/contracts/polytone_voice.wasm | Bin e2e/{ => ict}/go.mod | 0 e2e/{ => ict}/go.sum | 0 e2e/{ => ict}/helpers/common.go | 0 e2e/{ => ict}/helpers/cosmwasm.go | 0 e2e/{ => ict}/helpers/types.go | 0 e2e/{ => ict}/module_pfm_test.go | 0 e2e/{ => ict}/polytone_suite.go | 0 e2e/{ => ict}/polytone_test.go | 0 e2e/{ => ict}/polytone_types.go | 0 e2e/{ => ict}/setup.go | 0 e2e/{ => ict}/slashing_test.go | 0 e2e/{ => ict}/utils.go | 0 e2e/{ => ict}/workflow/cosmwasm.go | 0 e2e/localbitsong/README.md | 111 ++++++++++++- e2e/localbitsong/docker-compose.yml | 25 +++ e2e/localbitsong/scripts/add_keys.sh | 13 ++ e2e/localbitsong/scripts/setup.sh | 146 ++++++++++++++++++ scripts/makefiles/e2e.mk | 10 +- scripts/makefiles/localnet.mk | 40 ++--- 47 files changed, 680 insertions(+), 247 deletions(-) create mode 100644 app/upgrades/v020/upgrade_test.go delete mode 100644 docker-compose.yml rename e2e/{cw-orchestrator => cw-orch}/Cargo.lock (100%) rename e2e/{cw-orchestrator => cw-orch}/Cargo.toml (100%) rename e2e/{cw-orchestrator => cw-orch}/README.md (100%) rename e2e/{cw-orchestrator => cw-orch}/src/bin/grpc.rs (100%) rename e2e/{cw-orchestrator => cw-orch}/src/bin/iba.rs (99%) rename e2e/{cw-orchestrator => cw-orch}/src/bin/slashing.rs (100%) rename e2e/{cw-orchestrator => cw-orch}/src/lib.rs (100%) rename e2e/{ => ict}/basic_start_test.go (100%) rename e2e/{ => ict}/basic_upgrade_test.go (96%) rename e2e/{ => ict}/ci.go (100%) rename e2e/{ => ict}/conformance/cosmwasm.go (100%) rename e2e/{ => ict}/contracts/cw_template.wasm (100%) rename e2e/{ => ict}/contracts/polytone_listener.wasm (100%) rename e2e/{ => ict}/contracts/polytone_note.wasm (100%) rename e2e/{ => ict}/contracts/polytone_proxy.wasm (100%) rename e2e/{ => ict}/contracts/polytone_tester.wasm (100%) rename e2e/{ => ict}/contracts/polytone_voice.wasm (100%) rename e2e/{ => ict}/go.mod (100%) rename e2e/{ => ict}/go.sum (100%) rename e2e/{ => ict}/helpers/common.go (100%) rename e2e/{ => ict}/helpers/cosmwasm.go (100%) rename e2e/{ => ict}/helpers/types.go (100%) rename e2e/{ => ict}/module_pfm_test.go (100%) rename e2e/{ => ict}/polytone_suite.go (100%) rename e2e/{ => ict}/polytone_test.go (100%) rename e2e/{ => ict}/polytone_types.go (100%) rename e2e/{ => ict}/setup.go (100%) rename e2e/{ => ict}/slashing_test.go (100%) rename e2e/{ => ict}/utils.go (100%) rename e2e/{ => ict}/workflow/cosmwasm.go (100%) create mode 100644 e2e/localbitsong/docker-compose.yml create mode 100755 e2e/localbitsong/scripts/add_keys.sh create mode 100755 e2e/localbitsong/scripts/setup.sh diff --git a/app/app.go b/app/app.go index cea41aa4..d32734fd 100644 --- a/app/app.go +++ b/app/app.go @@ -29,9 +29,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/streaming" store "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/x/auth/posthandler" - paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" - upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" - ibcclientclient "github.com/cosmos/ibc-go/v7/modules/core/02-client/client" + "github.com/gorilla/mux" "github.com/rakyll/statik/fs" @@ -47,7 +45,7 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - fantokenclient "github.com/bitsongofficial/go-bitsong/x/fantoken/client" + "github.com/cosmos/cosmos-sdk/baseapp" nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" @@ -64,7 +62,6 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/cosmos/cosmos-sdk/x/crisis" - govclient "github.com/cosmos/cosmos-sdk/x/gov/client" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" @@ -88,14 +85,8 @@ var ( EnableSpecificProposals = "" Upgrades = []upgrades.Upgrade{ - v010.Upgrade, - v011.Upgrade, - v013.Upgrade, - v014.Upgrade, - v015.Upgrade, - v016.Upgrade, - v018.Upgrade, - v020.Upgrade, + v010.Upgrade, v011.Upgrade, v013.Upgrade, v014.Upgrade, + v015.Upgrade, v016.Upgrade, v018.Upgrade, v020.Upgrade, } ) @@ -160,21 +151,6 @@ func GetWasmOpts(appOpts servertypes.AppOptions) []wasm.Option { return wasmOpts } -func getGovProposalHandlers() []govclient.ProposalHandler { - var govProposalHandlers []govclient.ProposalHandler - - govProposalHandlers = append(govProposalHandlers, - paramsclient.ProposalHandler, - upgradeclient.LegacyProposalHandler, - upgradeclient.LegacyCancelProposalHandler, - ibcclientclient.UpdateClientProposalHandler, - ibcclientclient.UpgradeProposalHandler, - fantokenclient.ProposalHandler, - ) - - return govProposalHandlers -} - var ( _ CosmosApp = (*BitsongApp)(nil) _ servertypes.Application = (*BitsongApp)(nil) @@ -496,8 +472,8 @@ func (app *BitsongApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.AP // Register new tendermint queries routes from grpc-gateway. tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) - // Register legacy and grpc-gateway routes for all modules. - ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + // Register legacy and grpc-gateway routes for all application modules. + AppModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register new tendermint queries routes from grpc-gateway. nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) diff --git a/app/config.go b/app/config.go index 958dfdd2..a73463c8 100644 --- a/app/config.go +++ b/app/config.go @@ -30,7 +30,7 @@ func DefaultConfig() network.Config { InterfaceRegistry: encCfg.InterfaceRegistry, AccountRetriever: authtypes.AccountRetriever{}, AppConstructor: NewAppConstructor(encCfg), - GenesisState: ModuleBasics.DefaultGenesis(encCfg.Marshaler), + GenesisState: AppModuleBasics.DefaultGenesis(encCfg.Marshaler), TimeoutCommit: 1 * time.Second / 2, ChainID: "bitsong-test-1", NumValidators: 1, diff --git a/app/encoding.go b/app/encoding.go index 5521a185..b1e6e215 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -10,7 +10,7 @@ func MakeEncodingConfig() params.EncodingConfig { encodingConfig := params.MakeEncodingConfig() std.RegisterLegacyAminoCodec(encodingConfig.Amino) std.RegisterInterfaces(encodingConfig.InterfaceRegistry) - ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino) - ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry) + AppModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino) + AppModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry) return encodingConfig } diff --git a/app/genesis.go b/app/genesis.go index 8f2b18d4..a10c85d4 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -16,13 +16,8 @@ import ( // object provided to it during init. type GenesisState map[string]json.RawMessage -// NewDefaultGenesisState generates the default state for bitsong. -func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { - return ModuleBasics.DefaultGenesis(cdc) -} - func NewDefaultGenesisStateWithCodec(cdc codec.JSONCodec) GenesisState { - gen := ModuleBasics.DefaultGenesis(cdc) + gen := AppModuleBasics.DefaultGenesis(cdc) // here we override wasm config to make it permissioned by default wasmGen := wasmtypes.GenesisState{ @@ -84,3 +79,40 @@ func NewDefaultGenesisStateWithCodec(cdc codec.JSONCodec) GenesisState { // ), // } // } + +var defaultGenesisState GenesisState = nil + +// NewDefaultGenesisState generates the default state for bitsong. +func NewDefaultGenesisState() GenesisState { + if defaultGenesisState != nil { + return cloneGenesisState(defaultGenesisState) + } + encCfg := MakeEncodingConfig() + gen := AppModuleBasics.DefaultGenesis(encCfg.Marshaler) + + // here we override wasm config to make it permissioned by default + wasmGen := wasmtypes.GenesisState{ + Params: wasmtypes.Params{ + CodeUploadAccess: wasmtypes.AllowNobody, + InstantiateDefaultPermission: wasmtypes.AccessTypeEverybody, + }, + } + gen[wasmtypes.ModuleName] = encCfg.Marshaler.MustMarshalJSON(&wasmGen) + return gen +} + +// CloneGenesisState creates a deep clone of the provided GenesisState. +func cloneGenesisState(original GenesisState) GenesisState { + clone := make(GenesisState, len(original)) + for key, value := range original { + // Make a copy of the json.RawMessage (which is a []byte slice). + copiedValue := make(json.RawMessage, len(value)) + copy(copiedValue, value) + if len(copiedValue) == 0 { + // If the value is empty, set it to nil. + copiedValue = nil + } + clone[key] = copiedValue + } + return clone +} diff --git a/app/modules.go b/app/modules.go index af6f69c6..bb579c21 100644 --- a/app/modules.go +++ b/app/modules.go @@ -5,6 +5,7 @@ import ( wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" encparams "github.com/bitsongofficial/go-bitsong/app/params" "github.com/bitsongofficial/go-bitsong/x/fantoken" + fantokenclient "github.com/bitsongofficial/go-bitsong/x/fantoken/client" fantokentypes "github.com/bitsongofficial/go-bitsong/x/fantoken/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -30,30 +31,34 @@ import ( "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/mint" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/params" + paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/slashing" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/cosmos-sdk/x/upgrade" + upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" packetforward "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" "github.com/cosmos/ibc-go/v7/modules/apps/transfer" ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v7/modules/core" + ibcclientclient "github.com/cosmos/ibc-go/v7/modules/core/02-client/client" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" ) -// ModuleBasics defines the module BasicManager is in charge of setting up basic, +// AppModuleBasics defines the module BasicManager is in charge of setting up basic, // non-dependant module elements, such as codec registration // and genesis verification. -var ModuleBasics = module.NewBasicManager( +var AppModuleBasics = module.NewBasicManager( auth.AppModuleBasic{}, genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), bank.AppModuleBasic{}, @@ -61,7 +66,14 @@ var ModuleBasics = module.NewBasicManager( staking.AppModuleBasic{}, mint.AppModuleBasic{}, distr.AppModuleBasic{}, - gov.NewAppModuleBasic(getGovProposalHandlers()), + gov.NewAppModuleBasic([]govclient.ProposalHandler{ + paramsclient.ProposalHandler, + upgradeclient.LegacyProposalHandler, + upgradeclient.LegacyCancelProposalHandler, + ibcclientclient.UpdateClientProposalHandler, + ibcclientclient.UpgradeProposalHandler, + fantokenclient.ProposalHandler, + }), params.AppModuleBasic{}, crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, diff --git a/app/test_helper.go b/app/test_helper.go index 1c467ca2..3feb6929 100644 --- a/app/test_helper.go +++ b/app/test_helper.go @@ -44,11 +44,17 @@ const ( // EmptyBaseAppOptions is a stub implementing AppOptions type EmptyBaseAppOptions struct{} +// EmptyAppOptions is a stub implementing AppOptions +type EmptyAppOptions struct{} + // Get implements AppOptions func (ao EmptyBaseAppOptions) Get(_ string) interface{} { return nil } +// Get implements AppOptions +func (ao EmptyAppOptions) Get(o string) interface{} { return nil } + var DefaultConsensusParams = &tmproto.ConsensusParams{ Block: &tmproto.BlockParams{ MaxBytes: 200000, @@ -87,16 +93,10 @@ func Setup(t *testing.T) *BitsongApp { } app := SetupWithGenesisAccounts(t, valSet, []authtypes.GenesisAccount{acc}, balance) - return app } -// EmptyAppOptions is a stub implementing AppOptions -type EmptyAppOptions struct{} - -// Get implements AppOptions -func (ao EmptyAppOptions) Get(o string) interface{} { return nil } - +// Setup node for testing simulation func setup(t *testing.T, withGenesis bool, opts ...wasmkeeper.Option) (*BitsongApp, GenesisState) { db := dbm.NewMemDB() nodeHome := t.TempDir() @@ -111,9 +111,9 @@ func setup(t *testing.T, withGenesis bool, opts ...wasmkeeper.Option) (*BitsongA appOptions := make(simtestutil.AppOptionsMap, 0) appOptions[flags.FlagHome] = nodeHome // ensure unique folder - app := NewBitsongApp(log.NewNopLogger(), db, nil, true, EmptyAppOptions{}, opts, bam.SetChainID("testing"), bam.SetSnapshot(snapshotStore, snapshottypes.SnapshotOptions{KeepRecent: 2})) + app := NewBitsongApp(log.NewNopLogger(), db, nil, true, appOptions, opts, bam.SetChainID("testing"), bam.SetSnapshot(snapshotStore, snapshottypes.SnapshotOptions{KeepRecent: 2})) if withGenesis { - return app, NewDefaultGenesisState(app.AppCodec()) + return app, NewDefaultGenesisState() } return app, GenesisState{} } @@ -124,7 +124,8 @@ func SetupWithGenesisAccounts(t *testing.T, valSet *tmtypes.ValidatorSet, genAcc t.Helper() btsgApp, genesisState := setup(t, true) - genesisState = genesisStateWithValSet(t, btsgApp, genesisState, valSet, genAccs, balances...) + + genesisState = GenesisStateWithValSet(t, btsgApp, genesisState, valSet, genAccs, balances...) stateBytes, err := json.MarshalIndent(genesisState, "", " ") require.NoError(t, err) @@ -215,7 +216,7 @@ func CheckBalance(t *testing.T, app *BitsongApp, addr sdk.AccAddress, balances s require.True(t, balances.IsEqual(app.AppKeepers.BankKeeper.GetAllBalances(ctxCheck, addr))) } -func genesisStateWithValSet(t *testing.T, +func GenesisStateWithValSet(t *testing.T, app *BitsongApp, genesisState GenesisState, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance, @@ -230,19 +231,19 @@ func genesisStateWithValSet(t *testing.T, delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) bondAmt := sdk.DefaultPowerReduction + initValPowers := []abci.ValidatorUpdate{} for _, val := range valSet.Validators { - pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) - require.NoError(t, err) - pkAny, err := codectypes.NewAnyWithValue(pk) - require.NoError(t, err) + pk, _ := cryptocodec.FromTmPubKeyInterface(val.PubKey) + pkAny, _ := codectypes.NewAnyWithValue(pk) validator := stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress(val.Address).String(), - ConsensusPubkey: pkAny, - Jailed: false, - Status: stakingtypes.Bonded, - Tokens: bondAmt, - DelegatorShares: math.LegacyOneDec(), + OperatorAddress: sdk.ValAddress(val.Address).String(), + ConsensusPubkey: pkAny, + Jailed: false, + Status: stakingtypes.Bonded, + Tokens: bondAmt, + DelegatorShares: math.LegacyOneDec(), + // DelegatorShares: math.LegacyOneDec().MulTruncate(math.LegacyOneDec().Sub(math.LegacyNewDecWithPrec(1, 3))), // 1 % slash Description: stakingtypes.Description{}, UnbondingHeight: int64(0), UnbondingTime: time.Unix(0, 0).UTC(), @@ -252,6 +253,13 @@ func genesisStateWithValSet(t *testing.T, validators = append(validators, validator) delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), math.LegacyOneDec())) + // add initial validator powers so consumer InitGenesis runs correctly + pub, _ := val.ToProto() + initValPowers = append(initValPowers, abci.ValidatorUpdate{ + Power: val.VotingPower, + PubKey: pub.PubKey, + }) + } defaultStParams := stakingtypes.DefaultParams() @@ -268,21 +276,27 @@ func genesisStateWithValSet(t *testing.T, stakingGenesis := stakingtypes.NewGenesisState(stParams, validators, delegations) genesisState[stakingtypes.ModuleName] = codec.MustMarshalJSON(stakingGenesis) - // add bonded amount to bonded pool module account - balances = append(balances, banktypes.Balance{ - Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), - Coins: sdk.Coins{sdk.NewCoin(appparams.DefaultBondDenom, bondAmt.MulRaw(int64(len(valSet.Validators))))}, - }) - totalSupply := sdk.NewCoins() for _, b := range balances { // add genesis acc tokens to total supply totalSupply = totalSupply.Add(b.Coins...) } + for range delegations { + // add delegated tokens to total supply + totalSupply = totalSupply.Add(sdk.NewCoin(appparams.DefaultBondDenom, bondAmt)) + } + + // add bonded amount to bonded pool module account + balances = append(balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), + Coins: sdk.Coins{sdk.NewCoin(appparams.DefaultBondDenom, bondAmt.MulRaw(int64(len(valSet.Validators))))}, + }) + // update total supply bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{}) genesisState[banktypes.ModuleName] = codec.MustMarshalJSON(bankGenesis) + // println("genesisStateWithValSet bankState:", string(genesisState[banktypes.ModuleName])) return genesisState diff --git a/app/testing/test_suite.go b/app/testing/test_suite.go index e84e00f6..090304b7 100644 --- a/app/testing/test_suite.go +++ b/app/testing/test_suite.go @@ -1,31 +1,35 @@ -package testing +package apptesting import ( "time" + "cosmossdk.io/math" "github.com/bitsongofficial/go-bitsong/app" "github.com/cometbft/cometbft/crypto/ed25519" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/testutil" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakinghelper "github.com/cosmos/cosmos-sdk/x/staking/testutil" + "github.com/stretchr/testify/suite" ) type KeeperTestHelper struct { suite.Suite - App *app.BitsongApp - Ctx sdk.Context - QueryHelper *baseapp.QueryServiceTestHelper - TestAccs []sdk.AccAddress + App *app.BitsongApp // Mock bitsong application + Ctx sdk.Context // simulated context + QueryHelper *baseapp.QueryServiceTestHelper // GRPC query simulator + TestAccs []sdk.AccAddress // Test accounts - StakingHelper *stakinghelper.Helper + StakingHelper *stakinghelper.Helper // Useful staking helpers } func (s *KeeperTestHelper) Setup() { - t := s.T() - s.App = app.Setup(t) + s.App = app.Setup(s.T()) s.Ctx = s.App.BaseApp.NewContext(false, tmproto.Header{Height: 1, ChainID: "testing", Time: time.Now().UTC()}) s.QueryHelper = &baseapp.QueryServiceTestHelper{ GRPCQueryRouter: s.App.GRPCQueryRouter(), @@ -47,3 +51,53 @@ func CreateRandomAccounts(numAccts int) []sdk.AccAddress { return testAddrs } + +type GenerateAccountStrategy func(int) []sdk.AccAddress +type BondDenomProvider interface { + BondDenom(ctx sdk.Context) string +} + +// AddTestAddrs constructs and returns accNum amount of accounts with an +// initial balance of accAmt in random order +func AddTestAddrs(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress { + return addTestAddrs(bankKeeper, stakingKeeper, ctx, accNum, accAmt, CreateRandomAccounts) +} + +// addTestAddrs adds an account to the tests. +func addTestAddrs(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress { + testAddrs := strategy(accNum) + initCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), accAmt)) + + for _, addr := range testAddrs { + initAccountWithCoins(bankKeeper, ctx, addr, initCoins) + } + + return testAddrs +} + +func initAccountWithCoins(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) { + if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, coins); err != nil { + panic(err) + } + + if err := bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins); err != nil { + panic(err) + } +} + +// ConvertAddrsToValAddrs converts the provided addresses to ValAddress. +func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress { + valAddrs := make([]sdk.ValAddress, len(addrs)) + + for i, addr := range addrs { + valAddrs[i] = sdk.ValAddress(addr) + } + + return valAddrs +} + +// FundAcc funds target address with specified amount. +func (s *KeeperTestHelper) FundAcc(acc sdk.AccAddress, amounts sdk.Coins) { + err := testutil.FundAccount(s.App.AppKeepers.BankKeeper, s.Ctx, acc, amounts) + s.Require().NoError(err) +} diff --git a/app/upgrades/v020/upgrade_test.go b/app/upgrades/v020/upgrade_test.go new file mode 100644 index 00000000..33a20f0b --- /dev/null +++ b/app/upgrades/v020/upgrade_test.go @@ -0,0 +1,118 @@ +package v020_test + +import ( + "fmt" + "testing" + + "cosmossdk.io/math" + apptesting "github.com/bitsongofficial/go-bitsong/app/testing" + + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/stretchr/testify/suite" +) + +const dummyUpgradeHeight = 5 + +type UpgradeTestSuite struct { + apptesting.KeeperTestHelper +} + +func (s *UpgradeTestSuite) SetupTest() { + s.Setup() +} + +func TestUpgradeTestSuite(t *testing.T) { + suite.Run(t, new(UpgradeTestSuite)) +} + +func (s *UpgradeTestSuite) TestUpgrade() { + upgradeSetup := func() { + validators := s.App.AppKeepers.StakingKeeper.GetAllValidators(s.Ctx) + for _, val := range validators { + // update the tokens staked to validator due to slashing event + // mimic slashing event on staking power, but not update slashing event to distribution module + val.Tokens = math.LegacyNewDecFromInt(val.Tokens).MulTruncate(math.LegacyOneDec().Sub(math.LegacyNewDecWithPrec(1, 3))).RoundInt() // 1 % slash + + dels := s.App.AppKeepers.StakingKeeper.GetAllDelegations(s.Ctx) + for _, del := range dels { + endingPeriod := s.App.AppKeepers.DistrKeeper.IncrementValidatorPeriod(s.Ctx, val) + // assert v018 bug is present prior to upgrade + s.Require().Panics(func() { + s.App.AppKeepers.DistrKeeper.CalculateDelegationRewards(s.Ctx, val, del, endingPeriod) + }) + } + // create another delegator + del2 := s.TestAccs[2] + s.FundAcc(del2, types.NewCoins(types.NewCoin("ubtsg", math.NewInt(1000000)))) + s.StakingHelper.Delegate(del2, val.GetOperator(), math.NewInt(1000000)) + del, found := s.App.AppKeepers.StakingKeeper.GetDelegation(s.Ctx, del2, val.GetOperator()) + s.Require().True(found) + endingPeriod := s.App.AppKeepers.DistrKeeper.IncrementValidatorPeriod(s.Ctx, val) + s.Require().NotPanics(func() { + s.App.AppKeepers.DistrKeeper.CalculateDelegationRewards(s.Ctx, val, del, endingPeriod) + }) + } + } + + testCases := []struct { + name string + pre_upgrade func() + upgrade func() + post_upgrade func() + }{ + { + "Test that the upgrade succeeds", + func() { + upgradeSetup() + }, + func() { + s.Ctx = s.Ctx.WithBlockHeight(dummyUpgradeHeight - 1) + plan := upgradetypes.Plan{Name: "v020", Height: dummyUpgradeHeight} + err := s.App.AppKeepers.UpgradeKeeper.ScheduleUpgrade(s.Ctx, plan) + s.Require().NoError(err) + _, exists := s.App.AppKeepers.UpgradeKeeper.GetUpgradePlan(s.Ctx) + s.Require().True(exists) + + s.Ctx = s.Ctx.WithBlockHeight(dummyUpgradeHeight) + s.Require().NotPanics(func() { + beginBlockRequest := abcitypes.RequestBeginBlock{} + s.App.BeginBlocker(s.Ctx, beginBlockRequest) + }) + }, + func() { + // assert rewards can be calculated + validators := s.App.AppKeepers.StakingKeeper.GetAllValidators(s.Ctx) + for _, val := range validators { + dels := s.App.AppKeepers.StakingKeeper.GetAllDelegations(s.Ctx) + for _, del := range dels { + // confirm delegators can query, withdraw and stake + // require all rewards to have been claimed for this delegator + // confirm delegators claimed tokens was accurate + s.Ctx = s.Ctx.WithBlockHeight(dummyUpgradeHeight + 10) + endingPeriod := s.App.AppKeepers.DistrKeeper.IncrementValidatorPeriod(s.Ctx, val) + s.App.AppKeepers.DistrKeeper.CalculateDelegationRewards(s.Ctx, val, del, endingPeriod) + s.Ctx = s.Ctx.WithBlockHeight(dummyUpgradeHeight + 10) + s.FundAcc(del.GetDelegatorAddr(), types.NewCoins(types.NewCoin("ubtsg", math.NewInt(1000000)))) + s.StakingHelper.Delegate(del.GetDelegatorAddr(), del.GetValidatorAddr(), math.NewInt(1000000)) + s.Ctx = s.Ctx.WithBlockHeight(dummyUpgradeHeight + 10) + _, err := s.App.AppKeepers.DistrKeeper.WithdrawDelegationRewards(s.Ctx, del.GetDelegatorAddr(), del.GetValidatorAddr()) + s.Require().NoError(err) + } + } + + }, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() // reset + + tc.pre_upgrade() + tc.upgrade() + tc.post_upgrade() + }) + } +} diff --git a/app/upgrades/v020/upgrades.go b/app/upgrades/v020/upgrades.go index 9e52e0aa..85558853 100644 --- a/app/upgrades/v020/upgrades.go +++ b/app/upgrades/v020/upgrades.go @@ -25,7 +25,6 @@ func CreateV020UpgradeHandler(mm *module.Manager, configurator module.Configurat ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- `) - // manually claim rewards by calling keeper functions for _, validator := range k.StakingKeeper.GetAllValidators(ctx) { for _, del := range k.StakingKeeper.GetValidatorDelegations(ctx, validator.GetOperator()) { @@ -37,81 +36,82 @@ func CreateV020UpgradeHandler(mm *module.Manager, configurator module.Configurat return nil, distrtypes.ErrEmptyDelegationDistInfo } - // end current period and calculate rewards + // calculate rewards endingPeriod := k.DistrKeeper.IncrementValidatorPeriod(ctx, val) - rewardsRaw := customCalculateDelegationRewards(ctx, k, val, del, endingPeriod) + rewardsRaw, patched := customCalculateDelegationRewards(ctx, k, val, del, endingPeriod) outstanding := k.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, del.GetValidatorAddr()) + if patched { + // defensive edge case may happen on the very final digits + // of the decCoins due to operation order of the distribution mechanism. + rewards := rewardsRaw.Intersect(outstanding) + if !rewards.IsEqual(rewardsRaw) { + logger := k.DistrKeeper.Logger(ctx) + logger.Info( + "rounding error withdrawing rewards from validator", + "delegator", del.GetDelegatorAddr().String(), + "validator", val.GetOperator().String(), + "got", rewards.String(), + "expected", rewardsRaw.String(), + ) + } - // defensive edge case may happen on the very final digits - // of the decCoins due to operation order of the distribution mechanism. - rewards := rewardsRaw.Intersect(outstanding) - if !rewards.IsEqual(rewardsRaw) { - logger := k.DistrKeeper.Logger(ctx) - logger.Info( - "rounding error withdrawing rewards from validator", - "delegator", del.GetDelegatorAddr().String(), - "validator", val.GetOperator().String(), - "got", rewards.String(), - "expected", rewardsRaw.String(), - ) - } - - // truncate reward dec coins, return remainder to community pool - finalRewards, remainder := rewards.TruncateDecimal() + // truncate reward dec coins, return remainder to community pool + finalRewards, remainder := rewards.TruncateDecimal() - // add coins to user account - if !finalRewards.IsZero() { - withdrawAddr := k.DistrKeeper.GetDelegatorWithdrawAddr(ctx, del.GetDelegatorAddr()) - err := k.BankKeeper.SendCoinsFromModuleToAccount(ctx, distrtypes.ModuleName, withdrawAddr, finalRewards) - if err != nil { - return nil, err + // add coins to user account + if !finalRewards.IsZero() { + withdrawAddr := k.DistrKeeper.GetDelegatorWithdrawAddr(ctx, del.GetDelegatorAddr()) + err := k.BankKeeper.SendCoinsFromModuleToAccount(ctx, distrtypes.ModuleName, withdrawAddr, finalRewards) + if err != nil { + return nil, err + } } - } - // update the outstanding rewards and the community pool only if the - // transaction was successful - k.DistrKeeper.SetValidatorOutstandingRewards(ctx, del.GetValidatorAddr(), distrtypes.ValidatorOutstandingRewards{Rewards: outstanding.Sub(rewards)}) - feePool := k.DistrKeeper.GetFeePool(ctx) - feePool.CommunityPool = feePool.CommunityPool.Add(remainder...) - k.DistrKeeper.SetFeePool(ctx, feePool) - - // decrement reference count of starting period - startingInfo := k.DistrKeeper.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) - startingPeriod := startingInfo.PreviousPeriod - customDecrementReferenceCount(ctx, k, del.GetValidatorAddr(), startingPeriod) - - // remove delegator starting info - k.DistrKeeper.DeleteDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) - - if finalRewards.IsZero() { - baseDenom, _ := sdk.GetBaseDenom() - if baseDenom == "" { - baseDenom = sdk.DefaultBondDenom + // update the outstanding rewards and the community pool only if the + // transaction was successful + k.DistrKeeper.SetValidatorOutstandingRewards(ctx, del.GetValidatorAddr(), distrtypes.ValidatorOutstandingRewards{Rewards: outstanding.Sub(rewards)}) + feePool := k.DistrKeeper.GetFeePool(ctx) + feePool.CommunityPool = feePool.CommunityPool.Add(remainder...) + k.DistrKeeper.SetFeePool(ctx, feePool) + + // decrement reference count of starting period + startingInfo := k.DistrKeeper.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) + startingPeriod := startingInfo.PreviousPeriod + customDecrementReferenceCount(ctx, k, del.GetValidatorAddr(), startingPeriod) + + // remove delegator starting info + k.DistrKeeper.DeleteDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) + + if finalRewards.IsZero() { + baseDenom, _ := sdk.GetBaseDenom() + if baseDenom == "" { + baseDenom = sdk.DefaultBondDenom + } + + // Note, we do not call the NewCoins constructor as we do not want the zero + // coin removed. + finalRewards = sdk.Coins{sdk.NewCoin(baseDenom, math.ZeroInt())} + ctx.Logger().Info("No final rewards", finalRewards) } - // Note, we do not call the NewCoins constructor as we do not want the zero - // coin removed. - finalRewards = sdk.Coins{sdk.NewCoin(baseDenom, math.ZeroInt())} - ctx.Logger().Info("No final rewards", finalRewards) - } - - // reinitialize the delegation - // period has already been incremented - we want to store the period ended by this delegation action - previousPeriod := k.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddr).Period - 1 + // reinitialize the delegation + // period has already been incremented - we want to store the period ended by this delegation action + previousPeriod := k.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddr).Period - 1 - // increment reference count for the period we're going to track - incrementReferenceCount(ctx, k, valAddr, previousPeriod) + // increment reference count for the period we're going to track + incrementReferenceCount(ctx, k, valAddr, previousPeriod) - validator := k.StakingKeeper.Validator(ctx, valAddr) - delegation := k.StakingKeeper.Delegation(ctx, del.GetDelegatorAddr(), valAddr) + validator := k.StakingKeeper.Validator(ctx, valAddr) + delegation := k.StakingKeeper.Delegation(ctx, del.GetDelegatorAddr(), valAddr) - // calculate delegation stake in tokens - // we don't store directly, so multiply delegation shares * (tokens per share) - // note: necessary to truncate so we don't allow withdrawing more rewards than owed - stake := validator.TokensFromSharesTruncated(delegation.GetShares()) + // calculate delegation stake in tokens + // we don't store directly, so multiply delegation shares * (tokens per share) + // note: necessary to truncate so we don't allow withdrawing more rewards than owed + stake := validator.TokensFromSharesTruncated(delegation.GetShares()) - // save new delegator starting info to kv store - k.DistrKeeper.SetDelegatorStartingInfo(ctx, valAddr, del.GetDelegatorAddr(), distrtypes.NewDelegatorStartingInfo(previousPeriod, stake, uint64(ctx.BlockHeight()))) + // save new delegator starting info to kv store + k.DistrKeeper.SetDelegatorStartingInfo(ctx, valAddr, del.GetDelegatorAddr(), distrtypes.NewDelegatorStartingInfo(previousPeriod, stake, uint64(ctx.BlockHeight()))) + } } } @@ -143,7 +143,8 @@ func CreateV020UpgradeHandler(mm *module.Manager, configurator module.Configurat } } -func customCalculateDelegationRewards(ctx sdk.Context, k *keepers.AppKeepers, val stakingtypes.ValidatorI, del stakingtypes.DelegationI, endingPeriod uint64) (rewards sdk.DecCoins) { +func customCalculateDelegationRewards(ctx sdk.Context, k *keepers.AppKeepers, val stakingtypes.ValidatorI, del stakingtypes.DelegationI, endingPeriod uint64) (rewards sdk.DecCoins, patched bool) { + patched = false // fetch starting info for delegation startingInfo := k.DistrKeeper.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) if startingInfo.Height == uint64(ctx.BlockHeight()) { @@ -170,19 +171,21 @@ func customCalculateDelegationRewards(ctx sdk.Context, k *keepers.AppKeepers, va }, ) } + currentStake := val.TokensFromShares(del.GetShares()) if stake.GT(currentStake) { marginOfErr := currentStake.Mul(sdk.NewDecWithPrec(50, 3)) // 5.0% if stake.LTE(currentStake.Add(marginOfErr)) { stake = currentStake + patched = true } else { panic(fmt.Sprintln("current stake is not delgator from slashed validator, and is more than maximum margin of error")) } } // calculate rewards for final period rewards = rewards.Add(customCalculateDelegationRewardsBetween(ctx, k, val, startingPeriod, endingPeriod, stake)...) - return rewards + return rewards, patched } func customCalculateDelegationRewardsBetween(ctx sdk.Context, k *keepers.AppKeepers, val stakingtypes.ValidatorI, diff --git a/cmd/bitsongd/cmd/root.go b/cmd/bitsongd/cmd/root.go index 1cb43585..f465a8d4 100644 --- a/cmd/bitsongd/cmd/root.go +++ b/cmd/bitsongd/cmd/root.go @@ -194,7 +194,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { } rootCmd.AddCommand( - genutilcli.InitCmd(bitsong.ModuleBasics, bitsong.DefaultNodeHome), + genutilcli.InitCmd(bitsong.AppModuleBasics, bitsong.DefaultNodeHome), tmcli.NewCompletionCmd(rootCmd, true), ConfigCmd(), pruning.PruningCmd(ac.newApp), @@ -209,7 +209,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( rpc.StatusCommand(), - PrepareGenesisCmd(bitsong.DefaultNodeHome, bitsong.ModuleBasics), + PrepareGenesisCmd(bitsong.DefaultNodeHome, bitsong.AppModuleBasics), genesisCommand(encodingConfig), InitFromStateCmd(bitsong.DefaultNodeHome), queryCommand(), @@ -227,7 +227,7 @@ func addModuleInitFlags(startCmd *cobra.Command) { // genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter func genesisCommand(encodingConfig params.EncodingConfig, cmds ...*cobra.Command) *cobra.Command { - cmd := genutilcli.GenesisCoreCommand(encodingConfig.TxConfig, bitsong.ModuleBasics, bitsong.DefaultNodeHome) + cmd := genutilcli.GenesisCoreCommand(encodingConfig.TxConfig, bitsong.AppModuleBasics, bitsong.DefaultNodeHome) for _, subCmd := range cmds { cmd.AddCommand(subCmd) } @@ -252,7 +252,7 @@ func queryCommand() *cobra.Command { authcmd.QueryTxCmd(), ) - bitsong.ModuleBasics.AddQueryCommands(cmd) + bitsong.AppModuleBasics.AddQueryCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd @@ -280,7 +280,7 @@ func txCommand() *cobra.Command { authcmd.GetAuxToFeeCommand(), ) - bitsong.ModuleBasics.AddTxCommands(cmd) + bitsong.AppModuleBasics.AddTxCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 65fcaf39..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,67 +0,0 @@ -version: '3' - -services: - bitsongdnode0: - container_name: bitsongdnode0 - image: "bitsongofficial/bitsongdnode" - ports: - - "26656-26657:26656-26657" - environment: - - ID=0 - - LOG=${LOG:-bitsongd.log} - volumes: - - ./build:/bitsongd:Z - networks: - localnet: - ipv4_address: 192.168.10.2 - - bitsongdnode1: - container_name: bitsongdnode1 - image: "bitsongofficial/bitsongdnode" - ports: - - "26659-26660:26656-26657" - environment: - - ID=1 - - LOG=${LOG:-bitsongd.log} - volumes: - - ./build:/bitsongd:Z - networks: - localnet: - ipv4_address: 192.168.10.3 - - bitsongdnode2: - container_name: bitsongdnode2 - image: "bitsongofficial/bitsongdnode" - environment: - - ID=2 - - LOG=${LOG:-bitsongd.log} - ports: - - "26661-26662:26656-26657" - volumes: - - ./build:/bitsongd:Z - networks: - localnet: - ipv4_address: 192.168.10.4 - - bitsongdnode3: - container_name: bitsongdnode3 - image: "bitsongofficial/bitsongdnode" - environment: - - ID=3 - - LOG=${LOG:-bitsongd.log} - ports: - - "26663-26664:26656-26657" - volumes: - - ./build:/bitsongd:Z - networks: - localnet: - ipv4_address: 192.168.10.5 - -networks: - localnet: - driver: bridge - ipam: - driver: default - config: - - - subnet: 192.168.10.0/16 \ No newline at end of file diff --git a/e2e/cw-orchestrator/Cargo.lock b/e2e/cw-orch/Cargo.lock similarity index 100% rename from e2e/cw-orchestrator/Cargo.lock rename to e2e/cw-orch/Cargo.lock diff --git a/e2e/cw-orchestrator/Cargo.toml b/e2e/cw-orch/Cargo.toml similarity index 100% rename from e2e/cw-orchestrator/Cargo.toml rename to e2e/cw-orch/Cargo.toml diff --git a/e2e/cw-orchestrator/README.md b/e2e/cw-orch/README.md similarity index 100% rename from e2e/cw-orchestrator/README.md rename to e2e/cw-orch/README.md diff --git a/e2e/cw-orchestrator/src/bin/grpc.rs b/e2e/cw-orch/src/bin/grpc.rs similarity index 100% rename from e2e/cw-orchestrator/src/bin/grpc.rs rename to e2e/cw-orch/src/bin/grpc.rs diff --git a/e2e/cw-orchestrator/src/bin/iba.rs b/e2e/cw-orch/src/bin/iba.rs similarity index 99% rename from e2e/cw-orchestrator/src/bin/iba.rs rename to e2e/cw-orch/src/bin/iba.rs index f7950117..01c12133 100644 --- a/e2e/cw-orchestrator/src/bin/iba.rs +++ b/e2e/cw-orch/src/bin/iba.rs @@ -53,7 +53,6 @@ pub fn test_ibc_hook_callback() -> AnyResult<()> { .interchain_channel; let (abstr_bitsong, _abstr_bitsong2) = bitsong_starship_interfaces(&interchain)?; - let bitsong_sender = bitsong.sender_addr().to_string(); // Register this channel with the abstract ibc implementation for sending tokens diff --git a/e2e/cw-orchestrator/src/bin/slashing.rs b/e2e/cw-orch/src/bin/slashing.rs similarity index 100% rename from e2e/cw-orchestrator/src/bin/slashing.rs rename to e2e/cw-orch/src/bin/slashing.rs diff --git a/e2e/cw-orchestrator/src/lib.rs b/e2e/cw-orch/src/lib.rs similarity index 100% rename from e2e/cw-orchestrator/src/lib.rs rename to e2e/cw-orch/src/lib.rs diff --git a/e2e/basic_start_test.go b/e2e/ict/basic_start_test.go similarity index 100% rename from e2e/basic_start_test.go rename to e2e/ict/basic_start_test.go diff --git a/e2e/basic_upgrade_test.go b/e2e/ict/basic_upgrade_test.go similarity index 96% rename from e2e/basic_upgrade_test.go rename to e2e/ict/basic_upgrade_test.go index 852b7564..c64008e8 100644 --- a/e2e/basic_upgrade_test.go +++ b/e2e/ict/basic_upgrade_test.go @@ -26,9 +26,9 @@ import ( const ( chainName = "bitsong" - upgradeName = "v019" + upgradeName = "v020" - haltHeightDelta = int64(9) // will propose upgrade this many blocks in the future + haltHeightDelta = int64(10) // will propose upgrade this many blocks in the future blocksAfterUpgrade = int64(7) ) @@ -36,7 +36,7 @@ var ( // baseChain is the current version of the chain that will be upgraded from baseChain = ibc.DockerImage{ Repository: BitsongMainRepo, - Version: "v0.18.1", + Version: "v0.19.0", UidGid: "1025:1025", } ) @@ -103,7 +103,6 @@ func BitsongBasicUpgradeSanityTest(t *testing.T, chainName, upgradeBranchVersion proposalIDInt, err := strconv.ParseInt(proposalID, 10, 64) require.NoError(t, err, "failed to parse proposal ID") - ValidatorVoting(t, ctx, chain, proposalIDInt, height, haltHeight) ValidatorVoting(t, ctx, chain, proposalIDInt, height, haltHeight) UpgradeNodes(t, ctx, chain, client, haltHeight, upgradeRepo, upgradeBranchVersion) @@ -180,7 +179,7 @@ func SubmitUpgradeProposal(t *testing.T, ctx context.Context, chain *cosmos.Cosm upgradeMsg := []cosmosproto.Message{ &upgradetypes.MsgSoftwareUpgrade{ // gov Module account - Authority: "juno10d07y265gmmuvt4z0w9aw880jnsr700jvss730", + Authority: "bitsong10d07y265gmmuvt4z0w9aw880jnsr700jktpd5u", Plan: upgradetypes.Plan{ Name: upgradeName, Height: int64(haltHeight), diff --git a/e2e/ci.go b/e2e/ict/ci.go similarity index 100% rename from e2e/ci.go rename to e2e/ict/ci.go diff --git a/e2e/conformance/cosmwasm.go b/e2e/ict/conformance/cosmwasm.go similarity index 100% rename from e2e/conformance/cosmwasm.go rename to e2e/ict/conformance/cosmwasm.go diff --git a/e2e/contracts/cw_template.wasm b/e2e/ict/contracts/cw_template.wasm similarity index 100% rename from e2e/contracts/cw_template.wasm rename to e2e/ict/contracts/cw_template.wasm diff --git a/e2e/contracts/polytone_listener.wasm b/e2e/ict/contracts/polytone_listener.wasm similarity index 100% rename from e2e/contracts/polytone_listener.wasm rename to e2e/ict/contracts/polytone_listener.wasm diff --git a/e2e/contracts/polytone_note.wasm b/e2e/ict/contracts/polytone_note.wasm similarity index 100% rename from e2e/contracts/polytone_note.wasm rename to e2e/ict/contracts/polytone_note.wasm diff --git a/e2e/contracts/polytone_proxy.wasm b/e2e/ict/contracts/polytone_proxy.wasm similarity index 100% rename from e2e/contracts/polytone_proxy.wasm rename to e2e/ict/contracts/polytone_proxy.wasm diff --git a/e2e/contracts/polytone_tester.wasm b/e2e/ict/contracts/polytone_tester.wasm similarity index 100% rename from e2e/contracts/polytone_tester.wasm rename to e2e/ict/contracts/polytone_tester.wasm diff --git a/e2e/contracts/polytone_voice.wasm b/e2e/ict/contracts/polytone_voice.wasm similarity index 100% rename from e2e/contracts/polytone_voice.wasm rename to e2e/ict/contracts/polytone_voice.wasm diff --git a/e2e/go.mod b/e2e/ict/go.mod similarity index 100% rename from e2e/go.mod rename to e2e/ict/go.mod diff --git a/e2e/go.sum b/e2e/ict/go.sum similarity index 100% rename from e2e/go.sum rename to e2e/ict/go.sum diff --git a/e2e/helpers/common.go b/e2e/ict/helpers/common.go similarity index 100% rename from e2e/helpers/common.go rename to e2e/ict/helpers/common.go diff --git a/e2e/helpers/cosmwasm.go b/e2e/ict/helpers/cosmwasm.go similarity index 100% rename from e2e/helpers/cosmwasm.go rename to e2e/ict/helpers/cosmwasm.go diff --git a/e2e/helpers/types.go b/e2e/ict/helpers/types.go similarity index 100% rename from e2e/helpers/types.go rename to e2e/ict/helpers/types.go diff --git a/e2e/module_pfm_test.go b/e2e/ict/module_pfm_test.go similarity index 100% rename from e2e/module_pfm_test.go rename to e2e/ict/module_pfm_test.go diff --git a/e2e/polytone_suite.go b/e2e/ict/polytone_suite.go similarity index 100% rename from e2e/polytone_suite.go rename to e2e/ict/polytone_suite.go diff --git a/e2e/polytone_test.go b/e2e/ict/polytone_test.go similarity index 100% rename from e2e/polytone_test.go rename to e2e/ict/polytone_test.go diff --git a/e2e/polytone_types.go b/e2e/ict/polytone_types.go similarity index 100% rename from e2e/polytone_types.go rename to e2e/ict/polytone_types.go diff --git a/e2e/setup.go b/e2e/ict/setup.go similarity index 100% rename from e2e/setup.go rename to e2e/ict/setup.go diff --git a/e2e/slashing_test.go b/e2e/ict/slashing_test.go similarity index 100% rename from e2e/slashing_test.go rename to e2e/ict/slashing_test.go diff --git a/e2e/utils.go b/e2e/ict/utils.go similarity index 100% rename from e2e/utils.go rename to e2e/ict/utils.go diff --git a/e2e/workflow/cosmwasm.go b/e2e/ict/workflow/cosmwasm.go similarity index 100% rename from e2e/workflow/cosmwasm.go rename to e2e/ict/workflow/cosmwasm.go diff --git a/e2e/localbitsong/README.md b/e2e/localbitsong/README.md index ecfa3cab..f5feea59 100644 --- a/e2e/localbitsong/README.md +++ b/e2e/localbitsong/README.md @@ -1,3 +1,110 @@ -# LocalBitsong +# LocalBitSong - \ No newline at end of file +LocalBitSong is a complete BitSong testnet containerized with Docker and orchestrated with a simple docker-compose file. LocalBitSong comes preconfigured with opinionated, sensible defaults for a standard testing environment. + +LocalBitSong comes in two flavors: + +1. No initial state: brand new testnet with no initial state. +2. TBD - With mainnet state: creates a testnet from a mainnet state export + +Both ways, the chain-id for LocalBitSong is set to 'LocalBitSong'. + +## Prerequisites + +Ensure you have docker and docker-compose installed: + +```sh +# Docker +sudo apt-get remove docker docker-engine docker.io +sudo apt-get update +sudo apt install docker.io -y + +# Docker compose +sudo apt install docker-compose -y +``` + +## 1. LocalBitSong - No Initial State + +The following commands must be executed from the root folder of the BitSong repository. + +1. Make any change to the bitsong code that you want to test + +2. Initialize LocalBitSong: + +```bash +make localnet-init +``` + +The command: + +- Builds a local docker image with the latest changes +- Cleans the `$HOME/.bitsongd-local` folder + +3. Start LocalBitSong: + +```bash +make localnet-start +``` + +> Note +> +> You can also start LocalBitSong in detach mode with: +> +> `make localnet-startd` + +4. (optional) Add your validator wallet and 10 other preloaded wallets automatically: + +```bash +make localnet-keys +``` + +- These keys are added to your `--keyring-backend test` +- If the keys are already on your keyring, you will get an `"Error: aborted"` +- Ensure you use the name of the account as listed in the table below, as well as ensure you append the `--keyring-backend test` to your txs +- Example: `bitsongd tx bank send lo-test2 bitsong1cyyzpxplxdzkeea7kwsydadg87357qnahakaks --keyring-backend test --chain-id LocalBitSong` + +5. You can stop chain, keeping the state with + +```bash +make localnet-stop +``` + +6. When you are done you can clean up the environment with: + +```bash +make localnet-clean +``` + +## LocalBitSong Accounts and Keys + +LocalBitSong is pre-configured with one validator and 9 accounts with BTSG balances. + +| Account | Address | Mnemonic | +|-----------|--------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| val | `bitsong1gws6wz8q5kyyu4gqze48fwlmm4m0mdjz0620gw`
`bitsongvaloper1gws6wz8q5kyyu4gqze48fwlmm4m0mdjzw7kxcn` | `bottom loan skill merry east cradle onion journey palm apology verb edit desert impose absurd oil bubble sweet glove shallow size build burst effort` | +| lo-test1 | `bitsong1regz7kj3ylg2dn9rl8vwrhclkgz528mf0tfsck` | `notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius` | +| lo-test2 | `bitsong1hvrhhex6wfxh7r7nnc3y39p0qlmff6v9t5rc25` | `quality vacuum heart guard buzz spike sight swarm shove special gym robust assume sudden deposit grid alcohol choice devote leader tilt noodle tide penalty` | +| lo-test3 | `bitsong175vgzztymvvcxvqun54nlu9dq6856thgvyl5sa` | `symbol force gallery make bulk round subway violin worry mixture penalty kingdom boring survey tool fringe patrol sausage hard admit remember broken alien absorb` | +| lo-test4 | `bitsong1t8nznzj4sd6zzutwdmslgy4dcxyd2jafz7822x` | `bounce success option birth apple portion aunt rural episode solution hockey pencil lend session cause hedgehog slender journey system canvas decorate razor catch empty` | +| lo-test5 | `bitsong14vdrvstsffj8mq5e4fhm6y2hpfxtedajczsj5d` | `second render cat sing soup reward cluster island bench diet lumber grocery repeat balcony perfect diesel stumble piano distance caught occur example ozone loyal` | +| lo-test6 | `bitsong1vwe5hay74v0vhuzdhadteyqfasu5d7tdf83pyy` | `spatial forest elevator battle also spoon fun skirt flight initial nasty transfer glory palm drama gossip remove fan joke shove label dune debate quick` | +| lo-test7 | `bitsong16866dezn6ez2qpmpcrrv9cyud8v8c7ufnzwhhh` | `noble width taxi input there patrol clown public spell aunt wish punch moment will misery eight excess arena pen turtle minimum grain vague inmate` | +| lo-test8 | `bitsong1tlwh75lvu35nw9vcg557mxhspz5s88t6vzscd8` | `cream sport mango believe inhale text fish rely elegant below earth april wall rug ritual blossom cherry detail length blind digital proof identify ride` | +| lo-test9 | `bitsong16z9wj8n5f3zgzwspw0r9sj9v7k7hdasqj95us9` | `index light average senior silent limit usual local involve delay update rack cause inmate wall render magnet common feature laundry exact casual resource hundred` | +| lo-test10 | `bitsong1gulaxnca7rped0grw0lz4h4zy0xn3ttvmlad8x` | `prefer forget visit mistake mixture feel eyebrow autumn shop pair address airport diesel street pass vague innocent poem method awful require hurry unhappy shoulder` | + +To list all keys in the keyring named `test` +```bash +bitsongd keys list --keyring-backend test +``` + +To import an account into the keyring `test`. NOTE: replace the address with any of the above user accounts. +```bash +bitsongd keys add bitsong1regz7kj3ylg2dn9rl8vwrhclkgz528mf0tfsck --keyring-backend test --recover +``` + +## FAQ + +Q: How do I enable pprof server in LocalBitSong? + +A: everything but the Dockerfile is already configured. Since we use a production Dockerfile in LocalBitSong, we don't want to expose the pprof server there by default. As a result, if you would like to use pprof, make sure to add `EXPOSE 6060` to the Dockerfile and rebuild the LocalBitSong image. diff --git a/e2e/localbitsong/docker-compose.yml b/e2e/localbitsong/docker-compose.yml new file mode 100644 index 00000000..e0ca70e9 --- /dev/null +++ b/e2e/localbitsong/docker-compose.yml @@ -0,0 +1,25 @@ +version: "4" + +services: + bitsongd: + image: local:bitsong + build: + context: ../../ + dockerfile: Dockerfile + args: + RUNNER_IMAGE: golang:1.22.9-alpine3.19 + GO_VERSION: "1.22.9" + volumes: + - ./scripts/setup.sh:/bitsong/setup.sh + - $HOME/.bitsongd-local/:/bitsongd/.bitsongd/ + entrypoint: + - /bitsong/setup.sh + command: + - $STATE + ports: + - 26657:26657 + - 1317:1317 + - 9090:9090 + - 9091:9091 + - 6060:6060 + - 9092:9092 diff --git a/e2e/localbitsong/scripts/add_keys.sh b/e2e/localbitsong/scripts/add_keys.sh new file mode 100755 index 00000000..7e90e6ca --- /dev/null +++ b/e2e/localbitsong/scripts/add_keys.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +echo "bottom loan skill merry east cradle onion journey palm apology verb edit desert impose absurd oil bubble sweet glove shallow size build burst effort" | bitsongd keys add val --recover --keyring-backend test +echo "notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius" | bitsongd keys add lo-test1 --recover --keyring-backend test +echo "quality vacuum heart guard buzz spike sight swarm shove special gym robust assume sudden deposit grid alcohol choice devote leader tilt noodle tide penalty" | bitsongd keys add lo-test2 --recover --keyring-backend test +echo "symbol force gallery make bulk round subway violin worry mixture penalty kingdom boring survey tool fringe patrol sausage hard admit remember broken alien absorb" | bitsongd keys add lo-test3 --recover --keyring-backend test +echo "bounce success option birth apple portion aunt rural episode solution hockey pencil lend session cause hedgehog slender journey system canvas decorate razor catch empty" | bitsongd keys add lo-test4 --recover --keyring-backend test +echo "second render cat sing soup reward cluster island bench diet lumber grocery repeat balcony perfect diesel stumble piano distance caught occur example ozone loyal" | bitsongd keys add lo-test5 --recover --keyring-backend test +echo "spatial forest elevator battle also spoon fun skirt flight initial nasty transfer glory palm drama gossip remove fan joke shove label dune debate quick" | bitsongd keys add lo-test6 --recover --keyring-backend test +echo "noble width taxi input there patrol clown public spell aunt wish punch moment will misery eight excess arena pen turtle minimum grain vague inmate" | bitsongd keys add lo-test7 --recover --keyring-backend test +echo "cream sport mango believe inhale text fish rely elegant below earth april wall rug ritual blossom cherry detail length blind digital proof identify ride" | bitsongd keys add lo-test8 --recover --keyring-backend test +echo "index light average senior silent limit usual local involve delay update rack cause inmate wall render magnet common feature laundry exact casual resource hundred" | bitsongd keys add lo-test9 --recover --keyring-backend test +echo "prefer forget visit mistake mixture feel eyebrow autumn shop pair address airport diesel street pass vague innocent poem method awful require hurry unhappy shoulder" | bitsongd keys add lo-test10 --recover --keyring-backend test diff --git a/e2e/localbitsong/scripts/setup.sh b/e2e/localbitsong/scripts/setup.sh new file mode 100755 index 00000000..ecc5c735 --- /dev/null +++ b/e2e/localbitsong/scripts/setup.sh @@ -0,0 +1,146 @@ +#!/bin/sh + +CHAIN_ID=localbitsong +BITSONG_HOME=$HOME/.bitsongd +CONFIG_FOLDER=$BITSONG_HOME/config +MONIKER=val +STATE='false' + +MNEMONIC="bottom loan skill merry east cradle onion journey palm apology verb edit desert impose absurd oil bubble sweet glove shallow size build burst effort" + +while getopts s flag +do + case "${flag}" in + s) STATE='true';; + esac +done + +install_prerequisites () { + apk add dasel lz4 +} + +edit_genesis () { + + GENESIS=$CONFIG_FOLDER/genesis.json + + # Update staking module + dasel put string -f $GENESIS '.app_state.staking.params.bond_denom' -v 'ubtsg' + dasel put string -f $GENESIS '.app_state.staking.params.unbonding_time' -v '240s' + + # Update bank module + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].description' -v 'Registered denom ubtsg for localbitsong testing' + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].denom_units.[].denom' -v 'ubtsg' + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].denom_units.[0].exponent' -v 0 + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].base' -v 'ubtsg' + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].display' -v 'ubtsg' + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].name' -v 'ubtsg' + dasel put string -f $GENESIS '.app_state.bank.denom_metadata.[0].symbol' -v 'ubtsg' + + # Update crisis module + dasel put string -f $GENESIS '.app_state.crisis.constant_fee.denom' -v 'ubtsg' + + # Update gov module + dasel put string -f $GENESIS '.app_state.gov.voting_params.voting_period' -v '60s' + dasel put string -f $GENESIS '.app_state.gov.params.min_deposit.[0].denom' -v 'ubtsg' + + # Update mint module + dasel put string -f $GENESIS '.app_state.mint.params.mint_denom' -v "ubtsg" +} + +add_genesis_accounts () { + + # val + bitsongd genesis add-genesis-account bitsong1gws6wz8q5kyyu4gqze48fwlmm4m0mdjz0620gw 10000000000000ubtsg --home $BITSONG_HOME + + # wallets + bitsongd genesis add-genesis-account bitsong1regz7kj3ylg2dn9rl8vwrhclkgz528mf0tfsck 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong1hvrhhex6wfxh7r7nnc3y39p0qlmff6v9t5rc25 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong175vgzztymvvcxvqun54nlu9dq6856thgvyl5sa 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong1t8nznzj4sd6zzutwdmslgy4dcxyd2jafz7822x 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong14vdrvstsffj8mq5e4fhm6y2hpfxtedajczsj5d 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong1vwe5hay74v0vhuzdhadteyqfasu5d7tdf83pyy 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong16866dezn6ez2qpmpcrrv9cyud8v8c7ufnzwhhh 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong1tlwh75lvu35nw9vcg557mxhspz5s88t6vzscd8 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong16z9wj8n5f3zgzwspw0r9sj9v7k7hdasqj95us9 10000000000000ubtsg --home $BITSONG_HOME + bitsongd genesis add-genesis-account bitsong1gulaxnca7rped0grw0lz4h4zy0xn3ttvmlad8x 10000000000000ubtsg --home $BITSONG_HOME + + echo $MNEMONIC | bitsongd keys add $MONIKER --recover --keyring-backend=test --home $BITSONG_HOME + bitsongd genesis gentx $MONIKER 5000000000000ubtsg --keyring-backend=test --chain-id=$CHAIN_ID --home $BITSONG_HOME + + bitsongd genesis collect-gentxs --home $BITSONG_HOME + + bitsongd genesis validate-genesis --home $BITSONG_HOME +} + +edit_config () { + + # Remove seeds + dasel put string -f $CONFIG_FOLDER/config.toml '.p2p.seeds' -v '' + + # Expose the rpc + dasel put string -f $CONFIG_FOLDER/config.toml '.rpc.laddr' -v "tcp://0.0.0.0:26657" + + # Expose pprof for debugging + # To make the change enabled locally, make sure to add 'EXPOSE 6060' to the root Dockerfile + # and rebuild the image. + dasel put string -f $CONFIG_FOLDER/config.toml '.rpc.pprof_laddr' -v "0.0.0.0:6060" +} + +enable_cors () { + + # Enable cors on RPC + dasel put string -f $CONFIG_FOLDER/config.toml -v "*" '.rpc.cors_allowed_origins.[]' + dasel put string -f $CONFIG_FOLDER/config.toml -v "Accept-Encoding" '.rpc.cors_allowed_headers.[]' + dasel put string -f $CONFIG_FOLDER/config.toml -v "DELETE" '.rpc.cors_allowed_methods.[]' + dasel put string -f $CONFIG_FOLDER/config.toml -v "OPTIONS" '.rpc.cors_allowed_methods.[]' + dasel put string -f $CONFIG_FOLDER/config.toml -v "PATCH" '.rpc.cors_allowed_methods.[]' + dasel put string -f $CONFIG_FOLDER/config.toml -v "PUT" '.rpc.cors_allowed_methods.[]' + + # Enable unsafe cors and swagger on the api + dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.api.swagger' + dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.api.enabled-unsafe-cors' + + # Enable cors on gRPC Web + dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.grpc-web.enable-unsafe-cors' + + # Enable SQS & route caching + dasel put string -f $CONFIG_FOLDER/app.toml -v "true" '.bitsong-sqs.is-enabled' + dasel put string -f $CONFIG_FOLDER/app.toml -v "true" '.bitsong-sqs.route-cache-enabled' + + dasel put string -f $CONFIG_FOLDER/app.toml -v "redis" '.bitsong-sqs.db-host' +} + +run_with_retries() { + cmd=$1 + success_msg=$2 + + substring='code: 0' + COUNTER=0 + + while [ $COUNTER -lt 15 ]; do + string=$(eval $cmd 2>&1) + echo $string + + if [ "$string" != "${string%"$substring"*}" ]; then + echo "$success_msg" + break + else + COUNTER=$((COUNTER+1)) + sleep 0.5 + fi + done +} + +if [[ ! -d $CONFIG_FOLDER ]] +then + echo $MNEMONIC | bitsongd init -o --chain-id=$CHAIN_ID --home $BITSONG_HOME --recover $MONIKER + install_prerequisites + edit_genesis + add_genesis_accounts + edit_config + enable_cors +fi + +bitsongd start --home $BITSONG_HOME & + +wait diff --git a/scripts/makefiles/e2e.mk b/scripts/makefiles/e2e.mk index e0240755..9d3026e1 100644 --- a/scripts/makefiles/e2e.mk +++ b/scripts/makefiles/e2e.mk @@ -18,19 +18,19 @@ e2e-help: e2e: e2e-help e2e-basic: rm-testcache - cd e2e && go test -race -v -run TestBasicBtsgStart . + cd e2e/ict && go test -race -v -run TestBasicBtsgStart . e2e-upgrade: rm-testcache - cd e2e && go test -race -v -run TestBasicBitsongUpgrade . + cd e2e/ict && go test -race -v -run TestBasicBitsongUpgrade . e2e-pfm: rm-testcache - cd e2e && go test -race -v -run TestPacketForwardMiddlewareRouter . + cd e2e/ict && go test -race -v -run TestPacketForwardMiddlewareRouter . e2e-polytone: rm-testcache - cd e2e && go test -race -v -run TestPolytoneOnBitsong . + cd e2e/ict && go test -race -v -run TestPolytoneOnBitsong . e2e-slashing: rm-testcache - cd e2e && go test -race -v -run TestBasicBitsongSlashing . + cd e2e/ict && go test -race -v -run TestBasicBitsongSlashing . rm-testcache: go clean -testcache diff --git a/scripts/makefiles/localnet.mk b/scripts/makefiles/localnet.mk index ba29caa7..94ab82a1 100644 --- a/scripts/makefiles/localnet.mk +++ b/scripts/makefiles/localnet.mk @@ -1,6 +1,9 @@ ############################################################################### ### Localnet ### ############################################################################### +# +# Please refer to https://github.com/bitsongofficial/go-bitsong/blob/main/e2e/localbitsong/README.md for detailed +# usage of localnet. localnet-help: @echo "build subcommands" @@ -9,29 +12,28 @@ localnet-help: @echo " make [command]" @echo "" @echo "Available Commands:" - @echo "localnet-start Start a 4-node testnet locally" - @echo "localnet-stop Stop a local testnet" + @echo "localnet-start Start localnet" + @echo "localnet-stop Stop localnet" @echo "test-docker-push Push testnet docker image" localnet: localnet-help -# Run a 4-node testnet locally -localnet-start: build-linux build-docker-bitsongdnode - @if ! [ -f build/node0/bitsongd/config/genesis.json ]; \ - then docker run --rm -v $(CURDIR)/build:/bitsongd:Z bitsongofficial/bitsongdnode testnet --v 4 -o . --starting-ip-address 192.168.10.2 --keyring-backend=test ; \ - fi - docker-compose up -d +localnet-keys: + . e2e/localbitsong/scripts/add_keys.sh -# Stop testnet -localnet-stop: - docker-compose down +localnet-init: localnet-clean localnet-build + +localnet-build: + @DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1 docker compose -f e2e/localbitsong/docker-compose.yml build + +localnet-start: + @STATE="" docker compose -f e2e/localbitsong/docker-compose.yml up -test-docker: - @docker build -f contrib/Dockerfile.test -t ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) . - @docker tag ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) ${TEST_DOCKER_REPO}:$(shell git rev-parse --abbrev-ref HEAD | sed 's#/#_#g') - @docker tag ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) ${TEST_DOCKER_REPO}:latest +localnet-startd: + @STATE="" docker compose -f e2e/localbitsong/docker-compose.yml up -d + +localnet-stop: + @STATE="" docker compose -f e2e/localbitsong/docker-compose.yml down -test-docker-push: test-docker - @docker push ${TEST_DOCKER_REPO}:$(shell git rev-parse --short HEAD) - @docker push ${TEST_DOCKER_REPO}:$(shell git rev-parse --abbrev-ref HEAD | sed 's#/#_#g') - @docker push ${TEST_DOCKER_REPO}:latest \ No newline at end of file +localnet-clean: + @rm -rfI $(HOME)/.bitsongd-local/ \ No newline at end of file