Skip to content

Commit

Permalink
feat: store stake security for finalized bundles (backport #108) (#109)
Browse files Browse the repository at this point in the history
Co-authored-by: Maximilian Breithecker <72022235+mbreithecker@users.noreply.github.com>
  • Loading branch information
mergify[bot] and mbreithecker authored Jul 12, 2023
1 parent 22cdf3d commit 70f7468
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 68 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 @@

- (ibc) [#30](https://github.com/KYVENetwork/chain/pull/30) Integrate [Packet Forward Middleware](https://github.com/strangelove-ventures/packet-forward-middleware).
- (`x/bundles`) [#99](https://github.com/KYVENetwork/chain/pull/99) Use weighted round-robin approach for uploader selection.
- (`x/bundles`) [#108](https://github.com/KYVENetwork/chain/pull/108) Store stake security for finalized bundles.

### Improvements

Expand Down
1 change: 1 addition & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,7 @@ func NewKYVEApp(
app.AccountKeeper,
app.BankKeeper,
app.StakingKeeper,
app.BundlesKeeper,
),
)

Expand Down
16 changes: 16 additions & 0 deletions app/upgrades/v1_3/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package v1_3
import (
"fmt"

bundlesKeeper "github.com/KYVENetwork/chain/x/bundles/keeper"
bundlesTypes "github.com/KYVENetwork/chain/x/bundles/types"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/tendermint/tendermint/libs/log"
Expand All @@ -29,11 +32,13 @@ func CreateUpgradeHandler(
accountKeeper authKeeper.AccountKeeper,
bankKeeper bankKeeper.Keeper,
stakingKeeper stakingKeeper.Keeper,
bundlesKeeper bundlesKeeper.Keeper,
) upgradeTypes.UpgradeHandler {
return func(ctx sdk.Context, _ upgradeTypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
logger := ctx.Logger().With("upgrade", UpgradeName)

CheckPoolAccounts(ctx, logger, poolKeeper)
UpdateBundlesVersionMap(bundlesKeeper, ctx)

if ctx.ChainID() == MainnetChainID {
for _, address := range InvestorAccounts {
Expand Down Expand Up @@ -92,3 +97,14 @@ func CheckPoolAccounts(ctx sdk.Context, logger log.Logger, keeper poolKeeper.Kee
logger.Info("successfully initialised pool account", "name", name)
}
}

func UpdateBundlesVersionMap(keeper bundlesKeeper.Keeper, ctx sdk.Context) {
keeper.SetBundleVersionMap(ctx, bundlesTypes.BundleVersionMap{
Versions: []*bundlesTypes.BundleVersionEntry{
{
Height: uint64(ctx.BlockHeight()),
Version: 2,
},
},
})
}
8 changes: 5 additions & 3 deletions proto/kyve/bundles/v1beta1/bundles.proto
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ message FinalizedBundle {
uint32 storage_provider_id = 12;
// compression_id the id of the compression type with which the data was compressed
uint32 compression_id = 13;
// stake_security
StakeSecurity stake_security = 14;
}

// FinalizedAt ...
Expand All @@ -101,11 +103,11 @@ message FinalizedAt {
uint64 timestamp = 2;
}

// FinalizedAt ...
// StakeSecurity stores information about total stake and valid votes with which the bundle got finalized.
message StakeSecurity {
// valid_vote_power ...
// valid_vote_power is the total amount of stake of all pool stakers which voted valid for the given bundle.
uint64 valid_vote_power = 1;
// total_vote_power ...
// total_vote_power is the total amount of stake that was present during the finalization of the bundle
uint64 total_vote_power = 2;
}

Expand Down
2 changes: 2 additions & 0 deletions testutil/integration/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ func checkFinalizedBundle(queryBundle querytypes.FinalizedBundle, rawBundle bund
Expect(queryBundle.FromKey).To(Equal(rawBundle.FromKey))
Expect(queryBundle.StorageProviderId).To(Equal(uint64(rawBundle.StorageProviderId)))
Expect(queryBundle.CompressionId).To(Equal(uint64(rawBundle.CompressionId)))
Expect(queryBundle.StakeSecurity.ValidVotePower.Uint64()).To(Equal(rawBundle.StakeSecurity.ValidVotePower))
Expect(queryBundle.StakeSecurity.TotalVotePower.Uint64()).To(Equal(rawBundle.StakeSecurity.TotalVotePower))
}

func (suite *KeeperTestSuite) VerifyBundlesQueries() {
Expand Down
7 changes: 6 additions & 1 deletion x/bundles/keeper/getters_bundles.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,12 @@ func RawBundleToQueryBundle(rawFinalizedBundle types.FinalizedBundle, versionMap
}

// Check for version 2
// TODO will be done by separate PR
if rawFinalizedBundle.FinalizedAt.Height >= versionMap[2] {
validPower := cosmossdk_io_math.NewInt(int64(rawFinalizedBundle.StakeSecurity.ValidVotePower))
totalPower := cosmossdk_io_math.NewInt(int64(rawFinalizedBundle.StakeSecurity.TotalVotePower))
finalizedBundle.StakeSecurity.ValidVotePower = &validPower
finalizedBundle.StakeSecurity.TotalVotePower = &totalPower
}

return finalizedBundle
}
Expand Down
16 changes: 14 additions & 2 deletions x/bundles/keeper/keeper_suite_valid_bundles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(100 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(100 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand Down Expand Up @@ -263,6 +265,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(400 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(400 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand Down Expand Up @@ -401,6 +405,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(200 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(200 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand All @@ -409,7 +415,6 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(bundleProposal.PoolId).To(Equal(uint64(0)))
Expect(bundleProposal.StorageId).To(Equal("P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg"))
Expect(bundleProposal.Uploader).To(Equal(i.STAKER_0))
// TODO(postAudit,@troy): how to get next uploader deterministically?
Expect(bundleProposal.NextUploader).NotTo(BeEmpty())
Expect(bundleProposal.DataSize).To(Equal(uint64(100)))
Expect(bundleProposal.DataHash).To(Equal("test_hash2"))
Expand Down Expand Up @@ -557,6 +562,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(700 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(700 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand All @@ -565,7 +572,6 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(bundleProposal.PoolId).To(Equal(uint64(0)))
Expect(bundleProposal.StorageId).To(Equal("P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg"))
Expect(bundleProposal.Uploader).To(Equal(i.STAKER_0))
// TODO(postAudit,@troy): how to get next uploader deterministically?
Expect(bundleProposal.NextUploader).NotTo(BeEmpty())
Expect(bundleProposal.DataSize).To(Equal(uint64(100)))
Expect(bundleProposal.DataHash).To(Equal("test_hash2"))
Expand Down Expand Up @@ -720,6 +726,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(400 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(700 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand Down Expand Up @@ -884,6 +892,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(400 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(700 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand Down Expand Up @@ -1048,6 +1058,8 @@ var _ = Describe("valid bundles", Ordered, func() {
Expect(finalizedBundle.BundleSummary).To(Equal("test_value"))
Expect(finalizedBundle.DataHash).To(Equal("test_hash"))
Expect(finalizedBundle.FinalizedAt).NotTo(BeZero())
Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(400 * i.KYVE))
Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(700 * i.KYVE))

// check if next bundle proposal got registered
bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0)
Expand Down
4 changes: 4 additions & 0 deletions x/bundles/keeper/logic_bundles.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,10 @@ func (k Keeper) finalizeCurrentBundleProposal(ctx sdk.Context, poolId uint64, vo
DataHash: bundleProposal.DataHash,
StorageProviderId: bundleProposal.StorageProviderId,
CompressionId: bundleProposal.CompressionId,
StakeSecurity: &types.StakeSecurity{
ValidVotePower: voteDistribution.Valid,
TotalVotePower: voteDistribution.Total,
},
}

k.SetFinalizedBundle(ctx, finalizedBundle)
Expand Down
20 changes: 18 additions & 2 deletions x/bundles/spec/02_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,29 @@ type FinalizedBundle struct {
ToKey string
BundleSummary string
DataHash string
FinalizedAt uint64
FinalizedAt {
Height uint64
Timestamp uint64
}
FromKey string
StorageProviderId uint32
CompressionId uint32
StakeSecurity {
ValidVotePower uint64
TotalVotePower uint64
}
}
```

### BundleVersionMap

The version map keeps track of which protocol version was present at given
block heights. It is only updated during chain upgrades. It helps the query
handler to probably decode a finalized bundle. Later it might also be important
for on chain computations.

- BundleVersionMap `0x03 -> ProtocolBuffer(BundleVersionMap)`


## Round-Robin
For correctly determining the next uploader the current round-robin
Expand All @@ -89,7 +105,7 @@ type RoundRobinSingleValidatorProgress struct {
RoundRobinProgress stores the current state of the round-robin selection for a
given pool.

- RoundRobinProgress `0x03 | PoolId -> ProtocolBuffer(roundRobinProgress)`
- RoundRobinProgress `0x04 | PoolId -> ProtocolBuffer(roundRobinProgress)`

```go
message RoundRobinProgress {
Expand Down
Loading

0 comments on commit 70f7468

Please sign in to comment.