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: bc fusion hardfork implementation #358

Merged
merged 22 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 8 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 types/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type ValidatorSet interface {
ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address
ValidatorByVoteAddr(Context, []byte) Validator // get a particular validator by vote address
TotalPower(Context) Dec // total power of the validator set
GetSideChainTotalVotingPower(ctx Context) Dec // total voting power of the side chain validator set

// slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction
Slash(Context, ConsAddress, int64, int64, Dec)
Expand Down
9 changes: 9 additions & 0 deletions types/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ const (
FixDoubleSignChainId = "FixDoubleSignChainId"
BEP126 = "BEP126" //https://github.com/binance-chain/BEPs/pull/126
BEP255 = "BEP255" // https://github.com/bnb-chain/BEPs/pull/255

// TODO: to be determined
BCFusionFirstHardFork = "BCFusionFirstHardFork"
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
BCFusionSecondHardFork = "BCFusionSecondHardFork"
BCFusionThirdHardFork = "BCFusionThirdHardFork"
)

var (
BCFusionStopGovThreshold int64 = 5_000_000
)

var MainNetConfig = UpgradeConfig{
Expand Down
1 change: 1 addition & 0 deletions x/gov/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func NewHandler(keeper Keeper) sdk.Handler {
case MsgVote:
return handleMsgVote(ctx, keeper, msg)
case MsgSideChainDeposit:
// TODO: refund the token to the depositor after second hard fork
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
return handleMsgSideChainDeposit(ctx, keeper, msg)
case MsgSideChainSubmitProposal:
return handleMsgSideChainSubmitProposal(ctx, keeper, msg)
Expand Down
14 changes: 14 additions & 0 deletions x/gov/handler_sidechain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ import (
)

func handleMsgSideChainSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSideChainSubmitProposal) sdk.Result {
if sdk.IsUpgrade(sdk.BCFusionSecondHardFork) {
return sdk.ErrMsgNotSupported("").Result()
}
if sdk.IsUpgrade(sdk.BCFusionFirstHardFork) {
ctx, err := keeper.ScKeeper.PrepareCtxForSideChain(ctx, msg.SideChainId)
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return ErrInvalidSideChainId(keeper.codespace, msg.SideChainId).Result()
}
vp := keeper.vs.GetSideChainTotalVotingPower(ctx)
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
if vp.LTE(sdk.NewDecFromInt(sdk.BCFusionStopGovThreshold)) {
return sdk.ErrMsgNotSupported("").Result()
}
}

if msg.ProposalType == ProposalTypeText && !sdk.IsUpgrade(sdk.BEP173) {
return ErrInvalidProposalType(keeper.codespace, msg.ProposalType).Result()
}
Expand Down
47 changes: 45 additions & 2 deletions x/ibc/endblock.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,63 @@
package ibc

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
)

func EndBlocker(ctx sdk.Context, keeper Keeper) {
if len(keeper.packageCollector.collectedPackages) == 0 {
return
}
var attributes []sdk.Attribute
var (
attributes []sdk.Attribute
events sdk.Events
)
for _, ibcPackageRecord := range keeper.packageCollector.collectedPackages {
attributes = append(attributes,
sdk.NewAttribute(ibcPackageInfoAttributeKey,
buildIBCPackageAttributeValue(ibcPackageRecord.destChainID, ibcPackageRecord.channelID, ibcPackageRecord.sequence)))
}

keeper.packageCollector.collectedPackages = keeper.packageCollector.collectedPackages[:0]
event := sdk.NewEvent(ibcEventType, attributes...)
ctx.EventManager().EmitEvent(event)
events.AppendEvent(event)
if sdk.IsUpgrade(sdk.BCFusionThirdHardFork) {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
events = events.AppendEvents(closeSideChainChannels(ctx, keeper))
}
ctx.EventManager().EmitEvents(events)
}

func closeSideChainChannels(ctx sdk.Context, k Keeper) sdk.Events {
var events sdk.Events
sideChainId := k.sideKeeper.BscSideChainId(ctx)
// disable side chain channels
id := k.sideKeeper.Config().DestChainNameToID(sideChainId)

for _, channelId := range k.sideKeeper.Config().ChannelIDs() {
permissions := k.sideKeeper.GetChannelSendPermissions(ctx, id)
if permissions[channelId] == sdk.ChannelForbidden {
// skip forbidden channel
continue
}
_, err := k.sideKeeper.SaveChannelSettingChangeToIbc(ctx, id, 0, sdk.ChannelForbidden)
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
ctx.Logger().Error("closeSideChainChannels", "err", err.Error())
events.AppendEvent(sdk.NewEvent("failed to closeSideChainChannels ",
sdk.NewAttribute("sideChainId", sideChainId),
sdk.NewAttribute("channelId", fmt.Sprint(channelId)),
sdk.NewAttribute("error", err.Error()),
))
return events
}
events.AppendEvent(sdk.NewEvent("closeSideChainChannels",
sdk.NewAttribute("sideChainId", sideChainId),
sdk.NewAttribute("channelId", fmt.Sprint(channelId)),
))
// close bc side chain channel
k.sideKeeper.SetChannelSendPermission(ctx, id, channelId, sdk.ChannelForbidden)
}

return events
}
10 changes: 10 additions & 0 deletions x/sidechain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import sdk "github.com/cosmos/cosmos-sdk/types"
type crossChainConfig struct {
srcChainID sdk.ChainID

channelIDs []sdk.ChannelID
nameToChannelID map[string]sdk.ChannelID
channelIDToName map[sdk.ChannelID]string
channelIDToApp map[sdk.ChannelID]sdk.CrossChainApplication
Expand All @@ -16,6 +17,7 @@ type crossChainConfig struct {
func newCrossChainCfg() *crossChainConfig {
config := &crossChainConfig{
srcChainID: 0,
channelIDs: make([]sdk.ChannelID, 0),
nameToChannelID: make(map[string]sdk.ChannelID),
channelIDToName: make(map[sdk.ChannelID]string),
destChainNameToID: make(map[string]sdk.ChainID),
Expand All @@ -24,3 +26,11 @@ func newCrossChainCfg() *crossChainConfig {
}
return config
}

func (c *crossChainConfig) DestChainNameToID(name string) sdk.ChainID {
return c.destChainNameToID[name]
}

func (c *crossChainConfig) ChannelIDs() []sdk.ChannelID {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
return c.channelIDs
}
5 changes: 5 additions & 0 deletions x/sidechain/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func (k *Keeper) RegisterChannel(name string, id sdk.ChannelID, app sdk.CrossCha
if ok {
return fmt.Errorf("duplicated channel id")
}
k.cfg.channelIDs = append(k.cfg.channelIDs, id)
k.cfg.nameToChannelID[name] = id
k.cfg.channelIDToName[id] = name
k.cfg.channelIDToApp[id] = app
Expand Down Expand Up @@ -242,3 +243,7 @@ func EndBlock(ctx sdk.Context, k Keeper) {
}
return
}

func (k *Keeper) Config() *crossChainConfig {
return k.cfg
}
99 changes: 97 additions & 2 deletions x/stake/endblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,25 @@ import (

func EndBlocker(ctx sdk.Context, k keeper.Keeper) (validatorUpdates []abci.ValidatorUpdate, completedUbds []types.UnbondingDelegation) {
// only change validator set in breath block after BEP159
var events sdk.Events
var csEvents sdk.Events
var (
events sdk.Events
csEvents sdk.Events
refundEvents sdk.Events
)

if !sdk.IsUpgrade(sdk.BEP159) {
_, validatorUpdates, completedUbds, _, events = handleValidatorAndDelegations(ctx, k)
} else {
k.DistributeInBlock(ctx, types.ChainIDForBeaconChain)
validatorUpdates = k.PopPendingABCIValidatorUpdate(ctx)
}

if sdk.IsUpgrade(sdk.BCFusionSecondHardFork) {
refundEvents = handleRefundCrossStake(ctx, k)
validatorUpdates, completedUbds, events = endRefundBlock(ctx, k)
refundEvents.AppendEvents(events)
}

if sdk.IsUpgrade(sdk.BEP128) {
sideChainIds, storePrefixes := k.ScKeeper.GetAllSideChainPrefixes(ctx)
if len(sideChainIds) == len(storePrefixes) {
Expand All @@ -34,6 +45,9 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (validatorUpdates []abci.Valid
if sdk.IsUpgrade(sdk.BEP153) {
events = events.AppendEvents(csEvents)
}
if sdk.IsUpgrade(sdk.BCFusionSecondHardFork) {
events = events.AppendEvents(refundEvents)
}
ctx.EventManager().EmitEvents(events)
return
}
Expand Down Expand Up @@ -252,3 +266,84 @@ func handleMatureUnbondingDelegations(k keeper.Keeper, ctx sdk.Context) ([]types

return completed, events
}

const (
maxProcessedRefundCount = 50
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
)

func handleRefundCrossStake(ctx sdk.Context, k keeper.Keeper) sdk.Events {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
iterator := k.IteratorAllDelegations(ctx)
defer iterator.Close()
var refundEvents sdk.Events
count := 0
bcValidators := k.GetAllValidators(ctx)
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
bcValidatorsMap := make(map[string]types.Validator, len(bcValidators))
for _, v := range bcValidators {
bcValidatorsMap[v.OperatorAddr.String()] = v
}
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.CDC(), iterator.Key(), iterator.Value())
if delegation.CrossStake {
result := handleMsgSideChainUndelegate(ctx, types.MsgSideChainUndelegate{
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

@pythonberg1997 pythonberg1997 Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctx should be like this:

ctx = ctx.WithCrossStake(true)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Amount: sdk.NewCoin(k.BondDenom(ctx), delegation.GetShares().RawInt()),
SideChainId: k.ScKeeper.BscSideChainId(ctx),
}, k)
refundEvents = refundEvents.AppendEvents(result.Events)
} else {
if _, exist := bcValidatorsMap[delegation.DelegatorAddr.String()]; !exist {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
result := handleMsgUndelegate(ctx, types.MsgUndelegate{
DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Amount: sdk.NewCoin(k.BondDenom(ctx), delegation.GetShares().RawInt()),
}, k)
refundEvents = refundEvents.AppendEvents(result.Events)
}
}
count++
if count >= maxProcessedRefundCount {
break
}
}
return refundEvents
}

func endRefundBlock(ctx sdk.Context, k keeper.Keeper) (validatorUpdates []abci.ValidatorUpdate, completedUbds []types.UnbondingDelegation, events sdk.Events) {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
var newVals []types.Validator
var completedREDs []types.DVVTriplet
newVals, validatorUpdates, completedUbds, completedREDs, events = handleValidatorAndDelegations(ctx, k)
ctx.Logger().Debug("endRefundBlock", "newValsLen", len(newVals), "newVals", newVals)
publishCompletedUBD(k, completedUbds, ChainIDForBeaconChain, ctx.BlockHeight())
publishCompletedRED(k, completedREDs, ChainIDForBeaconChain)
if k.PbsbServer != nil {
sideValidatorsEvent := types.ElectedValidatorsEvent{
Validators: newVals,
ChainId: ChainIDForBeaconChain,
}
k.PbsbServer.Publish(sideValidatorsEvent)
}
if sdk.IsUpgrade(sdk.BEP159) {
storeValidatorsWithHeight(ctx, newVals, k)
}

if sdk.IsUpgrade(sdk.LaunchBscUpgrade) && k.ScKeeper != nil {
// distribute sidechain rewards
sideChainIds, storePrefixes := k.ScKeeper.GetAllSideChainPrefixes(ctx)
for i := range storePrefixes {
sideChainCtx := ctx.WithSideChainKeyPrefix(storePrefixes[i])
newVals, _, completedUbds, completedREDs, scEvents := handleValidatorAndDelegations(sideChainCtx, k)
for j := range scEvents {
scEvents[j] = scEvents[j].AppendAttributes(sdk.NewAttribute(types.AttributeKeySideChainId, sideChainIds[i]))
}
events = events.AppendEvents(scEvents)
// TODO: need to add UBDs for side chains to the return value

storeValidatorsWithHeight(sideChainCtx, newVals, k)

publishCompletedUBD(k, completedUbds, sideChainIds[i], ctx.BlockHeight())
publishCompletedRED(k, completedREDs, sideChainIds[i])
}
}
return
}
18 changes: 18 additions & 0 deletions x/stake/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,31 @@ func NewHandler(k keeper.Keeper, govKeeper gov.Keeper) sdk.Handler {
return handleMsgUndelegate(ctx, msg, k)
// case MsgSideChain
case types.MsgCreateSideChainValidator:
if sdk.IsUpgrade(sdk.BCFusionFirstHardFork) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disable MsgCreateValidatorOpen?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgCreateSideChainValidator(ctx, msg, k)
case types.MsgEditSideChainValidator:
return handleMsgEditSideChainValidator(ctx, msg, k)
case types.MsgCreateSideChainValidatorWithVoteAddr:
if sdk.IsUpgrade(sdk.BCFusionFirstHardFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgCreateSideChainValidatorWithVoteAddr(ctx, msg, k)
case types.MsgEditSideChainValidatorWithVoteAddr:
if sdk.IsUpgrade(sdk.BCFusionFirstHardFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgEditSideChainValidatorWithVoteAddr(ctx, msg, k)
case types.MsgSideChainDelegate:
if sdk.IsUpgrade(sdk.BCFusionSecondHardFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgSideChainDelegate(ctx, msg, k)
case types.MsgSideChainRedelegate:
if sdk.IsUpgrade(sdk.BCFusionFirstHardFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgSideChainRedelegate(ctx, msg, k)
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
case types.MsgSideChainUndelegate:
return handleMsgSideChainUndelegate(ctx, msg, k)
Expand Down Expand Up @@ -462,6 +477,9 @@ func handleMsgBeginUnbonding(ctx sdk.Context, msg types.MsgBeginUnbonding, k kee
}

func handleMsgRedelegate(ctx sdk.Context, msg types.MsgRedelegate, k keeper.Keeper) sdk.Result {
if sdk.IsUpgrade(sdk.BCFusionSecondHardFork) {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
return sdk.ErrMsgNotSupported("").Result()
}
if msg.Amount.Denom != k.BondDenom(ctx) {
return ErrBadDenom(k.Codespace()).Result()
}
Expand Down
5 changes: 5 additions & 0 deletions x/stake/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegati
return delegations
}

func (k Keeper) IteratorAllDelegations(ctx sdk.Context) sdk.Iterator {
store := ctx.KVStore(k.storeKey)
return sdk.KVStorePrefixIterator(store, DelegationKey)
}

// return a given amount of all the delegations from a delegator
func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress,
maxRetrieve uint16) (delegations []types.Delegation) {
Expand Down
5 changes: 5 additions & 0 deletions x/stake/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ func (k Keeper) Codespace() sdk.CodespaceType {
return k.codespace
}

// return the cdc
func (k Keeper) CDC() *codec.Codec {
return k.cdc
}

//_______________________________________________________________________

// load the pool
Expand Down
18 changes: 18 additions & 0 deletions x/stake/keeper/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ func (k Keeper) GetValidatorBySideConsAddr(ctx sdk.Context, sideConsAddr []byte)
return k.GetValidator(ctx, opAddr)
}

func (k Keeper) GetSideChainTotalVotingPower(ctx sdk.Context) sdk.Dec {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsByConsAddrKey)
defer iterator.Close()

votingPower := sdk.NewDecFromInt(0)
for ; iterator.Valid(); iterator.Next() {
address := iterator.Value()
validator, found := k.GetValidator(ctx, address)
if !found {
ctx.Logger().Error("GetSideChainTotalVotingPower can't load validator", "operator_addr", string(address))
continue
}
votingPower = votingPower.Add(validator.GetPower())
}
return votingPower
}

func (k Keeper) GetValidatorBySideVoteAddr(ctx sdk.Context, sideVoteAddr []byte) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
opAddr := store.Get(GetValidatorBySideVoteAddrKey(sideVoteAddr))
Expand Down