Skip to content

Commit

Permalink
Merge pull request #159 from icon-project/goldworm-BDT-664-imp-set-sl…
Browse files Browse the repository at this point in the history
…ashing-rate

Implement slashingRate related APIs
  • Loading branch information
goldworm-icon authored Aug 7, 2023
2 parents ae2ac36 + 68b09a9 commit 761b3ca
Show file tree
Hide file tree
Showing 12 changed files with 425 additions and 85 deletions.
27 changes: 25 additions & 2 deletions icon/chainscore.go
Original file line number Diff line number Diff line change
Expand Up @@ -658,15 +658,38 @@ var chainMethods = []*chainMethod{
{"slashingRate", scoreapi.Integer, nil, nil},
},
nil,
}, icmodule.RevisionICON2R3, 0},
}, icmodule.RevisionICON2R3, icmodule.RevisionPreIISS4-1},
{scoreapi.Method{
scoreapi.Function, "setNonVoteSlashingRate",
scoreapi.FlagExternal, 1,
[]scoreapi.Parameter{
{"slashingRate", scoreapi.Integer, nil, nil},
},
nil,
}, icmodule.RevisionICON2R3, 0},
}, icmodule.RevisionICON2R3, icmodule.RevisionPreIISS4-1},
{scoreapi.Method{
scoreapi.Function, "setSlashingRates",
scoreapi.FlagExternal, 1,
[]scoreapi.Parameter{
{"rates", scoreapi.ListTypeOf(1, scoreapi.Struct), nil,
[]scoreapi.Field{
{"name", scoreapi.String, nil},
{"value", scoreapi.Integer, nil},
},
},
},
nil,
}, icmodule.RevisionPreIISS4, 0},
{scoreapi.Method{
scoreapi.Function, "getSlashingRates",
scoreapi.FlagReadOnly, 0,
[]scoreapi.Parameter{
{"names", scoreapi.ListTypeOf(1, scoreapi.String), nil, nil},
},
[]scoreapi.DataType{
scoreapi.Dict,
},
}, icmodule.RevisionPreIISS4, 0},
{scoreapi.Method{
scoreapi.Function, "setUseSystemDeposit",
scoreapi.FlagExternal, 2,
Expand Down
38 changes: 31 additions & 7 deletions icon/chainscore_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (s *chainScore) handleRevisionChange(as state.AccountState, r1, r2 int) err
return err
}
// 10% slashRate is hardcoded for backward compatibility
if err := es.State.SetConsistentValidationPenaltySlashRate(icmodule.ToRate(10)); err != nil {
if err := es.State.SetConsistentValidationPenaltySlashRate(r2, icmodule.ToRate(10)); err != nil {
return err
}
}
Expand Down Expand Up @@ -301,11 +301,11 @@ func (s *chainScore) handleRevisionChange(as state.AccountState, r1, r2 int) err
if r1 < icmodule.RevisionICON2R3 && r2 >= icmodule.RevisionICON2R3 {
iconConfig := s.loadIconConfig()
if err := es.State.SetConsistentValidationPenaltySlashRate(
icmodule.ToRate(iconConfig.ConsistentValidationPenaltySlashRate.Int64())); err != nil {
r2, icmodule.ToRate(iconConfig.ConsistentValidationPenaltySlashRate.Int64())); err != nil {
return err
}
if err := es.State.SetNonVotePenaltySlashRate(
icmodule.ToRate(iconConfig.NonVotePenaltySlashRate.Int64())); err != nil {
r2, icmodule.ToRate(iconConfig.NonVotePenaltySlashRate.Int64())); err != nil {
return err
}
}
Expand All @@ -320,9 +320,7 @@ func (s *chainScore) handleRevisionChange(as state.AccountState, r1, r2 int) err
}

if r1 < icmodule.RevisionPreIISS4 && r2 >= icmodule.RevisionPreIISS4 {
// RewardFundAllocation2
r := es.State.GetRewardFund()
if err := es.State.SetRewardFund2(r.ToRewardFund2()); err != nil {
if err := s.onRevisionPreIISS4(es); err != nil {
return err
}
}
Expand All @@ -336,14 +334,40 @@ func (s *chainScore) handleRevisionChange(as state.AccountState, r1, r2 int) err
if err := es.State.SetIISSVersion(iissVersion); err != nil {
return err
}

}
if r1 < icmodule.Revision21 && r2 >= icmodule.Revision21 && s.cc.ChainID() == CIDForMainNet {
s.blockAccounts2()
}
return nil
}

func (s *chainScore) onRevisionPreIISS4(es *iiss.ExtensionStateImpl) error {
// RewardFundAllocation2
r := es.State.GetRewardFund()
if err := es.State.SetRewardFund2(r.ToRewardFund2()); err != nil {
return err
}

if s.cc.ChainID() == CIDForMainNet {
items := []struct {
pt icmodule.PenaltyType
rate icmodule.Rate
}{
{icmodule.PenaltyPRepDisqualification, icmodule.DefaultPRepDisqualificationSlashingRate},
{icmodule.PenaltyContinuousBlockValidation, icmodule.DefaultContinuousBlockValidationSlashingRate},
{icmodule.PenaltyBlockValidation, icmodule.DefaultBlockValidationSlashingRate},
{icmodule.PenaltyMissingNetworkProposalVote, icmodule.DefaultMissingNetworkProposalVoteSlashingRate},
{icmodule.PenaltyDoubleVote, icmodule.DefaultDoubleVoteSlashingRate},
}
for _, item := range items {
if err := es.State.SetSlashingRate(item.pt, item.rate); err != nil {
return err
}
}
}
return nil
}

func (s *chainScore) blockAccounts() {
targets := []string{
"hx76dcc464a27d74ca7798dd789d2e1da8193219b4",
Expand Down
59 changes: 57 additions & 2 deletions icon/chainscore_iiss.go
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ func (s *chainScore) Ex_setConsistentValidationSlashingRate(slashingRate *common
return err
}
rate := icmodule.ToRate(slashingRate.Int64())
if err = es.State.SetConsistentValidationPenaltySlashRate(rate); err != nil {
if err = es.State.SetConsistentValidationPenaltySlashRate(s.cc.Revision().Value(), rate); err != nil {
if errors.IllegalArgumentError.Equals(err) {
return icmodule.IllegalArgumentError.Errorf("Invalid range")
}
Expand All @@ -852,7 +852,7 @@ func (s *chainScore) Ex_setNonVoteSlashingRate(slashingRate *common.HexInt) erro
return err
}
rate := icmodule.ToRate(slashingRate.Int64())
if err = es.State.SetNonVotePenaltySlashRate(rate); err != nil {
if err = es.State.SetNonVotePenaltySlashRate(s.cc.Revision().Value(), rate); err != nil {
if errors.IllegalArgumentError.Equals(err) {
return icmodule.IllegalArgumentError.Errorf("Invalid range")
}
Expand All @@ -862,6 +862,61 @@ func (s *chainScore) Ex_setNonVoteSlashingRate(slashingRate *common.HexInt) erro
return nil
}

func (s *chainScore) Ex_setSlashingRates(values []interface{}) error {
if err := s.checkGovernance(true); err != nil {
return err
}
es, err := s.getExtensionState()
if err != nil {
return err
}
if len(values) == 0 {
return nil
}

rates := make(map[string]icmodule.Rate)
for _, v := range values {
pair, ok := v.(map[string]interface{})
name, ok := pair["name"].(string)
if !ok {
return scoreresult.InvalidParameterError.New("InvalidNameType")
}
value, ok := pair["value"].(*common.HexInt)
if !ok {
return scoreresult.InvalidParameterError.New("InvalidRateType")
}
if _, ok = rates[name]; ok {
return icmodule.DuplicateError.Errorf("DuplicatePenaltyName(%s)", name)
}
rates[name] = icmodule.Rate(value.Int64())
}
return es.SetSlashingRates(s.newCallContext(s.cc), rates)
}

func (s *chainScore) Ex_getSlashingRates(values []interface{}) (map[string]interface{}, error) {
if err := s.tryChargeCall(true); err != nil {
return nil, err
}
es, err := s.getExtensionState()
if err != nil {
return nil, err
}

var penaltyTypes []icmodule.PenaltyType
for _, v := range values {
name, ok := v.(string)
if !ok {
return nil, scoreresult.InvalidParameterError.New("InvalidPenaltyNameType")
}
if pt := icmodule.ToPenaltyType(name); pt == icmodule.PenaltyNone {
return nil, scoreresult.InvalidParameterError.Errorf("InvalidPenaltyName(%s)", name)
} else {
penaltyTypes = append(penaltyTypes, pt)
}
}
return es.GetSlashingRates(penaltyTypes)
}

func (s *chainScore) onSlashingRateChangedEvent(name string, rate icmodule.Rate) {
s.cc.OnEvent(state.SystemAddress,
[][]byte{[]byte("SlashingRateChanged(str,int)"), []byte(name)},
Expand Down
7 changes: 7 additions & 0 deletions icon/icmodule/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ const (
DefaultDelegationSlotMax = 100
DefaultExtraMainPRepCount = 3
DefaultNonVotePenaltySlashRate = 0 // 0%

// IISS-4.0
DefaultPRepDisqualificationSlashingRate = Rate(DenomInRate) // 100%
DefaultContinuousBlockValidationSlashingRate = Rate(1) // 0.01%
DefaultBlockValidationSlashingRate = Rate(0) // 0%
DefaultMissingNetworkProposalVoteSlashingRate = Rate(1) // 0.01%
DefaultDoubleVoteSlashingRate = Rate(1000) // 10%
)

// The following variables are read-only
Expand Down
52 changes: 50 additions & 2 deletions icon/icmodule/penalty.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,55 @@ type PenaltyType int
const (
PenaltyNone PenaltyType = iota
PenaltyPRepDisqualification
PenaltyLowProductivity
PenaltyContinuousBlockValidation
PenaltyBlockValidation
PenaltyNonVote
PenaltyMissingNetworkProposalVote
PenaltyDoubleVote
PenaltyReserved
)

var penaltyNames = []string{
"",
"prepDisqualification",
"continuousValidation",
"validation",
"missingNetworkProposalVote",
"doubleVote",
}

var penaltyTypes = []PenaltyType {
PenaltyPRepDisqualification,
PenaltyContinuousBlockValidation,
PenaltyBlockValidation,
PenaltyMissingNetworkProposalVote,
PenaltyDoubleVote,
}

func (p PenaltyType) String() string {
if p > PenaltyNone && p < PenaltyReserved {
return penaltyNames[p]
}
return ""
}

func (p PenaltyType) IsValid() bool {
return p > PenaltyNone && p < PenaltyReserved
}

func ToPenaltyType(name string) PenaltyType {
for i, penaltyName := range penaltyNames {
if name == penaltyName {
return PenaltyType(i)
}
}
return PenaltyNone
}

func PenaltyNames() []string {
return penaltyNames
}

func GetPenaltyTypes() []PenaltyType {
return penaltyTypes

}
2 changes: 1 addition & 1 deletion icon/icsim/revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (sim *simulatorImpl) handleRevIISS(ws state.WorldState, r1, r2 int) error {
return err
}
if err := es.State.SetConsistentValidationPenaltySlashRate(
icmodule.ToRate(int64(config.ConsistentValidationPenaltySlashRate))); err != nil {
r2, icmodule.ToRate(int64(config.ConsistentValidationPenaltySlashRate))); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion icon/icsim/simulatorimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ func (sim *simulatorImpl) GetPRepStats(address module.Address) map[string]interf

func (sim *simulatorImpl) GetNetworkInfo() map[string]interface{} {
es := sim.getExtensionState(true)
jso, err := es.State.GetNetworkInfoInJSON(sim.revision.Value())
jso, err := es.State.GetNetworkInfoInJSON(sim.Revision().Value())
if err != nil {
return nil
}
Expand Down
33 changes: 33 additions & 0 deletions icon/iiss/eventlog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2023 ICON Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package iiss

import (
"github.com/icon-project/goloop/common/intconv"
"github.com/icon-project/goloop/icon/icmodule"
"github.com/icon-project/goloop/service/state"
)

func recordSlashingRateChangedV2Event(cc icmodule.CallContext, penaltyType icmodule.PenaltyType, rate icmodule.Rate) {
cc.OnEvent(state.SystemAddress,
[][]byte{[]byte("SlashingRateChangedV2(str,int)")},
[][]byte{
[]byte(penaltyType.String()),
intconv.Int64ToBytes(rate.NumInt64()),
},
)
}
50 changes: 48 additions & 2 deletions icon/iiss/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,11 +618,11 @@ func (es *ExtensionStateImpl) PenalizeNonVoters(cc icmodule.CallContext, address
[][]byte{[]byte("PenaltyImposed(Address,int,int)"), address.Bytes()},
[][]byte{
intconv.Int64ToBytes(int64(ps.Status())),
intconv.Int64ToBytes(int64(icmodule.PenaltyNonVote)),
intconv.Int64ToBytes(int64(icmodule.PenaltyMissingNetworkProposalVote)),
},
)

return es.slash(cc, address, es.State.GetNonVotePenaltySlashRate())
return es.slash(cc, address, es.State.GetNonVotePenaltySlashRate(cc.Revision().Value()))
}

func (es *ExtensionStateImpl) SetBond(blockHeight int64, from module.Address, bonds icstate.Bonds) error {
Expand Down Expand Up @@ -1838,3 +1838,49 @@ func (es *ExtensionStateImpl) OnSetPublicKey(cc icmodule.CallContext, from modul
dsaIndex,
)
}

func (es *ExtensionStateImpl) SetSlashingRates(cc icmodule.CallContext, values map[string]icmodule.Rate) error {
var pt icmodule.PenaltyType
rates := make(map[icmodule.PenaltyType]icmodule.Rate)

for name, rate := range values {
pt = icmodule.ToPenaltyType(name)
if !pt.IsValid() {
return scoreresult.InvalidParameterError.Errorf("InvalidPenaltyName(%s)", name)
}
rates[pt] = rate
}

for _, pt = range icmodule.GetPenaltyTypes() {
if rate, ok := rates[pt]; ok {
oldRate, err := es.State.GetSlashingRate(pt)
if err != nil {
return err
}
if oldRate != rate {
if err = es.State.SetSlashingRate(pt, rate); err != nil {
return err
}
// Record slashingRateChangedV2 eventLogs in PenaltyType order
recordSlashingRateChangedV2Event(cc, pt, rate)
}
}
}
return nil
}

func (es *ExtensionStateImpl) GetSlashingRates(penaltyTypes []icmodule.PenaltyType) (map[string]interface{}, error) {
if len(penaltyTypes) == 0 {
penaltyTypes = icmodule.GetPenaltyTypes()
}

jso := make(map[string]interface{})
for _, pt := range penaltyTypes {
if rate, err := es.State.GetSlashingRate(pt); err == nil {
jso[pt.String()] = rate.NumInt64()
} else {
return nil, err
}
}
return jso, nil
}
Loading

0 comments on commit 761b3ca

Please sign in to comment.