Skip to content

Commit

Permalink
refine codes, remove unneeded data from genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
forcodedancing committed Feb 23, 2023
1 parent 6e77932 commit 0affb06
Show file tree
Hide file tree
Showing 20 changed files with 352 additions and 390 deletions.
4 changes: 0 additions & 4 deletions proto/greenfield/challenge/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,5 @@ option go_package = "github.com/bnb-chain/greenfield/x/challenge/types";
// GenesisState defines the challenge module's genesis state.
message GenesisState {
Params params = 1 [(gogoproto.nullable) = false];
repeated Challenge ongoingChallenges = 2 [(gogoproto.nullable) = false];
repeated Slash recentSlashes = 3 [(gogoproto.nullable) = false];
uint64 recentSlashCount = 4;
uint64 startingChallengeId = 5;
// this line is used by starport scaffolding # genesis/proto/state
}
22 changes: 10 additions & 12 deletions x/challenge/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,14 @@ func EndBlocker(ctx sdk.Context, keeper k.Keeper) {
var spOperatorAddress string
secondarySpAddresses := objectInfo.SecondarySpAddresses

redundancyIndex := k.RandomRedundancyIndex(ctx.BlockHeader().RandaoMix, uint64(len(secondarySpAddresses)+1))
redundancyIndex--

bucket, found := keeper.StorageKeeper.GetBucket(ctx, objectInfo.ObjectName)
if !found {
continue
}

redundancyIndex := k.RandomRedundancyIndex(ctx.BlockHeader().RandaoMix, uint64(len(secondarySpAddresses)+1))
redundancyIndex--

if redundancyIndex == types.RedundancyIndexPrimary { // primary sp
spOperatorAddress = bucket.PrimarySpAddress
} else {
Expand All @@ -95,6 +96,11 @@ func EndBlocker(ctx sdk.Context, keeper k.Keeper) {
continue
}

mapKey := fmt.Sprintf("%s-%d", spOperatorAddress, objectInfo.Id)
if _, ok := objectMap[mapKey]; ok { // already generated for this pair
continue
}

// check recent slash
if keeper.ExistsSlash(ctx, strings.ToLower(spOperatorAddress), objectKey) {
continue
Expand All @@ -104,16 +110,8 @@ func EndBlocker(ctx sdk.Context, keeper k.Keeper) {
segments := k.CalculateSegments(objectInfo.PayloadSize, keeper.StorageKeeper.MaxSegmentSize(ctx))
segmentIndex := k.RandomSegmentIndex(ctx.BlockHeader().RandaoMix, segments)

mapKey := fmt.Sprintf("%s-%d", spOperatorAddress, objectInfo.Id)
if _, ok := objectMap[mapKey]; ok { // already generated for this pair
continue
}

objectMap[mapKey] = struct{}{}
challengeId, err := keeper.GetChallengeId(ctx)
if err != nil {
continue
}
challengeId := keeper.GetChallengeId(ctx)
challenge := types.Challenge{
Id: challengeId,
SpOperatorAddress: spOperatorAddress,
Expand Down
70 changes: 70 additions & 0 deletions x/challenge/client/cli/tx_heartbeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package cli

import (
"encoding/hex"
"fmt"
"strconv"
"strings"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/spf13/cobra"

"github.com/bnb-chain/greenfield/x/challenge/types"
)

var _ = strconv.Itoa(0)

func CmdHeartbeat() *cobra.Command {
cmd := &cobra.Command{
Use: "heartbeat [challenge-id] [vote-validator-set] [vote-agg-signature]",
Short: "Broadcast message heartbeat",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) (err error) {
// validate that the challenge id is an uint
argChallengeId, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return fmt.Errorf("challenge-id %s not a valid uint, please input a valid challenge-id", args[0])
}

argVoteValidatorSet := make([]uint64, 0)
splits := strings.Split(args[1], ",")
for _, split := range splits {
val, err := strconv.ParseUint(split, 10, 64)
if err != nil {
return fmt.Errorf("vote-validator-set %s not a valid comma seperated uint array, please input a valid vote-validator-set", args[1])
}
argVoteValidatorSet = append(argVoteValidatorSet, val)
}
if len(argVoteValidatorSet) == 0 {
return fmt.Errorf("vote-validator-set %s not a valid comma seperated uint array, please input a valid vote-validator-set", args[1])
}

argVoteAggSignature, err := hex.DecodeString(args[2])
if err != nil {
return fmt.Errorf("vote-agg-signature %s not a hex encoded bytes, please input a valid vote-agg-signature", args[2])
}

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgHeartbeat(
clientCtx.GetFromAddress(),
argChallengeId,
argVoteValidatorSet,
argVoteAggSignature,
)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
14 changes: 0 additions & 14 deletions x/challenge/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,6 @@ import (

// InitGenesis initializes the module's state from a provided genesis state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) {
// Set all the ongoingChallenge
for _, elem := range genState.OngoingChallenges {
k.SetOngoingChallenge(ctx, elem)
}
// Set all the recentSlash
for _, elem := range genState.RecentSlashes {
k.SetRecentSlash(ctx, elem)
}

// Set recentSlash count
k.SetRecentSlashCount(ctx, genState.RecentSlashCount)
// this line is used by starport scaffolding # genesis/module/init
k.SetParams(ctx, genState.Params)
}
Expand All @@ -29,9 +18,6 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
genesis := types.DefaultGenesis()
genesis.Params = k.GetParams(ctx)

genesis.OngoingChallenges = k.GetAllOngoingChallenge(ctx)
genesis.RecentSlashes = k.GetAllRecentSlash(ctx)
genesis.RecentSlashCount = k.GetRecentSlashCount(ctx)
// this line is used by starport scaffolding # genesis/module/export

return genesis
Expand Down
20 changes: 0 additions & 20 deletions x/challenge/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,6 @@ func TestGenesis(t *testing.T) {
genesisState := types.GenesisState{
Params: types.DefaultParams(),

OngoingChallenges: []types.Challenge{
{
Id: 0,
},
{
Id: 1,
},
},
RecentSlashes: []types.Slash{
{
Id: 0,
},
{
Id: 1,
},
},
RecentSlashCount: 2,
// this line is used by starport scaffolding # genesis/test/state
}

Expand All @@ -43,8 +26,5 @@ func TestGenesis(t *testing.T) {
nullify.Fill(&genesisState)
nullify.Fill(got)

require.ElementsMatch(t, genesisState.OngoingChallenges, got.OngoingChallenges)
require.ElementsMatch(t, genesisState.RecentSlashes, got.RecentSlashes)
require.Equal(t, genesisState.RecentSlashCount, got.RecentSlashCount)
// this line is used by starport scaffolding # genesis/test/assert
}
10 changes: 4 additions & 6 deletions x/challenge/keeper/challenge.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package keeper
import (
"encoding/binary"

"github.com/bnb-chain/greenfield/x/challenge/types"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/bnb-chain/greenfield/x/challenge/types"
)

// SetOngoingChallenge set a specific ongoingChallenge in the store from its index
Expand Down Expand Up @@ -63,16 +61,16 @@ func (k Keeper) GetAllOngoingChallenge(ctx sdk.Context) (list []types.Challenge)
}

// GetChallengeId gets the highest challenge ID
func (k Keeper) GetChallengeId(ctx sdk.Context) (challengeId uint64, err error) {
func (k Keeper) GetChallengeId(ctx sdk.Context) uint64 {
store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte{})
byteKey := types.KeyPrefix(types.ChallengeIdKey)
bz := store.Get(byteKey)

if bz == nil {
return 0, sdkerrors.Wrap(types.ErrInvalidGenesis, "initial challenge ID hasn't been set")
return 0
}

return binary.BigEndian.Uint64(bz), nil
return binary.BigEndian.Uint64(bz)
}

// SetChallengeID sets the new challenge ID to the store
Expand Down
12 changes: 6 additions & 6 deletions x/challenge/keeper/msg_server_attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/bnb-chain/greenfield/x/challenge/types"
sptypes "github.com/bnb-chain/greenfield/x/sp/types"
storagetypes "github.com/bnb-chain/greenfield/x/storage/types"
)

func (k msgServer) Attest(goCtx context.Context, msg *types.MsgAttest) (*types.MsgAttestResponse, error) {
Expand All @@ -28,9 +27,10 @@ func (k msgServer) Attest(goCtx context.Context, msg *types.MsgAttest) (*types.M
if !found {
return nil, types.ErrUnknownObject
}
if objectInfo.ObjectStatus != storagetypes.OBJECT_STATUS_IN_SERVICE {
return nil, types.ErrInvalidObjectStatus
}
//be noted: even the object info is not in service now, we will continue slash the storage provider
//if objectInfo.ObjectStatus != storagetypes.OBJECT_STATUS_IN_SERVICE {
// return nil, types.ErrInvalidObjectStatus
//}

// check attest validators and signatures
validators, err := k.verifySignature(ctx, msg)
Expand Down Expand Up @@ -59,13 +59,13 @@ func (k msgServer) Attest(goCtx context.Context, msg *types.MsgAttest) (*types.M
}

func (k msgServer) calculateChallengeSlash(ctx sdk.Context, objectSize uint64) sdkmath.Int {
perKb := k.SlashAmountSizeRate(ctx)
sizeRate := k.SlashAmountSizeRate(ctx)
decSize := sdk.NewDecFromBigInt(new(big.Int).SetUint64(objectSize))
decRoot, err := decSize.ApproxSqrt()
if err != nil {
panic(err)
}
slashAmount := decRoot.MulMut(perKb).TruncateInt()
slashAmount := decRoot.MulMut(sizeRate).TruncateInt()

min := k.SlashAmountMin(ctx)
if slashAmount.LT(min) {
Expand Down
81 changes: 81 additions & 0 deletions x/challenge/keeper/msg_server_heartbeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package keeper

import (
"context"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"

app "github.com/bnb-chain/greenfield/sdk/types"
"github.com/bnb-chain/greenfield/x/challenge/types"
paymentmoduletypes "github.com/bnb-chain/greenfield/x/payment/types"
)

func (k msgServer) Heartbeat(goCtx context.Context, msg *types.MsgHeartbeat) (*types.MsgHeartbeatResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

submitterAddress, err := sdk.AccAddressFromHexUnsafe(msg.Creator)
if err != nil {
return nil, err
}

// check challenge id
heartbeatInterval := k.HeartbeatInterval(ctx)
maxChallengeId := k.GetChallengeId(ctx)
heartbeatChallengeId := k.GetHeartbeatChallengeId(ctx)

if msg.ChallengeId > maxChallengeId || msg.ChallengeId <= heartbeatChallengeId ||
msg.ChallengeId%heartbeatInterval != 0 { // be noted, we allow to skip some heartbeats
return nil, types.ErrInvalidChallengeId
}

// check heartbeat validators and signatures
_, err = k.verifySignature(ctx, msg)
if err != nil {
return nil, err
}

// calculate rewards
total := k.paymentKeeper.QueryValidatorRewards(ctx)
validatorReward, submitterReward := k.calculateHeartbeatRewards(ctx, total)

// reward tx validator & submitter
toValidator := sdk.Coins{
sdk.Coin{Denom: app.Denom, Amount: validatorReward},
}
err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, paymentmoduletypes.ModuleName, distributiontypes.ModuleName, toValidator)
if err != nil {
return nil, err
}
toSubmitter := sdk.Coins{
sdk.Coin{Denom: app.Denom, Amount: submitterReward},
}
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, paymentmoduletypes.ModuleName, submitterAddress, toSubmitter)
if err != nil {
return nil, err
}

if err := ctx.EventManager().EmitTypedEvents(&types.EventChallengeHeartbeat{
ChallengeId: msg.ChallengeId,
}); err != nil {
return nil, err
}

k.SetHeartbeatChallengeId(ctx, msg.ChallengeId)

return &types.MsgHeartbeatResponse{}, nil
}

func (k msgServer) calculateHeartbeatRewards(ctx sdk.Context, total sdkmath.Int) (sdkmath.Int, sdkmath.Int) {
var submitterReward sdkmath.Int
threshold := k.HeartbeatRewardThreshold(ctx)
rated := k.HeartbeatRewardRate(ctx).Mul(sdk.NewDecFromInt(total)).TruncateInt()
if rated.GT(threshold) {
submitterReward = threshold
} else {
submitterReward = rated
}

return total.Sub(submitterReward), submitterReward
}
5 changes: 1 addition & 4 deletions x/challenge/keeper/msg_server_submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,7 @@ func (k msgServer) Submit(goCtx context.Context, msg *types.MsgSubmit) (*types.M
}
}

challengeId, err := k.GetChallengeId(ctx)
if err != nil {
return nil, err
}
challengeId := k.GetChallengeId(ctx)
challenge := types.Challenge{
Id: challengeId,
SpOperatorAddress: msg.SpOperatorAddress,
Expand Down
30 changes: 30 additions & 0 deletions x/challenge/simulation/heartbeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package simulation

import (
"math/rand"

"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"

"github.com/bnb-chain/greenfield/x/challenge/keeper"
"github.com/bnb-chain/greenfield/x/challenge/types"
)

func SimulateMsgHeartbeat(
ak types.AccountKeeper,
bk types.BankKeeper,
k keeper.Keeper,
) simtypes.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
simAccount, _ := simtypes.RandomAcc(r, accs)
msg := &types.MsgHeartbeat{
Creator: simAccount.Address.String(),
}

// TODO: Handling the Heartbeat simulation

return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "Heartbeat simulation not implemented"), nil, nil
}
}
2 changes: 1 addition & 1 deletion x/challenge/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ var (
ErrInvalidBlsPubKey = sdkerrors.Register(ModuleName, 17, "invalid bls public key")
ErrNotEnoughVotes = sdkerrors.Register(ModuleName, 18, "attest votes are not enough")

ErrInvalidChallenge = sdkerrors.Register(ModuleName, 19, "invalid challenge id")
ErrInvalidChallengeId = sdkerrors.Register(ModuleName, 19, "invalid challenge id")
)
Loading

0 comments on commit 0affb06

Please sign in to comment.