diff --git a/smartcontract/service/native/governance/governance.go b/smartcontract/service/native/governance/governance.go index 5778a0dd5c..1d9379f7d4 100644 --- a/smartcontract/service/native/governance/governance.go +++ b/smartcontract/service/native/governance/governance.go @@ -48,22 +48,23 @@ const ( const ( //function name - INIT_CONFIG = "initConfig" - REGISTER_CANDIDATE = "registerCandidate" - APPROVE_CANDIDATE = "approveCandidate" - REJECT_CANDIDATE = "rejectCandidate" - BLACK_NODE = "blackNode" - WHITE_NODE = "whiteNode" - QUIT_NODE = "quitNode" - VOTE_FOR_PEER = "voteForPeer" - UNVOTE_FOR_PEER = "unVoteForPeer" - WITHDRAW = "withdraw" - COMMIT_DPOS = "commitDpos" - UPDATE_CONFIG = "updateConfig" - UPDATE_GLOBAL_PARAM = "updateGlobalParam" - UPDATE_SPLIT_CURVE = "updateSplitCurve" - CALL_SPLIT = "callSplit" - TRANSFER_PENALTY = "transferPenalty" + INIT_CONFIG = "initConfig" + REGISTER_CANDIDATE = "registerCandidate" + UNREGISTER_CANDIDATE = "unRegisterCandidate" + APPROVE_CANDIDATE = "approveCandidate" + REJECT_CANDIDATE = "rejectCandidate" + BLACK_NODE = "blackNode" + WHITE_NODE = "whiteNode" + QUIT_NODE = "quitNode" + VOTE_FOR_PEER = "voteForPeer" + UNVOTE_FOR_PEER = "unVoteForPeer" + WITHDRAW = "withdraw" + COMMIT_DPOS = "commitDpos" + UPDATE_CONFIG = "updateConfig" + UPDATE_GLOBAL_PARAM = "updateGlobalParam" + UPDATE_SPLIT_CURVE = "updateSplitCurve" + CALL_SPLIT = "callSplit" + TRANSFER_PENALTY = "transferPenalty" //key prefix GLOBAL_PARAM = "globalParam" @@ -102,6 +103,7 @@ func InitGovernance() { func RegisterGovernanceContract(native *native.NativeService) { native.Register(REGISTER_CANDIDATE, RegisterCandidate) + native.Register(UNREGISTER_CANDIDATE, UnRegisterCandidate) native.Register(VOTE_FOR_PEER, VoteForPeer) native.Register(UNVOTE_FOR_PEER, UnVoteForPeer) native.Register(WITHDRAW, Withdraw) @@ -304,11 +306,6 @@ func RegisterCandidate(native *native.NativeService) ([]byte, error) { return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "getGlobalParam, getGlobalParam error!") } - //check initPos - if params.InitPos < globalParam.MinInitStake { - return utils.BYTE_FALSE, fmt.Errorf("registerCandidate, initPos must >= %v", globalParam.MinInitStake) - } - //check peerPubkey if err := validatePeerPubKeyFormat(params.PeerPubkey); err != nil { return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "invalid peer pubkey") @@ -371,6 +368,67 @@ func RegisterCandidate(native *native.NativeService) ([]byte, error) { return utils.BYTE_TRUE, nil } +func UnRegisterCandidate(native *native.NativeService) ([]byte, error) { + params := new(UnRegisterCandidateParam) + if err := params.Deserialize(bytes.NewBuffer(native.Input)); err != nil { + return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "deserialize, contract params deserialize error!") + } + address := params.Address + contract := native.ContextRef.CurrentContext().ContractAddress + + //check witness + err := utils.ValidateOwner(native, address) + if err != nil { + return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "validateOwner, checkWitness error!") + } + + //get current view + view, err := GetView(native, contract) + if err != nil { + return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "getView, get view error!") + } + + //get peerPoolMap + peerPoolMap, err := GetPeerPoolMap(native, contract, view) + if err != nil { + return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "getPeerPoolMap, get peerPoolMap error!") + } + + //check if exist in PeerPool + peerPoolItem, ok := peerPoolMap.PeerPoolMap[params.PeerPubkey] + if !ok { + return utils.BYTE_FALSE, errors.NewErr("unRegisterCandidate, peerPubkey is not in peerPoolMap!") + } + + if peerPoolItem.Status != RegisterCandidateStatus { + return utils.BYTE_FALSE, errors.NewErr("unRegisterCandidate, peer status is not RegisterCandidateStatus!") + } + + //check owner address + if peerPoolItem.Address != params.Address { + return utils.BYTE_FALSE, errors.NewErr("unRegisterCandidate, address is not peer owner!") + } + + //unfreeze initPos + voteInfo := &VoteInfo{ + PeerPubkey: peerPoolItem.PeerPubkey, + Address: peerPoolItem.Address, + WithdrawUnfreezePos: peerPoolItem.InitPos, + } + err = putVoteInfo(native, contract, voteInfo) + if err != nil { + return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "putVoteInfo, put voteInfo error!") + } + + delete(peerPoolMap.PeerPoolMap, params.PeerPubkey) + err = putPeerPoolMap(native, contract, view, peerPoolMap) + if err != nil { + return utils.BYTE_FALSE, errors.NewDetailErr(err, errors.ErrNoCode, "putPeerPoolMap, put peerPoolMap error!") + } + + return utils.BYTE_TRUE, nil +} + func ApproveCandidate(native *native.NativeService) ([]byte, error) { params := new(ApproveCandidateParam) if err := params.Deserialize(bytes.NewBuffer(native.Input)); err != nil { @@ -425,6 +483,11 @@ func ApproveCandidate(native *native.NativeService) ([]byte, error) { return utils.BYTE_FALSE, errors.NewErr("approveCandidate, peerPubkey is not in peerPoolMap!") } + //check initPos + if peerPoolItem.InitPos < globalParam.MinInitStake { + return utils.BYTE_FALSE, fmt.Errorf("approveCandidate, initPos must >= %v", globalParam.MinInitStake) + } + if peerPoolItem.Status != RegisterCandidateStatus { return utils.BYTE_FALSE, errors.NewErr("approveCandidate, peer status is not RegisterCandidateStatus!") } diff --git a/smartcontract/service/native/governance/param.go b/smartcontract/service/native/governance/param.go index 25e4494974..a6cc91ab55 100644 --- a/smartcontract/service/native/governance/param.go +++ b/smartcontract/service/native/governance/param.go @@ -83,6 +83,35 @@ func (this *RegisterCandidateParam) Deserialize(r io.Reader) error { return nil } +type UnRegisterCandidateParam struct { + PeerPubkey string + Address common.Address +} + +func (this *UnRegisterCandidateParam) Serialize(w io.Writer) error { + if err := serialization.WriteString(w, this.PeerPubkey); err != nil { + return errors.NewDetailErr(err, errors.ErrNoCode, "serialization.WriteString, request peerPubkey error!") + } + if err := serialization.WriteVarBytes(w, this.Address[:]); err != nil { + return errors.NewDetailErr(err, errors.ErrNoCode, "serialization.WriteVarBytes, address address error!") + } + return nil +} + +func (this *UnRegisterCandidateParam) Deserialize(r io.Reader) error { + peerPubkey, err := serialization.ReadString(r) + if err != nil { + return errors.NewDetailErr(err, errors.ErrNoCode, "serialization.ReadString, deserialize peerPubkey error!") + } + address, err := utils.ReadAddress(r) + if err != nil { + return errors.NewDetailErr(err, errors.ErrNoCode, "utils.ReadAddress, deserialize address error!") + } + this.PeerPubkey = peerPubkey + this.Address = address + return nil +} + type QuitNodeParam struct { PeerPubkey string Address common.Address @@ -531,6 +560,9 @@ func (this *SplitCurve) Serialize(w io.Writer) error { if len(this.Yi) != 101 { return errors.NewErr("length of split curve != 101!") } + if err := utils.WriteVarUint(w, uint64(len(this.Yi))); err != nil { + return errors.NewDetailErr(err, errors.ErrNoCode, "serialization.WriteVarUint, serialize Yi length error!") + } for _, v := range this.Yi { if err := utils.WriteVarUint(w, v); err != nil { return errors.NewDetailErr(err, errors.ErrNoCode, "utils.WriteVarUint, serialize splitCurve error!") @@ -540,8 +572,12 @@ func (this *SplitCurve) Serialize(w io.Writer) error { } func (this *SplitCurve) Deserialize(r io.Reader) error { + n, err := utils.ReadVarUint(r) + if err != nil { + return errors.NewDetailErr(err, errors.ErrNoCode, "serialization.ReadVarUint, deserialize Yi length error!") + } yi := make([]uint64, 0) - for i := 0; i < 101; i++ { + for i := 0; uint64(i) < n; i++ { k, err := utils.ReadVarUint(r) if err != nil { return errors.NewDetailErr(err, errors.ErrNoCode, "utils.ReadVarUint, deserialize splitCurve error!") diff --git a/smartcontract/service/native/governance/utils.go b/smartcontract/service/native/governance/utils.go index 80929583d5..32244b740b 100644 --- a/smartcontract/service/native/governance/utils.go +++ b/smartcontract/service/native/governance/utils.go @@ -196,13 +196,13 @@ func appCallTransferFromOng(native *native.NativeService, sender common.Address, } func getOngBalance(native *native.NativeService, address common.Address) (uint64, error) { - buf := bytes.NewBuffer(nil) - err := address.Serialize(buf) + bf := new(bytes.Buffer) + err := utils.WriteAddress(bf, address) if err != nil { - return 0, errors.NewDetailErr(err, errors.ErrNoCode, "getOngBalance, address.Serialize error!") + return 0, errors.NewDetailErr(err, errors.ErrNoCode, "getOngBalance, utils.WriteAddress error!") } - value, err := native.NativeCall(utils.OngContractAddress, "balanceOf", buf.Bytes()) + value, err := native.NativeCall(utils.OngContractAddress, "balanceOf", bf.Bytes()) if err != nil { return 0, errors.NewDetailErr(err, errors.ErrNoCode, "getOngBalance, appCall error!") }