From 657bb7575e8d1ddd7a488ead081c04ae71274f55 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 1 Jun 2020 23:27:03 +0300 Subject: [PATCH] rpc: change getunclaimed to getunclaimedgas getunclaimed doesn't exist on Neo 3 and getunclaimedgas works for NEP5 GAS. --- docs/rpc.md | 8 +++- pkg/core/blockchain.go | 11 ++++++ pkg/core/blockchainer/blockchainer.go | 1 + pkg/network/helper_test.go | 4 ++ pkg/rpc/client/doc.go | 3 +- pkg/rpc/client/rpc.go | 17 ++++++--- pkg/rpc/client/rpc_test.go | 20 ++++------ pkg/rpc/response/result/unclaimed.go | 54 --------------------------- pkg/rpc/server/server.go | 20 +++++----- pkg/rpc/server/server_test.go | 13 +++---- 10 files changed, 58 insertions(+), 93 deletions(-) delete mode 100644 pkg/rpc/response/result/unclaimed.go diff --git a/docs/rpc.md b/docs/rpc.md index 3eac4e3e3..dc0f72907 100644 --- a/docs/rpc.md +++ b/docs/rpc.md @@ -51,7 +51,7 @@ which would yield the response: | `getrawtransaction` | | `getstorage` | | `gettransactionheight` | -| `getunclaimed` | +| `getunclaimedgas` | | `getvalidators` | | `getversion` | | `invoke` | @@ -73,6 +73,11 @@ in returning it. Both methods also don't currently support arrays in function parameters. +##### `getunclaimedgas` + +It's possible to call this method for any address with neo-go, unlike with C# +node where it only works for addresses from opened wallet. + ### Unsupported methods Methods listed down below are not going to be supported for various reasons @@ -85,7 +90,6 @@ and we're not accepting issues related to them. | `getbalance` | Use `getaccountstate` instead, see `claimgas` comment also | | `getmetricblocktimestamp` | Not really useful, use other means for node monitoring | | `getnewaddress` | See `claimgas` comment | -| `getunclaimedgas` | Use `getunclaimed` instead, see `claimgas` comment also | | `getwalletheight` | Not applicable to neo-go, see `claimgas` comment | | `importprivkey` | Not applicable to neo-go, see `claimgas` comment | | `listaddress` | Not applicable to neo-go, see `claimgas` comment | diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 035c01dbd..4fecf3a9b 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -930,6 +930,17 @@ func (bc *Blockchain) GetUtilityTokenBalance(acc util.Uint160) util.Fixed8 { return util.Fixed8(bc.GetNEP5Balances(acc).Trackers[bc.contracts.GAS.Hash].Balance) } +// GetGoverningTokenBalance returns governing token (NEO) balance and the height +// of the last balance change for the account. +func (bc *Blockchain) GetGoverningTokenBalance(acc util.Uint160) (util.Fixed8, uint32) { + bs, err := bc.dao.GetNEP5Balances(acc) + if err != nil { + return 0, 0 + } + neo := bs.Trackers[bc.contracts.NEO.Hash] + return util.Fixed8(neo.Balance), neo.LastUpdatedBlock +} + // LastBatch returns last persisted storage batch. func (bc *Blockchain) LastBatch() *storage.MemBatch { return bc.lastBatch diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index dacb0f2fd..344dac5ea 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -25,6 +25,7 @@ type Blockchainer interface { GetBlock(hash util.Uint256) (*block.Block, error) GetContractState(hash util.Uint160) *state.Contract GetEnrollments() ([]state.Validator, error) + GetGoverningTokenBalance(acc util.Uint160) (util.Fixed8, uint32) GetHeaderHash(int) util.Uint256 GetHeader(hash util.Uint256) (*block.Header, error) CurrentHeaderHash() util.Uint256 diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index b09f5e885..b48c4b985 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -138,6 +138,10 @@ func (chain testChain) IsLowPriority(util.Fixed8) bool { panic("TODO") } +func (chain testChain) GetGoverningTokenBalance(acc util.Uint160) (util.Fixed8, uint32) { + panic("TODO") +} + func (chain testChain) GetUtilityTokenBalance(uint160 util.Uint160) util.Fixed8 { panic("TODO") } diff --git a/pkg/rpc/client/doc.go b/pkg/rpc/client/doc.go index 7863752fe..3ac507dc6 100644 --- a/pkg/rpc/client/doc.go +++ b/pkg/rpc/client/doc.go @@ -35,7 +35,7 @@ Supported methods getrawtransaction getstorage gettransactionheight - getunclaimed + getunclaimedgas getvalidators getversion invoke @@ -52,7 +52,6 @@ Unsupported methods getbalance getmetricblocktimestamp getnewaddress - getunclaimedgas getwalletheight importprivkey listaddress diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index bf5a07179..5062d87a6 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -2,6 +2,7 @@ package client import ( "encoding/hex" + "strconv" "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/block" @@ -307,16 +308,20 @@ func (c *Client) GetTransactionHeight(hash util.Uint256) (uint32, error) { return resp, nil } -// GetUnclaimed returns unclaimed GAS amount of the specified address. -func (c *Client) GetUnclaimed(address string) (*result.Unclaimed, error) { +// GetUnclaimedGas returns unclaimed GAS amount for the specified address. +func (c *Client) GetUnclaimedGas(address string) (util.Fixed8, error) { var ( params = request.NewRawParams(address) - resp = &result.Unclaimed{} + resp string ) - if err := c.performRequest("getunclaimed", params, resp); err != nil { - return nil, err + if err := c.performRequest("getunclaimedgas", params, &resp); err != nil { + return 0, err } - return resp, nil + i, err := strconv.ParseInt(resp, 10, 64) + if err != nil { + return 0, err + } + return util.Fixed8(i), nil } // GetValidators returns the current NEO consensus nodes information and voting status. diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index ceb99fbaa..965425e65 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -670,19 +670,15 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, }, }, - "getunclaimed": { + "getunclaimedgas": { { name: "positive", invoke: func(c *Client) (interface{}, error) { - return c.GetUnclaimed("AGofsxAUDwt52KjaB664GYsqVAkULYvKNt") + return c.GetUnclaimedGas("AGofsxAUDwt52KjaB664GYsqVAkULYvKNt") }, - serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"available":750.032,"unavailable":2815.408,"unclaimed":3565.44}}`, + serverResponse: `{"jsonrpc":"2.0","id":1,"result":"897299680935"}`, result: func(c *Client) interface{} { - return &result.Unclaimed{ - Available: util.Fixed8FromFloat(750.032), - Unavailable: util.Fixed8FromFloat(2815.408), - Unclaimed: util.Fixed8FromFloat(3565.44), - } + return util.Fixed8(897299680935) }, }, }, @@ -1039,9 +1035,9 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, }, { - name: "getunclaimed_invalid_params_error", + name: "getunclaimedgas_invalid_params_error", invoke: func(c *Client) (interface{}, error) { - return c.GetUnclaimed("") + return c.GetUnclaimedGas("") }, }, { @@ -1209,9 +1205,9 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, }, { - name: "getunclaimed_unmarshalling_error", + name: "getunclaimedgas_unmarshalling_error", invoke: func(c *Client) (interface{}, error) { - return c.GetUnclaimed("") + return c.GetUnclaimedGas("") }, }, { diff --git a/pkg/rpc/response/result/unclaimed.go b/pkg/rpc/response/result/unclaimed.go deleted file mode 100644 index f8cd8d1a9..000000000 --- a/pkg/rpc/response/result/unclaimed.go +++ /dev/null @@ -1,54 +0,0 @@ -package result - -import ( - "github.com/nspcc-dev/neo-go/pkg/core" - "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" - "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// Unclaimed wrapper is used to represent getunclaimed return result. -type Unclaimed struct { - Available util.Fixed8 `json:"available"` - Unavailable util.Fixed8 `json:"unavailable"` - Unclaimed util.Fixed8 `json:"unclaimed"` -} - -// NewUnclaimed creates a new Unclaimed wrapper using given Blockchainer. -func NewUnclaimed(a *state.Account, chain blockchainer.Blockchainer) (*Unclaimed, error) { - var ( - available util.Fixed8 - unavailable util.Fixed8 - ) - - err := a.Unclaimed.ForEach(func(ucb *state.UnclaimedBalance) error { - gen, sys, err := chain.CalculateClaimable(ucb.Value, ucb.Start, ucb.End) - if err != nil { - return err - } - available += gen + sys - return nil - }) - if err != nil { - return nil, err - } - - blockHeight := chain.BlockHeight() - for _, usb := range a.Balances[core.GoverningTokenID()] { - _, txHeight, err := chain.GetTransaction(usb.Tx) - if err != nil { - return nil, err - } - gen, sys, err := chain.CalculateClaimable(usb.Value, txHeight, blockHeight) - if err != nil { - return nil, err - } - unavailable += gen + sys - } - - return &Unclaimed{ - Available: available, - Unavailable: unavailable, - Unclaimed: available + unavailable, - }, nil -} diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index d1d041e7a..cd554395a 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -96,7 +96,7 @@ var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, *respon "getrawtransaction": (*Server).getrawtransaction, "getstorage": (*Server).getStorage, "gettransactionheight": (*Server).getTransactionHeight, - "getunclaimed": (*Server).getUnclaimed, + "getunclaimedgas": (*Server).getUnclaimedGas, "getvalidators": (*Server).getValidators, "getversion": (*Server).getVersion, "invoke": (*Server).invoke, @@ -827,8 +827,8 @@ func (s *Server) getBlockHeader(reqParams request.Params) (interface{}, *respons return hex.EncodeToString(buf.Bytes()), nil } -// getUnclaimed returns unclaimed GAS amount of the specified address. -func (s *Server) getUnclaimed(ps request.Params) (interface{}, *response.Error) { +// getUnclaimedGas returns unclaimed GAS amount of the specified address. +func (s *Server) getUnclaimedGas(ps request.Params) (interface{}, *response.Error) { p, ok := ps.ValueWithType(0, request.StringT) if !ok { return nil, response.ErrInvalidParams @@ -838,15 +838,15 @@ func (s *Server) getUnclaimed(ps request.Params) (interface{}, *response.Error) return nil, response.ErrInvalidParams } - acc := s.chain.GetAccountState(u) - if acc == nil { - return nil, response.NewInternalServerError("unknown account", nil) + neo, neoHeight := s.chain.GetGoverningTokenBalance(u) + if neo == 0 { + return "0", nil } - res, errRes := result.NewUnclaimed(acc, s.chain) - if errRes != nil { - return nil, response.NewInternalServerError("can't create unclaimed response", errRes) + gasG, gasF, err := s.chain.CalculateClaimable(neo, neoHeight, s.chain.BlockHeight()+1) // +1 as in C#, for the next block. + if err != nil { + return nil, response.NewInternalServerError("calculation error", err) } - return res, nil + return strconv.FormatInt(int64(gasG+gasF), 10), nil // It's not represented as Fixed8 in C#. } // getValidators returns the current NEO consensus nodes information and voting status. diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 16693d412..76d25dfb8 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -507,7 +507,7 @@ var rpcTestCases = map[string][]rpcTestCase{ fail: true, }, }, - "getunclaimed": { + "getunclaimedgas": { { name: "no params", params: "[]", @@ -522,14 +522,13 @@ var rpcTestCases = map[string][]rpcTestCase{ name: "positive", params: `["` + testchain.MultisigAddress() + `"]`, result: func(*executor) interface{} { - return &result.Unclaimed{} + var s string + return &s }, - check: func(t *testing.T, e *executor, uncl interface{}) { - res, ok := uncl.(*result.Unclaimed) + check: func(t *testing.T, e *executor, resp interface{}) { + s, ok := resp.(*string) require.True(t, ok) - assert.Equal(t, res.Available, util.Fixed8FromInt64(8)) - assert.True(t, res.Unavailable > 0) - assert.Equal(t, res.Available+res.Unavailable, res.Unclaimed) + assert.Equal(t, "1772", *s) }, }, },