Skip to content

Commit

Permalink
Merge pull request #2577 from 0chain/users/sunilmhta/fix/2544/0chain/…
Browse files Browse the repository at this point in the history
…usingmap
  • Loading branch information
sunilmhta committed Jul 4, 2023
2 parents 685b273 + 8281b18 commit e36f104
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 13 deletions.
61 changes: 61 additions & 0 deletions code/go/0chain.net/smartcontract/dto/minerdto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package dto

import (
"0chain.net/core/common"
"0chain.net/smartcontract/provider"
"github.com/0chain/common/core/currency"
)

// NodeType used in pools statistic.
type NodeType int

// MinerDtoNode struct that holds information about the registering miner.
// swagger:model MinerDtoNode
type MinerDtoNode struct {
*SimpleDtoNode `json:"simple_miner,omitempty"`
*StakePool `json:"stake_pool,omitempty"`
}

// swagger:model SimpleDtoNode
type SimpleDtoNode struct {
provider.Provider
N2NHost string `json:"n2n_host"`
Host string `json:"host"`
Port int `json:"port"`
Geolocation SimpleNodeGeolocation `json:"geolocation"`
Path string `json:"path"`
PublicKey string `json:"public_key"`
ShortName string `json:"short_name"`
BuildTag string `json:"build_tag"`
TotalStaked currency.Coin `json:"total_stake"`
Delete bool `json:"delete"`

// settings and statistic

// NodeType used for delegate pools statistic.
NodeType NodeType `json:"node_type,omitempty"`

// LastHealthCheck used to check for active node
LastHealthCheck common.Timestamp `json:"last_health_check"`

// Status will be set either node.NodeStatusActive or node.NodeStatusInactive
Status int `json:"-" msg:"-"`

//LastSettingUpdateRound will be set to round number when settings were updated
LastSettingUpdateRound int64 `json:"last_setting_update_round"`
}

// swagger:model SimpleNodeGeolocation
type SimpleNodeGeolocation struct {
Latitude *float64 `json:"latitude,omitempty"`
Longitude *float64 `json:"longitude,omitempty"`
}

func NewMinerDtoNode() *MinerDtoNode {
return &MinerDtoNode{
SimpleDtoNode: &SimpleDtoNode{
Provider: provider.Provider{},
},
StakePool: NewStakePool(),
}
}
39 changes: 39 additions & 0 deletions code/go/0chain.net/smartcontract/dto/stakepooldto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dto

import (
cstate "0chain.net/chaincore/chain/state"
"0chain.net/core/common"
"github.com/0chain/common/core/currency"
)

type PoolStatus int

// StakePool holds delegate information for an 0chain providers
type StakePool struct {
Pools map[string]*DelegatePool `json:"pools"`
Reward currency.Coin `json:"rewards"`
StakePoolSettings Settings `json:"settings"`
Minter cstate.ApprovedMinter `json:"minter"`
HasBeenKilled bool `json:"is_dead"`
}

type DelegatePool struct {
Balance currency.Coin `json:"balance"`
Reward currency.Coin `json:"reward"`
Status *PoolStatus `json:"status"`
RoundCreated *int64 `json:"round_created"` // used for cool down
DelegateID *string `json:"delegate_id"`
StakedAt common.Timestamp `json:"staked_at"`
}

type Settings struct {
DelegateWallet *string `json:"delegate_wallet,omitempty"`
MaxNumDelegates *int `json:"num_delegates,omitempty"`
ServiceChargeRatio *float64 `json:"service_charge,omitempty"`
}

func NewStakePool() *StakePool {
return &StakePool{
Pools: make(map[string]*DelegatePool),
}
}
54 changes: 47 additions & 7 deletions code/go/0chain.net/smartcontract/minersc/miner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package minersc

import (
"0chain.net/smartcontract/dto"
"encoding/json"
"fmt"

"0chain.net/smartcontract/stakepool/spenum"
Expand Down Expand Up @@ -252,24 +254,24 @@ func (msc *MinerSmartContract) UpdateMinerSettings(t *transaction.Transaction,
inputData []byte, gn *GlobalNode, balances cstate.StateContextI) (
resp string, err error) {

var update = NewMinerNode()
if err = update.Decode(inputData); err != nil {
requiredUpdateInMinerNode := dto.NewMinerDtoNode()
if err = json.Unmarshal(inputData, &requiredUpdateInMinerNode); err != nil {
return "", common.NewErrorf("update_miner_settings",
"decoding request: %v", err)
}

err = validateNodeSettings(update, gn, "update_miner_settings")
err = validateNodeUpdateSettings(requiredUpdateInMinerNode, gn, "update_miner_settings")
if err != nil {
return "", err
}

var mn *MinerNode
mn, err = getMinerNode(update.ID, balances)
mn, err = getMinerNode(requiredUpdateInMinerNode.ID, balances)
switch err {
case nil:
case util.ErrValueNotPresent:
mn = NewMinerNode()
mn.ID = update.ID
mn.ID = requiredUpdateInMinerNode.ID
default:
return "", common.NewError("update_miner_settings", err.Error())
}
Expand All @@ -287,8 +289,14 @@ func (msc *MinerSmartContract) UpdateMinerSettings(t *transaction.Transaction,
return "", common.NewError("update_miner_settings", "access denied")
}

mn.Settings.ServiceChargeRatio = update.Settings.ServiceChargeRatio
mn.Settings.MaxNumDelegates = update.Settings.MaxNumDelegates
// only update when there were values sent
if requiredUpdateInMinerNode.StakePool.StakePoolSettings.ServiceChargeRatio != nil {
mn.Settings.ServiceChargeRatio = *requiredUpdateInMinerNode.StakePoolSettings.ServiceChargeRatio
}

if requiredUpdateInMinerNode.StakePool.StakePoolSettings.MaxNumDelegates != nil {
mn.Settings.MaxNumDelegates = *requiredUpdateInMinerNode.StakePoolSettings.MaxNumDelegates
}

if err = mn.save(balances); err != nil {
return "", common.NewErrorf("update_miner_settings", "saving: %v", err)
Expand Down Expand Up @@ -349,3 +357,35 @@ func validateNodeSettings(node *MinerNode, gn *GlobalNode, opcode string) error

return nil
}

func validateNodeUpdateSettings(update *dto.MinerDtoNode, gn *GlobalNode, opcode string) error {
if update.StakePoolSettings.ServiceChargeRatio != nil {
serviceChargeValue := *update.StakePoolSettings.ServiceChargeRatio
if serviceChargeValue < 0 {
return common.NewErrorf(opcode,
"invalid negative service charge: %v", serviceChargeValue)
}

if serviceChargeValue > gn.MaxCharge {
return common.NewErrorf(opcode,
"max_charge is greater than allowed by SC: %v > %v",
serviceChargeValue, gn.MaxCharge)
}
}

if update.StakePoolSettings.MaxNumDelegates != nil {
maxDelegateValue := *update.StakePoolSettings.MaxNumDelegates
if maxDelegateValue <= 0 {
return common.NewErrorf(opcode,
"invalid non-positive number_of_delegates: %v", maxDelegateValue)
}

if maxDelegateValue > gn.MaxDelegates {
return common.NewErrorf(opcode,
"number_of_delegates greater than max_delegates of SC: %v > %v",
maxDelegateValue, gn.MaxDelegates)
}
}

return nil
}
20 changes: 14 additions & 6 deletions code/go/0chain.net/smartcontract/minersc/sharder.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package minersc

import (
"0chain.net/smartcontract/dto"
"encoding/json"
"errors"
"fmt"

Expand All @@ -21,19 +23,19 @@ func (msc *MinerSmartContract) UpdateSharderSettings(t *transaction.Transaction,
inputData []byte, gn *GlobalNode, balances cstate.StateContextI) (
resp string, err error) {

var update = NewMinerNode()
if err = update.Decode(inputData); err != nil {
requiredUpdateInSharderNode := dto.NewMinerDtoNode()
if err = json.Unmarshal(inputData, &requiredUpdateInSharderNode); err != nil {
return "", common.NewErrorf("update_sharder_settings",
"decoding request: %v", err)
}

err = validateNodeSettings(update, gn, "update_sharder_settings")
err = validateNodeUpdateSettings(requiredUpdateInSharderNode, gn, "update_sharder_settings")
if err != nil {
return "", err
}

var sn *MinerNode
sn, err = msc.getSharderNode(update.ID, balances)
sn, err = msc.getSharderNode(requiredUpdateInSharderNode.ID, balances)
if err != nil {
return "", common.NewError("update_sharder_settings", err.Error())
}
Expand All @@ -49,8 +51,14 @@ func (msc *MinerSmartContract) UpdateSharderSettings(t *transaction.Transaction,
return "", common.NewError("update_sharder_settings", "access denied")
}

sn.Settings.ServiceChargeRatio = update.Settings.ServiceChargeRatio
sn.Settings.MaxNumDelegates = update.Settings.MaxNumDelegates
// only update when there were values sent
if requiredUpdateInSharderNode.StakePool.StakePoolSettings.ServiceChargeRatio != nil {
sn.Settings.ServiceChargeRatio = *requiredUpdateInSharderNode.StakePoolSettings.ServiceChargeRatio
}

if requiredUpdateInSharderNode.StakePool.StakePoolSettings.MaxNumDelegates != nil {
sn.Settings.MaxNumDelegates = *requiredUpdateInSharderNode.StakePoolSettings.MaxNumDelegates
}

if err = sn.save(balances); err != nil {
return "", common.NewErrorf("update_sharder_settings", "saving: %v", err)
Expand Down

0 comments on commit e36f104

Please sign in to comment.