From 413caac9415642b2cbf9aad47cfe6fd58fc8e36a Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 9 Oct 2023 22:34:33 +0300 Subject: [PATCH] rpcclient: drop deprecated Client APIs Signed-off-by: Roman Khimov --- ROADMAP.md | 14 - cli/wallet/nep17.go | 14 +- docs/notary.md | 35 +-- pkg/rpcclient/client.go | 18 +- pkg/rpcclient/helper.go | 44 --- pkg/rpcclient/native.go | 172 ------------ pkg/rpcclient/nep.go | 60 ---- pkg/rpcclient/nep11.go | 232 ---------------- pkg/rpcclient/nep17.go | 188 ------------- pkg/rpcclient/policy.go | 66 ----- pkg/rpcclient/rpc.go | 375 +------------------------ pkg/rpcclient/rpc_test.go | 222 --------------- pkg/rpcclient/wsclient.go | 2 +- pkg/services/rpcsrv/client_test.go | 425 +---------------------------- 14 files changed, 36 insertions(+), 1831 deletions(-) delete mode 100644 pkg/rpcclient/helper.go delete mode 100644 pkg/rpcclient/native.go delete mode 100644 pkg/rpcclient/nep.go delete mode 100644 pkg/rpcclient/nep11.go delete mode 100644 pkg/rpcclient/nep17.go delete mode 100644 pkg/rpcclient/policy.go diff --git a/ROADMAP.md b/ROADMAP.md index 87f74a873..cd747077f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -26,20 +26,6 @@ APIs/commands/configurations will be removed and here is a list of scheduled breaking changes. Consider changing your code/scripts/configurations if you're using anything mentioned here. -## Old RPC client APIs - -A huge set of RPC client APIs was deprecated in versions 0.99.2 and 0.99.3 -(August-September 2022), including very frequently used ones like -SignAndPushInvocationTx, AddNetworkFee, TransferNEP17. A new set of -invoker/actor/unwrap/nep17/etc packages was introduced decoupling these -functions from RPC client and simplifying typical backend code. Please refer -to rpcclient package documentation for specific replacements for each of these -APIs and convert your code to using them. - -While a lot of the code is already converted to new APIs, old ones still can -be used in some code not known to us. Therefore we will remove old APIs not -earlier than May 2023, with 0.103.0 release. - ## WSClient Notifications channel and SubscribeFor* APIs Version 0.99.5 of NeoGo introduces a new set of subscription APIs that gives diff --git a/cli/wallet/nep17.go b/cli/wallet/nep17.go index 7a7ad5a4e..bb3173792 100644 --- a/cli/wallet/nep17.go +++ b/cli/wallet/nep17.go @@ -30,6 +30,14 @@ import ( "github.com/urfave/cli" ) +// transferTarget represents target address, token amount and data for transfer. +type transferTarget struct { + Token util.Uint160 + Address util.Uint160 + Amount int64 + Data any +} + var ( tokenFlag = cli.StringFlag{ Name: "token", @@ -531,7 +539,7 @@ func multiTransferNEP17(ctx *cli.Context) error { return cli.NewExitError("empty recipients list", 1) } var ( - recipients []rpcclient.TransferTarget + recipients []transferTarget cosignersOffset = ctx.NArg() ) cache := make(map[string]*wallet.Token) @@ -564,7 +572,7 @@ func multiTransferNEP17(ctx *cli.Context) error { if err != nil { return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1) } - recipients = append(recipients, rpcclient.TransferTarget{ + recipients = append(recipients, transferTarget{ Token: token.Hash, Address: addr, Amount: amount.Int64(), @@ -690,7 +698,7 @@ func transferNEP(ctx *cli.Context, standard string) error { return txctx.SignAndSend(ctx, act, acc, tx) } -func makeMultiTransferNEP17(act *actor.Actor, recipients []rpcclient.TransferTarget) (*transaction.Transaction, error) { +func makeMultiTransferNEP17(act *actor.Actor, recipients []transferTarget) (*transaction.Transaction, error) { scr := smartcontract.NewBuilder() for i := range recipients { scr.InvokeWithAssert(recipients[i].Token, "transfer", act.Sender(), diff --git a/docs/notary.md b/docs/notary.md index 7c348940c..b75d40a45 100644 --- a/docs/notary.md +++ b/docs/notary.md @@ -392,34 +392,17 @@ subpackage with an example written in Go doc. that includes simple-signature accounts and multisignature accounts where the client has one of the keys (in which case an invocation script is created that pushes just one signature onto the stack). -10. Define lifetime for the fallback transaction. Let the `fallbackValidFor` be - the lifetime. Let `N` be the current chain's height and `VUB` be - `ValidUntilBlock` value estimated at step 3. Then, the notary node is trying to - collect signatures for the main transaction from `N` up to - `VUB-fallbackValidFor`. In case of failure after `VUB-fallbackValidFor`-th - block is accepted, the notary node abandons attempts to complete the main transaction and - tries to push all associated fallbacks. Use the following rules to define - `fallbackValidFor`: - - `fallbackValidFor` shouldn't be more than `MaxNotValidBeforeDelta` value. - - Use notary package's GetMaxNotValidBeforeDelta to check `MaxNotValidBefore` value. -11. Construct a script for the fallback transaction. The script may do something useful, - i.g. invoke method of a contract. However, if you don't need to perform anything - special on fallback invocation, you can use simple `opcode.RET` script. -12. Sign and submit P2P notary request. Use - [func (*Client) SignAndPushP2PNotaryRequest](https://pkg.go.dev/github.com/nspcc-dev/neo-go@v0.97.2/pkg/rpcclient#Client.SignAndPushP2PNotaryRequest) for it. +10. Sign and submit P2P notary request. Use + [func (*Actor) Notarize](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/rpcclient/notary#Actor.Notarize) for it. - Use the signed main transaction from step 9 as `mainTx` argument. - - Use the fallback script from step 10 as `fallbackScript` argument. - - Use `-1` as `fallbackSysFee` argument to define system fee by test - invocation or provide any custom value. - - Use `0` as `fallbackNetFee` argument not to add extra network fee to the - fallback. - - Use the `fallbackValidFor` estimated at step 9 as `fallbackValidFor` argument. - - Use your account you'd like to send request (and fallback transaction) from - to sign the request (and fallback transaction). - `SignAndPushP2PNotaryRequest` will construct and sign a fallback transaction, - construct and sign a P2PNotaryRequest and submit it to the RPC node. The - resulting notary request and an error are returned. + `Notarize` will construct and sign a fallback transaction using `Actor` + configuration (just a simple `RET` script by default), pack both transactions + into a P2PNotaryRequest and submit it to the RPC node. It returns hashes of + the main and fallback transactions as well as their `ValidUntilBlock` value. + If you need more control over fallback transction use `Actor` options or + [func (*Actor) SendRequest](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/rpcclient/notary#Actor.SendRequest) + API. After P2PNotaryRequests are sent, participants should wait for one of their transactions (main or fallback) to get accepted into one of subsequent blocks. diff --git a/pkg/rpcclient/client.go b/pkg/rpcclient/client.go index 9c67ad43a..8d762560d 100644 --- a/pkg/rpcclient/client.go +++ b/pkg/rpcclient/client.go @@ -22,8 +22,6 @@ import ( const ( defaultDialTimeout = 4 * time.Second defaultRequestTimeout = 4 * time.Second - // Number of blocks after which cache is expired. - cacheTimeout = 100 ) // Client represents the middleman for executing JSON RPC calls @@ -74,18 +72,10 @@ type Options struct { // cache stores cache values for the RPC client methods. type cache struct { - initDone bool - network netmode.Magic - stateRootInHeader bool - calculateValidUntilBlock calculateValidUntilBlockCache - nativeHashes map[string]util.Uint160 -} - -// calculateValidUntilBlockCache stores a cached number of validators and -// cache expiration value in blocks. -type calculateValidUntilBlockCache struct { - validatorsCount uint32 - expiresAt uint32 + initDone bool + network netmode.Magic + stateRootInHeader bool + nativeHashes map[string]util.Uint160 } // New returns a new Client ready to use. You should call Init method to diff --git a/pkg/rpcclient/helper.go b/pkg/rpcclient/helper.go deleted file mode 100644 index af394cde9..000000000 --- a/pkg/rpcclient/helper.go +++ /dev/null @@ -1,44 +0,0 @@ -package rpcclient - -import ( - "fmt" - - "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// InvokeAndPackIteratorResults creates a script containing System.Contract.Call -// of the specified contract with the specified arguments. It assumes that the -// specified operation will return iterator. The script traverses the resulting -// iterator, packs all its values into array and pushes the resulting array on -// stack. Constructed script is invoked via `invokescript` JSON-RPC API using -// the provided signers. The result of the script invocation contains single array -// stackitem on stack if invocation HALTed. InvokeAndPackIteratorResults can be -// used to interact with JSON-RPC server where iterator sessions are disabled to -// retrieve iterator values via single `invokescript` JSON-RPC call. It returns -// maxIteratorResultItems items at max which is set to -// config.DefaultMaxIteratorResultItems by default. -// -// Deprecated: please use more convenient and powerful invoker.Invoker interface with -// CallAndExpandIterator method. This method will be removed in future versions. -func (c *Client) InvokeAndPackIteratorResults(contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer, maxIteratorResultItems ...int) (*result.Invoke, error) { - max := config.DefaultMaxIteratorResultItems - if len(maxIteratorResultItems) != 0 { - max = maxIteratorResultItems[0] - } - values, err := smartcontract.ExpandParameterToEmitable(smartcontract.Parameter{ - Type: smartcontract.ArrayType, - Value: params, - }) - if err != nil { - return nil, fmt.Errorf("expanding params to emitable: %w", err) - } - bytes, err := smartcontract.CreateCallAndUnwrapIteratorScript(contract, operation, max, values.([]any)...) - if err != nil { - return nil, fmt.Errorf("failed to create iterator unwrapper script: %w", err) - } - return c.InvokeScript(bytes, signers) -} diff --git a/pkg/rpcclient/native.go b/pkg/rpcclient/native.go deleted file mode 100644 index 267013455..000000000 --- a/pkg/rpcclient/native.go +++ /dev/null @@ -1,172 +0,0 @@ -package rpcclient - -// Various non-policy things from native contracts. - -import ( - "crypto/elliptic" - "errors" - "fmt" - - "github.com/google/uuid" - "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" - "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" -) - -// GetOraclePrice invokes `getPrice` method on a native Oracle contract. -// -// Deprecated: please use oracle subpackage. -func (c *Client) GetOraclePrice() (int64, error) { - oracleHash, err := c.GetNativeContractHash(nativenames.Oracle) - if err != nil { - return 0, fmt.Errorf("failed to get native Oracle hash: %w", err) - } - return c.invokeNativeGetMethod(oracleHash, "getPrice") -} - -// GetNNSPrice invokes `getPrice` method on a NeoNameService contract with the specified hash. -// -// Deprecated: please use nns subpackage. This method will be removed in future versions. -func (c *Client) GetNNSPrice(nnsHash util.Uint160) (int64, error) { - return c.invokeNativeGetMethod(nnsHash, "getPrice") -} - -// GetGasPerBlock invokes `getGasPerBlock` method on a native NEO contract. -// -// Deprecated: please use neo subpackage. This method will be removed in future releases. -func (c *Client) GetGasPerBlock() (int64, error) { - return c.getFromNEO("getGasPerBlock") -} - -// GetCandidateRegisterPrice invokes `getRegisterPrice` method on native NEO contract. -// -// Deprecated: please use neo subpackage. This method will be removed in future releases. -func (c *Client) GetCandidateRegisterPrice() (int64, error) { - return c.getFromNEO("getRegisterPrice") -} - -func (c *Client) getFromNEO(meth string) (int64, error) { - neoHash, err := c.GetNativeContractHash(nativenames.Neo) - if err != nil { - return 0, fmt.Errorf("failed to get native NEO hash: %w", err) - } - return c.invokeNativeGetMethod(neoHash, meth) -} - -// GetDesignatedByRole invokes `getDesignatedByRole` method on a native RoleManagement contract. -// -// Deprecated: please use rolemgmt package. -func (c *Client) GetDesignatedByRole(role noderoles.Role, index uint32) (keys.PublicKeys, error) { - rmHash, err := c.GetNativeContractHash(nativenames.Designation) - if err != nil { - return nil, fmt.Errorf("failed to get native RoleManagement hash: %w", err) - } - arr, err := unwrap.Array(c.reader.Call(rmHash, "getDesignatedByRole", int64(role), index)) - if err != nil { - return nil, err - } - pks := make(keys.PublicKeys, len(arr)) - for i, item := range arr { - val, err := item.TryBytes() - if err != nil { - return nil, fmt.Errorf("invalid array element #%d: %s", i, item.Type()) - } - pks[i], err = keys.NewPublicKeyFromBytes(val, elliptic.P256()) - if err != nil { - return nil, err - } - } - return pks, nil -} - -// NNSResolve invokes `resolve` method on a NameService contract with the specified hash. -// -// Deprecated: please use nns subpackage. This method will be removed in future versions. -func (c *Client) NNSResolve(nnsHash util.Uint160, name string, typ nns.RecordType) (string, error) { - if typ == nns.CNAME { - return "", errors.New("can't resolve CNAME record type") - } - return unwrap.UTF8String(c.reader.Call(nnsHash, "resolve", name, int64(typ))) -} - -// NNSIsAvailable invokes `isAvailable` method on a NeoNameService contract with the specified hash. -// -// Deprecated: please use nns subpackage. This method will be removed in future versions. -func (c *Client) NNSIsAvailable(nnsHash util.Uint160, name string) (bool, error) { - return unwrap.Bool(c.reader.Call(nnsHash, "isAvailable", name)) -} - -// NNSGetAllRecords returns iterator over records for a given name from NNS service. -// First return value is the session ID, the second one is Iterator itself, the -// third one is an error. Use TraverseIterator method to traverse iterator values or -// TerminateSession to terminate opened iterator session. See TraverseIterator and -// TerminateSession documentation for more details. -// -// Deprecated: please use nns subpackage. This method will be removed in future versions. -func (c *Client) NNSGetAllRecords(nnsHash util.Uint160, name string) (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.reader.Call(nnsHash, "getAllRecords", name)) -} - -// NNSUnpackedGetAllRecords returns a set of records for a given name from NNS service -// (config.DefaultMaxIteratorResultItems at max). It differs from NNSGetAllRecords in -// that no iterator session is used to retrieve values from iterator. Instead, unpacking -// VM script is created and invoked via `invokescript` JSON-RPC call. -// -// Deprecated: please use nns subpackage. This method will be removed in future versions. -func (c *Client) NNSUnpackedGetAllRecords(nnsHash util.Uint160, name string) ([]nns.RecordState, error) { - arr, err := unwrap.Array(c.reader.CallAndExpandIterator(nnsHash, "getAllRecords", config.DefaultMaxIteratorResultItems, name)) - if err != nil { - return nil, err - } - res := make([]nns.RecordState, len(arr)) - for i := range arr { - rs, ok := arr[i].Value().([]stackitem.Item) - if !ok { - return nil, fmt.Errorf("failed to decode RecordState from stackitem #%d: not a struct", i) - } - if len(rs) != 3 { - return nil, fmt.Errorf("failed to decode RecordState from stackitem #%d: wrong number of elements", i) - } - name, err := rs[0].TryBytes() - if err != nil { - return nil, fmt.Errorf("failed to decode RecordState from stackitem #%d: %w", i, err) - } - typ, err := rs[1].TryInteger() - if err != nil { - return nil, fmt.Errorf("failed to decode RecordState from stackitem #%d: %w", i, err) - } - data, err := rs[2].TryBytes() - if err != nil { - return nil, fmt.Errorf("failed to decode RecordState from stackitem #%d: %w", i, err) - } - u64Typ := typ.Uint64() - if !typ.IsUint64() || u64Typ > 255 { - return nil, fmt.Errorf("failed to decode RecordState from stackitem #%d: bad type", i) - } - res[i] = nns.RecordState{ - Name: string(name), - Type: nns.RecordType(u64Typ), - Data: string(data), - } - } - return res, nil -} - -// GetNotaryServiceFeePerKey returns a reward per notary request key for the designated -// notary nodes. It doesn't cache the result. -// -// Deprecated: please use the Notary contract wrapper from the notary subpackage. This -// method will be removed in future versions. -func (c *Client) GetNotaryServiceFeePerKey() (int64, error) { - notaryHash, err := c.GetNativeContractHash(nativenames.Notary) - if err != nil { - return 0, fmt.Errorf("failed to get native Notary hash: %w", err) - } - return c.invokeNativeGetMethod(notaryHash, "getNotaryServiceFeePerKey") -} diff --git a/pkg/rpcclient/nep.go b/pkg/rpcclient/nep.go deleted file mode 100644 index 3fa41a913..000000000 --- a/pkg/rpcclient/nep.go +++ /dev/null @@ -1,60 +0,0 @@ -package rpcclient - -import ( - "fmt" - - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/wallet" -) - -// nepDecimals invokes `decimals` NEP* method on the specified contract. -func (c *Client) nepDecimals(tokenHash util.Uint160) (int64, error) { - return unwrap.Int64(c.reader.Call(tokenHash, "decimals")) -} - -// nepSymbol invokes `symbol` NEP* method on the specified contract. -func (c *Client) nepSymbol(tokenHash util.Uint160) (string, error) { - return unwrap.PrintableASCIIString(c.reader.Call(tokenHash, "symbol")) -} - -// nepTotalSupply invokes `totalSupply` NEP* method on the specified contract. -func (c *Client) nepTotalSupply(tokenHash util.Uint160) (int64, error) { - return unwrap.Int64(c.reader.Call(tokenHash, "totalSupply")) -} - -// nepBalanceOf invokes `balanceOf` NEP* method on the specified contract. -func (c *Client) nepBalanceOf(tokenHash, acc util.Uint160, tokenID []byte) (int64, error) { - params := []any{acc} - if tokenID != nil { - params = append(params, tokenID) - } - return unwrap.Int64(c.reader.Call(tokenHash, "balanceOf", params...)) -} - -// nepTokenInfo returns full NEP* token info. -func (c *Client) nepTokenInfo(tokenHash util.Uint160, standard string) (*wallet.Token, error) { - cs, err := c.GetContractStateByHash(tokenHash) - if err != nil { - return nil, err - } - var isStandardOK bool - for _, st := range cs.Manifest.SupportedStandards { - if st == standard { - isStandardOK = true - break - } - } - if !isStandardOK { - return nil, fmt.Errorf("token %s does not support %s standard", tokenHash.StringLE(), standard) - } - symbol, err := c.nepSymbol(tokenHash) - if err != nil { - return nil, err - } - decimals, err := c.nepDecimals(tokenHash) - if err != nil { - return nil, err - } - return wallet.NewToken(tokenHash, cs.Manifest.Name, symbol, decimals, standard), nil -} diff --git a/pkg/rpcclient/nep11.go b/pkg/rpcclient/nep11.go deleted file mode 100644 index e80999c04..000000000 --- a/pkg/rpcclient/nep11.go +++ /dev/null @@ -1,232 +0,0 @@ -package rpcclient - -import ( - "fmt" - - "github.com/google/uuid" - "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/wallet" -) - -// NEP11Decimals invokes `decimals` NEP-11 method on the specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11Decimals(tokenHash util.Uint160) (int64, error) { - return c.nepDecimals(tokenHash) -} - -// NEP11Symbol invokes `symbol` NEP-11 method on the specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11Symbol(tokenHash util.Uint160) (string, error) { - return c.nepSymbol(tokenHash) -} - -// NEP11TotalSupply invokes `totalSupply` NEP-11 method on the specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11TotalSupply(tokenHash util.Uint160) (int64, error) { - return c.nepTotalSupply(tokenHash) -} - -// NEP11BalanceOf invokes `balanceOf` NEP-11 method on the specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11BalanceOf(tokenHash, owner util.Uint160) (int64, error) { - return c.nepBalanceOf(tokenHash, owner, nil) -} - -// NEP11TokenInfo returns full NEP-11 token info. -// -// Deprecated: please use Info method from the neptoken subpackage. This method -// will be removed in future versions. -func (c *Client) NEP11TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) { - return c.nepTokenInfo(tokenHash, manifest.NEP11StandardName) -} - -// TransferNEP11 creates an invocation transaction that invokes 'transfer' method -// on the given token to move the whole NEP-11 token with the specified token ID to -// the given account and sends it to the network returning just a hash of it. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) TransferNEP11(acc *wallet.Account, to util.Uint160, - tokenHash util.Uint160, tokenID string, data any, gas int64, cosigners []SignerAccount) (util.Uint256, error) { - tx, err := c.CreateNEP11TransferTx(acc, tokenHash, gas, cosigners, to, tokenID, data) - if err != nil { - return util.Uint256{}, err - } - - return c.SignAndPushTx(tx, acc, cosigners) -} - -// CreateNEP11TransferTx creates an invocation transaction for the 'transfer' -// method of the given contract (token) to move the whole (or the specified amount -// of) NEP-11 token with the specified token ID to the given account and returns it. -// The returned transaction is not signed. CreateNEP11TransferTx is also a -// helper for TransferNEP11 and TransferNEP11D. -// `args` for TransferNEP11: to util.Uint160, tokenID string, data interface{}; -// `args` for TransferNEP11D: from, to util.Uint160, amount int64, tokenID string, data interface{}. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) CreateNEP11TransferTx(acc *wallet.Account, tokenHash util.Uint160, - gas int64, cosigners []SignerAccount, args ...any) (*transaction.Transaction, error) { - script, err := smartcontract.CreateCallWithAssertScript(tokenHash, "transfer", args...) - if err != nil { - return nil, fmt.Errorf("failed to create NEP-11 transfer script: %w", err) - } - return c.CreateTxFromScript(script, acc, -1, gas, append([]SignerAccount{{ - Signer: transaction.Signer{ - Account: acc.ScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc, - }}, cosigners...)) -} - -// NEP11TokensOf returns iterator over token IDs for the specified owner of the -// specified NFT token. First return value is the session ID, the second one is -// Iterator itself, the third one is an error. Use TraverseIterator method to -// traverse iterator values or TerminateSession to terminate opened iterator -// session. See TraverseIterator and TerminateSession documentation for more details. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11TokensOf(tokenHash util.Uint160, owner util.Uint160) (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.reader.Call(tokenHash, "tokensOf", owner)) -} - -// NEP11UnpackedTokensOf returns an array of token IDs for the specified owner of the specified NFT token -// (config.DefaultMaxIteratorResultItems at max). It differs from NEP11TokensOf in that no iterator session -// is used to retrieve values from iterator. Instead, unpacking VM script is created and invoked via -// `invokescript` JSON-RPC call. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11UnpackedTokensOf(tokenHash util.Uint160, owner util.Uint160) ([][]byte, error) { - return unwrap.ArrayOfBytes(c.reader.CallAndExpandIterator(tokenHash, "tokensOf", config.DefaultMaxIteratorResultItems, owner)) -} - -// Non-divisible NFT methods section start. - -// NEP11NDOwnerOf invokes `ownerOf` non-divisible NEP-11 method with the -// specified token ID on the specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11NDOwnerOf(tokenHash util.Uint160, tokenID []byte) (util.Uint160, error) { - return unwrap.Uint160(c.reader.Call(tokenHash, "ownerOf", tokenID)) -} - -// Non-divisible NFT methods section end. - -// Divisible NFT methods section start. - -// TransferNEP11D creates an invocation transaction that invokes 'transfer' -// method on the given token to move the specified amount of divisible NEP-11 assets -// (in FixedN format using contract's number of decimals) to the given account and -// sends it to the network returning just a hash of it. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) TransferNEP11D(acc *wallet.Account, to util.Uint160, - tokenHash util.Uint160, amount int64, tokenID []byte, data any, gas int64, cosigners []SignerAccount) (util.Uint256, error) { - tx, err := c.CreateNEP11TransferTx(acc, tokenHash, gas, cosigners, acc.ScriptHash(), to, amount, tokenID, data) - if err != nil { - return util.Uint256{}, err - } - - return c.SignAndPushTx(tx, acc, cosigners) -} - -// NEP11DBalanceOf invokes `balanceOf` divisible NEP-11 method on a -// specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11DBalanceOf(tokenHash, owner util.Uint160, tokenID []byte) (int64, error) { - return c.nepBalanceOf(tokenHash, owner, tokenID) -} - -// NEP11DOwnerOf returns iterator over the specified NEP-11 divisible token owners. First return value -// is the session ID, the second one is Iterator itself, the third one is an error. Use TraverseIterator -// method to traverse iterator values or TerminateSession to terminate opened iterator session. See -// TraverseIterator and TerminateSession documentation for more details. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11DOwnerOf(tokenHash util.Uint160, tokenID []byte) (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.reader.Call(tokenHash, "ownerOf", tokenID)) -} - -// NEP11DUnpackedOwnerOf returns list of the specified NEP-11 divisible token owners -// (config.DefaultMaxIteratorResultItems at max). It differs from NEP11DOwnerOf in that no -// iterator session is used to retrieve values from iterator. Instead, unpacking VM -// script is created and invoked via `invokescript` JSON-RPC call. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11DUnpackedOwnerOf(tokenHash util.Uint160, tokenID []byte) ([]util.Uint160, error) { - arr, err := unwrap.ArrayOfBytes(c.reader.CallAndExpandIterator(tokenHash, "ownerOf", config.DefaultMaxIteratorResultItems, tokenID)) - if err != nil { - return nil, err - } - owners := make([]util.Uint160, len(arr)) - for i := range arr { - owners[i], err = util.Uint160DecodeBytesBE(arr[i]) - if err != nil { - return nil, fmt.Errorf("not a Uint160 at %d: %w", i, err) - } - } - return owners, nil -} - -// Divisible NFT methods section end. - -// Optional NFT methods section start. - -// NEP11Properties invokes `properties` optional NEP-11 method on the -// specified contract. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11Properties(tokenHash util.Uint160, tokenID []byte) (*stackitem.Map, error) { - return unwrap.Map(c.reader.Call(tokenHash, "properties", tokenID)) -} - -// NEP11Tokens returns iterator over the tokens minted by the contract. First return -// value is the session ID, the second one is Iterator itself, the third one is an -// error. Use TraverseIterator method to traverse iterator values or -// TerminateSession to terminate opened iterator session. See TraverseIterator and -// TerminateSession documentation for more details. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11Tokens(tokenHash util.Uint160) (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.reader.Call(tokenHash, "tokens")) -} - -// NEP11UnpackedTokens returns list of the tokens minted by the contract -// (config.DefaultMaxIteratorResultItems at max). It differs from NEP11Tokens in that no -// iterator session is used to retrieve values from iterator. Instead, unpacking -// VM script is created and invoked via `invokescript` JSON-RPC call. -// -// Deprecated: please use nep11 package, this method will be removed in future -// versions. -func (c *Client) NEP11UnpackedTokens(tokenHash util.Uint160) ([][]byte, error) { - return unwrap.ArrayOfBytes(c.reader.CallAndExpandIterator(tokenHash, "tokens", config.DefaultMaxIteratorResultItems)) -} - -// Optional NFT methods section end. diff --git a/pkg/rpcclient/nep17.go b/pkg/rpcclient/nep17.go deleted file mode 100644 index ea2c5c894..000000000 --- a/pkg/rpcclient/nep17.go +++ /dev/null @@ -1,188 +0,0 @@ -package rpcclient - -import ( - "fmt" - - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/wallet" -) - -// TransferTarget represents target address, token amount and data for transfer. -type TransferTarget struct { - Token util.Uint160 - Address util.Uint160 - Amount int64 - Data any -} - -// SignerAccount represents combination of the transaction.Signer and the -// corresponding wallet.Account. -type SignerAccount struct { - Signer transaction.Signer - Account *wallet.Account -} - -// NEP17Decimals invokes `decimals` NEP-17 method on the specified contract. -// -// Deprecated: please use nep17 package, this method will be removed in future -// versions. -func (c *Client) NEP17Decimals(tokenHash util.Uint160) (int64, error) { - return c.nepDecimals(tokenHash) -} - -// NEP17Symbol invokes `symbol` NEP-17 method on the specified contract. -// -// Deprecated: please use nep17 package, this method will be removed in future -// versions. -func (c *Client) NEP17Symbol(tokenHash util.Uint160) (string, error) { - return c.nepSymbol(tokenHash) -} - -// NEP17TotalSupply invokes `totalSupply` NEP-17 method on the specified contract. -// -// Deprecated: please use nep17 package, this method will be removed in future -// versions. This method is also wrong since tokens can return values overflowing -// int64. -func (c *Client) NEP17TotalSupply(tokenHash util.Uint160) (int64, error) { - return c.nepTotalSupply(tokenHash) -} - -// NEP17BalanceOf invokes `balanceOf` NEP-17 method on the specified contract. -// -// Deprecated: please use nep17 package, this method will be removed in future -// versions. This method is also wrong since tokens can return values overflowing -// int64. -func (c *Client) NEP17BalanceOf(tokenHash, acc util.Uint160) (int64, error) { - return c.nepBalanceOf(tokenHash, acc, nil) -} - -// NEP17TokenInfo returns full NEP-17 token info. -// -// Deprecated: please use Info method from the neptoken subpackage. This method -// will be removed in future versions. -func (c *Client) NEP17TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) { - return c.nepTokenInfo(tokenHash, manifest.NEP17StandardName) -} - -// CreateNEP17TransferTx creates an invocation transaction for the 'transfer' -// method of the given contract (token) to move the specified amount of NEP-17 assets -// (in FixedN format using contract's number of decimals) to the given account and -// returns it. The returned transaction is not signed. -// -// Deprecated: please use nep17 package, this method will be removed in future -// versions. -func (c *Client) CreateNEP17TransferTx(acc *wallet.Account, to util.Uint160, - token util.Uint160, amount int64, gas int64, data any, cosigners []SignerAccount) (*transaction.Transaction, error) { - return c.CreateNEP17MultiTransferTx(acc, gas, []TransferTarget{ - {Token: token, - Address: to, - Amount: amount, - Data: data, - }, - }, cosigners) -} - -// CreateNEP17MultiTransferTx creates an invocation transaction for performing -// NEP-17 transfers from a single sender to multiple recipients with the given -// data and cosigners. The transaction sender is included with the CalledByEntry -// scope by default. -// -// Deprecated: please use nep17 package (when transferring the same token) or -// [smartcontract.Builder] (when transferring multiple tokens), this method will -// be removed in future versions. -func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, - recipients []TransferTarget, cosigners []SignerAccount) (*transaction.Transaction, error) { - from := acc.ScriptHash() - b := smartcontract.NewBuilder() - for i := range recipients { - b.InvokeWithAssert(recipients[i].Token, "transfer", - from, recipients[i].Address, recipients[i].Amount, recipients[i].Data) - } - script, err := b.Script() - if err != nil { - return nil, fmt.Errorf("failed to create transfer script: %w", err) - } - return c.CreateTxFromScript(script, acc, -1, gas, append([]SignerAccount{{ - Signer: transaction.Signer{ - Account: from, - Scopes: transaction.CalledByEntry, - }, - Account: acc, - }}, cosigners...)) -} - -// CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee. -// If sysFee <= 0, it is determined via result of `invokescript` RPC. You should -// initialize network magic with Init before calling CreateTxFromScript. -// -// Deprecated: please use actor.Actor API, this method will be removed in future -// versions. -func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, netFee int64, - cosigners []SignerAccount) (*transaction.Transaction, error) { - signers, accounts, err := getSigners(acc, cosigners) - if err != nil { - return nil, fmt.Errorf("failed to construct tx signers: %w", err) - } - if sysFee < 0 { - result, err := c.InvokeScript(script, signers) - if err != nil { - return nil, fmt.Errorf("can't add system fee to transaction: %w", err) - } - if result.State != "HALT" { - return nil, fmt.Errorf("can't add system fee to transaction: bad vm state: %s due to an error: %s", result.State, result.FaultException) - } - sysFee = result.GasConsumed - } - - tx := transaction.New(script, sysFee) - tx.Signers = signers - - tx.ValidUntilBlock, err = c.CalculateValidUntilBlock() - if err != nil { - return nil, fmt.Errorf("failed to add validUntilBlock to transaction: %w", err) - } - - err = c.AddNetworkFee(tx, netFee, accounts...) - if err != nil { - return nil, fmt.Errorf("failed to add network fee: %w", err) - } - - return tx, nil -} - -// TransferNEP17 creates an invocation transaction that invokes 'transfer' method -// on the given token to move the specified amount of NEP-17 assets (in FixedN format -// using contract's number of decimals) to the given account with the data specified and -// sends it to the network returning just a hash of it. Cosigners argument -// specifies a set of the transaction cosigners (may be nil or may include sender) -// with a proper scope and the accounts to cosign the transaction. If cosigning is -// impossible (e.g. due to locked cosigner's account) an error is returned. -// -// Deprecated: please use nep17 package, this method will be removed in future -// versions. -func (c *Client) TransferNEP17(acc *wallet.Account, to util.Uint160, token util.Uint160, - amount int64, gas int64, data any, cosigners []SignerAccount) (util.Uint256, error) { - tx, err := c.CreateNEP17TransferTx(acc, to, token, amount, gas, data, cosigners) - if err != nil { - return util.Uint256{}, err - } - - return c.SignAndPushTx(tx, acc, cosigners) -} - -// MultiTransferNEP17 is similar to TransferNEP17, buf allows to have multiple recipients. -// -// Deprecated: please use nep17 package (when transferring the same token) or -// [smartcontract.Builder] (when transferring multiple tokens), this method will -// be removed in future versions. -func (c *Client) MultiTransferNEP17(acc *wallet.Account, gas int64, recipients []TransferTarget, cosigners []SignerAccount) (util.Uint256, error) { - tx, err := c.CreateNEP17MultiTransferTx(acc, gas, recipients, cosigners) - if err != nil { - return util.Uint256{}, err - } - - return c.SignAndPushTx(tx, acc, cosigners) -} diff --git a/pkg/rpcclient/policy.go b/pkg/rpcclient/policy.go deleted file mode 100644 index 4d45ffb09..000000000 --- a/pkg/rpcclient/policy.go +++ /dev/null @@ -1,66 +0,0 @@ -package rpcclient - -import ( - "fmt" - - "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// GetFeePerByte invokes `getFeePerByte` method on a native Policy contract. -// -// Deprecated: please use policy subpackage. -func (c *Client) GetFeePerByte() (int64, error) { - return c.invokeNativePolicyMethod("getFeePerByte") -} - -// GetExecFeeFactor invokes `getExecFeeFactor` method on a native Policy contract. -// -// Deprecated: please use policy subpackage. -func (c *Client) GetExecFeeFactor() (int64, error) { - return c.invokeNativePolicyMethod("getExecFeeFactor") -} - -// GetStoragePrice invokes `getStoragePrice` method on a native Policy contract. -// -// Deprecated: please use policy subpackage. -func (c *Client) GetStoragePrice() (int64, error) { - return c.invokeNativePolicyMethod("getStoragePrice") -} - -// GetMaxNotValidBeforeDelta invokes `getMaxNotValidBeforeDelta` method on a native Notary contract. -// -// Deprecated: please use notary subpackage. This method will be removed -// in future versions. -func (c *Client) GetMaxNotValidBeforeDelta() (int64, error) { - notaryHash, err := c.GetNativeContractHash(nativenames.Notary) - if err != nil { - return 0, fmt.Errorf("failed to get native Notary hash: %w", err) - } - return c.invokeNativeGetMethod(notaryHash, "getMaxNotValidBeforeDelta") -} - -// invokeNativePolicy method invokes Get* method on a native Policy contract. -func (c *Client) invokeNativePolicyMethod(operation string) (int64, error) { - policyHash, err := c.GetNativeContractHash(nativenames.Policy) - if err != nil { - return 0, fmt.Errorf("failed to get native Policy hash: %w", err) - } - return c.invokeNativeGetMethod(policyHash, operation) -} - -func (c *Client) invokeNativeGetMethod(hash util.Uint160, operation string) (int64, error) { - return unwrap.Int64(c.reader.Call(hash, operation)) -} - -// IsBlocked invokes `isBlocked` method on native Policy contract. -// -// Deprecated: please use policy subpackage. -func (c *Client) IsBlocked(hash util.Uint160) (bool, error) { - policyHash, err := c.GetNativeContractHash(nativenames.Policy) - if err != nil { - return false, fmt.Errorf("failed to get native Policy hash: %w", err) - } - return unwrap.Bool(c.reader.Call(policyHash, "isBlocked", hash)) -} diff --git a/pkg/rpcclient/rpc.go b/pkg/rpcclient/rpc.go index c6a66df38..fe6abc154 100644 --- a/pkg/rpcclient/rpc.go +++ b/pkg/rpcclient/rpc.go @@ -9,27 +9,19 @@ import ( "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" - "github.com/nspcc-dev/neo-go/pkg/core/fee" - "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" - "github.com/nspcc-dev/neo-go/pkg/core/native/nativeprices" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neorpc" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/network/payload" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/wallet" ) var errNetworkNotInitialized = errors.New("RPC client network is not initialized") @@ -103,7 +95,7 @@ func (c *Client) getBlock(param any) (*block.Block, error) { return nil, err } r := io.NewBinReaderFromBuf(resp) - sr, err := c.StateRootInHeader() + sr, err := c.stateRootInHeader() if err != nil { return nil, err } @@ -136,7 +128,7 @@ func (c *Client) getBlockVerbose(param any) (*result.Block, error) { resp = &result.Block{} err error ) - sr, err := c.StateRootInHeader() + sr, err := c.stateRootInHeader() if err != nil { return nil, err } @@ -171,7 +163,7 @@ func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) { if err := c.performRequest("getblockheader", params, &resp); err != nil { return nil, err } - sr, err := c.StateRootInHeader() + sr, err := c.stateRootInHeader() if err != nil { return nil, err } @@ -844,234 +836,6 @@ func (c *Client) SubmitRawOracleResponse(ps []any) error { return c.performRequest("submitoracleresponse", ps, new(result.RelayResult)) } -// SignAndPushInvocationTx signs and pushes the given script as an invocation -// transaction using the given wif to sign it and the given cosigners to cosign it if -// possible. It spends the amount of gas specified. It returns a hash of the -// invocation transaction and an error. If one of the cosigners accounts is -// neither contract-based nor unlocked, an error is returned. -// -// Deprecated: please use actor.Actor API, this method will be removed in future -// versions. -func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee fixedn.Fixed8, cosigners []SignerAccount) (util.Uint256, error) { - tx, err := c.CreateTxFromScript(script, acc, sysfee, int64(netfee), cosigners) - if err != nil { - return util.Uint256{}, fmt.Errorf("failed to create tx: %w", err) - } - return c.SignAndPushTx(tx, acc, cosigners) -} - -// SignAndPushTx signs the given transaction using the given wif and cosigners and pushes -// it to the chain. It returns a hash of the transaction and an error. If one of -// the cosigners accounts is neither contract-based nor unlocked, an error is -// returned. -// -// Deprecated: please use actor.Actor API, this method will be removed in future -// versions. -func (c *Client) SignAndPushTx(tx *transaction.Transaction, acc *wallet.Account, cosigners []SignerAccount) (util.Uint256, error) { - var ( - txHash util.Uint256 - err error - ) - m, err := c.GetNetwork() - if err != nil { - return txHash, fmt.Errorf("failed to sign tx: %w", err) - } - if err = acc.SignTx(m, tx); err != nil { - return txHash, fmt.Errorf("failed to sign tx: %w", err) - } - // try to add witnesses for the rest of the signers - for i, signer := range tx.Signers[1:] { - var isOk bool - for _, cosigner := range cosigners { - if signer.Account == cosigner.Signer.Account { - err = cosigner.Account.SignTx(m, tx) - if err != nil { // then account is non-contract-based and locked, but let's provide more detailed error - if paramNum := len(cosigner.Account.Contract.Parameters); paramNum != 0 && cosigner.Account.Contract.Deployed { - return txHash, fmt.Errorf("failed to add contract-based witness for signer #%d (%s): "+ - "%d parameters must be provided to construct invocation script", i, address.Uint160ToString(signer.Account), paramNum) - } - return txHash, fmt.Errorf("failed to add witness for signer #%d (%s): account should be unlocked to add the signature. "+ - "Store partially-signed transaction and then use 'wallet sign' command to cosign it", i, address.Uint160ToString(signer.Account)) - } - isOk = true - break - } - } - if !isOk { - return txHash, fmt.Errorf("failed to add witness for signer #%d (%s): account wasn't provided", i, address.Uint160ToString(signer.Account)) - } - } - txHash = tx.Hash() - actualHash, err := c.SendRawTransaction(tx) - if err != nil { - return txHash, fmt.Errorf("failed to send tx: %w", err) - } - if !actualHash.Equals(txHash) { - return actualHash, fmt.Errorf("sent and actual tx hashes mismatch:\n\tsent: %v\n\tactual: %v", txHash.StringLE(), actualHash.StringLE()) - } - return txHash, nil -} - -// getSigners returns an array of transaction signers and corresponding accounts from -// given sender and cosigners. If cosigners list already contains sender, the sender -// will be placed at the start of the list. -func getSigners(sender *wallet.Account, cosigners []SignerAccount) ([]transaction.Signer, []*wallet.Account, error) { - var ( - signers []transaction.Signer - accounts []*wallet.Account - ) - from := sender.ScriptHash() - s := transaction.Signer{ - Account: from, - Scopes: transaction.None, - } - for _, c := range cosigners { - if c.Signer.Account == from { - s = c.Signer - continue - } - signers = append(signers, c.Signer) - accounts = append(accounts, c.Account) - } - signers = append([]transaction.Signer{s}, signers...) - accounts = append([]*wallet.Account{sender}, accounts...) - return signers, accounts, nil -} - -// SignAndPushP2PNotaryRequest creates and pushes a P2PNotary request constructed from the main -// and fallback transactions using the given wif to sign it. It returns the request and an error. -// Fallback transaction is constructed from the given script using the amount of gas specified. -// For successful fallback transaction validation at least 2*transaction.NotaryServiceFeePerKey -// GAS should be deposited to the Notary contract. -// Main transaction should be constructed by the user. Several rules should be met for -// successful main transaction acceptance: -// 1. Native Notary contract should be a signer of the main transaction. -// 2. Notary signer should have None scope. -// 3. Main transaction should have dummy contract witness for Notary signer. -// 4. Main transaction should have NotaryAssisted attribute with NKeys specified. -// 5. NotaryAssisted attribute and dummy Notary witness (as long as the other incomplete witnesses) -// should be paid for. Use CalculateNotaryWitness to calculate the amount of network fee to pay -// for the attribute and Notary witness. -// 6. Main transaction either shouldn't have all witnesses attached (in this case none of them -// can be multisignature), or it only should have a partial multisignature. -// -// Note: client should be initialized before SignAndPushP2PNotaryRequest call. -// -// Deprecated: please use Actor from the notary subpackage. This method will be -// deleted in future versions. -func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fallbackScript []byte, fallbackSysFee int64, fallbackNetFee int64, fallbackValidFor uint32, acc *wallet.Account) (*payload.P2PNotaryRequest, error) { - var err error - notaryHash, err := c.GetNativeContractHash(nativenames.Notary) - if err != nil { - return nil, fmt.Errorf("failed to get native Notary hash: %w", err) - } - from := acc.ScriptHash() - signers := []transaction.Signer{{Account: notaryHash}, {Account: from}} - if fallbackSysFee < 0 { - result, err := c.InvokeScript(fallbackScript, signers) - if err != nil { - return nil, fmt.Errorf("can't add system fee to fallback transaction: %w", err) - } - if result.State != "HALT" { - return nil, fmt.Errorf("can't add system fee to fallback transaction: bad vm state %s due to an error: %s", result.State, result.FaultException) - } - fallbackSysFee = result.GasConsumed - } - - maxNVBDelta, err := c.GetMaxNotValidBeforeDelta() - if err != nil { - return nil, fmt.Errorf("failed to get MaxNotValidBeforeDelta") - } - if int64(fallbackValidFor) > maxNVBDelta { - return nil, fmt.Errorf("fallback transaction should be valid for not more than %d blocks", maxNVBDelta) - } - fallbackTx := transaction.New(fallbackScript, fallbackSysFee) - fallbackTx.Signers = signers - fallbackTx.ValidUntilBlock = mainTx.ValidUntilBlock - fallbackTx.Attributes = []transaction.Attribute{ - { - Type: transaction.NotaryAssistedT, - Value: &transaction.NotaryAssisted{NKeys: 0}, - }, - { - Type: transaction.NotValidBeforeT, - Value: &transaction.NotValidBefore{Height: fallbackTx.ValidUntilBlock - fallbackValidFor + 1}, - }, - { - Type: transaction.ConflictsT, - Value: &transaction.Conflicts{Hash: mainTx.Hash()}, - }, - } - - fallbackTx.Scripts = []transaction.Witness{ - { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), keys.SignatureLen}, make([]byte, keys.SignatureLen)...), - VerificationScript: []byte{}, - }, - { - InvocationScript: []byte{}, - VerificationScript: acc.GetVerificationScript(), - }, - } - fallbackTx.NetworkFee, err = c.CalculateNetworkFee(fallbackTx) - if err != nil { - return nil, fmt.Errorf("failed to add network fee: %w", err) - } - fallbackTx.NetworkFee += fallbackNetFee - m, err := c.GetNetwork() - if err != nil { - return nil, fmt.Errorf("failed to sign fallback tx: %w", err) - } - if err = acc.SignTx(m, fallbackTx); err != nil { - return nil, fmt.Errorf("failed to sign fallback tx: %w", err) - } - fallbackHash := fallbackTx.Hash() - req := &payload.P2PNotaryRequest{ - MainTransaction: mainTx, - FallbackTransaction: fallbackTx, - } - req.Witness = transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), keys.SignatureLen}, acc.SignHashable(m, req)...), - VerificationScript: acc.GetVerificationScript(), - } - actualHash, err := c.SubmitP2PNotaryRequest(req) - if err != nil { - return req, fmt.Errorf("failed to submit notary request: %w", err) - } - if !actualHash.Equals(fallbackHash) { - return req, fmt.Errorf("sent and actual fallback tx hashes mismatch:\n\tsent: %v\n\tactual: %v", fallbackHash.StringLE(), actualHash.StringLE()) - } - return req, nil -} - -// CalculateNotaryFee calculates network fee for one dummy Notary witness and NotaryAssisted attribute with NKeys specified. -// The result should be added to the transaction's net fee for successful verification. -// -// Deprecated: NeoGo calculatenetworkfee method handles notary fees as well since 0.99.3, so -// this method is just no longer needed and will be removed in future versions. -func (c *Client) CalculateNotaryFee(nKeys uint8) (int64, error) { - baseExecFee, err := c.GetExecFeeFactor() - if err != nil { - return 0, fmt.Errorf("failed to get BaseExecFeeFactor: %w", err) - } - feePerByte, err := c.GetFeePerByte() - if err != nil { - return 0, fmt.Errorf("failed to get FeePerByte: %w", err) - } - feePerKey, err := c.GetNotaryServiceFeePerKey() - if err != nil { - return 0, fmt.Errorf("failed to get NotaryServiceFeePerKey: %w", err) - } - return int64((nKeys+1))*feePerKey + // fee for NotaryAssisted attribute - fee.Opcode(baseExecFee, // Notary node witness - opcode.PUSHDATA1, opcode.RET, // invocation script - opcode.PUSH0, opcode.SYSCALL, opcode.RET) + // System.Contract.CallNative - nativeprices.NotaryVerificationPrice*baseExecFee + // Notary witness verification price - feePerByte*int64(io.GetVarSize(make([]byte, 66))) + // invocation script per-byte fee - feePerByte*int64(io.GetVarSize([]byte{})), // verification script per-byte fee - nil -} - // SubmitP2PNotaryRequest submits given P2PNotaryRequest payload to the RPC node. func (c *Client) SubmitP2PNotaryRequest(req *payload.P2PNotaryRequest) (util.Uint256, error) { var resp = new(result.RelayResult) @@ -1103,113 +867,9 @@ func (c *Client) ValidateAddress(address string) error { return nil } -// CalculateValidUntilBlock calculates ValidUntilBlock field for tx as -// current blockchain height + number of validators. Number of validators -// is the length of blockchain validators list got from GetNextBlockValidators() -// method. Validators count is being cached and updated every 100 blocks. -// -// Deprecated: please use (*Actor).CalculateValidUntilBlock. This method will be -// removed in future versions. -func (c *Client) CalculateValidUntilBlock() (uint32, error) { - var ( - result uint32 - validatorsCount uint32 - ) - blockCount, err := c.GetBlockCount() - if err != nil { - return result, fmt.Errorf("can't get block count: %w", err) - } - - c.cacheLock.RLock() - if c.cache.calculateValidUntilBlock.expiresAt > blockCount { - validatorsCount = c.cache.calculateValidUntilBlock.validatorsCount - c.cacheLock.RUnlock() - } else { - c.cacheLock.RUnlock() - validators, err := c.GetNextBlockValidators() - if err != nil { - return result, fmt.Errorf("can't get validators: %w", err) - } - validatorsCount = uint32(len(validators)) - c.cacheLock.Lock() - c.cache.calculateValidUntilBlock = calculateValidUntilBlockCache{ - validatorsCount: validatorsCount, - expiresAt: blockCount + cacheTimeout, - } - c.cacheLock.Unlock() - } - return blockCount + validatorsCount + 1, nil -} - -// AddNetworkFee adds network fee for each witness script and optional extra -// network fee to transaction. `accs` is an array signer's accounts. -// -// Deprecated: please use CalculateNetworkFee or actor.Actor. This method will -// be removed in future versions. -func (c *Client) AddNetworkFee(tx *transaction.Transaction, extraFee int64, accs ...*wallet.Account) error { - if len(tx.Signers) != len(accs) { - return errors.New("number of signers must match number of scripts") - } - size := io.GetVarSize(tx) - var ef int64 - for i, cosigner := range tx.Signers { - if accs[i].Contract.Deployed { - res, err := c.InvokeContractVerify(cosigner.Account, []smartcontract.Parameter{}, tx.Signers) - if err != nil { - return fmt.Errorf("failed to invoke verify: %w", err) - } - r, err := unwrap.Bool(res, err) - if err != nil { - return fmt.Errorf("signer #%d: %w", i, err) - } - if !r { - return fmt.Errorf("signer #%d: `verify` returned `false`", i) - } - tx.NetworkFee += res.GasConsumed - size += io.GetVarSize([]byte{}) * 2 // both scripts are empty - continue - } - - if ef == 0 { - var err error - ef, err = c.GetExecFeeFactor() - if err != nil { - return fmt.Errorf("can't get `ExecFeeFactor`: %w", err) - } - } - netFee, sizeDelta := fee.Calculate(ef, accs[i].Contract.Script) - tx.NetworkFee += netFee - size += sizeDelta - } - fee, err := c.GetFeePerByte() - if err != nil { - return err - } - tx.NetworkFee += int64(size)*fee + extraFee - return nil -} - -// GetNetwork returns the network magic of the RPC node the client connected to. It -// requires Init to be done first, otherwise an error is returned. -// -// Deprecated: please use GetVersion (it has the same data in the Protocol section) -// or actor subpackage. This method will be removed in future versions. -func (c *Client) GetNetwork() (netmode.Magic, error) { - c.cacheLock.RLock() - defer c.cacheLock.RUnlock() - - if !c.cache.initDone { - return 0, errNetworkNotInitialized - } - return c.cache.network, nil -} - -// StateRootInHeader returns true if the state root is contained in the block header. -// You should initialize Client cache with Init() before calling StateRootInHeader. -// -// Deprecated: please use GetVersion (it has the same data in the Protocol section). -// This method will be removed in future versions. -func (c *Client) StateRootInHeader() (bool, error) { +// stateRootInHeader returns true if the state root is contained in the block header. +// Requires Init() before use. +func (c *Client) stateRootInHeader() (bool, error) { c.cacheLock.RLock() defer c.cacheLock.RUnlock() @@ -1219,29 +879,6 @@ func (c *Client) StateRootInHeader() (bool, error) { return c.cache.stateRootInHeader, nil } -// GetNativeContractHash returns native contract hash by its name. -// -// Deprecated: please use native contract subpackages that have hashes directly -// (gas, management, neo, notary, oracle, policy, rolemgmt) or -// GetContractStateByAddressOrName method that will return hash along with other -// data. -func (c *Client) GetNativeContractHash(name string) (util.Uint160, error) { - c.cacheLock.RLock() - hash, ok := c.cache.nativeHashes[name] - c.cacheLock.RUnlock() - if ok { - return hash, nil - } - cs, err := c.GetContractStateByAddressOrName(name) - if err != nil { - return util.Uint160{}, err - } - c.cacheLock.Lock() - c.cache.nativeHashes[name] = cs.Hash - c.cacheLock.Unlock() - return cs.Hash, nil -} - // TraverseIterator returns a set of iterator values (maxItemsCount at max) for // the specified iterator and session. If result contains no elements, then either // Iterator has no elements or session was expired and terminated by the server. diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index 0c0b51a23..da9139d09 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -2,7 +2,6 @@ package rpcclient import ( "context" - "crypto/elliptic" "encoding/base64" "encoding/hex" "encoding/json" @@ -18,7 +17,6 @@ import ( "github.com/nspcc-dev/neo-go/internal/testserdes" "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" - "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -403,136 +401,6 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, }, }, - "getFeePerByte": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetFeePerByte() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"1000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(1000) - }, - }, - }, - "getExecFeeFactor": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetExecFeeFactor() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"1000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(1000) - }, - }, - }, - "getStoragePrice": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetStoragePrice() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"100000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(100000) - }, - }, - }, - "getOraclePrice": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetOraclePrice() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"10000000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(10000000) - }, - }, - }, - "getNNSPrice": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetNNSPrice(util.Uint160{1, 2, 3}) - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"1000000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(1000000) - }, - }, - }, - "getGasPerBlock": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetGasPerBlock() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"500000000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(500000000) - }, - }, - }, - "getCandidateRegisterPrice": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetCandidateRegisterPrice() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMDWdldEZlZVBlckJ5dGUMFJphpG7sl7iTBtfOgfFbRiCR0AkyQWJ9W1I=","stack":[{"type":"Integer","value":"100000000000"}],"tx":null}}`, - result: func(c *Client) any { - return int64(100000000000) - }, - }, - }, - "getDesignatedByRole": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetDesignatedByRole(noderoles.P2PNotary, 10) - }, - serverResponse: `{"id" : 1,"result" : {"stack" : [{"value" : [{"type":"ByteString","value":"Aw0WkQoDc8WqpG18xPMTEgfHO6gRTVtMN0Mw6zw06fzl"},{"type":"ByteString","value":"A+bmJ9wIaj96Ygr+uQQvQ0AaUrQmj2b3AGnztAOkU3/L"}],"type" : "Array"}],"exception" : null,"script" : "ERQSwB8ME2dldERlc2lnbmF0ZWRCeVJvbGUMFOKV45FUTBeK2U8D7E3N/3hTTs9JQWJ9W1I=","gasconsumed" : "2028150","state" : "HALT"}, "jsonrpc" : "2.0"}`, - result: func(c *Client) any { - pk1Bytes, _ := base64.StdEncoding.DecodeString("Aw0WkQoDc8WqpG18xPMTEgfHO6gRTVtMN0Mw6zw06fzl") - pk1, err := keys.NewPublicKeyFromBytes(pk1Bytes, elliptic.P256()) - if err != nil { - panic("invalid pub key #1 bytes") - } - pk2Bytes, _ := base64.StdEncoding.DecodeString("A+bmJ9wIaj96Ygr+uQQvQ0AaUrQmj2b3AGnztAOkU3/L") - pk2, err := keys.NewPublicKeyFromBytes(pk2Bytes, elliptic.P256()) - if err != nil { - panic("invalid pub key #2 bytes") - } - return keys.PublicKeys{pk1, pk2} - }, - }, - }, - "getMaxNotValidBeforeDelta": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.GetMaxNotValidBeforeDelta() - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMD2dldE1heEJsb2NrU2l6ZQwUmmGkbuyXuJMG186B8VtGIJHQCTJBYn1bUg==","stack":[{"type":"Integer","value":"262144"}],"tx":null}}`, - result: func(c *Client) any { - return int64(262144) - }, - }, - }, - "isBlocked": { - { - name: "positive", - invoke: func(c *Client) (any, error) { - return c.IsBlocked(util.Uint160{1, 2, 3}) - }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"state":"HALT","gasconsumed":"2007390","script":"EMAMEmdldEJsb2NrZWRBY2NvdW50cwwUmmGkbuyXuJMG186B8VtGIJHQCTJBYn1bUg==","stack":[{"type":"Boolean","value":false}],"tx":null}}`, - result: func(c *Client) any { - return false - }, - }, - }, "getnep11balances": { { name: "positive", @@ -2138,92 +2006,6 @@ func wrapInitResponse(r *params.In, resp string) string { return response } -func TestCalculateValidUntilBlock(t *testing.T) { - var ( - getBlockCountCalled int - getValidatorsCalled int - ) - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - r := params.NewRequest() - err := r.DecodeData(req.Body) - if err != nil { - t.Fatalf("Cannot decode request body: %s", req.Body) - } - var response string - switch r.In.Method { - case "getblockcount": - getBlockCountCalled++ - response = `{"jsonrpc":"2.0","id":1,"result":50}` - case "getnextblockvalidators": - getValidatorsCalled++ - response = `{"id":1,"jsonrpc":"2.0","result":[{"publickey":"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2","votes":"0","active":true},{"publickey":"02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e","votes":"0","active":true},{"publickey":"03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699","votes":"0","active":true},{"publickey":"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62","votes":"0","active":true}]}` - } - requestHandler(t, r.In, w, response) - })) - t.Cleanup(srv.Close) - - endpoint := srv.URL - opts := Options{} - c, err := New(context.TODO(), endpoint, opts) - if err != nil { - t.Fatal(err) - } - c.getNextRequestID = getTestRequestID - require.NoError(t, c.Init()) - - validUntilBlock, err := c.CalculateValidUntilBlock() - assert.NoError(t, err) - assert.Equal(t, uint32(55), validUntilBlock) - assert.Equal(t, 1, getBlockCountCalled) - assert.Equal(t, 1, getValidatorsCalled) - - // check, whether caching is working - validUntilBlock, err = c.CalculateValidUntilBlock() - assert.NoError(t, err) - assert.Equal(t, uint32(55), validUntilBlock) - assert.Equal(t, 2, getBlockCountCalled) - assert.Equal(t, 1, getValidatorsCalled) -} - -func TestGetNetwork(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - r := params.NewRequest() - err := r.DecodeData(req.Body) - if err != nil { - t.Fatalf("Cannot decode request body: %s", req.Body) - } - // request handler already have `getversion` response wrapper - requestHandler(t, r.In, w, "") - })) - t.Cleanup(srv.Close) - endpoint := srv.URL - opts := Options{} - - t.Run("bad", func(t *testing.T) { - c, err := New(context.TODO(), endpoint, opts) - if err != nil { - t.Fatal(err) - } - c.getNextRequestID = getTestRequestID - // network was not initialised - _, err = c.GetNetwork() - require.ErrorIs(t, err, errNetworkNotInitialized) - require.Equal(t, false, c.cache.initDone) - }) - - t.Run("good", func(t *testing.T) { - c, err := New(context.TODO(), endpoint, opts) - if err != nil { - t.Fatal(err) - } - c.getNextRequestID = getTestRequestID - require.NoError(t, c.Init()) - m, err := c.GetNetwork() - require.NoError(t, err) - require.Equal(t, netmode.UnitTestNet, m) - }) -} - func TestUninitedClient(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { r := params.NewRequest() @@ -2250,10 +2032,6 @@ func TestUninitedClient(t *testing.T) { require.Error(t, err) _, err = c.GetRawTransactionVerbose(util.Uint256{}) require.Error(t, err) - _, err = c.IsBlocked(util.Uint160{}) - require.Error(t, err) - _, err = c.GetFeePerByte() - require.Error(t, err) } func newTestNEF(script []byte) nef.File { diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index e4f11a0f0..b11d611a5 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -566,7 +566,7 @@ readloop: ntf := Notification{Type: event} switch event { case neorpc.BlockEventID: - sr, err := c.StateRootInHeader() + sr, err := c.stateRootInHeader() if err != nil { // Client is not initialized. connCloseErr = fmt.Errorf("failed to fetch StateRootInHeader: %w", err) diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 7beb69f8b..b2ac2f9f0 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -31,7 +31,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neorpc" @@ -544,7 +543,7 @@ func TestClientNotary(t *testing.T) { require.Error(t, err) // Can't be withdrawn until 1111. } -func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { +func TestCalculateNetworkFee_Base(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) defer chain.Close() defer rpcSrv.Shutdown() @@ -555,27 +554,8 @@ func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { require.NoError(t, err) require.NoError(t, c.Init()) - getAccounts := func(t *testing.T, n int) []*wallet.Account { - accs := make([]*wallet.Account, n) - var err error - for i := range accs { - accs[i], err = wallet.NewAccount() - require.NoError(t, err) - } - return accs - } - feePerByte := chain.FeePerByte() - t.Run("Invalid", func(t *testing.T) { - tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - accs := getAccounts(t, 2) - tx.Signers = []transaction.Signer{{ - Account: accs[0].PrivateKey().GetScriptHash(), - Scopes: transaction.CalledByEntry, - }} - require.Error(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1])) //nolint:staticcheck // SA1019: c.AddNetworkFee is deprecated - }) t.Run("Simple", func(t *testing.T) { acc0 := wallet.NewAccountFromPrivateKey(testchain.PrivateKeyByID(0)) check := func(t *testing.T, extraFee int64) { @@ -593,16 +573,12 @@ func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { } actualCalculatedNetFee, err := c.CalculateNetworkFee(tx) require.NoError(t, err) - - tx.Scripts = nil - require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0)) //nolint:staticcheck // SA1019: c.AddNetworkFee is deprecated - actual := tx.NetworkFee + tx.NetworkFee = actualCalculatedNetFee + extraFee require.NoError(t, acc0.SignTx(testchain.Network(), tx)) cFee, _ := fee.Calculate(chain.GetBaseExecFee(), acc0.Contract.Script) expected := int64(io.GetVarSize(tx))*feePerByte + cFee + extraFee - require.Equal(t, expected, actual) require.Equal(t, expected, actualCalculatedNetFee+extraFee) err = chain.VerifyTx(tx) if extraFee < 0 { @@ -658,12 +634,9 @@ func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { } actualCalculatedNetFee, err := c.CalculateNetworkFee(tx) require.NoError(t, err) + tx.NetworkFee = actualCalculatedNetFee + extraFee tx.Scripts = nil - - require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1)) //nolint:staticcheck // SA1019: c.AddNetworkFee is deprecated - actual := tx.NetworkFee - require.NoError(t, acc0.SignTx(testchain.Network(), tx)) tx.Scripts = append(tx.Scripts, transaction.Witness{ InvocationScript: testchain.Sign(tx), @@ -673,7 +646,6 @@ func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { cFeeM, _ := fee.Calculate(chain.GetBaseExecFee(), acc1.Contract.Script) expected := int64(io.GetVarSize(tx))*feePerByte + cFee + cFeeM + extraFee - require.Equal(t, expected, actual) require.Equal(t, expected, actualCalculatedNetFee+extraFee) err = chain.VerifyTx(tx) if extraFee < 0 { @@ -732,12 +704,11 @@ func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { } actual, err := c.CalculateNetworkFee(tx) require.NoError(t, err) - tx.Scripts = nil + tx.NetworkFee = actual + extraFee - require.NoError(t, c.AddNetworkFee(tx, extraFee, acc0, acc1)) //nolint:staticcheck // SA1019: c.AddNetworkFee is deprecated + tx.Scripts = nil require.NoError(t, acc0.SignTx(testchain.Network(), tx)) tx.Scripts = append(tx.Scripts, transaction.Witness{}) - require.Equal(t, tx.NetworkFee, actual+extraFee) err = chain.VerifyTx(tx) if extraFee < 0 { require.Error(t, err) @@ -759,37 +730,6 @@ func TestAddNetworkFeeCalculateNetworkFee(t *testing.T) { check(t, -1) }) }) - t.Run("Invalid", func(t *testing.T) { - tx := newTx(t) - acc0, err := wallet.NewAccount() - require.NoError(t, err) - tx.Signers = []transaction.Signer{ - { - Account: acc0.PrivateKey().GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - { - Account: h, - Scopes: transaction.Global, - }, - } - require.Error(t, c.AddNetworkFee(tx, 10, acc0, acc1)) //nolint:staticcheck // SA1019: c.AddNetworkFee is deprecated - }) - t.Run("InvalidContract", func(t *testing.T) { - tx := newTx(t) - acc0 := wallet.NewAccountFromPrivateKey(priv) - tx.Signers = []transaction.Signer{ - { - Account: acc0.PrivateKey().GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - { - Account: util.Uint160{}, - Scopes: transaction.Global, - }, - } - require.Error(t, c.AddNetworkFee(tx, 10, acc0, acc1)) //nolint:staticcheck // SA1019: c.AddNetworkFee is deprecated - }) }) } @@ -863,160 +803,6 @@ func TestCalculateNetworkFee(t *testing.T) { }) }) } -func TestSignAndPushInvocationTx(t *testing.T) { - chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) - defer chain.Close() - defer rpcSrv.Shutdown() - - c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) - require.NoError(t, err) - require.NoError(t, c.Init()) - - priv0 := testchain.PrivateKeyByID(0) - acc0 := wallet.NewAccountFromPrivateKey(priv0) - - verifyWithoutParamsCtr, err := util.Uint160DecodeStringLE(verifyContractHash) - require.NoError(t, err) - acc1 := &wallet.Account{ - Address: address.Uint160ToString(verifyWithoutParamsCtr), - Contract: &wallet.Contract{ - Parameters: []wallet.ContractParam{}, - Deployed: true, - }, - Default: false, - } - - verifyWithParamsCtr, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash) - require.NoError(t, err) - acc2 := &wallet.Account{ - Address: address.Uint160ToString(verifyWithParamsCtr), - Contract: &wallet.Contract{ - Parameters: []wallet.ContractParam{ - {Name: "argString", Type: smartcontract.StringType}, - {Name: "argInt", Type: smartcontract.IntegerType}, - {Name: "argBool", Type: smartcontract.BoolType}, - }, - Deployed: true, - }, - Default: false, - } - - priv3 := testchain.PrivateKeyByID(3) - acc3 := wallet.NewAccountFromPrivateKey(priv3) - - check := func(t *testing.T, h util.Uint256) { - mp := chain.GetMemPool() - tx, ok := mp.TryGetValue(h) - require.True(t, ok) - require.Equal(t, h, tx.Hash()) - require.EqualValues(t, 30, tx.SystemFee) - } - - t.Run("good", func(t *testing.T) { - t.Run("signer0: sig", func(t *testing.T) { - h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc0, 30, 0, []rpcclient.SignerAccount{ //nolint:staticcheck // SA1019: c.SignAndPushInvocationTx is deprecated - { - Signer: transaction.Signer{ - Account: priv0.GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc0, - }, - }) - require.NoError(t, err) - check(t, h) - }) - t.Run("signer0: sig; signer1: sig", func(t *testing.T) { - h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc0, 30, 0, []rpcclient.SignerAccount{ //nolint:staticcheck // SA1019: c.SignAndPushInvocationTx is deprecated - { - Signer: transaction.Signer{ - Account: priv0.GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc0, - }, - { - Signer: transaction.Signer{ - Account: priv3.GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc3, - }, - }) - require.NoError(t, err) - check(t, h) - }) - t.Run("signer0: sig; signer1: contract-based paramless", func(t *testing.T) { - h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc0, 30, 0, []rpcclient.SignerAccount{ //nolint:staticcheck // SA1019: c.SignAndPushInvocationTx is deprecated - { - Signer: transaction.Signer{ - Account: priv0.GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc0, - }, - { - Signer: transaction.Signer{ - Account: verifyWithoutParamsCtr, - Scopes: transaction.CalledByEntry, - }, - Account: acc1, - }, - }) - require.NoError(t, err) - check(t, h) - }) - }) - t.Run("error", func(t *testing.T) { - t.Run("signer0: sig; signer1: contract-based with params", func(t *testing.T) { - _, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc0, 30, 0, []rpcclient.SignerAccount{ //nolint:staticcheck // SA1019: c.SignAndPushInvocationTx is deprecated - { - Signer: transaction.Signer{ - Account: priv0.GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc0, - }, - { - Signer: transaction.Signer{ - Account: verifyWithParamsCtr, - Scopes: transaction.CalledByEntry, - }, - Account: acc2, - }, - }) - require.Error(t, err) - }) - t.Run("signer0: sig; signer1: locked sig", func(t *testing.T) { - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - acc4 := &wallet.Account{ - Address: address.Uint160ToString(pk.GetScriptHash()), - Contract: &wallet.Contract{ - Script: pk.PublicKey().GetVerificationScript(), - Parameters: []wallet.ContractParam{{Name: "parameter0", Type: smartcontract.SignatureType}}, - }, - } - _, err = c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc0, 30, 0, []rpcclient.SignerAccount{ //nolint:staticcheck // SA1019: c.SignAndPushInvocationTx is deprecated - { - Signer: transaction.Signer{ - Account: priv0.GetScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc0, - }, - { - Signer: transaction.Signer{ - Account: util.Uint160{1, 2, 3}, - Scopes: transaction.CalledByEntry, - }, - Account: acc4, - }, - }) - require.Error(t, err) - }) - }) -} func TestNotaryActor(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChainAndServices(t, false, true, false) @@ -1049,92 +835,6 @@ func TestNotaryActor(t *testing.T) { require.NoError(t, err) } -func TestSignAndPushP2PNotaryRequest(t *testing.T) { - chain, rpcSrv, httpSrv := initServerWithInMemoryChainAndServices(t, false, true, false) - defer chain.Close() - defer rpcSrv.Shutdown() - - c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) - require.NoError(t, err) - acc, err := wallet.NewAccount() - require.NoError(t, err) - - t.Run("client wasn't initialized", func(t *testing.T) { - _, err := c.SignAndPushP2PNotaryRequest(transaction.New([]byte{byte(opcode.RET)}, 123), []byte{byte(opcode.RET)}, -1, 0, 100, acc) //nolint:staticcheck // SA1019: c.SignAndPushP2PNotaryRequest is deprecated - require.NotNil(t, err) - }) - - require.NoError(t, c.Init()) - t.Run("bad fallback script", func(t *testing.T) { - _, err := c.SignAndPushP2PNotaryRequest(nil, []byte{byte(opcode.ASSERT)}, -1, 0, 0, acc) //nolint:staticcheck // SA1019: c.SignAndPushP2PNotaryRequest is deprecated - require.NotNil(t, err) - }) - - t.Run("too large fallbackValidFor", func(t *testing.T) { - _, err := c.SignAndPushP2PNotaryRequest(nil, []byte{byte(opcode.RET)}, -1, 0, 141, acc) //nolint:staticcheck // SA1019: c.SignAndPushP2PNotaryRequest is deprecated - require.NotNil(t, err) - }) - - t.Run("good", func(t *testing.T) { - sender := testchain.PrivateKeyByID(0) // owner of the deposit in testchain - acc := wallet.NewAccountFromPrivateKey(sender) - expected := transaction.Transaction{ - Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, - Script: []byte{byte(opcode.RET)}, - ValidUntilBlock: chain.BlockHeight() + 5, - Signers: []transaction.Signer{{Account: util.Uint160{1, 5, 9}}}, - Scripts: []transaction.Witness{{ - InvocationScript: []byte{1, 4, 7}, - VerificationScript: []byte{3, 6, 9}, - }}, - } - mainTx := expected - _ = expected.Hash() - req, err := c.SignAndPushP2PNotaryRequest(&mainTx, []byte{byte(opcode.RET)}, -1, 0, 6, acc) //nolint:staticcheck // SA1019: c.SignAndPushP2PNotaryRequest is deprecated - require.NoError(t, err) - - // check that request was correctly completed - require.Equal(t, expected, *req.MainTransaction) // main tx should be the same - require.ElementsMatch(t, []transaction.Attribute{ - { - Type: transaction.NotaryAssistedT, - Value: &transaction.NotaryAssisted{NKeys: 0}, - }, - { - Type: transaction.NotValidBeforeT, - Value: &transaction.NotValidBefore{Height: chain.BlockHeight()}, - }, - { - Type: transaction.ConflictsT, - Value: &transaction.Conflicts{Hash: mainTx.Hash()}, - }, - }, req.FallbackTransaction.Attributes) - require.Equal(t, []transaction.Signer{ - {Account: chain.GetNotaryContractScriptHash()}, - {Account: acc.PrivateKey().GetScriptHash()}, - }, req.FallbackTransaction.Signers) - - // it shouldn't be an error to add completed fallback to the chain - w, err := wallet.NewWalletFromFile(notaryPath) - require.NoError(t, err) - ntr := w.Accounts[0] - err = ntr.Decrypt(notaryPass, w.Scrypt) - require.NoError(t, err) - req.FallbackTransaction.Scripts[0] = transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), keys.SignatureLen}, ntr.PrivateKey().SignHashable(uint32(testchain.Network()), req.FallbackTransaction)...), - VerificationScript: []byte{}, - } - b := testchain.NewBlock(t, chain, 1, 0, req.FallbackTransaction) - require.NoError(t, chain.AddBlock(b)) - appLogs, err := chain.GetAppExecResults(req.FallbackTransaction.Hash(), trigger.Application) - require.NoError(t, err) - require.Equal(t, 1, len(appLogs)) - appLog := appLogs[0] - require.Equal(t, vmstate.Halt, appLog.VMState) - require.Equal(t, appLog.GasConsumed, req.FallbackTransaction.SystemFee) - }) -} - func TestGetRawNotaryPoolAndTransaction(t *testing.T) { var ( mainHash1, fallbackHash1, mainHash2, fallbackHash2 util.Uint256 @@ -1266,20 +966,6 @@ func TestGetRawNotaryPoolAndTransaction(t *testing.T) { }) } -func TestCalculateNotaryFee(t *testing.T) { - chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) - defer chain.Close() - defer rpcSrv.Shutdown() - - c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) - require.NoError(t, err) - - t.Run("client not initialized", func(t *testing.T) { - _, err := c.CalculateNotaryFee(0) //nolint:staticcheck // SA1019: c.CalculateNotaryFee is deprecated - require.NoError(t, err) // Do not require client initialisation for this. - }) -} - func TestPing(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) defer chain.Close() @@ -1294,35 +980,6 @@ func TestPing(t *testing.T) { require.Error(t, c.Ping()) } -func TestCreateTxFromScript(t *testing.T) { - chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) - defer chain.Close() - defer rpcSrv.Shutdown() - - c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) - require.NoError(t, err) - require.NoError(t, c.Init()) - - priv := testchain.PrivateKey(0) - acc := wallet.NewAccountFromPrivateKey(priv) - t.Run("NoSystemFee", func(t *testing.T) { - tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, -1, 10, nil) //nolint:staticcheck // SA1019: c.CreateTxFromScript is deprecated - require.NoError(t, err) - require.True(t, tx.ValidUntilBlock > chain.BlockHeight()) - require.EqualValues(t, 30, tx.SystemFee) // PUSH1 - require.True(t, len(tx.Signers) == 1) - require.Equal(t, acc.PrivateKey().GetScriptHash(), tx.Signers[0].Account) - }) - t.Run("ProvideSystemFee", func(t *testing.T) { - tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, 123, 10, nil) //nolint:staticcheck // SA1019: c.CreateTxFromScript is deprecated - require.NoError(t, err) - require.True(t, tx.ValidUntilBlock > chain.BlockHeight()) - require.EqualValues(t, 123, tx.SystemFee) - require.True(t, len(tx.Signers) == 1) - require.Equal(t, acc.PrivateKey().GetScriptHash(), tx.Signers[0].Account) - }) -} - func TestCreateNEP17TransferTx(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) defer chain.Close() @@ -1885,21 +1542,6 @@ func TestClient_IteratorSessions(t *testing.T) { }) } -func TestClient_GetNotaryServiceFeePerKey(t *testing.T) { - chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) - defer chain.Close() - defer rpcSrv.Shutdown() - - c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) - require.NoError(t, err) - require.NoError(t, c.Init()) - - var defaultNotaryServiceFeePerKey int64 = 1000_0000 - actual, err := c.GetNotaryServiceFeePerKey() //nolint:staticcheck // SA1019: c.GetNotaryServiceFeePerKey is deprecated - require.NoError(t, err) - require.Equal(t, defaultNotaryServiceFeePerKey, actual) -} - func TestClient_States(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) defer chain.Close() @@ -1973,63 +1615,6 @@ func TestClientOracle(t *testing.T) { require.Equal(t, newPrice, actual) } -func TestClient_InvokeAndPackIteratorResults(t *testing.T) { - chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) - defer chain.Close() - defer rpcSrv.Shutdown() - - c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{}) - require.NoError(t, err) - require.NoError(t, c.Init()) - - // storageItemsCount is the amount of storage items stored in Storage contract, it's hard-coded in the contract code. - const storageItemsCount = 255 - expected := make([][]byte, storageItemsCount) - for i := 0; i < storageItemsCount; i++ { - expected[i] = stackitem.NewBigInteger(big.NewInt(int64(i))).Bytes() - } - sort.Slice(expected, func(i, j int) bool { - if len(expected[i]) != len(expected[j]) { - return len(expected[i]) < len(expected[j]) - } - return bytes.Compare(expected[i], expected[j]) < 0 - }) - storageHash, err := util.Uint160DecodeStringLE(storageContractHash) - require.NoError(t, err) - - t.Run("default max items constraint", func(t *testing.T) { - res, err := c.InvokeAndPackIteratorResults(storageHash, "iterateOverValues", []smartcontract.Parameter{}, nil) //nolint:staticcheck // SA1019: c.InvokeAndPackIteratorResults is deprecated - require.NoError(t, err) - require.Equal(t, vmstate.Halt.String(), res.State) - require.Equal(t, 1, len(res.Stack)) - require.Equal(t, stackitem.ArrayT, res.Stack[0].Type()) - arr, ok := res.Stack[0].Value().([]stackitem.Item) - require.True(t, ok) - require.Equal(t, config.DefaultMaxIteratorResultItems, len(arr)) - - for i := range arr { - require.Equal(t, stackitem.ByteArrayT, arr[i].Type()) - require.Equal(t, expected[i], arr[i].Value().([]byte)) - } - }) - t.Run("custom max items constraint", func(t *testing.T) { - max := 123 - res, err := c.InvokeAndPackIteratorResults(storageHash, "iterateOverValues", []smartcontract.Parameter{}, nil, max) //nolint:staticcheck // SA1019: c.InvokeAndPackIteratorResults is deprecated - require.NoError(t, err) - require.Equal(t, vmstate.Halt.String(), res.State) - require.Equal(t, 1, len(res.Stack)) - require.Equal(t, stackitem.ArrayT, res.Stack[0].Type()) - arr, ok := res.Stack[0].Value().([]stackitem.Item) - require.True(t, ok) - require.Equal(t, max, len(arr)) - - for i := range arr { - require.Equal(t, stackitem.ByteArrayT, arr[i].Type()) - require.Equal(t, expected[i], arr[i].Value().([]byte)) - } - }) -} - func TestClient_Iterator_SessionConfigVariations(t *testing.T) { var expected [][]byte storageHash, err := util.Uint160DecodeStringLE(storageContractHash)