diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 2a3a2faa1..237479c06 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -96,6 +96,11 @@ func NewNEO() *NEO { md = newMethodAndPrice(n.registerCandidate, 5000000, smartcontract.AllowModifyStates) n.AddMethod(md, desc, false) + desc = newDescriptor("unregisterCandidate", smartcontract.BoolType, + manifest.NewParameter("pubkey", smartcontract.PublicKeyType)) + md = newMethodAndPrice(n.unregisterCandidate, 5000000, smartcontract.AllowModifyStates) + n.AddMethod(md, desc, false) + desc = newDescriptor("vote", smartcontract.BoolType, manifest.NewParameter("account", smartcontract.Hash160Type), manifest.NewParameter("pubkey", smartcontract.PublicKeyType)) @@ -237,6 +242,28 @@ func (n *NEO) RegisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey return ic.DAO.PutStorageItem(n.ContractID, key, si) } +func (n *NEO) unregisterCandidate(ic *interop.Context, args []stackitem.Item) stackitem.Item { + err := n.UnregisterCandidateInternal(ic, toPublicKey(args[0])) + return stackitem.NewBool(err == nil) +} + +// UnregisterCandidateInternal unregisters pub as a candidate. +func (n *NEO) UnregisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error { + key := makeValidatorKey(pub) + si := ic.DAO.GetStorageItem(n.ContractID, key) + if si == nil { + return nil + } + n.validators.Store(keys.PublicKeys(nil)) + c := new(candidate).FromBytes(si.Value) + if c.Votes.Sign() == 0 { + return ic.DAO.DeleteStorageItem(n.ContractID, key) + } + c.Registered = false + si.Value = c.Bytes() + return ic.DAO.PutStorageItem(n.ContractID, key, si) +} + func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item { acc := toUint160(args[0]) var pub *keys.PublicKey diff --git a/pkg/core/native_neo_test.go b/pkg/core/native_neo_test.go index 72da75bb9..8ef63432d 100644 --- a/pkg/core/native_neo_test.go +++ b/pkg/core/native_neo_test.go @@ -92,4 +92,13 @@ func TestNEO_Vote(t *testing.T) { pubs, err = neo.GetValidatorsInternal(bc, ic.DAO) require.NoError(t, err) require.Equal(t, candidates, pubs) + + require.NoError(t, neo.UnregisterCandidateInternal(ic, candidates[0])) + require.Error(t, neo.VoteInternal(ic, h, candidates[0])) + + pubs, err = neo.GetValidatorsInternal(bc, ic.DAO) + require.NoError(t, err) + for i := range pubs { + require.NotEqual(t, candidates[0], pubs[i]) + } }