Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: automatically halt pool if a node's voting power is too high (backport #142) #143

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ An '!' indicates a state machine breaking change.

### Improvements

- ! (`x/bundles`) [#142](https://github.com/KYVENetwork/chain/pull/142) Halt the pool if a single validator has more than 50% voting power.
- (deps) [#33](https://github.com/KYVENetwork/chain/pull/33) Upgrade Cosmos SDK to [v0.47.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.5) ([`v0.47.5-kyve`](https://github.com/KYVENetwork/cosmos-sdk/releases/tag/v0.47.5-kyve-rc0)).

## [v1.3.1](https://github.com/KYVENetwork/chain/releases/tag/v1.3.1) - 2023-08-02
Expand Down
9 changes: 9 additions & 0 deletions docs/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
points:
type: string
Expand Down Expand Up @@ -1083,6 +1084,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
title: >-
BasicPool contains the necessary properties need for a
Expand Down Expand Up @@ -3949,6 +3951,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
points:
type: string
Expand Down Expand Up @@ -4999,6 +5002,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
account:
type: string
Expand Down Expand Up @@ -5515,6 +5519,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
account:
type: string
Expand Down Expand Up @@ -5992,6 +5997,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
points:
type: string
Expand Down Expand Up @@ -6421,6 +6427,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
points:
type: string
Expand Down Expand Up @@ -6962,6 +6969,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
points:
type: string
Expand Down Expand Up @@ -7434,6 +7442,7 @@ paths:
- POOL_STATUS_NO_FUNDS
- POOL_STATUS_NOT_ENOUGH_DELEGATION
- POOL_STATUS_UPGRADING
- POOL_STATUS_VOTING_POWER_TOO_HIGH
default: POOL_STATUS_UNSPECIFIED
points:
type: string
Expand Down
22 changes: 16 additions & 6 deletions proto/kyve/pool/v1beta1/pool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,28 @@ option go_package = "github.com/KYVENetwork/chain/x/pool/types";
enum PoolStatus {
option (gogoproto.goproto_enum_prefix) = false;

// POOL_STATUS_UNSPECIFIED ...
// POOL_STATUS_UNSPECIFIED indicates an unknown status, likely
// due to an error
POOL_STATUS_UNSPECIFIED = 0;
// POOL_STATUS_ACTIVE ...
// POOL_STATUS_ACTIVE indicates, that the pool is running
// normally
POOL_STATUS_ACTIVE = 1;
// POOL_STATUS_DISABLED ...
// POOL_STATUS_DISABLED indicates, that the pool was disabled
// by the governance and does not continue until it is enabled
// by the governance again
POOL_STATUS_DISABLED = 2;
// POOL_STATUS_NO_FUNDS ...
// POOL_STATUS_NO_FUNDS indicates, that the pool currently has no
// funds, but is continuing normally anyway, due to inflation splitting
POOL_STATUS_NO_FUNDS = 3;
// POOL_STATUS_NOT_ENOUGH_DELEGATION ...
// POOL_STATUS_NOT_ENOUGH_DELEGATION indicates, that the min delegation
// requirement has not been met and that the pool is halted
POOL_STATUS_NOT_ENOUGH_DELEGATION = 4;
// POOL_STATUS_UPGRADING ...
// POOL_STATUS_UPGRADING indicates, that the runtime is currently
// being upgraded and that the pool is halted
POOL_STATUS_UPGRADING = 5;
// POOL_STATUS_VOTING_POWER_TOO_HIGH indicates, that one validator
// has more than 50% voting power and that the pool is halted
POOL_STATUS_VOTING_POWER_TOO_HIGH = 6;
}

// Protocol holds all info about the current pool version and the
Expand Down
6 changes: 3 additions & 3 deletions testutil/integration/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ func (suite *KeeperTestSuite) GetNextUploader() (nextStaker string, nextValaddre
switch bundleProposal.NextUploader {
case STAKER_0:
nextStaker = STAKER_0
nextValaddress = VALADDRESS_0
nextValaddress = VALADDRESS_0_A
case STAKER_1:
nextStaker = STAKER_1
nextValaddress = VALADDRESS_1
nextValaddress = VALADDRESS_1_A
case STAKER_2:
nextStaker = STAKER_2
nextValaddress = VALADDRESS_2
nextValaddress = VALADDRESS_2_A
default:
nextStaker = ""
nextValaddress = ""
Expand Down
42 changes: 33 additions & 9 deletions testutil/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,27 @@ const (
ALICE = "kyve1jq304cthpx0lwhpqzrdjrcza559ukyy3zsl2vd"
BOB = "kyve1hvg7zsnrj6h29q9ss577mhrxa04rn94h7zjugq"
CHARLIE = "kyve1ay22rr3kz659fupu0tcswlagq4ql6rwm4nuv0s"
DAVID = "kyve1jxa7kp37jlm8hzwgc5qprquv9k7vawq79qhctt"

STAKER_0 = "kyve1htgfatqevuvfzvl0sxp97ywteqhg5leha9emf4"
VALADDRESS_0 = "kyve1qnf86dkvvtpdukx30r3vajav7rdq8snktm90hm"
STAKER_0 = "kyve1htgfatqevuvfzvl0sxp97ywteqhg5leha9emf4"
VALADDRESS_0_A = "kyve1qnf86dkvvtpdukx30r3vajav7rdq8snktm90hm"
VALADDRESS_0_B = "kyve10t8gnqjnem7tsu09erzswj3zm8599lsnex79rz"
VALADDRESS_0_C = "kyve13ztkcm2pket6mrmxj8rrmwc6supw7aqakg3uu3"

STAKER_1 = "kyve1gnr35rwn8rmflnlzs6nn5hhkmzzkxg9ap8xepw"
VALADDRESS_1 = "kyve1hpjgzljglmv00nstk3jvcw0zzq94nu0cuxv5ga"
STAKER_1 = "kyve1gnr35rwn8rmflnlzs6nn5hhkmzzkxg9ap8xepw"
VALADDRESS_1_A = "kyve1hpjgzljglmv00nstk3jvcw0zzq94nu0cuxv5ga"
VALADDRESS_1_B = "kyve14runw9qkltpz2mcx3gsfmlqyyvdzkt3rq3w6fm"
VALADDRESS_1_C = "kyve15w9m7zpq9ctsxsveqaqkp4uuvw98z5vct6s9g9"

STAKER_2 = "kyve1xsemlxghgvusumhqzm2ztjw7dz9krvu3de54e2"
VALADDRESS_2 = "kyve1u0870dkae6ql63hxvy9y7g65c0y8csfh8allzl"
STAKER_2 = "kyve1xsemlxghgvusumhqzm2ztjw7dz9krvu3de54e2"
VALADDRESS_2_A = "kyve1u0870dkae6ql63hxvy9y7g65c0y8csfh8allzl"
VALADDRESS_2_B = "kyve16g3utghkvvlz53jk0fq96zwrhxmqfu36ue965q"
VALADDRESS_2_C = "kyve18gjtzsn6jme3qsczj9q7wefymlkfu7ngyq5f9c"

STAKER_3 = "kyve1ca7rzyrxfpdm7j8jgccq4rduuf4sxpq0dhmwm4"
VALADDRESS_3_A = "kyve1d2clkfrw0r99ctgmkjvluzn6xm98yls06mnxv8"
VALADDRESS_3_B = "kyve1f36cvde6jnygcrz2yas4acp0akn9cw7vp5ze0w"
VALADDRESS_3_C = "kyve1gcnd8gya2ysfur6d6z4wpl9z54zadg7qzk8uyc"

// To avoid giving burner permissions to a module for the tests
BURNER = "kyve1ld23ktfwc9zstaq8aanwkkj8cf0ru6adtz59y5"
Expand Down Expand Up @@ -71,15 +83,27 @@ func (suite *KeeperTestSuite) initDummyAccounts() {
_ = suite.Mint(ALICE, 1000*KYVE)
_ = suite.Mint(BOB, 1000*KYVE)
_ = suite.Mint(CHARLIE, 1000*KYVE)
_ = suite.Mint(DAVID, 1000*KYVE)

_ = suite.Mint(STAKER_0, 1000*KYVE)
_ = suite.Mint(VALADDRESS_0, 1000*KYVE)
_ = suite.Mint(VALADDRESS_0_A, 1000*KYVE)
_ = suite.Mint(VALADDRESS_0_B, 1000*KYVE)
_ = suite.Mint(VALADDRESS_0_C, 1000*KYVE)

_ = suite.Mint(STAKER_1, 1000*KYVE)
_ = suite.Mint(VALADDRESS_1, 1000*KYVE)
_ = suite.Mint(VALADDRESS_1_A, 1000*KYVE)
_ = suite.Mint(VALADDRESS_1_B, 1000*KYVE)
_ = suite.Mint(VALADDRESS_1_C, 1000*KYVE)

_ = suite.Mint(STAKER_2, 1000*KYVE)
_ = suite.Mint(VALADDRESS_2, 1000*KYVE)
_ = suite.Mint(VALADDRESS_2_A, 1000*KYVE)
_ = suite.Mint(VALADDRESS_2_B, 1000*KYVE)
_ = suite.Mint(VALADDRESS_2_C, 1000*KYVE)

_ = suite.Mint(STAKER_3, 1000*KYVE)
_ = suite.Mint(VALADDRESS_3_A, 1000*KYVE)
_ = suite.Mint(VALADDRESS_3_B, 1000*KYVE)
_ = suite.Mint(VALADDRESS_3_C, 1000*KYVE)

DUMMY = make([]string, 50)

Expand Down
48 changes: 41 additions & 7 deletions x/bundles/keeper/abci_protocol_split_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,18 @@ var _ = Describe("abci.go", Ordered, func() {
s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_0,
PoolId: 0,
Valaddress: i.VALADDRESS_0,
Valaddress: i.VALADDRESS_0_A,
})

s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{
Creator: i.STAKER_1,
Amount: 100 * i.KYVE,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_1,
PoolId: 0,
Valaddress: i.VALADDRESS_1_A,
})

b1, b2 := uint64(0), uint64(0)
Expand Down Expand Up @@ -119,21 +130,33 @@ var _ = Describe("abci.go", Ordered, func() {
Amount: 100 * i.KYVE,
})

s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{
Creator: i.STAKER_1,
Amount: 100 * i.KYVE,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_0,
PoolId: 0,
Valaddress: i.VALADDRESS_0,
Valaddress: i.VALADDRESS_0_A,
})

s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{
Creator: i.STAKER_1,
Amount: 100 * i.KYVE,
s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_1,
PoolId: 0,
Valaddress: i.VALADDRESS_1_A,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_0,
PoolId: 1,
Valaddress: i.VALADDRESS_0_B,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_1,
PoolId: 1,
Valaddress: i.VALADDRESS_1,
Valaddress: i.VALADDRESS_1_B,
})

// ACT
Expand Down Expand Up @@ -174,7 +197,18 @@ var _ = Describe("abci.go", Ordered, func() {
s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_0,
PoolId: 0,
Valaddress: i.VALADDRESS_0,
Valaddress: i.VALADDRESS_0_A,
})

s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{
Creator: i.STAKER_1,
Amount: 100 * i.KYVE,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_1,
PoolId: 0,
Valaddress: i.VALADDRESS_1_A,
})

// ACT
Expand Down
36 changes: 23 additions & 13 deletions x/bundles/keeper/keeper_suite_dropped_bundles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ var _ = Describe("dropped bundles", Ordered, func() {
s := i.NewCleanChain()

initialBalanceStaker0 := s.GetBalanceFromAddress(i.STAKER_0)
initialBalanceValaddress0 := s.GetBalanceFromAddress(i.VALADDRESS_0)
initialBalanceValaddress0 := s.GetBalanceFromAddress(i.VALADDRESS_0_A)

initialBalanceStaker1 := s.GetBalanceFromAddress(i.STAKER_1)
initialBalanceValaddress1 := s.GetBalanceFromAddress(i.VALADDRESS_1)
initialBalanceValaddress1 := s.GetBalanceFromAddress(i.VALADDRESS_1_A)

BeforeEach(func() {
// init new clean chain
Expand Down Expand Up @@ -60,20 +60,31 @@ var _ = Describe("dropped bundles", Ordered, func() {
s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_0,
PoolId: 0,
Valaddress: i.VALADDRESS_0,
Valaddress: i.VALADDRESS_0_A,
})

s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{
Creator: i.STAKER_1,
Amount: 100 * i.KYVE,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_1,
PoolId: 0,
Valaddress: i.VALADDRESS_1_A,
})

s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{
Creator: i.VALADDRESS_0,
Creator: i.VALADDRESS_0_A,
Staker: i.STAKER_0,
PoolId: 0,
})

initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0)
initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0)
initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A)

initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1)
initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1)
initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A)

s.CommitAfterSeconds(60)
})
Expand All @@ -84,22 +95,21 @@ var _ = Describe("dropped bundles", Ordered, func() {

It("Produce a dropped bundle because not enough validators voted", func() {
// ARRANGE
// stake a bit more than first node so >50% is reached
s.RunTxStakersSuccess(&stakertypes.MsgCreateStaker{
Creator: i.STAKER_1,
Amount: 200 * i.KYVE,
Creator: i.STAKER_2,
Amount: 100 * i.KYVE,
})

s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{
Creator: i.STAKER_1,
Creator: i.STAKER_2,
PoolId: 0,
Valaddress: i.VALADDRESS_1,
Valaddress: i.VALADDRESS_2_A,
})

initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1)
initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_2)

s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{
Creator: i.VALADDRESS_0,
Creator: i.VALADDRESS_0_A,
Staker: i.STAKER_0,
PoolId: 0,
StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI",
Expand Down
Loading