Skip to content

Commit

Permalink
feat: automatically halt pool if a node's voting power is too high (#142
Browse files Browse the repository at this point in the history
)

(cherry picked from commit 1aaf221)
  • Loading branch information
troykessler authored and mergify[bot] committed Nov 6, 2023
1 parent 6fa1431 commit 8aa67bb
Show file tree
Hide file tree
Showing 37 changed files with 2,236 additions and 1,606 deletions.
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

0 comments on commit 8aa67bb

Please sign in to comment.