diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index ce8f17fa3..fe8e8ad88 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -17,26 +17,21 @@ jobs: integration-tests: name: Integration Test (${{ matrix.test.name }}) runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 30 env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} strategy: # other jobs should run even if one integration test fails - fail-fast: false + fail-fast: true matrix: test: [ { - name: "Dex Module", + name: "Dex & Wasm Module", scripts: [ "docker exec sei-node-0 integration_test/contracts/deploy_dex_contract.sh mars", "python3 integration_test/scripts/runner.py integration_test/dex_module/place_order_test.yaml", - "python3 integration_test/scripts/runner.py integration_test/dex_module/cancel_order_test.yaml" - ] - }, - { - name: "Wasm Module", - scripts: [ + "python3 integration_test/scripts/runner.py integration_test/dex_module/cancel_order_test.yaml", "docker exec sei-node-0 integration_test/contracts/deploy_timelocked_token_contract.sh", "python3 integration_test/scripts/runner.py integration_test/wasm_module/timelocked_token_delegation_test.yaml", "python3 integration_test/scripts/runner.py integration_test/wasm_module/timelocked_token_admin_test.yaml", @@ -46,44 +41,35 @@ jobs: ] }, { - name: "Mint Module", + name: "Mint & Staking & Bank Module", scripts: [ + "python3 integration_test/scripts/runner.py integration_test/staking_module/staking_test.yaml", + "python3 integration_test/scripts/runner.py integration_test/bank_module/send_funds_test.yaml", "python3 integration_test/scripts/runner.py integration_test/mint_module/mint_test.yaml" ] }, { - name: "Staking Module", - scripts: [ - "python3 integration_test/scripts/runner.py integration_test/staking_module/staking_test.yaml" - ] - }, - { - name: "Gov Module", + name: "Gov & Oracle & Authz Module", scripts: [ "python3 integration_test/scripts/runner.py integration_test/gov_module/gov_proposal_test.yaml", - "python3 integration_test/scripts/runner.py integration_test/gov_module/staking_proposal_test.yaml" - ] - }, - { - name: "Oracle Module", - scripts: [ + "python3 integration_test/scripts/runner.py integration_test/gov_module/staking_proposal_test.yaml", "python3 integration_test/scripts/runner.py integration_test/oracle_module/verify_penalty_counts.yaml", - "python3 integration_test/scripts/runner.py integration_test/oracle_module/set_feeder_test.yaml" - ] - }, - { - name: "Authz Module", - scripts: [ + "python3 integration_test/scripts/runner.py integration_test/oracle_module/set_feeder_test.yaml", "python3 integration_test/scripts/runner.py integration_test/authz_module/send_authorization_test.yaml", "python3 integration_test/scripts/runner.py integration_test/authz_module/staking_authorization_test.yaml", "python3 integration_test/scripts/runner.py integration_test/authz_module/generic_authorization_test.yaml" ] }, { - name: "Bank Module", + name: "Chain Operation Test", scripts: [ - "python3 integration_test/scripts/runner.py integration_test/bank_module/send_funds_test.yaml", + "until [ $(cat build/generated/rpc-launch.complete |wc -l) = 1 ]; do sleep 10; done", + "until [[ $(docker exec sei-rpc-node build/seid status |jq -M -r .SyncInfo.latest_block_height) -gt 10 ]]; do sleep 10; done", + "echo rpc node started", + "python3 integration_test/scripts/runner.py integration_test/chain_operation/snapshot_operation.yaml", + "python3 integration_test/scripts/runner.py integration_test/chain_operation/statesync_operation.yaml" ] + }, { name: "Accesscontrol Module", @@ -91,6 +77,13 @@ jobs: "python3 integration_test/scripts/runner.py integration_test/acl_module/accesscontrol_register_test.yaml", ] }, + { + name: "Distribution Module", + scripts: [ + "python3 integration_test/scripts/runner.py integration_test/distribution_module/community_pool.yaml", + "python3 integration_test/scripts/runner.py integration_test/distribution_module/rewards.yaml", + ] + }, ] steps: - uses: actions/checkout@v3 @@ -121,6 +114,9 @@ jobs: done sleep 10 + - name: Start rpc node + run: make run-rpc-node-skipbuild & + - name: Verify Sei Chain is running run: python3 integration_test/scripts/runner.py integration_test/startup/startup_test.yaml diff --git a/Makefile b/Makefile index b0192ec81..284e3b45f 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ run-local-node: kill-sei-node build-docker-node .PHONY: run-local-node # Run a single rpc state sync node docker container -run-rpc-node: kill-rpc-node build-rpc-node +run-rpc-node: build-rpc-node docker run --rm \ --name sei-rpc-node \ --network docker_localnet \ @@ -153,6 +153,20 @@ run-rpc-node: kill-rpc-node build-rpc-node sei-chain/rpcnode .PHONY: run-rpc-node +run-rpc-node-skipbuild: build-rpc-node + docker run --rm \ + --name sei-rpc-node \ + --network docker_localnet \ + -v $(PROJECT_HOME):/sei-protocol/sei-chain:Z \ + -v $(PROJECT_HOME)/../sei-tendermint:/sei-protocol/sei-tendermint:Z \ + -v $(PROJECT_HOME)/../sei-cosmos:/sei-protocol/sei-cosmos:Z \ + -v $(GO_PKG_PATH)/mod:/root/go/pkg/mod:Z \ + -p 26668-26670:26656-26658 \ + --platform linux/x86_64 \ + --env SKIP_BUILD=true \ + sei-chain/rpcnode +.PHONY: run-rpc-node + kill-sei-node: docker ps --filter name=sei-node --filter status=running -aq | xargs docker kill diff --git a/app/antedecorators/gasless.go b/app/antedecorators/gasless.go index 9696d2cf7..e21bf3b96 100644 --- a/app/antedecorators/gasless.go +++ b/app/antedecorators/gasless.go @@ -48,9 +48,7 @@ func (gd GaslessDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, // Otherwise (i.e. in the case of checkTx), we only want to perform fee checks and fee deduction if the tx is not considered // gasless, or if it specifies a non-zero gas limit even if it is considered gasless, so that the wrapped deduct fee // handler will assign an appropriate priority to it. - if !isGasless { - ctx = ctx.WithGasMeter(originalGasMeter) - } + ctx = ctx.WithGasMeter(originalGasMeter) return gd.handleWrapped(ctx, tx, simulate, next) } diff --git a/app/antedecorators/gasless_test.go b/app/antedecorators/gasless_test.go index 2415a9fa4..7d367d13d 100644 --- a/app/antedecorators/gasless_test.go +++ b/app/antedecorators/gasless_test.go @@ -149,7 +149,7 @@ func TestGaslessDecorator(t *testing.T) { // gasless tx (checkTx w/ gas limit) -> wrapped should still be run output = "" outputDeps = "" - _, err = chainedHandler(ctx.WithIsCheckTx(true), FakeTx{ + resCtx, err := chainedHandler(ctx.WithIsCheckTx(true), FakeTx{ FakeMsgs: []sdk.Msg{&types.MsgPlaceOrders{}}, Gas: 100, }, false) @@ -158,11 +158,12 @@ func TestGaslessDecorator(t *testing.T) { _, err = depGen([]accesscontrol.AccessOperation{}, FakeTx{}, 1) require.NoError(t, err) require.Equal(t, "onetwothree", outputDeps) + require.NotEqual(t, resCtx.GasMeter().Limit(), 0) // make sure gas meter is limited // gasless tx (checkTx w/o gas limit) -> wrapped should not be run output = "" outputDeps = "" - _, err = chainedHandler(ctx.WithIsCheckTx(true), FakeTx{ + resCtx, err = chainedHandler(ctx.WithIsCheckTx(true), FakeTx{ FakeMsgs: []sdk.Msg{&types.MsgPlaceOrders{}}, }, false) require.NoError(t, err) @@ -170,6 +171,7 @@ func TestGaslessDecorator(t *testing.T) { _, err = depGen([]accesscontrol.AccessOperation{}, FakeTx{}, 1) require.NoError(t, err) require.Equal(t, "onetwothree", outputDeps) + require.NotEqual(t, resCtx.GasMeter().Limit(), 0) // make sure gas meter is limited } func TestOracleVoteGasless(t *testing.T) { diff --git a/app/app.go b/app/app.go index 1135f9575..37acf6bd1 100644 --- a/app/app.go +++ b/app/app.go @@ -346,6 +346,8 @@ type App struct { CheckTxMemState *dexcache.MemState ProcessProposalMemState *dexcache.MemState MemState *dexcache.MemState + + HardForkManager *HardForkManager } // New returns a reference to an initialized blockchain app @@ -779,6 +781,11 @@ func New( app.SetInitChainer(app.InitChainer) app.SetBeginBlocker(app.BeginBlocker) + // register hard fork handlers with the hard fork manager + app.HardForkManager = NewHardForkManager(app.ChainID) + // register and hard fork handlers below + // example: app.HardForkManager.RegisterHandler(myHandler) + signModeHandler := encodingConfig.TxConfig.SignModeHandler() // app.batchVerifier = ante.NewSR25519BatchVerifier(app.AccountKeeper, signModeHandler) @@ -893,8 +900,8 @@ func (app *App) SetStoreUpgradeHandlers() { // configure store loader that checks if version == upgradeHeight and applies store upgrades app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) } - // TODO: add upgrade name for authz module - if false && upgradeInfo.Name == "TODO" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + + if upgradeInfo.Name == "3.0.6" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { storeUpgrades := storetypes.StoreUpgrades{ Added: []string{authzkeeper.StoreKey}, } @@ -913,6 +920,10 @@ func (app App) GetBaseApp() *baseapp.BaseApp { return app.BaseApp } // BeginBlocker application updates every begin block func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { metrics.GaugeSeidVersionAndCommit(app.versionInfo.Version, app.versionInfo.GitCommit) + // check if we've reached a target height, if so, execute any applicable handlers + if app.HardForkManager.TargetHeightReached(ctx) { + app.HardForkManager.ExecuteForTargetHeight(ctx) + } return app.mm.BeginBlock(ctx, req) } diff --git a/app/fork_manager.go b/app/fork_manager.go new file mode 100644 index 000000000..4c41d24cb --- /dev/null +++ b/app/fork_manager.go @@ -0,0 +1,92 @@ +package app + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/sei-protocol/goutils" +) + +type HardForkHandler interface { + // a unique identifying name to ensure no duplicate handlers are registered + GetName() string + // The target chain ID for which to run this handler (which chain to run on) + GetTargetChainID() string + // The target height at which the handler should be executed + GetTargetHeight() int64 + // An execution function used to process a hard fork handler + ExecuteHandler(ctx sdk.Context) error +} + +type HardForkManager struct { + chainID string + handlerMap map[int64][]HardForkHandler + uniqueNameMap map[string]struct{} +} + +// Create a new hard fork manager for a given chain ID. +// This will filter out any handlers for other chain IDs, +// and create a map that maps between target height and handlers to run for the given heights. +func NewHardForkManager(chainID string) *HardForkManager { + return &HardForkManager{ + chainID: chainID, + handlerMap: make(map[int64][]HardForkHandler), + uniqueNameMap: make(map[string]struct{}), + } +} + +// This tries to register a handler with the hard fork manager. +// If the handler's target chain ID doesn't match the chain ID of the manager, +// this is a no-op and the handler is ignored. +func (hfm *HardForkManager) RegisterHandler(handler HardForkHandler) { + if handler.GetTargetChainID() != hfm.chainID { + return + } + handlerName := handler.GetName() + if _, ok := hfm.uniqueNameMap[handlerName]; ok { + // we already have a migration with this name - panic + panic(fmt.Errorf("hard fork handler with name %s already registered", handlerName)) + } + // register name for uniqueness assertion + hfm.uniqueNameMap[handlerName] = struct{}{} + targetHeight := handler.GetTargetHeight() + if handlers, ok := hfm.handlerMap[targetHeight]; ok { + goutils.InPlaceAppend[[]HardForkHandler](&handlers, handler) + hfm.handlerMap[targetHeight] = handlers + } else { + hfm.handlerMap[targetHeight] = []HardForkHandler{handler} + } +} + +// This returns a boolean indicating whether or not the current height is a +// target height for which there are hard fork handlers to run. +func (hfm *HardForkManager) TargetHeightReached(ctx sdk.Context) bool { + _, ok := hfm.handlerMap[ctx.BlockHeight()] + return ok +} + +// This executes the hard fork handlers for the current height. This will function will panic upon receiving an error during hard fork handler execution +func (hfm *HardForkManager) ExecuteForTargetHeight(ctx sdk.Context) { + handlers, ok := hfm.handlerMap[ctx.BlockHeight()] + if !ok { + return + } + for _, handler := range handlers { + handlerName := handler.GetName() + ctx.Logger().Info(fmt.Sprintf( + "Executing hard fork handler %s for chain ID %s at height %d", + handlerName, + handler.GetTargetChainID(), + handler.GetTargetHeight(), + )) + err := handler.ExecuteHandler(ctx) + if err != nil { + panic(err) + } + ctx.Logger().Info(fmt.Sprintf( + "Completed execution for hard fork handler %s", + handlerName, + )) + } + // TODO: do we want to emit any events to the context event manager (for use in beginBlockResponse) +} diff --git a/app/fork_manager_test.go b/app/fork_manager_test.go new file mode 100644 index 000000000..67ca6822d --- /dev/null +++ b/app/fork_manager_test.go @@ -0,0 +1,114 @@ +package app_test + +import ( + "fmt" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + app "github.com/sei-protocol/sei-chain/app" + "github.com/sei-protocol/sei-chain/app/apptesting" + "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + tmtypes "github.com/tendermint/tendermint/proto/tendermint/types" +) + +type ForkTestSuite struct { + apptesting.KeeperTestHelper +} + +type TestHandler struct { + TargetHeight int64 + TargetChain string + Name string + ShouldError bool + RunVal *bool +} + +func NewTestHandler(chainID string, height int64, name string, shouldError bool, runFlag *bool) TestHandler { + return TestHandler{ + TargetHeight: height, + TargetChain: chainID, + ShouldError: shouldError, + RunVal: runFlag, + Name: name, + } +} + +func (th TestHandler) GetTargetChainID() string { + return th.TargetChain +} + +func (th TestHandler) GetTargetHeight() int64 { + return th.TargetHeight +} + +func (th TestHandler) GetName() string { + return th.Name +} + +func (th TestHandler) ExecuteHandler(ctx sdk.Context) error { + *th.RunVal = true + if th.ShouldError { + return fmt.Errorf("error executing handler") + } + return nil +} + +var _ app.HardForkHandler = TestHandler{} + +func TestForkSuite(t *testing.T) { + suite.Run(t, new(ForkTestSuite)) +} + +func (suite *ForkTestSuite) TestHardForkManager() { + suite.Setup() + suite.CreateTestContext() + runFlag1 := false + runFlag2 := false + runFlag3 := false + runFlag4 := false + runFlag5 := false + testHandler1 := NewTestHandler(suite.Ctx.ChainID(), 3, "handler1", false, &runFlag1) + testHandler2 := NewTestHandler("otherChainID", 3, "handler2", false, &runFlag2) + testHandler3 := NewTestHandler(suite.Ctx.ChainID(), 4, "handler3", true, &runFlag3) + dupeHandler := NewTestHandler(suite.Ctx.ChainID(), 3, "handler1", false, &runFlag4) + testHandler5 := NewTestHandler(suite.Ctx.ChainID(), 3, "handler5", false, &runFlag5) + suite.App.HardForkManager.RegisterHandler(testHandler1) + suite.App.HardForkManager.RegisterHandler(testHandler2) + suite.App.HardForkManager.RegisterHandler(testHandler3) + suite.Require().Panics(func() { + suite.App.HardForkManager.RegisterHandler(dupeHandler) + }) + suite.App.HardForkManager.RegisterHandler(testHandler5) + + // run with height of 2 - nothing should happen since not a target height + // increments height and runs begin block + suite.Ctx = suite.Ctx.WithBlockHeight(2) + newHeader := tmtypes.Header{Height: suite.Ctx.BlockHeight(), ChainID: suite.Ctx.ChainID(), Time: time.Now().UTC()} + suite.App.BeginBlocker(suite.Ctx, abci.RequestBeginBlock{Header: newHeader}) + suite.Require().False(runFlag1) + suite.Require().False(runFlag2) + suite.Require().False(runFlag3) + suite.Require().False(runFlag4) + suite.Require().False(runFlag5) + + // run with height of 3 - runflag 1 should now be true + suite.Ctx = suite.Ctx.WithBlockHeight(3) + newHeader = tmtypes.Header{Height: suite.Ctx.BlockHeight(), ChainID: suite.Ctx.ChainID(), Time: time.Now().UTC()} + suite.App.BeginBlocker(suite.Ctx, abci.RequestBeginBlock{Header: newHeader}) + suite.Require().True(runFlag1) + suite.Require().False(runFlag2) + suite.Require().False(runFlag3) + suite.Require().False(runFlag4) + suite.Require().True(runFlag5) + + // run with height of 4 - runflag 3 should now be true and we expect a panic + suite.Require().Panics(func() { + suite.Ctx = suite.Ctx.WithBlockHeight(4) + newHeader = tmtypes.Header{Height: suite.Ctx.BlockHeight(), ChainID: suite.Ctx.ChainID(), Time: time.Now().UTC()} + suite.App.BeginBlocker(suite.Ctx, abci.RequestBeginBlock{Header: newHeader}) + }) + suite.Require().True(runFlag3) + suite.Require().False(runFlag4) +} diff --git a/app/test_helpers.go b/app/test_helpers.go index 43e3aae1a..a687888c5 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -10,7 +10,6 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" crptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" - cosmostestutil "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" @@ -43,6 +42,15 @@ func (t TestTx) ValidateBasic() error { return nil } +type TestAppOpts struct{} + +func (t TestAppOpts) Get(s string) interface{} { + if s == "chain-id" { + return "sei-test" + } + return nil +} + type TestWrapper struct { suite.Suite @@ -159,7 +167,7 @@ func Setup(isCheckTx bool) *App { config.TestConfig(), encodingConfig, wasm.EnableAllProposals, - &cosmostestutil.TestAppOpts{}, + TestAppOpts{}, EmptyWasmOpts, EmptyACLOpts, ) @@ -204,7 +212,7 @@ func SetupTestingAppWithLevelDb(isCheckTx bool) (*App, func()) { nil, encodingConfig, wasm.EnableAllProposals, - &cosmostestutil.TestAppOpts{}, + TestAppOpts{}, EmptyWasmOpts, EmptyACLOpts, ) diff --git a/cmd/seid/cmd/root.go b/cmd/seid/cmd/root.go index 63b0b8514..7f034b408 100644 --- a/cmd/seid/cmd/root.go +++ b/cmd/seid/cmd/root.go @@ -243,12 +243,16 @@ func newApp( panic(err) } - snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") - snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDir) + snapshotDirectory := cast.ToString(appOpts.Get(server.FlagStateSyncSnapshotDir)) + if snapshotDirectory == "" { + snapshotDirectory = filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") + } + + snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDirectory) if err != nil { panic(err) } - snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) + snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDirectory) if err != nil { panic(err) } @@ -290,6 +294,7 @@ func newApp( baseapp.SetSnapshotStore(snapshotStore), baseapp.SetSnapshotInterval(cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval))), baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(server.FlagStateSyncSnapshotKeepRecent))), + baseapp.SetSnapshotDirectory(cast.ToString(appOpts.Get(server.FlagStateSyncSnapshotDir))), baseapp.SetOrphanConfig(&iavl.Options{ SeparateOrphanStorage: cast.ToBool(appOpts.Get(server.FlagSeparateOrphanStorage)), SeparateOphanVersionsToKeep: cast.ToInt64(appOpts.Get(server.FlagSeparateOrphanVersionsToKeep)), @@ -389,10 +394,8 @@ func initAppConfig() (string, interface{}) { srvCfg.API.Enable = true // Pruning configs - srvCfg.Pruning = "custom" - // With block times of 0.3 seconds, this gives us 3 days worth of blocks to store (in case of outage) - srvCfg.PruningKeepRecent = "864000" - // Randomly generate pruning interval. We want the following properties: + srvCfg.Pruning = "default" + // Randomly generate pruning interval. Note this only takes affect if using custom pruning. We want the following properties: // - random: if everyone has the same value, the block that everyone prunes will be slow // - prime: no overlap primes := getPrimeNums(2500, 4000) diff --git a/docker/localnode/Dockerfile b/docker/localnode/Dockerfile index c35df8fc1..1d0747903 100644 --- a/docker/localnode/Dockerfile +++ b/docker/localnode/Dockerfile @@ -21,7 +21,7 @@ COPY scripts/step0_build.sh /usr/bin/build.sh COPY scripts/step1_configure_init.sh /usr/bin/configure_init.sh COPY scripts/step2_genesis.sh /usr/bin/genesis.sh COPY scripts/step3_add_validator_to_genesis.sh /usr/bin/add_validator_to_gensis.sh -COPY scripts/step4_persistent_peers.sh /usr/bin/persistent_peers.sh +COPY scripts/step4_config_override.sh /usr/bin/config_override.sh COPY scripts/step5_start_sei.sh /usr/bin/start_sei.sh COPY scripts/step6_start_price_feeder.sh /usr/bin/start_price_feeder.sh ENV PATH "$PATH:$HOME/go/bin" diff --git a/docker/localnode/config/app.toml b/docker/localnode/config/app.toml index a137e81a4..d41087026 100644 --- a/docker/localnode/config/app.toml +++ b/docker/localnode/config/app.toml @@ -190,10 +190,13 @@ enable-unsafe-cors = true # snapshot-interval specifies the block interval at which local state sync snapshots are # taken (0 to disable). Must be a multiple of pruning-keep-every. -snapshot-interval = 500 +snapshot-interval = 100 # snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all). -snapshot-keep-recent = 2 +snapshot-keep-recent = 3 + +# snapshot-directory specifies and overrides the directory for where to store the snapshots +snapshot-directory = "" [wasm] # This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries diff --git a/docker/localnode/scripts/deploy.sh b/docker/localnode/scripts/deploy.sh index 17abd5682..4b971a39a 100755 --- a/docker/localnode/scripts/deploy.sh +++ b/docker/localnode/scripts/deploy.sh @@ -52,8 +52,8 @@ do sleep 1 done -# Step 4: Configure persistent peers -/usr/bin/persistent_peers.sh +# Step 4: Config overrides +/usr/bin/config_override.sh # Step 5: Start the chain /usr/bin/start_sei.sh diff --git a/docker/localnode/scripts/step1_configure_init.sh b/docker/localnode/scripts/step1_configure_init.sh index 3c799bf3e..b006d3060 100755 --- a/docker/localnode/scripts/step1_configure_init.sh +++ b/docker/localnode/scripts/step1_configure_init.sh @@ -24,10 +24,13 @@ seid init "$MONIKER" --chain-id sei >/dev/null 2>&1 # Copy configs ORACLE_CONFIG_FILE="build/generated/node_$NODE_ID/price_feeder_config.toml" -cp docker/localnode/config/app.toml ~/.sei/config/app.toml -cp docker/localnode/config/config.toml ~/.sei/config/config.toml +APP_CONFIG_FILE="build/generated/node_$NODE_ID/app.toml" +TENDERMINT_CONFIG_FILE="build/generated/node_$NODE_ID/config.toml" +cp docker/localnode/config/app.toml "$APP_CONFIG_FILE" +cp docker/localnode/config/config.toml "$TENDERMINT_CONFIG_FILE" cp docker/localnode/config/price_feeder_config.toml "$ORACLE_CONFIG_FILE" + # Set up persistent peers SEI_NODE_ID=$(seid tendermint show-node-id) NODE_IP=$(hostname -i | awk '{print $1}') diff --git a/docker/localnode/scripts/step4_config_override.sh b/docker/localnode/scripts/step4_config_override.sh new file mode 100755 index 000000000..e0ec4b422 --- /dev/null +++ b/docker/localnode/scripts/step4_config_override.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +NODE_ID=${ID:-0} + +APP_CONFIG_FILE="build/generated/node_$NODE_ID/app.toml" +TENDERMINT_CONFIG_FILE="build/generated/node_$NODE_ID/config.toml" +cp build/generated/genesis.json ~/.sei/config/genesis.json +cp "$APP_CONFIG_FILE" ~/.sei/config/app.toml +cp "$TENDERMINT_CONFIG_FILE" ~/.sei/config/config.toml + +# Override up persistent peers +NODE_IP=$(hostname -i | awk '{print $1}') +PEERS=$(cat build/generated/persistent_peers.txt |grep -v "$NODE_IP" | paste -sd "," -) +sed -i'' -e 's/persistent-peers = ""/persistent-peers = "'$PEERS'"/g' ~/.sei/config/config.toml + +# Override snapshot directory +sed -i.bak -e "s|^snapshot-directory *=.*|snapshot-directory = \"./build/generated/node_$NODE_ID/snapshots\"|" ~/.sei/config/app.toml diff --git a/docker/localnode/scripts/step4_persistent_peers.sh b/docker/localnode/scripts/step4_persistent_peers.sh deleted file mode 100755 index c43ccc617..000000000 --- a/docker/localnode/scripts/step4_persistent_peers.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env sh - -# Greeting output -echo "Loading persistent peers" - -# Set up persistent peers -NODE_IP=$(hostname -i | awk '{print $1}') -PEERS=$(cat build/generated/persistent_peers.txt |grep -v $NODE_IP | paste -sd "," -) -sed -i'' -e 's/persistent-peers = ""/persistent-peers = "'$PEERS'"/g' ~/.sei/config/config.toml \ No newline at end of file diff --git a/docker/localnode/scripts/step5_start_sei.sh b/docker/localnode/scripts/step5_start_sei.sh index 0be95475d..bb02f0835 100755 --- a/docker/localnode/scripts/step5_start_sei.sh +++ b/docker/localnode/scripts/step5_start_sei.sh @@ -6,9 +6,8 @@ INVARIANT_CHECK_INTERVAL=${INVARIANT_CHECK_INTERVAL:-0} LOG_DIR="build/generated/logs" mkdir -p $LOG_DIR -# Starting sei chain echo "Starting the seid process for node $NODE_ID with invariant check interval=$INVARIANT_CHECK_INTERVAL..." -cp build/generated/genesis.json ~/.sei/config/genesis.json + seid start --chain-id sei --inv-check-period ${INVARIANT_CHECK_INTERVAL} > "$LOG_DIR/seid-$NODE_ID.log" 2>&1 & echo "Node $NODE_ID seid is started now" echo "Done" >> build/generated/launch.complete diff --git a/docker/rpcnode/Dockerfile b/docker/rpcnode/Dockerfile index 952079ba9..55f33e826 100644 --- a/docker/rpcnode/Dockerfile +++ b/docker/rpcnode/Dockerfile @@ -2,6 +2,8 @@ FROM ubuntu:latest RUN apt-get update && \ apt-get install -y make git golang jq python3 curl vim +SHELL ["/bin/bash", "-c"] + VOLUME [ "/sei-protocol" ] VOLUME [ "/root/go/pkg/mod" ] WORKDIR /sei-protocol/sei-chain @@ -16,3 +18,4 @@ COPY scripts/deploy.sh /usr/bin/deploy.sh COPY scripts/step0_build.sh /usr/bin/build.sh COPY scripts/step1_configure_init.sh /usr/bin/configure_init.sh COPY scripts/step2_start_sei.sh /usr/bin/start_sei.sh +ENV PATH "$PATH:$HOME/go/bin" diff --git a/docker/rpcnode/scripts/deploy.sh b/docker/rpcnode/scripts/deploy.sh index 2b9d28e77..e51b09a20 100755 --- a/docker/rpcnode/scripts/deploy.sh +++ b/docker/rpcnode/scripts/deploy.sh @@ -1,6 +1,7 @@ #!/usr/bin/env sh -NODE_ID=${ID:-0} +SKIP_BUILD=${SKIP_BUILD:-""} + # Set up env export GOPATH=$HOME/go export GOBIN=$GOPATH/bin @@ -11,8 +12,13 @@ echo "GOBIN=$GOPATH/bin" >> /root/.bashrc echo "export PATH=$GOBIN:$PATH:/usr/local/go/bin:$BUILD_PATH" >> /root/.bashrc /bin/bash -c "source /root/.bashrc" mkdir -p $GOBIN + # Step 1 build seid -/usr/bin/build.sh +if [ -z "$SKIP_BUILD" ] +then + /usr/bin/build.sh +fi +cp build/seid "$GOBIN"/ # Run init to set up state sync configurations /usr/bin/configure_init.sh diff --git a/docker/rpcnode/scripts/step2_start_sei.sh b/docker/rpcnode/scripts/step2_start_sei.sh index 26401e808..b67c45571 100755 --- a/docker/rpcnode/scripts/step2_start_sei.sh +++ b/docker/rpcnode/scripts/step2_start_sei.sh @@ -4,6 +4,7 @@ LOG_DIR="build/generated/logs" mkdir -p $LOG_DIR # Starting sei chain -echo "Starting the sei chain rpc node" +echo "RPC Node is starting now, check logs under $LOG_DIR" + seid start --chain-id sei > "$LOG_DIR/rpc-node.log" 2>&1 & -echo "RPC Node is started now, check logs under $LOG_DIR" \ No newline at end of file +echo "Done" >> build/generated/rpc-launch.complete \ No newline at end of file diff --git a/go.mod b/go.mod index 70b9a4e18..ff194d942 100644 --- a/go.mod +++ b/go.mod @@ -273,7 +273,7 @@ require ( replace ( github.com/CosmWasm/wasmd => github.com/sei-protocol/sei-wasmd v0.0.2 github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.2.53 + github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.2.59 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.7 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.1.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/go.sum b/go.sum index d31e4cf99..dde6eefc8 100644 --- a/go.sum +++ b/go.sum @@ -1074,8 +1074,8 @@ github.com/securego/gosec/v2 v2.11.0/go.mod h1:SX8bptShuG8reGC0XS09+a4H2BoWSJi+f github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= -github.com/sei-protocol/sei-cosmos v0.2.53 h1:MSH00lb3ahioaOnJNC4yvMNNPuC9rC0kBZcY30ay5QI= -github.com/sei-protocol/sei-cosmos v0.2.53/go.mod h1:XSmrSNlBQ7OQrk6VZMgARWsnD+1JSnQeDEZ7LEmexbo= +github.com/sei-protocol/sei-cosmos v0.2.59 h1:GCi8R+yuEFIzEzTe+oRUxa2Y/QUvIRCK57aXninBvDk= +github.com/sei-protocol/sei-cosmos v0.2.59/go.mod h1:XSmrSNlBQ7OQrk6VZMgARWsnD+1JSnQeDEZ7LEmexbo= github.com/sei-protocol/sei-iavl v0.1.7 h1:cUdHDBkxs0FF/kOt1qCVLm0K+Bqaw92/dbZSgn4kxiA= github.com/sei-protocol/sei-iavl v0.1.7/go.mod h1:7PfkEVT5dcoQE+s/9KWdoXJ8VVVP1QpYYPLdxlkSXFk= github.com/sei-protocol/sei-ibc-go/v3 v3.1.0 h1:rFHk2R/3vbG9iNr7cYtVclW/UyEDSRFjNVPz60zZswU= diff --git a/integration_test/bank_module/multi_sig_send_test.yaml b/integration_test/bank_module/multi_sig_send_test.yaml new file mode 100644 index 000000000..c8341ac07 --- /dev/null +++ b/integration_test/bank_module/multi_sig_send_test.yaml @@ -0,0 +1,31 @@ +- name: Test multi-sig sending funds + inputs: + # Create 3 wallets that manages 1 multisig wallet + - cmd: seid keys add wallet1 --keyring-backend test --output json | jq -r ".address" + env: WALLET_1_ACC + - cmd: seid keys add wallet2 --keyring-backend test --output json | jq -r ".address" + env: WALLET_2_ACC + - cmd: seid keys add wallet3 --keyring-backend test --output json | jq -r ".address" + env: WALLET_3_ACC + - cmd: seid keys add multisig --multisig-threshold=2 --multisig=wallet1,wallet2,wallet3 --keyring-backend test --output json | jq -r ".address" + env: MULTI_SIG_ACC + + # Send funds to the multisig + - cmd: printf "12345678\n" | seid keys show -a admin + env: ADMIN_ACC + - cmd: printf "12345678\n" | seid tx bank send $ADMIN_ACC $MULTI_SIG_ACC 11sei -b block --fees 2000usei --chain-id sei -y + + # Creat and send multi-sig transaction + - cmd: seid tx bank send $MULTI_SIG_ACC $MULTI_SIG_ACC 1sei -b block -y --fees 1sei -y --from $MULTI_SIG_ACC --generate-only --keyring-backend test > unsigned-tx.json + - cmd: seid tx sign unsigned-tx.json --multisig=$MULTI_SIG_ACC --keyring-backend test --from=wallet1 --output-document=wallet1.json --chain-id sei -b block --fees 1sei + - cmd: seid tx sign unsigned-tx.json --multisig=$MULTI_SIG_ACC --keyring-backend test --from=wallet2 --output-document=wallet2.json --chain-id sei -b block --fees 1sei + - cmd: seid tx multisign unsigned-tx.json multisig wallet1.json wallet2.json --chain-id sei --keyring-backend test > signed-tx.json + - cmd: seid tx broadcast signed-tx.json --chain-id sei -b block -y + + # Check multi-sig balance + - cmd: seid q bank balances $MULTI_SIG_ACC --output json | jq -r .balances[0].amount + env: MULTI_SIG_ACC_BALANCE + verifiers: + # Bank balance should be 10 sei, 1 sei paid and 10sei sent to self + - type: eval + expr: MULTI_SIG_ACC_BALANCE == 10000000 diff --git a/integration_test/bank_module/simulation_tx.yaml b/integration_test/bank_module/simulation_tx.yaml new file mode 100644 index 000000000..d0b138b33 --- /dev/null +++ b/integration_test/bank_module/simulation_tx.yaml @@ -0,0 +1,26 @@ +- name: Test simulation sending funds + inputs: + # Create test account + - cmd: seid keys add simulation-test --keyring-backend test + - cmd: printf "12345678\n" | seid keys show -a admin + env: ADMIN_ACC + - cmd: seid keys show -a simulation-test --keyring-backend test + env: SIMULATION_TEST_ACC + + # Send funds + - cmd: printf "12345678\n" | seid tx bank send $ADMIN_ACC $SIMULATION_TEST_ACC 1sei -b block --fees 2000usei --chain-id sei -y + + - cmd: seid tx bank send $ADMIN_ACC $SIMULATION_TEST_ACC 1000sei --from $ADMIN_ACC --chain-id sei -b block -y --dry-run --keyring-backend test + env: GAS_ESIMATE + + # Validate that only the 1sei is sent + - cmd: seid q bank balances $SIMULATION_TEST_ACC --output json | jq -r .balances[0].amount + env: SIMULATION_TEST_ACC_BALANCE + + verifiers: + # Bank balance should be 1sei + - type: eval + expr: SIMULATION_TEST_ACC_BALANCE == 1000000 + - type: regex + expr: "^gas estimate.*[0-9]+" + result: GAS_ESIMATE diff --git a/integration_test/chain_operation/snapshot_operation.yaml b/integration_test/chain_operation/snapshot_operation.yaml new file mode 100644 index 000000000..81c05eb6b --- /dev/null +++ b/integration_test/chain_operation/snapshot_operation.yaml @@ -0,0 +1,9 @@ +- name: Test validators should be able to create snapshot with custom location + inputs: + # Check if snapshotd are created + - cmd: if [ -d "./build/generated/node_0/snapshots" ]; then echo "true"; else echo "false"; fi + env: FOUND + node: sei-node-0 + verifiers: + - type: eval + expr: FOUND == "true" diff --git a/integration_test/chain_operation/statesync_operation.yaml b/integration_test/chain_operation/statesync_operation.yaml new file mode 100644 index 000000000..133f4911a --- /dev/null +++ b/integration_test/chain_operation/statesync_operation.yaml @@ -0,0 +1,9 @@ +- name: Test rpc node should be able to state sync from the snapshots + inputs: + # Check if rpc node is up and running + - cmd: seid status |jq -M -r .SyncInfo.latest_block_height + env: HEIGHT + node: sei-rpc-node + verifiers: + - type: eval + expr: HEIGHT > 0 diff --git a/integration_test/dex_module/place_order_test.yaml b/integration_test/dex_module/place_order_test.yaml index 5b0422a0b..725c1a499 100644 --- a/integration_test/dex_module/place_order_test.yaml +++ b/integration_test/dex_module/place_order_test.yaml @@ -6,6 +6,8 @@ # Prepare parameter - cmd: echo "LONG?1.01?5?SEI?ATOM?LIMIT?{\"leverage\":\"1\",\"position_effect\":\"Open\"}" env: PARAMS + # Verify that placing a dex order with gas > max block gas fails but does not halt chain + - cmd: printf "12345678\n" | seid tx dex place-orders $CONTRACT_ADDR $PARAMS --amount=1000000000usei -y --from=admin --chain-id=sei --fees=1000000usei --gas=500000000 --broadcast-mode=block --output json|jq -M -r ".logs[].events[].attributes[] | select(.key == \"order_id\").value" # Place an order and set ORDER_ID - cmd: printf "12345678\n" | seid tx dex place-orders $CONTRACT_ADDR $PARAMS --amount=1000000000usei -y --from=admin --chain-id=sei --fees=1000000usei --gas=50000000 --broadcast-mode=block --output json|jq -M -r ".logs[].events[].attributes[] | select(.key == \"order_id\").value" env: ORDER_ID diff --git a/integration_test/distribution_module/community_pool.yaml b/integration_test/distribution_module/community_pool.yaml new file mode 100644 index 000000000..2cbb85640 --- /dev/null +++ b/integration_test/distribution_module/community_pool.yaml @@ -0,0 +1,15 @@ +- name: Test funding community pool + inputs: + # Start with initial community pool amount + - cmd: printf "12345678\n" | seid tx distribution fund-community-pool 10sei --from admin -b block --fees 2000usei --chain-id sei -y + - cmd: seid q distribution community-pool -o json | jq -r ".pool[0].amount" + env: COMMUNITY_FUND_POOL_START + # Fund community pool + - cmd: printf "12345678\n" | seid tx distribution fund-community-pool 10sei --from admin -b block --fees 2000usei --chain-id sei -y + - cmd: seid q distribution community-pool -o json | jq -r ".pool[0].amount" + env: COMMUNITY_FUND_POOL_END + verifiers: + # Community fund pool should have increased + - type: eval + expr: COMMUNITY_FUND_POOL_START < COMMUNITY_FUND_POOL_END + diff --git a/integration_test/distribution_module/rewards.yaml b/integration_test/distribution_module/rewards.yaml new file mode 100644 index 000000000..881459c71 --- /dev/null +++ b/integration_test/distribution_module/rewards.yaml @@ -0,0 +1,28 @@ +- name: Test withdraw rewards + inputs: + # Create test account + - cmd: seid keys add --keyring-backend test distribution-test + - cmd: printf "12345678\n" | seid keys show -a node_admin + env: NODE_ADMIN_ACC + - cmd: seid keys show -a distribution-test --keyring-backend test + env: DISTRIBUTION_TEST_ACC + # Get current rewards + - cmd: seid q distribution rewards $NODE_ADMIN_ACC -o json | jq -r ".total[0].amount" + env: REWARDS_START + # Simple tx to increase rewards + - cmd: printf "12345678\n" | seid tx bank send $NODE_ADMIN_ACC $DISTRIBUTION_TEST_ACC 1sei -b block --fees 2000usei --chain-id sei -y + # Get rewards after tx + - cmd: seid q distribution rewards $NODE_ADMIN_ACC -o json | jq -r ".total[0].amount" + env: REWARDS_AFTER_TX + # Withdraw all rewards + - cmd: printf "12345678\n" | seid tx distribution withdraw-all-rewards -b block --fees 2000usei --chain-id sei -y --from node_admin + # Get rewards after withdraw + - cmd: seid q distribution rewards $NODE_ADMIN_ACC -o json | jq -r ".total[0].amount" + env: REWARDS_AFTER_WITHDRAW + verifiers: + # Rewards should have increased + - type: eval + expr: REWARDS_AFTER_TX > REWARDS_START + - type: eval + expr: REWARDS_AFTER_WITHDRAW < REWARDS_AFTER_TX + diff --git a/scripts/initialize_local_chain.sh b/scripts/initialize_local_chain.sh index 02d4a28c7..9f9de2a8d 100755 --- a/scripts/initialize_local_chain.sh +++ b/scripts/initialize_local_chain.sh @@ -2,6 +2,14 @@ # require success for commands set -e + +# Use python3 as default, but fall back to python if python3 doesn't exist +PYTHON_CMD=python3 +if ! command -v $PYTHON_CMD &> /dev/null +then + PYTHON_CMD=python +fi + # set key name keyname=admin #docker stop jaeger @@ -47,13 +55,19 @@ python3 loadtest/scripts/populate_genesis_accounts.py 10 loc # update some params in genesis file for easier use of the chain localls (make gov props faster) cat ~/.sei/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["max_deposit_period"]="300s"' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json cat ~/.sei/config/genesis.json | jq '.app_state["gov"]["voting_params"]["voting_period"]="30s"' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json -cat ~/.sei/config/genesis.json | jq --arg start_date "$(date +"%Y-%m-%d")" --arg end_date "$(date -v+3d +"%Y-%m-%d")" '.app_state["mint"]["params"]["token_release_schedule"]=[{"start_date": $start_date, "end_date": $end_date, "token_release_amount": "999999999999"}]' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json -cat ~/.sei/config/genesis.json | jq --arg start_date "$(date -v+3d +"%Y-%m-%d")" --arg end_date "$(date -v+5d +"%Y-%m-%d")" '.app_state["mint"]["params"]["token_release_schedule"] += [{"start_date": $start_date, "end_date": $end_date, "token_release_amount": "999999999999"}]' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json cat ~/.sei/config/genesis.json | jq '.app_state["gov"]["voting_params"]["expedited_voting_period"]="10s"' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json cat ~/.sei/config/genesis.json | jq '.app_state["oracle"]["params"]["vote_period"]="1"' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json cat ~/.sei/config/genesis.json | jq '.app_state["oracle"]["params"]["whitelist"]=[{"name": "ueth"},{"name": "ubtc"},{"name": "uusdc"},{"name": "uusdt"}]' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json cat ~/.sei/config/genesis.json | jq '.app_state["distribution"]["params"]["community_tax"]="0.000000000000000000"' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json +# Use the Python command to get the dates +START_DATE=$($PYTHON_CMD -c "from datetime import datetime; print(datetime.now().strftime('%Y-%m-%d'))") +END_DATE_3DAYS=$($PYTHON_CMD -c "from datetime import datetime, timedelta; print((datetime.now() + timedelta(days=3)).strftime('%Y-%m-%d'))") +END_DATE_5DAYS=$($PYTHON_CMD -c "from datetime import datetime, timedelta; print((datetime.now() + timedelta(days=5)).strftime('%Y-%m-%d'))") + +cat ~/.sei/config/genesis.json | jq --arg start_date "$START_DATE" --arg end_date "$END_DATE_3DAYS" '.app_state["mint"]["params"]["token_release_schedule"]=[{"start_date": $start_date, "end_date": $end_date, "token_release_amount": "999999999999"}]' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json +cat ~/.sei/config/genesis.json | jq --arg start_date "$END_DATE_3DAYS" --arg end_date "$END_DATE_5DAYS" '.app_state["mint"]["params"]["token_release_schedule"] += [{"start_date": $start_date, "end_date": $end_date, "token_release_amount": "999999999999"}]' > ~/.sei/config/tmp_genesis.json && mv ~/.sei/config/tmp_genesis.json ~/.sei/config/genesis.json + # set block time to 2s if [ ! -z "$1" ]; then CONFIG_PATH="$1" diff --git a/x/mint/types/minter.go b/x/mint/types/minter.go index 9df99e4cc..d7d194bc6 100644 --- a/x/mint/types/minter.go +++ b/x/mint/types/minter.go @@ -20,7 +20,7 @@ func NewMinter( return Minter{ StartDate: startDate, EndDate: endDate, - Denom: sdk.DefaultBondDenom, + Denom: denom, TotalMintAmount: totalMintAmount, RemainingMintAmount: totalMintAmount, LastMintDate: time.Time{}.Format(TokenReleaseDateFormat), @@ -55,6 +55,9 @@ func ValidateMinter(minter Minter) error { if endDate.Before(startDate) { return fmt.Errorf("end date must be after start date %s < %s", endDate, startDate) } + if err := validateMintDenom(minter.Denom); err != nil { + return err + } return nil } diff --git a/x/mint/types/minter_test.go b/x/mint/types/minter_test.go index adbd7d70b..8106752b8 100644 --- a/x/mint/types/minter_test.go +++ b/x/mint/types/minter_test.go @@ -369,6 +369,15 @@ func TestValidateMinterBase(t *testing.T) { err := types.ValidateMinter(m) require.NotNil(t, err) + m = types.NewMinter( + time.Now().Format(types.TokenReleaseDateFormat), + time.Now().AddDate(0, 0, 1).Format(types.TokenReleaseDateFormat), + "invalid denom", + 1000, + ) + err = types.ValidateMinter(m) + require.NotNil(t, err) + m = types.NewMinter( time.Now().Format(types.TokenReleaseDateFormat), time.Now().AddDate(0, 0, 1).Format(types.TokenReleaseDateFormat), diff --git a/x/oracle/keeper/querier_test.go b/x/oracle/keeper/querier_test.go index 14d6ff8af..070ae2709 100755 --- a/x/oracle/keeper/querier_test.go +++ b/x/oracle/keeper/querier_test.go @@ -86,19 +86,26 @@ func TestQueryFeederDelegation(t *testing.T) { func TestQuerySlashingWindow(t *testing.T) { input := CreateTestInput(t) querier := NewQuerier(input.OracleKeeper) + votePeriod := input.OracleKeeper.VotePeriod(input.Ctx) - input.Ctx = input.Ctx.WithBlockHeight(12502) + blocks := int64(12502) + expectedWindows := uint64(blocks) / votePeriod + + input.Ctx = input.Ctx.WithBlockHeight(blocks) ctx := sdk.WrapSDKContext(input.Ctx) res, err := querier.SlashWindow(ctx, &types.QuerySlashWindowRequest{}) require.NoError(t, err) // Based on voting period - require.Equal(t, 12502, int(res.WindowProgress)) + require.Equal(t, expectedWindows, res.WindowProgress) + + blocks = int64(300501 % input.OracleKeeper.SlashWindow(input.Ctx)) + expectedWindows = uint64(blocks) / votePeriod - input.Ctx = input.Ctx.WithBlockHeight(300501) + input.Ctx = input.Ctx.WithBlockHeight(blocks) ctx = sdk.WrapSDKContext(input.Ctx) res, err = querier.SlashWindow(ctx, &types.QuerySlashWindowRequest{}) require.NoError(t, err) - require.Equal(t, 300501, int(res.WindowProgress)) + require.Equal(t, expectedWindows, res.WindowProgress) } func TestQueryVoteTargets(t *testing.T) { diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 0c85f3b55..ef76e1461 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -25,14 +25,14 @@ var ( // Default parameter values const ( - DefaultVotePeriod = 1 // Voting every block - DefaultSlashWindow = utils.BlocksPerWeek // window for a week + DefaultVotePeriod = 2 // Voting every other block + DefaultSlashWindow = utils.BlocksPerDay * 2 // 2 days for oracle slashing ) // Default parameter values var ( - DefaultVoteThreshold = sdk.NewDecWithPrec(50, 2) // 50% - DefaultRewardBand = sdk.NewDecWithPrec(2, 2) // 2% (-1, 1) + DefaultVoteThreshold = sdk.NewDecWithPrec(667, 3) // 66.7% + DefaultRewardBand = sdk.NewDecWithPrec(2, 2) // 2% (-1, 1) DefaultWhitelist = DenomList{ {Name: utils.MicroAtomDenom}, // {Name: utils.MicroUsdcDenom},