From 2093bf806f4b2017ea91147592462a4eed887174 Mon Sep 17 00:00:00 2001 From: anastasia prasolova Date: Thu, 22 Sep 2022 19:29:14 +0300 Subject: [PATCH 001/125] [nspcc-dev/nspcc-infra#840]: Add DCO check Signed-off-by: anastasia prasolova --- .github/workflows/dco.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 000000000..40ed8fcb4 --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,21 @@ +name: DCO check + +on: + pull_request: + branches: + - master + +jobs: + commits_check_job: + runs-on: ubuntu-latest + name: Commits Check + steps: + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@master + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} From 7e709313d30ef27fd7be0c4d53fb51504dc4f1be Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 26 Jan 2023 07:11:57 +0300 Subject: [PATCH 002/125] cli: ask for NEP2 account label if not provided If NEP2 account label is not provided as a flag for import-related CLI commands then ask it in the interactive mode. This change breaks the compatibility with the old behaviour (add the unnamed account if the name wasn't specified). --- cli/wallet/wallet.go | 13 ++++++------- cli/wallet/wallet_test.go | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/cli/wallet/wallet.go b/cli/wallet/wallet.go index 212092f47..f5051efb8 100644 --- a/cli/wallet/wallet.go +++ b/cli/wallet/wallet.go @@ -985,7 +985,12 @@ func newAccountFromWIF(w io.Writer, wif string, scrypt keys.ScryptParams, label if pass != nil { phrase = *pass } - if label != nil { + if label == nil { + name, err = readAccountName() + if err != nil { + return nil, fmt.Errorf("failed to read account label: %w", err) + } + } else { name = *label } // note: NEP2 strings always have length of 58 even though @@ -1024,12 +1029,6 @@ func newAccountFromWIF(w io.Writer, wif string, scrypt keys.ScryptParams, label } fmt.Fprintln(w, "Provided WIF was unencrypted. Wallet can contain only encrypted keys.") - if label == nil { - name, err = readAccountName() - if err != nil { - return nil, fmt.Errorf("failed to read account label: %w", err) - } - } if pass == nil { phrase, err = readNewPassword() if err != nil { diff --git a/cli/wallet/wallet_test.go b/cli/wallet/wallet_test.go index 7425237e9..f3387a336 100644 --- a/cli/wallet/wallet_test.go +++ b/cli/wallet/wallet_test.go @@ -356,9 +356,26 @@ func TestWalletInit(t *testing.T) { t.Run("InvalidPassword", func(t *testing.T) { e.In.WriteString("password1\r") e.RunWithError(t, "neo-go", "wallet", "import", "--wallet", walletPath, - "--wif", acc.EncryptedWIF) + "--wif", acc.EncryptedWIF, "--name", "acc1") }) + e.In.WriteString("somepass\r") + e.Run(t, "neo-go", "wallet", "import", "--wallet", walletPath, + "--wif", acc.EncryptedWIF, "--name", "acc1") + + w, err := wallet.NewWalletFromFile(walletPath) + require.NoError(t, err) + actual := w.GetAccount(acc.PrivateKey().GetScriptHash()) + require.NotNil(t, actual) + require.Equal(t, "acc1", actual.Label) + require.NoError(t, actual.Decrypt("somepass", w.Scrypt)) + }) + t.Run("EncryptedWIF with name specified via input", func(t *testing.T) { + acc, err := wallet.NewAccount() + require.NoError(t, err) + require.NoError(t, acc.Encrypt("somepass", keys.NEP2ScryptParams())) + + e.In.WriteString("acc2\r") e.In.WriteString("somepass\r") e.Run(t, "neo-go", "wallet", "import", "--wallet", walletPath, "--wif", acc.EncryptedWIF) @@ -367,6 +384,7 @@ func TestWalletInit(t *testing.T) { require.NoError(t, err) actual := w.GetAccount(acc.PrivateKey().GetScriptHash()) require.NotNil(t, actual) + require.Equal(t, "acc2", actual.Label) require.NoError(t, actual.Decrypt("somepass", w.Scrypt)) }) t.Run("EncryptedWIF with wallet config", func(t *testing.T) { @@ -388,12 +406,13 @@ func TestWalletInit(t *testing.T) { e.In.WriteString(pass + "\r") } e.Run(t, "neo-go", "wallet", "import", "--wallet-config", configPath, - "--wif", acc.EncryptedWIF) + "--wif", acc.EncryptedWIF, "--name", "acc3"+configPass) w, err := wallet.NewWalletFromFile(walletPath) require.NoError(t, err) actual := w.GetAccount(acc.PrivateKey().GetScriptHash()) require.NotNil(t, actual) + require.Equal(t, "acc3"+configPass, actual.Label) require.NoError(t, actual.Decrypt(pass, w.Scrypt)) } t.Run("config password mismatch", func(t *testing.T) { From 4671fbb3be8390f6f3a4e238cd33014d0b0b89ab Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 18 Mar 2023 10:44:12 +0300 Subject: [PATCH 003/125] interop: drop deprecated util.FromAddress It still was used in a number of places, surprisingly. --- ROADMAP.md | 11 --- cli/vm/cli_test.go | 4 +- examples/nft-d/nft.go | 3 +- examples/nft-nd/nft.go | 3 +- examples/runtime/runtime.go | 4 +- examples/timer/timer.go | 4 +- examples/token/token.go | 4 +- internal/basicchain/testdata/test_contract.go | 4 +- .../testdata/verify/verification_contract.go | 3 +- pkg/compiler/analysis.go | 16 ----- pkg/compiler/codegen.go | 12 ++-- pkg/compiler/function_call_test.go | 6 +- pkg/compiler/interop_test.go | 67 +++++-------------- pkg/core/blockchain_neotest_test.go | 4 +- pkg/interop/util/util.go | 10 --- 15 files changed, 42 insertions(+), 113 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index ae96679a7..669b0b259 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -40,17 +40,6 @@ 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. -## util.FromAddress smart contract helper - -`util` smart contract library has a FromAddress function that is one of the -oldest lines in the entire NeoGo code base, dating back to 2018. Version -0.99.4 of NeoGo (October 2022) has introduced a new `address` package with -`ToHash160` function, it covers a bit more use cases but can be used as a -direct replacement of the old function, so please update your code. - -util.FromAddress is expected to be removed around March 2023 (~0.102.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/vm/cli_test.go b/cli/vm/cli_test.go index 2b6e7db45..6cdd5c3eb 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -432,10 +432,10 @@ go 1.17`) srcCheckWitness := `package kek import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" - "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" ) func Main() bool { - var owner = util.FromAddress("` + ownerAddress + `") + var owner = address.ToHash160("` + ownerAddress + `") return runtime.CheckWitness(owner) } ` diff --git a/examples/nft-d/nft.go b/examples/nft-d/nft.go index 66afd2ef6..26313f716 100644 --- a/examples/nft-d/nft.go +++ b/examples/nft-d/nft.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/iterator" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/native/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/native/gas" "github.com/nspcc-dev/neo-go/pkg/interop/native/management" @@ -39,7 +40,7 @@ var ( // contractOwner is a special address that can perform some management // functions on this contract like updating/destroying it and can also // be used for contract address verification. - contractOwner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") + contractOwner = address.ToHash160("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") ) // ObjectIdentifier represents NFT structure and contains the container ID and diff --git a/examples/nft-nd/nft.go b/examples/nft-nd/nft.go index f4f87b743..3dd5f201c 100644 --- a/examples/nft-nd/nft.go +++ b/examples/nft-nd/nft.go @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/iterator" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/native/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/native/gas" "github.com/nspcc-dev/neo-go/pkg/interop/native/management" @@ -35,7 +36,7 @@ var ( // contractOwner is a special address that can perform some management // functions on this contract like updating/destroying it and can also // be used for contract address verification. - contractOwner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") + contractOwner = address.ToHash160("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") ) // Symbol returns token symbol, it's HASHY. diff --git a/examples/runtime/runtime.go b/examples/runtime/runtime.go index 9ecdd559d..6c9eb4b6c 100644 --- a/examples/runtime/runtime.go +++ b/examples/runtime/runtime.go @@ -1,14 +1,14 @@ package runtimecontract import ( + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/native/management" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" - "github.com/nspcc-dev/neo-go/pkg/interop/util" ) var ( // Check if the invoker of the contract is the specified owner - owner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") + owner = address.ToHash160("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") ) // init is transformed into _initialize method that is called whenever contract diff --git a/examples/timer/timer.go b/examples/timer/timer.go index 3e09d39ba..7f7e600ee 100644 --- a/examples/timer/timer.go +++ b/examples/timer/timer.go @@ -3,10 +3,10 @@ package timer import ( "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/contract" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/native/std" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" - "github.com/nspcc-dev/neo-go/pkg/interop/util" ) const defaultTicks = 3 @@ -16,7 +16,7 @@ var ( // ctx holds storage context for contract methods ctx storage.Context // Check if the invoker of the contract is the specified owner - owner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") + owner = address.ToHash160("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") // ticksKey is a storage key for ticks counter ticksKey = []byte("ticks") ) diff --git a/examples/token/token.go b/examples/token/token.go index 7cede5d3f..f9d690a16 100644 --- a/examples/token/token.go +++ b/examples/token/token.go @@ -3,8 +3,8 @@ package tokencontract import ( "github.com/nspcc-dev/neo-go/examples/token/nep17" "github.com/nspcc-dev/neo-go/pkg/interop" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/storage" - "github.com/nspcc-dev/neo-go/pkg/interop/util" ) const ( @@ -13,7 +13,7 @@ const ( ) var ( - owner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") + owner = address.ToHash160("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") token nep17.Token ctx storage.Context ) diff --git a/internal/basicchain/testdata/test_contract.go b/internal/basicchain/testdata/test_contract.go index e6b98ab57..0b534f9dd 100644 --- a/internal/basicchain/testdata/test_contract.go +++ b/internal/basicchain/testdata/test_contract.go @@ -3,12 +3,12 @@ package testdata import ( "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/contract" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/native/ledger" "github.com/nspcc-dev/neo-go/pkg/interop/native/management" "github.com/nspcc-dev/neo-go/pkg/interop/native/neo" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" - "github.com/nspcc-dev/neo-go/pkg/interop/util" ) const ( @@ -16,7 +16,7 @@ const ( decimals = 2 ) -var owner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") +var owner = address.ToHash160("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") func Init() bool { ctx := storage.GetContext() diff --git a/internal/basicchain/testdata/verify/verification_contract.go b/internal/basicchain/testdata/verify/verification_contract.go index a12bcb186..d03b15615 100644 --- a/internal/basicchain/testdata/verify/verification_contract.go +++ b/internal/basicchain/testdata/verify/verification_contract.go @@ -1,6 +1,7 @@ package verify import ( + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/util" ) @@ -9,6 +10,6 @@ import ( // It returns true iff it is signed by Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn (id-0 private key from testchain). func Verify() bool { tx := runtime.GetScriptContainer() - addr := util.FromAddress("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn") + addr := address.ToHash160("Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn") return util.Equals(string(tx.Sender), string(addr)) } diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index f725bc771..0dfefd2e6 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -24,10 +24,6 @@ var ( var ( // Go language builtin functions. goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover", "delete"} - // Custom builtin utility functions. - customBuiltins = []string{ - "FromAddress", - } // Custom builtin utility functions that contain some meaningful code inside and // require code generation using standard rules, but sometimes (depending on // the expression usage condition) may be optimized at compile time. @@ -642,18 +638,6 @@ func isGoBuiltin(name string) bool { return false } -func isCustomBuiltin(f *funcScope) bool { - if !isInteropPath(f.pkg.Path()) { - return false - } - for _, n := range customBuiltins { - if f.name == n { - return true - } - } - return false -} - func isPotentialCustomBuiltin(f *funcScope, expr ast.Expr) bool { if !isInteropPath(f.pkg.Path()) { return false diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 50edd84c9..14793c8ad 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -458,10 +458,10 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl, pkg *types. } else { f, ok = c.funcs[c.getFuncNameFromDecl("", decl)] if ok { - // If this function is a syscall or builtin we will not convert it to bytecode. + // If this function is a syscall we will not convert it to bytecode. // If it's a potential custom builtin then it needs more specific usages research, // thus let's emit the code for it. - if isSyscall(f) || isCustomBuiltin(f) { + if isSyscall(f) { return f } c.setLabel(f.label) @@ -978,7 +978,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { f, ok = c.funcs[name] if ok { f.selector = fun.X - isBuiltin = isCustomBuiltin(f) || isPotentialCustomBuiltin(f, n) + isBuiltin = isPotentialCustomBuiltin(f, n) if canInline(f.pkg.Path(), f.decl.Name.Name, isBuiltin) { c.inlineCall(f, n) return nil @@ -1926,7 +1926,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { c.emitStoreByIndex(varGlobal, c.exceptionIndex) case "delete": emit.Opcodes(c.prog.BinWriter, opcode.REMOVE) - case "FromAddress", "ToHash160": + case "ToHash160": // We can be sure that this is an ast.BasicLit just containing a simple // address string. Note that the string returned from calling Value will // contain double quotes that need to be stripped. @@ -1946,7 +1946,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { // transformArgs returns a list of function arguments // which should be put on stack. // There are special cases for builtins: -// 1. With FromAddress and with ToHash160 in case if it behaves like builtin, +// 1. With ToHash160 in case if it behaves like builtin, // parameter conversion is happening at compile-time so there is no need to // push parameters on stack and perform an actual call // 2. With panic, the generated code depends on the fact if an argument was nil or a string; @@ -1954,7 +1954,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { func transformArgs(fs *funcScope, fun ast.Expr, isBuiltin bool, args []ast.Expr) []ast.Expr { switch f := fun.(type) { case *ast.SelectorExpr: - if f.Sel.Name == "FromAddress" || (isBuiltin && f.Sel.Name == "ToHash160") { + if isBuiltin && f.Sel.Name == "ToHash160" { return args[1:] } if fs != nil && isSyscall(fs) { diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index c409108be..f1848be4f 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -89,10 +89,10 @@ func TestNotAssignedFunctionCall(t *testing.T) { }) t.Run("Builtin", func(t *testing.T) { src := `package foo - import "github.com/nspcc-dev/neo-go/pkg/interop/util" + import "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" func Main() int { - util.FromAddress("NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8") - util.FromAddress("NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8") + address.ToHash160("NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8") + address.ToHash160("NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8") return 1 }` eval(t, src, big.NewInt(1)) diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 2ba7a5f2f..a18e97003 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -71,62 +71,13 @@ func TestTypeConstantSize(t *testing.T) { }) } -func TestFromAddress(t *testing.T) { - as1 := "NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN" - addr1, err := address.StringToUint160(as1) - require.NoError(t, err) - - as2 := "NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8" - addr2, err := address.StringToUint160(as2) - require.NoError(t, err) - - t.Run("append 2 addresses", func(t *testing.T) { - src := ` - package foo - import "github.com/nspcc-dev/neo-go/pkg/interop/util" - func Main() []byte { - addr1 := util.FromAddress("` + as1 + `") - addr2 := util.FromAddress("` + as2 + `") - sum := append(addr1, addr2...) - return sum - } - ` - - eval(t, src, append(addr1.BytesBE(), addr2.BytesBE()...)) - }) - - t.Run("append 2 addresses inline", func(t *testing.T) { - src := ` - package foo - import "github.com/nspcc-dev/neo-go/pkg/interop/util" - func Main() []byte { - addr1 := util.FromAddress("` + as1 + `") - sum := append(addr1, util.FromAddress("` + as2 + `")...) - return sum - } - ` - - eval(t, src, append(addr1.BytesBE(), addr2.BytesBE()...)) - }) - - t.Run("AliasPackage", func(t *testing.T) { - src := ` - package foo - import uu "github.com/nspcc-dev/neo-go/pkg/interop/util" - func Main() []byte { - addr1 := uu.FromAddress("` + as1 + `") - addr2 := uu.FromAddress("` + as2 + `") - sum := append(addr1, addr2...) - return sum - }` - eval(t, src, append(addr1.BytesBE(), addr2.BytesBE()...)) - }) -} - func TestAddressToHash160BuiltinConversion(t *testing.T) { a := "NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN" h, err := address.StringToUint160(a) require.NoError(t, err) + a2 := "NPAsqZkx9WhNd4P72uhZxBhLinSuNkxfB8" + addr2, err := address.StringToUint160(a2) + require.NoError(t, err) t.Run("builtin conversion", func(t *testing.T) { src := `package foo import ( @@ -163,6 +114,18 @@ func TestAddressToHash160BuiltinConversion(t *testing.T) { // On the contrary, there should be an address string. require.True(t, strings.Contains(string(prog), a)) }) + t.Run("AliasPackage", func(t *testing.T) { + src := ` + package foo + import ad "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" + func Main() []byte { + addr1 := ad.ToHash160("` + a + `") + addr2 := ad.ToHash160("` + a2 + `") + sum := append(addr1, addr2...) + return sum + }` + eval(t, src, append(h.BytesBE(), addr2.BytesBE()...)) + }) } func TestInvokeAddressToFromHash160(t *testing.T) { diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index f71b8890b..03be30191 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -650,10 +650,10 @@ func TestBlockchain_IsTxStillRelevant(t *testing.T) { src := fmt.Sprintf(`package verify import ( "github.com/nspcc-dev/neo-go/pkg/interop/contract" - "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" ) func Verify() bool { - addr := util.FromAddress("`+address.Uint160ToString(e.NativeHash(t, nativenames.Ledger))+`") + addr := address.ToHash160("`+address.Uint160ToString(e.NativeHash(t, nativenames.Ledger))+`") currentHeight := contract.Call(addr, "currentIndex", contract.ReadStates) return currentHeight.(int) < %d }`, bc.BlockHeight()+2) // deploy + next block diff --git a/pkg/interop/util/util.go b/pkg/interop/util/util.go index 038b17aa9..41ff5ae97 100644 --- a/pkg/interop/util/util.go +++ b/pkg/interop/util/util.go @@ -14,16 +14,6 @@ func Abort() { neogointernal.Opcode0NoReturn("ABORT") } -// FromAddress is an utility function that converts a Neo address to its hash -// (160 bit BE value in a 20 byte slice). It can only be used for strings known -// at compilation time, because the conversion is actually being done by the -// compiler. -// -// Deprecated: use address.ToHash160 instead. -func FromAddress(address string) interop.Hash160 { - return nil -} - // Equals compares a with b and will return true when a and b are equal. It's // implemented as an EQUAL VM opcode, so the rules of comparison are those // of EQUAL. From 6e27883c106678aa37ae1fe2d57e8cae0df5d0a4 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 18 Mar 2023 10:52:24 +0300 Subject: [PATCH 004/125] rpcsrv: remove deprecated RPC counters --- ROADMAP.md | 9 --------- pkg/services/rpcsrv/prometheus.go | 17 +---------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 669b0b259..dbeabf41d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -50,15 +50,6 @@ Receive* APIs. Removal of these APIs is scheduled for May 2023 (~0.103.0 release). -## Prometheus RPC counters - -A number of neogo_${method}_called Prometheus counters are marked as -deprecated since version 0.99.5, neogo_rpc_${method}_time histograms can be -used instead (that also have a counter). - -It's not a frequently used thing and it's easy to replace it, so removal of -old counters is scheduled for January-February 2023 (~0.100.X release). - ## SecondsPerBlock protocol configuration With 0.100.0 version SecondsPerBlock protocol configuration setting was diff --git a/pkg/services/rpcsrv/prometheus.go b/pkg/services/rpcsrv/prometheus.go index b90f1ae94..4e24a4e9d 100644 --- a/pkg/services/rpcsrv/prometheus.go +++ b/pkg/services/rpcsrv/prometheus.go @@ -1,7 +1,6 @@ package rpcsrv import ( - "fmt" "strings" "time" @@ -10,8 +9,7 @@ import ( // Metrics used in monitoring service. var ( - rpcCounter = map[string]prometheus.Counter{} - rpcTimes = map[string]prometheus.Histogram{} + rpcTimes = map[string]prometheus.Histogram{} ) func addReqTimeMetric(name string, t time.Duration) { @@ -19,22 +17,9 @@ func addReqTimeMetric(name string, t time.Duration) { if ok { hist.Observe(t.Seconds()) } - ctr, ok := rpcCounter[name] - if ok { - ctr.Inc() - } } func regCounter(call string) { - ctr := prometheus.NewCounter( - prometheus.CounterOpts{ - Help: fmt.Sprintf("Number of calls to %s rpc endpoint (obsolete, to be removed)", call), - Name: fmt.Sprintf("%s_called", call), - Namespace: "neogo", - }, - ) - prometheus.MustRegister(ctr) - rpcCounter[call] = ctr rpcTimes[call] = prometheus.NewHistogram( prometheus.HistogramOpts{ Help: "RPC " + call + " call handling time", From f672a97d1b26b4987dcd19258e3956e1f4c0d73a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 22 Mar 2023 16:22:02 +0300 Subject: [PATCH 005/125] docs: add minor note to `MinPeers` config section --- docs/node-configuration.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/node-configuration.md b/docs/node-configuration.md index b4b024205..0baaabc4c 100644 --- a/docs/node-configuration.md +++ b/docs/node-configuration.md @@ -86,7 +86,9 @@ where: sender stored in a local pool. - `MaxPeers` (`int`) is the maximum numbers of peers that can be connected to the server. - `MinPeers` (`int`) is the minimum number of peers for normal operation; when the node has - less than this number of peers it tries to connect with some new ones. + less than this number of peers it tries to connect with some new ones. Note that consensus + node won't start the consensus process until at least `MinPeers` number of peers are + connected. - `PingInterval` (`Duration`) is the interval used in pinging mechanism for syncing blocks. - `PingTimeout` (`Duration`) is the time to wait for pong (response for sent ping request). From f21e618be5dded28eb37f48b0fee5c0d58708280 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Thu, 23 Mar 2023 17:03:22 +0800 Subject: [PATCH 006/125] rpcclient: add GetProof and VerifyProof (fix #2942) --- pkg/rpcclient/rpc.go | 25 ++++++++++++ pkg/rpcclient/rpc_test.go | 61 ++++++++++++++++++++++++++++++ pkg/services/rpcsrv/client_test.go | 30 +++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/pkg/rpcclient/rpc.go b/pkg/rpcclient/rpc.go index 0e7147baa..6b97c8895 100644 --- a/pkg/rpcclient/rpc.go +++ b/pkg/rpcclient/rpc.go @@ -447,6 +447,31 @@ func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.Transactio return resp, nil } +// GetProof returns existence proof of storage item state by the given stateroot +// historical contract hash and historical item key. +func (c *Client) GetProof(stateroot util.Uint256, historicalContractHash util.Uint160, historicalKey []byte) (*result.ProofWithKey, error) { + var ( + params = []interface{}{stateroot.StringLE(), historicalContractHash.StringLE(), historicalKey} + resp = &result.ProofWithKey{} + ) + if err := c.performRequest("getproof", params, resp); err != nil { + return nil, err + } + return resp, nil +} + +// VerifyProof returns value by the given stateroot and proof. +func (c *Client) VerifyProof(stateroot util.Uint256, proof *result.ProofWithKey) ([]byte, error) { + var ( + params = []interface{}{stateroot.StringLE(), proof.String()} + resp []byte + ) + if err := c.performRequest("verifyproof", params, &resp); err != nil { + return nil, err + } + return resp, nil +} + // GetState returns historical contract storage item state by the given stateroot, // historical contract hash and historical item key. func (c *Client) GetState(stateroot util.Uint256, historicalContractHash util.Uint160, historicalKey []byte) ([]byte, error) { diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index 815798f4b..9458e0830 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -25,6 +25,7 @@ import ( "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/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" @@ -831,6 +832,66 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, }, }, + "getproof": { + { + name: "positive", + invoke: func(c *Client) (interface{}, error) { + root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") + cHash, _ := util.Uint160DecodeStringLE("cc5e4edd9f5f8dba8bb65734541df7a1c081c67b") + key := []byte{10} + return c.GetProof(root, cHash, key) + }, + serverResponse: `{"jsonrpc":"2.0","id":1,"result":"Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD"}`, + result: func(c *Client) interface{} { + b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD") + proof := &result.ProofWithKey{} + r := io.NewBinReaderFromBuf(b) + proof.DecodeBinary(r) + return proof + }, + }, + { + name: "not found", + invoke: func(c *Client) (interface{}, error) { + root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") + cHash, _ := util.Uint160DecodeStringLE("cc5e4edd9f5f8dba8bb65734541df7a1c081c67b") + key := []byte{01} + return c.GetProof(root, cHash, key) + }, + serverResponse: `{"id":1,"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":"failed to get proof: item not found"}}`, + fails: true, + }, + }, + "verifyproof": { + { + name: "positive", + invoke: func(c *Client) (interface{}, error) { + root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") + b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD") + proof := &result.ProofWithKey{} + r := io.NewBinReaderFromBuf(b) + proof.DecodeBinary(r) + return c.VerifyProof(root, proof) + }, + serverResponse: `{"jsonrpc":"2.0","id":1,"result":"6AM="}`, + result: func(c *Client) interface{} { + return bigint.ToPreallocatedBytes(big.NewInt(1000), nil) + }, + }, + { + name: "fail", + invoke: func(c *Client) (interface{}, error) { + root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") + b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD") + proof := &result.ProofWithKey{} + r := io.NewBinReaderFromBuf(b) + proof.DecodeBinary(r) + return c.VerifyProof(root, proof) + }, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":"invalid"}`, + fails: true, + }, + }, "findstates": { { name: "positive", diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 031dab5ee..86d8c7346 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -23,12 +23,15 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core" "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" + "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/core/state" "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" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" @@ -1764,6 +1767,33 @@ func TestClient_GetNotaryServiceFeePerKey(t *testing.T) { require.Equal(t, defaultNotaryServiceFeePerKey, actual) } +func TestClient_States(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()) + + stateheight, err := c.GetStateHeight() + assert.NoError(t, err) + assert.Equal(t, chain.BlockHeight(), stateheight.Local) + + stateroot, err := c.GetStateRootByHeight(stateheight.Local) + assert.NoError(t, err) + + t.Run("proof", func(t *testing.T) { + policy, err := chain.GetNativeContractScriptHash(nativenames.Policy) + assert.NoError(t, err) + proof, err := c.GetProof(stateroot.Root, policy, []byte{19}) // storagePrice key in policy contract + assert.NoError(t, err) + value, err := c.VerifyProof(stateroot.Root, proof) + assert.NoError(t, err) + assert.Equal(t, big.NewInt(native.DefaultStoragePrice), bigint.FromBytes(value)) + }) +} + func TestClientOracle(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) defer chain.Close() From d36df15878f0734efb8b242f47eedc984f0a1915 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 29 Mar 2023 11:19:23 +0800 Subject: [PATCH 007/125] ci: fix lint issues (fix #2948) --- .golangci.yml | 4 ++++ internal/contracts/oracle_contract/go.mod | 2 +- pkg/core/dao/dao.go | 3 ++- pkg/core/interop/storage/find.go | 2 +- pkg/core/native/management.go | 2 +- pkg/core/native/native_neo.go | 2 +- pkg/network/tcp_peer_test.go | 3 ++- pkg/rpcclient/actor/doc_test.go | 2 +- pkg/rpcclient/invoker/doc_test.go | 12 +++++++----- pkg/smartcontract/doc_test.go | 6 +++--- 10 files changed, 23 insertions(+), 15 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index b79417f01..8c7a48623 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -69,3 +69,7 @@ issues: - EXC0003 # test/Test ... consider calling this - EXC0004 # govet - EXC0005 # C-style breaks + exclude-rules: + - linters: + - revive + text: "unused-parameter" diff --git a/internal/contracts/oracle_contract/go.mod b/internal/contracts/oracle_contract/go.mod index fea68d385..4bc15dd05 100644 --- a/internal/contracts/oracle_contract/go.mod +++ b/internal/contracts/oracle_contract/go.mod @@ -1,4 +1,4 @@ -module github.com/nspcc-dev/neo-go/examples/oracle +module github.com/nspcc-dev/neo-go/internal/examples/oracle go 1.17 diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 54a9cd85a..ae3862eee 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -457,7 +457,8 @@ func (v *Version) FromBytes(data []byte) error { return errors.New("missing version") } i := 0 - for ; i < len(data) && data[i] != '\x00'; i++ { + for i < len(data) && data[i] != '\x00' { + i++ } if i == len(data) { diff --git a/pkg/core/interop/storage/find.go b/pkg/core/interop/storage/find.go index 62a59b688..9d2f96668 100644 --- a/pkg/core/interop/storage/find.go +++ b/pkg/core/interop/storage/find.go @@ -120,7 +120,7 @@ func Find(ic *interop.Context) error { // Underlying persistent store is likely to be a private MemCachedStore. Thus, // to avoid concurrent map iteration and map write we need to wait until internal // seek goroutine is finished, because it can access underlying persistent store. - for range seekres { + for range seekres { //nolint:revive //empty-block } }) diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index c56159398..a5bc83d6c 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -282,7 +282,7 @@ func (m *Management) getContractHashes(ic *interop.Context, _ []stackitem.Item) item := istorage.NewIterator(filteredRes, prefix, int64(opts)) ic.RegisterCancelFunc(func() { cancel() - for range seekres { + for range seekres { //nolint:revive //empty-block } }) return stackitem.NewInterop(item) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 756f308ef..b0b8b1f1e 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -1022,7 +1022,7 @@ func (n *NEO) getAllCandidatesCall(ic *interop.Context, _ []stackitem.Item) stac item := istorage.NewIterator(filteredRes, prefix, int64(opts)) ic.RegisterCancelFunc(func() { cancel() - for range seekres { + for range seekres { //nolint:revive //empty-block } }) return stackitem.NewInterop(item) diff --git a/pkg/network/tcp_peer_test.go b/pkg/network/tcp_peer_test.go index 7e03f84bb..993459177 100644 --- a/pkg/network/tcp_peer_test.go +++ b/pkg/network/tcp_peer_test.go @@ -11,7 +11,8 @@ import ( func connReadStub(conn net.Conn) { b := make([]byte, 1024) var err error - for ; err == nil; _, err = conn.Read(b) { + for err == nil { + _, err = conn.Read(b) } } diff --git a/pkg/rpcclient/actor/doc_test.go b/pkg/rpcclient/actor/doc_test.go index a1297b2bc..71035603f 100644 --- a/pkg/rpcclient/actor/doc_test.go +++ b/pkg/rpcclient/actor/doc_test.go @@ -33,7 +33,7 @@ func ExampleActor() { // have a signer with the first wallet account and CalledByEntry scope. res, _ := a.Call(customContract, "method", 1, 2, 3) if res.State != vmstate.Halt.String() { - // The call failed. + panic("failed") } // All of the side-effects in res can be analyzed. diff --git a/pkg/rpcclient/invoker/doc_test.go b/pkg/rpcclient/invoker/doc_test.go index fe01b9490..882f35a65 100644 --- a/pkg/rpcclient/invoker/doc_test.go +++ b/pkg/rpcclient/invoker/doc_test.go @@ -33,9 +33,9 @@ func ExampleInvoker() { // Test-invoke transfer call. res, _ := inv.Call(neo.Hash, "transfer", acc, util.Uint160{1, 2, 3}, 1, nil) if res.State == vmstate.Halt.String() { - // NEO is broken! inv has no signers and transfer requires a witness to be performed. + panic("NEO is broken!") // inv has no signers and transfer requires a witness to be performed. } else { - // OK, this actually should fail. + println("ok") // this actually should fail } // A historic invoker with no signers at block 1000000. @@ -57,9 +57,11 @@ func ExampleInvoker() { // transfer actually returns a value, so check it too. ok, _ := unwrap.Bool(res, nil) if ok { - // OK, as expected. res.Script contains the corresponding - // script and res.GasConsumed has an appropriate system fee - // required for a transaction. + // OK, as expected. + // res.Script contains the corresponding script. + _ = res.Script + // res.GasConsumed has an appropriate system fee required for a transaction. + _ = res.GasConsumed } } diff --git a/pkg/smartcontract/doc_test.go b/pkg/smartcontract/doc_test.go index 39c76dbfb..fe54126be 100644 --- a/pkg/smartcontract/doc_test.go +++ b/pkg/smartcontract/doc_test.go @@ -34,17 +34,17 @@ func ExampleBuilder() { // Actor has an Invoker inside, so we can perform test invocation using the script. res, _ := a.Run(script) if res.State != "HALT" || len(res.Stack) != 2 { - // The script failed completely or didn't return proper number of return values. + panic("failed") // The script failed completely or didn't return proper number of return values. } transferResult, _ := res.Stack[0].TryBool() voteResult, _ := res.Stack[1].TryBool() if !transferResult { - // Transfer failed. + panic("transfer failed") } if !voteResult { - // Vote failed. + panic("vote failed") } b.Reset() // Copy the old script above if you need it! From 856edcca39562ce2da676606d5a2d06f92b30bf4 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 31 Mar 2023 09:54:55 +0300 Subject: [PATCH 008/125] *: bump min supported go version from 1.17 to 1.18 --- examples/engine/go.mod | 2 +- examples/events/go.mod | 2 +- examples/iterator/go.mod | 2 +- examples/nft-d/go.mod | 2 +- examples/nft-nd-nns/go.mod | 2 +- examples/nft-nd-nns/go.sum | 147 ---------------------- examples/nft-nd/go.mod | 2 +- examples/oracle/go.mod | 2 +- examples/runtime/go.mod | 2 +- examples/storage/go.mod | 2 +- examples/timer/go.mod | 2 +- examples/token/go.mod | 2 +- go.mod | 2 +- go.sum | 23 ---- internal/contracts/oracle_contract/go.mod | 2 +- pkg/interop/go.mod | 2 +- 16 files changed, 14 insertions(+), 184 deletions(-) diff --git a/examples/engine/go.mod b/examples/engine/go.mod index ec13bbd62..293079d43 100644 --- a/examples/engine/go.mod +++ b/examples/engine/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/engine -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/events/go.mod b/examples/events/go.mod index 10c7e8519..9f5a5d8ea 100644 --- a/examples/events/go.mod +++ b/examples/events/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/events -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/iterator/go.mod b/examples/iterator/go.mod index 29706059a..17cb817ac 100644 --- a/examples/iterator/go.mod +++ b/examples/iterator/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/iterator -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/nft-d/go.mod b/examples/nft-d/go.mod index 101373d3b..c6869184a 100644 --- a/examples/nft-d/go.mod +++ b/examples/nft-d/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/nft -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/nft-nd-nns/go.mod b/examples/nft-nd-nns/go.mod index 3956674ea..7388cbdd3 100644 --- a/examples/nft-nd-nns/go.mod +++ b/examples/nft-nd-nns/go.mod @@ -1,6 +1,6 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd-nns -go 1.17 +go 1.18 require ( github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 diff --git a/examples/nft-nd-nns/go.sum b/examples/nft-nd-nns/go.sum index 9adab2ac1..1244eceba 100644 --- a/examples/nft-nd-nns/go.sum +++ b/examples/nft-nd-nns/go.sum @@ -33,44 +33,18 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0= -github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig= -github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I= -github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA= -github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= -github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= -github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs= -github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= -github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521073959-f0d4d129b7f1/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -80,36 +54,23 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -121,9 +82,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -136,7 +95,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -154,10 +112,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -169,9 +125,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -183,14 +137,12 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= @@ -199,12 +151,8 @@ github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -213,28 +161,15 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -242,60 +177,33 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw= -github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY= -github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= -github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= -github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= github.com/nspcc-dev/dbft v0.0.0-20221020093431-31c1bbdc74f2 h1:2soBy8en5W4/1Gvbog8RyVpEbarGWZwPxppZjffWzZE= -github.com/nspcc-dev/dbft v0.0.0-20221020093431-31c1bbdc74f2/go.mod h1:g9xisXmX9NP9MjioaTe862n9SlZTrP+6PVUWLBYOr98= -github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= -github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= -github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= -github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 h1:NCIUxkLRB3ovLzM1lvQA6wBNn8fuY7dQx4cMJKLuaAs= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5/go.mod h1:aWrWJZBYO+9kYC4+qJXvEjySW1WIyPnrHpmdrzd5mJY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220927123257-24c107e3a262/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= -github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= -github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= -github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 h1:rpMCoRa7expLc9gMiOP724gz6YSykZzmMALR/CmiwnU= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= -github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= -github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -304,7 +212,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -316,7 +223,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= @@ -324,15 +230,12 @@ github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8 github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -341,24 +244,20 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/twmb/murmur3 v1.1.5 h1:i9OLS9fkuLzBXjt6dptlAEyk58fJsSTXbRg3SgVyqgk= github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= @@ -366,12 +265,6 @@ github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -379,31 +272,21 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -437,10 +320,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -472,15 +353,10 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -496,19 +372,15 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -517,18 +389,14 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -546,21 +414,16 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -576,7 +439,6 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -618,8 +480,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -672,7 +532,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -692,10 +551,7 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -708,10 +564,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -723,7 +577,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/examples/nft-nd/go.mod b/examples/nft-nd/go.mod index a759fd464..0d6c758ad 100644 --- a/examples/nft-nd/go.mod +++ b/examples/nft-nd/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/oracle/go.mod b/examples/oracle/go.mod index fea68d385..71a02b91a 100644 --- a/examples/oracle/go.mod +++ b/examples/oracle/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/oracle -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/runtime/go.mod b/examples/runtime/go.mod index 6c54bb35d..9edc86543 100644 --- a/examples/runtime/go.mod +++ b/examples/runtime/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/runtime -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/storage/go.mod b/examples/storage/go.mod index 58c91afd2..66494077d 100644 --- a/examples/storage/go.mod +++ b/examples/storage/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/storage -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/timer/go.mod b/examples/timer/go.mod index f1c4823f8..17b43d5b1 100644 --- a/examples/timer/go.mod +++ b/examples/timer/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/timer -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/examples/token/go.mod b/examples/token/go.mod index de2cffb75..f26033259 100644 --- a/examples/token/go.mod +++ b/examples/token/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/token -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/go.mod b/go.mod index 5a9e395f9..66a0024df 100644 --- a/go.mod +++ b/go.mod @@ -60,4 +60,4 @@ require ( google.golang.org/protobuf v1.28.1 // indirect ) -go 1.17 +go 1.18 diff --git a/go.sum b/go.sum index 4ade3e148..5b0ca7430 100644 --- a/go.sum +++ b/go.sum @@ -172,7 +172,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -364,8 +363,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -383,7 +380,6 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -402,8 +398,6 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -436,7 +430,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -473,13 +466,9 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -500,7 +489,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -550,24 +538,16 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -577,8 +557,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -627,7 +605,6 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/contracts/oracle_contract/go.mod b/internal/contracts/oracle_contract/go.mod index fea68d385..71a02b91a 100644 --- a/internal/contracts/oracle_contract/go.mod +++ b/internal/contracts/oracle_contract/go.mod @@ -1,5 +1,5 @@ module github.com/nspcc-dev/neo-go/examples/oracle -go 1.17 +go 1.18 require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb diff --git a/pkg/interop/go.mod b/pkg/interop/go.mod index 2e0512988..d4822fa7e 100644 --- a/pkg/interop/go.mod +++ b/pkg/interop/go.mod @@ -1,3 +1,3 @@ module github.com/nspcc-dev/neo-go/pkg/interop -go 1.17 \ No newline at end of file +go 1.18 From 110356857d149d662ce060d0f70f889b4d1ceb66 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 31 Mar 2023 10:03:19 +0300 Subject: [PATCH 009/125] *: drop go 1.17 support for github actions and tests And support go 1.20 for github workflows. --- .github/workflows/build.yml | 4 ++-- .github/workflows/run_tests.yml | 16 ++++++++-------- README.md | 2 +- cli/vm/cli_test.go | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 90e46f211..284c9f3b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: '1.20' cache: true - name: Update Go modules @@ -135,7 +135,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: '1.20' cache: true - name: Login to DockerHub diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 1eb45a742..f4579e1c7 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: '1.20' - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 @@ -103,7 +103,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: '1.20' cache: true - name: Update Go modules @@ -125,20 +125,20 @@ jobs: strategy: matrix: os: [ubuntu-20.04, windows-2022, macos-12] - go_versions: [ '1.17', '1.18', '1.19' ] + go_versions: [ '1.18', '1.19', '1.20' ] exclude: # Only latest Go version for Windows and MacOS. - os: windows-2022 - go_versions: '1.17' + go_versions: '1.18' - os: windows-2022 - go_versions: '1.18' - - os: macos-12 - go_versions: '1.17' + go_versions: '1.19' - os: macos-12 go_versions: '1.18' + - os: macos-12 + go_versions: '1.19' # Exclude latest Go version for Ubuntu as Coverage uses it. - os: ubuntu-20.04 - go_versions: '1.19' + go_versions: '1.20' fail-fast: false steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index bef2d78a2..0fbd656ad 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ NeoGo, `:latest` points to the latest release) or build yourself. ### Building -Building NeoGo requires Go 1.17+ and `make`: +Building NeoGo requires Go 1.18+ and `make`: ``` make diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index 2b6e7db45..bd95b0df7 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -376,7 +376,7 @@ func TestLoad(t *testing.T) { require.NoError(t, os.WriteFile(filenameErr, []byte(src+"invalid_token"), os.ModePerm)) filenameErr = "'" + filenameErr + "'" goMod := []byte(`module test.example/vmcli -go 1.17`) +go 1.18`) require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm)) e := newTestVMCLI(t) @@ -407,7 +407,7 @@ require ( github.com/nspcc-dev/neo-go/pkg/interop v0.0.0 ) replace github.com/nspcc-dev/neo-go/pkg/interop => ` + filepath.Join(wd, "../../pkg/interop") + ` -go 1.17`) +go 1.18`) require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm)) return filename } From 3f6a88c2399a0f9b1b1d7f088407ad6c64943ec9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 31 Mar 2023 10:14:48 +0300 Subject: [PATCH 010/125] .github: bump setup-go version from v3 to v4 --- .github/workflows/build.yml | 4 ++-- .github/workflows/run_tests.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 284c9f3b9..c062c509f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,7 +53,7 @@ jobs: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '1.20' cache: true @@ -133,7 +133,7 @@ jobs: # For proper `deps` make target execution. - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '1.20' cache: true diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index f4579e1c7..bab9e99fb 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' - uses: actions/checkout@v3 @@ -101,7 +101,7 @@ jobs: git submodule update --init - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '1.20' cache: true @@ -146,7 +146,7 @@ jobs: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '${{ matrix.go_versions }}' cache: true From ec002f31df30dea65c4fcdb414facfece2b4db8e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 31 Mar 2023 10:35:38 +0300 Subject: [PATCH 011/125] Dockerfile: build docker images on go 1.20 --- Dockerfile | 2 +- Dockerfile.wsc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 814944743..debcff904 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # Builder image # Keep go version in sync with Build GA job. -FROM golang:1.18-alpine as builder +FROM golang:1.20-alpine as builder # Display go version for information purposes. RUN go version diff --git a/Dockerfile.wsc b/Dockerfile.wsc index 7eef193c3..25b35ff62 100644 --- a/Dockerfile.wsc +++ b/Dockerfile.wsc @@ -43,14 +43,14 @@ RUN $newPath = ('{0}\bin;C:\Program Files\Go\bin;{1}' -f $env:GOPATH, $env:PATH) [Environment]::SetEnvironmentVariable('PATH', $newPath, [EnvironmentVariableTarget]::Machine); # Keep go version in sync with Build GA job. -ENV GOLANG_VERSION=1.19 +ENV GOLANG_VERSION=1.20 -RUN $url = 'https://go.dev/dl/go1.19.windows-amd64.zip'; \ +RUN $url = 'https://go.dev/dl/go1.20.windows-amd64.zip'; \ Write-Host ('Downloading {0} ...' -f $url); \ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; \ Invoke-WebRequest -Uri $url -OutFile 'go.zip'; \ \ - $sha256 = 'bcaaf966f91980d35ae93c37a8fe890e4ddfca19448c0d9f66c027d287e2823a'; \ + $sha256 = 'e8f6d8bbcf3df58d2ba29818e13b04c2e42ba2e4d90d580720b21c34d10bbf68'; \ Write-Host ('Verifying sha256 ({0}) ...' -f $sha256); \ if ((Get-FileHash go.zip -Algorithm sha256).Hash -ne $sha256) { \ Write-Host 'FAILED!'; \ From 83545b8451cfc16b92c73d8ab99ab8e4364f6fc7 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 3 Apr 2023 09:41:32 +0300 Subject: [PATCH 012/125] network: fix Address test failing on Windows/macOS with go 1.20 See the trace: ``` 2023-03-31T07:46:21.1886260Z === RUN TestEncodeDecodeAddress 2023-03-31T07:46:21.1886420Z address_test.go:30: 2023-03-31T07:46:21.1887000Z Error Trace: /Users/runner/work/neo-go/neo-go/pkg/network/payload/address_test.go:30 2023-03-31T07:46:21.1887180Z Error: Not equal: 2023-03-31T07:46:21.1887580Z expected: net.IP{0x7f, 0x0, 0x0, 0x1} 2023-03-31T07:46:21.1888290Z actual : net.IP{0x7f, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 2023-03-31T07:46:21.1888450Z 2023-03-31T07:46:21.1888640Z Diff: 2023-03-31T07:46:21.1888960Z --- Expected 2023-03-31T07:46:21.1889180Z +++ Actual 2023-03-31T07:46:21.1889510Z @@ -1,3 +1,3 @@ 2023-03-31T07:46:21.1889870Z -(net.IP) (len=4) { 2023-03-31T07:46:21.1890530Z - 00000000 7f 00 00 01 |....| 2023-03-31T07:46:21.1891140Z +(net.IP) (len=16) { 2023-03-31T07:46:21.1891780Z + 00000000 7f 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 |................| 2023-03-31T07:46:21.1891970Z } 2023-03-31T07:46:21.1892510Z Test: TestEncodeDecodeAddress 2023-03-31T07:46:21.1892770Z --- FAIL: TestEncodeDecodeAddress (0.00s) ``` I'm still not sure what's the original root of this problem, there's nothing about resolving scheme changes in https://go.dev/doc/go1.20, but it didn't happen earlier and it works as expected in Ubuntu. --- pkg/network/payload/address_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/network/payload/address_test.go b/pkg/network/payload/address_test.go index 843aeecc0..55adb9882 100644 --- a/pkg/network/payload/address_test.go +++ b/pkg/network/payload/address_test.go @@ -25,9 +25,15 @@ func TestEncodeDecodeAddress(t *testing.T) { ) assert.Equal(t, ts.UTC().Unix(), int64(addr.Timestamp)) + + // On Windows or macOS localhost can be resolved to 4-bytes IPv4. + expected := make(net.IP, 16) + copy(expected, e.IP[:]) + aatip := make(net.IP, 16) copy(aatip, addr.IP[:]) - assert.Equal(t, e.IP, aatip) + + assert.Equal(t, expected, aatip) assert.Equal(t, 1, len(addr.Capabilities)) assert.Equal(t, capability.Capability{ Type: capability.TCPServer, From 6b21ad9922ac7333b072f264f14ece5d7cd601c4 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 3 Apr 2023 13:34:24 +0300 Subject: [PATCH 013/125] *: replace `interface{}` with `any` keyword Everywhere including examples, external interop APIs, bindings generators code and in other valuable places. A couple of `interface{}` usages are intentionally left in the CHANGELOG.md, documentation and tests. --- cli/cmdargs/parser.go | 4 +- cli/server/server.go | 2 +- cli/smartcontract/generate_test.go | 10 +- cli/smartcontract/permission.go | 14 +- cli/smartcontract/smart_contract.go | 10 +- cli/smartcontract/smart_contract_test.go | 2 +- cli/smartcontract/testdata/deploy/main.go | 8 +- cli/smartcontract/testdata/deploy/sub/put.go | 2 +- cli/smartcontract/testdata/nameservice/nns.go | 12 +- cli/smartcontract/testdata/nex/nex.go | 12 +- cli/smartcontract/testdata/nonepiter/iter.go | 4 +- .../testdata/structs/rpcbindings.out | 6 +- .../testdata/types/rpcbindings.out | 6 +- cli/smartcontract/testdata/types/types.go | 2 +- cli/smartcontract/testdata/verify.go | 4 +- .../testdata/verifyrpc/verify.go | 6 +- cli/vm/cli.go | 2 +- cli/vm/cli_test.go | 14 +- examples/iterator/iterator.go | 2 +- examples/nft-d/nft.go | 10 +- examples/nft-nd-nns/nns.go | 10 +- examples/nft-nd-nns/nns_test.go | 10 +- examples/nft-nd/nft.go | 6 +- examples/oracle/oracle.go | 2 +- examples/runtime/runtime.go | 4 +- examples/storage/storage.go | 4 +- examples/timer/timer.go | 2 +- examples/token/nep17/nep17.go | 2 +- examples/token/token.go | 2 +- internal/basicchain/basic.go | 6 +- .../testdata/storage/storage_contract.go | 2 +- internal/basicchain/testdata/test_contract.go | 4 +- internal/contracts/oracle_contract/oracle.go | 8 +- internal/fakechain/fakechain.go | 6 +- internal/testserdes/testing.go | 4 +- pkg/compiler/compiler.go | 2 +- pkg/compiler/compiler_test.go | 24 +- pkg/compiler/convert_test.go | 18 +- pkg/compiler/debug.go | 8 +- pkg/compiler/debug_test.go | 2 +- pkg/compiler/for_test.go | 4 +- pkg/compiler/function_call_test.go | 17 +- pkg/compiler/global_test.go | 60 +-- pkg/compiler/interop_test.go | 6 +- pkg/compiler/native_test.go | 2 +- pkg/compiler/nilcheck_test.go | 4 +- pkg/compiler/return_test.go | 2 +- pkg/compiler/syscall_test.go | 2 +- pkg/compiler/testdata/util/equals.go | 2 +- pkg/compiler/vardecl_test.go | 12 +- pkg/compiler/vm_test.go | 12 +- pkg/consensus/consensus.go | 2 +- pkg/consensus/payload.go | 4 +- pkg/core/block/block_test.go | 12 +- pkg/core/block/helper_test.go | 4 +- pkg/core/blockchain.go | 12 +- pkg/core/blockchain_neotest_test.go | 12 +- pkg/core/interop/contract/account_test.go | 10 +- pkg/core/interop/contract/call_test.go | 6 +- pkg/core/interop/crypto/ecdsa_test.go | 2 +- pkg/core/interop/runtime/engine_test.go | 4 +- pkg/core/interop/runtime/ext_test.go | 8 +- pkg/core/interop/storage/interops_test.go | 2 +- pkg/core/mempool/mem_pool.go | 10 +- pkg/core/mempool/mem_pool_test.go | 2 +- pkg/core/mempoolevent/event.go | 2 +- pkg/core/mpt/empty.go | 2 +- pkg/core/mpt/extension.go | 2 +- pkg/core/native/crypto_test.go | 2 +- pkg/core/native/native_test/common_test.go | 2 +- pkg/core/native/native_test/designate_test.go | 4 +- pkg/core/native/native_test/gas_test.go | 4 +- .../native/native_test/management_test.go | 8 +- pkg/core/native/native_test/notary_test.go | 26 +- pkg/core/native/native_test/oracle_test.go | 4 +- pkg/core/native/oracle_types_test.go | 2 +- pkg/core/native/std_test.go | 6 +- pkg/core/transaction/attribute.go | 4 +- pkg/core/transaction/conflicts.go | 2 +- pkg/core/transaction/not_valid_before.go | 2 +- pkg/core/transaction/notary_assisted.go | 2 +- pkg/core/transaction/oracle.go | 2 +- pkg/core/transaction/oracle_test.go | 2 +- pkg/core/transaction/reserved.go | 2 +- pkg/core/transaction/witness_condition.go | 2 +- pkg/crypto/keys/publickey.go | 2 +- pkg/encoding/fixedn/fixed8.go | 4 +- pkg/interop/contract/contract.go | 2 +- pkg/interop/convert/convert.go | 8 +- pkg/interop/doc.go | 1 + pkg/interop/iterator/iterator.go | 2 +- pkg/interop/lib/contract/contract.go | 2 +- pkg/interop/native/gas/gas.go | 2 +- pkg/interop/native/ledger/block.go | 2 +- pkg/interop/native/ledger/ledger.go | 4 +- .../native/ledger/transaction_signer.go | 2 +- pkg/interop/native/management/contract.go | 2 +- pkg/interop/native/management/management.go | 4 +- pkg/interop/native/neo/neo.go | 2 +- pkg/interop/native/oracle/oracle.go | 4 +- pkg/interop/native/std/std.go | 9 +- pkg/interop/neogointernal/call.go | 4 +- pkg/interop/neogointernal/opcode.go | 8 +- pkg/interop/neogointernal/syscall.go | 18 +- pkg/interop/runtime/runtime.go | 8 +- pkg/interop/storage/storage.go | 16 +- pkg/interop/types.go | 20 +- pkg/interop/util/util.go | 4 +- pkg/io/binaryReader.go | 2 +- pkg/io/binaryWriter.go | 2 +- pkg/io/size.go | 2 +- pkg/io/size_test.go | 4 +- pkg/neorpc/result/validate_address.go | 4 +- pkg/neorpc/rpcevent/filter.go | 4 +- pkg/neorpc/rpcevent/filter_test.go | 8 +- pkg/neorpc/types.go | 10 +- pkg/neotest/basic.go | 14 +- pkg/neotest/client.go | 14 +- pkg/network/server.go | 8 +- pkg/rpcclient/actor/actor.go | 4 +- pkg/rpcclient/actor/maker.go | 6 +- pkg/rpcclient/actor/waiter.go | 4 +- pkg/rpcclient/client.go | 4 +- pkg/rpcclient/gas/gas_test.go | 2 +- pkg/rpcclient/helper.go | 2 +- pkg/rpcclient/invoker/invoker.go | 6 +- pkg/rpcclient/local.go | 2 +- pkg/rpcclient/management/management.go | 18 +- pkg/rpcclient/management/management_test.go | 14 +- pkg/rpcclient/neo/neo.go | 10 +- pkg/rpcclient/neo/neo_test.go | 10 +- pkg/rpcclient/nep.go | 2 +- pkg/rpcclient/nep11.go | 6 +- pkg/rpcclient/nep11/base.go | 10 +- pkg/rpcclient/nep11/base_test.go | 6 +- pkg/rpcclient/nep11/divisible.go | 6 +- pkg/rpcclient/nep11/divisible_test.go | 2 +- pkg/rpcclient/nep17.go | 6 +- pkg/rpcclient/nep17/nep17.go | 8 +- pkg/rpcclient/nep17/nep17_test.go | 12 +- pkg/rpcclient/neptoken/base.go | 2 +- pkg/rpcclient/neptoken/base_test.go | 2 +- pkg/rpcclient/nns/contract_test.go | 4 +- pkg/rpcclient/notary/contract.go | 8 +- pkg/rpcclient/notary/contract_test.go | 8 +- pkg/rpcclient/oracle/oracle.go | 8 +- pkg/rpcclient/oracle/oracle_test.go | 8 +- pkg/rpcclient/policy/policy.go | 8 +- pkg/rpcclient/policy/policy_test.go | 8 +- pkg/rpcclient/rolemgmt/roles.go | 8 +- pkg/rpcclient/rolemgmt/roles_test.go | 8 +- pkg/rpcclient/rpc.go | 100 ++--- pkg/rpcclient/rpc_test.go | 408 +++++++++--------- pkg/rpcclient/unwrap/unwrap_test.go | 42 +- pkg/rpcclient/wsclient.go | 74 ++-- .../helpers/rpcbroadcaster/broadcaster.go | 6 +- pkg/services/helpers/rpcbroadcaster/client.go | 6 +- pkg/services/notary/core_test.go | 6 +- pkg/services/oracle/broadcaster/oracle.go | 4 +- pkg/services/oracle/filter.go | 2 +- pkg/services/oracle/jsonpath/jsonpath.go | 44 +- pkg/services/oracle/jsonpath/jsonpath_test.go | 4 +- pkg/services/oracle/oracle_test.go | 8 +- pkg/services/rpcsrv/client_test.go | 2 +- pkg/services/rpcsrv/error.go | 2 +- pkg/services/rpcsrv/params/param.go | 4 +- pkg/services/rpcsrv/params/params.go | 2 +- pkg/services/rpcsrv/params/params_test.go | 4 +- pkg/services/rpcsrv/server.go | 136 +++--- pkg/services/rpcsrv/server_test.go | 254 +++++------ pkg/services/rpcsrv/subscription.go | 4 +- pkg/services/rpcsrv/subscription_test.go | 62 +-- pkg/services/rpcsrv/tokens.go | 6 +- pkg/services/stateroot/service_test.go | 6 +- pkg/smartcontract/binding/generate.go | 8 +- pkg/smartcontract/binding/override.go | 4 +- pkg/smartcontract/builder.go | 4 +- pkg/smartcontract/callflag/call_flags.go | 4 +- pkg/smartcontract/entry.go | 6 +- pkg/smartcontract/manifest/manifest.go | 2 +- pkg/smartcontract/manifest/permission.go | 6 +- pkg/smartcontract/manifest/permission_test.go | 2 +- pkg/smartcontract/param_type.go | 6 +- pkg/smartcontract/param_type_test.go | 2 +- pkg/smartcontract/parameter.go | 12 +- pkg/smartcontract/parameter_test.go | 12 +- pkg/smartcontract/rpcbinding/binding.go | 22 +- pkg/util/uint160.go | 4 +- pkg/vm/emit/emit.go | 6 +- pkg/vm/emit/emit_test.go | 2 +- pkg/vm/exception.go | 2 +- pkg/vm/json_test.go | 2 +- pkg/vm/opcodebench_test.go | 20 +- pkg/vm/stack.go | 6 +- pkg/vm/stackitem/item.go | 30 +- pkg/vm/stackitem/item_test.go | 4 +- pkg/vm/stackitem/json_test.go | 2 +- pkg/vm/vm.go | 6 +- pkg/vm/vm_test.go | 160 +++---- 199 files changed, 1256 insertions(+), 1231 deletions(-) diff --git a/cli/cmdargs/parser.go b/cli/cmdargs/parser.go index b90fa60d7..b26c2ee91 100644 --- a/cli/cmdargs/parser.go +++ b/cli/cmdargs/parser.go @@ -230,9 +230,9 @@ func parseCosigner(c string) (transaction.Signer, error) { } // GetDataFromContext returns data parameter from context args. -func GetDataFromContext(ctx *cli.Context) (int, interface{}, *cli.ExitError) { +func GetDataFromContext(ctx *cli.Context) (int, any, *cli.ExitError) { var ( - data interface{} + data any offset int params []smartcontract.Parameter err error diff --git a/cli/server/server.go b/cli/server/server.go index 2856c4f57..bcea6b115 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -662,7 +662,7 @@ func initBlockChain(cfg config.Config, log *zap.Logger) (*core.Blockchain, stora chain, err := core.NewBlockchain(store, cfg.Blockchain(), log) if err != nil { errText := "could not initialize blockchain: %w" - errArgs := []interface{}{err} + errArgs := []any{err} closeErr := store.Close() if closeErr != nil { errText += "; failed to close the DB: %w" diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index 1b60f830e..ae0ef741f 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -187,7 +187,7 @@ func Zum(typev int, typev_ int, funcv int) int { } // JustExecute invokes ` + "`justExecute`" + ` method of contract. -func JustExecute(arr []interface{}) { +func JustExecute(arr []any) { neogointernal.CallWithTokenNoRet(Hash, "justExecute", int(contract.All), arr) } @@ -197,7 +197,7 @@ func GetPublicKey() interop.PublicKey { } // OtherTypes invokes ` + "`otherTypes`" + ` method of contract. -func OtherTypes(ctr interop.Hash160, tx interop.Hash256, sig interop.Signature, data interface{}) bool { +func OtherTypes(ctr interop.Hash160, tx interop.Hash256, sig interop.Signature, data any) bool { return neogointernal.CallWithToken(Hash, "otherTypes", int(contract.All), ctr, tx, sig, data).(bool) } @@ -212,8 +212,8 @@ func GetFromMap(intMap map[string]int, indices []string) []int { } // DoSomething invokes ` + "`doSomething`" + ` method of contract. -func DoSomething(bytes []byte, str string) interface{} { - return neogointernal.CallWithToken(Hash, "doSomething", int(contract.ReadStates), bytes, str).(interface{}) +func DoSomething(bytes []byte, str string) any { + return neogointernal.CallWithToken(Hash, "doSomething", int(contract.ReadStates), bytes, str).(any) } // GetBlockWrapper invokes ` + "`getBlockWrapper`" + ` method of contract. @@ -303,7 +303,7 @@ var Hash = util.Uint160{0x4, 0x8, 0x15, 0x16, 0x23, 0x42, 0x43, 0x44, 0x0, 0x1, // Invoker is used by ContractReader to call various safe methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // ContractReader implements safe contract methods. diff --git a/cli/smartcontract/permission.go b/cli/smartcontract/permission.go index 0c4608b84..cfb28ad0b 100644 --- a/cli/smartcontract/permission.go +++ b/cli/smartcontract/permission.go @@ -19,7 +19,7 @@ const ( permMethodKey = "methods" ) -func (p permission) MarshalYAML() (interface{}, error) { +func (p permission) MarshalYAML() (any, error) { m := yaml.Node{Kind: yaml.MappingNode} switch p.Contract.Type { case manifest.PermissionWildcard: @@ -36,7 +36,7 @@ func (p permission) MarshalYAML() (interface{}, error) { return nil, fmt.Errorf("invalid permission type: %d", p.Contract.Type) } - var val interface{} = "*" + var val any = "*" if !p.Methods.IsWildcard() { val = p.Methods.Value } @@ -53,8 +53,8 @@ func (p permission) MarshalYAML() (interface{}, error) { return m, nil } -func (p *permission) UnmarshalYAML(unmarshal func(interface{}) error) error { - var m map[string]interface{} +func (p *permission) UnmarshalYAML(unmarshal func(any) error) error { + var m map[string]any if err := unmarshal(&m); err != nil { return err } @@ -66,7 +66,7 @@ func (p *permission) UnmarshalYAML(unmarshal func(interface{}) error) error { return p.fillMethods(m) } -func (p *permission) fillType(m map[string]interface{}) error { +func (p *permission) fillType(m map[string]any) error { vh, ok1 := m[permHashKey] vg, ok2 := m[permGroupKey] switch { @@ -104,7 +104,7 @@ func (p *permission) fillType(m map[string]interface{}) error { return nil } -func (p *permission) fillMethods(m map[string]interface{}) error { +func (p *permission) fillMethods(m map[string]any) error { methods, ok := m[permMethodKey] if !ok { return errors.New("'methods' field is missing from permission") @@ -116,7 +116,7 @@ func (p *permission) fillMethods(m map[string]interface{}) error { p.Methods.Value = nil return nil } - case []interface{}: + case []any: ms := make([]string, len(mt)) for i := range mt { ms[i], ok = mt[i].(string) diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 61d026bc9..818f07ac2 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -81,7 +81,7 @@ func init() { } // RuntimeNotify sends runtime notification with "Hello world!" name -func RuntimeNotify(args []interface{}) { +func RuntimeNotify(args []any) { runtime.Notify(notificationName, args) }` ) @@ -495,7 +495,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { err error exitErr *cli.ExitError operation string - params []interface{} + params []any paramsStart = 1 scParams []smartcontract.Parameter cosigners []transaction.Signer @@ -521,7 +521,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { if err != nil { return cli.NewExitError(err, 1) } - params = make([]interface{}, len(scParams)) + params = make([]any, len(scParams)) for i := range scParams { params[i] = scParams[i] } @@ -548,7 +548,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { return invokeWithArgs(ctx, acc, w, script, operation, params, cosigners) } -func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet, script util.Uint160, operation string, params []interface{}, cosigners []transaction.Signer) error { +func invokeWithArgs(ctx *cli.Context, acc *wallet.Account, wall *wallet.Wallet, script util.Uint160, operation string, params []any, cosigners []transaction.Signer) error { var ( err error signersAccounts []actor.SignerAccount @@ -787,7 +787,7 @@ func contractDeploy(ctx *cli.Context) error { return cli.NewExitError(fmt.Errorf("failed to read manifest file: %w", err), 1) } - var appCallParams = []interface{}{f, manifestBytes} + var appCallParams = []any{f, manifestBytes} signOffset, data, err := cmdargs.ParseParams(ctx.Args(), true) if err != nil { diff --git a/cli/smartcontract/smart_contract_test.go b/cli/smartcontract/smart_contract_test.go index a2b119dfe..cd89b16f6 100644 --- a/cli/smartcontract/smart_contract_test.go +++ b/cli/smartcontract/smart_contract_test.go @@ -51,7 +51,7 @@ func init() { } // RuntimeNotify sends runtime notification with "Hello world!" name -func RuntimeNotify(args []interface{}) { +func RuntimeNotify(args []any) { runtime.Notify(notificationName, args) }`, string(main)) diff --git a/cli/smartcontract/testdata/deploy/main.go b/cli/smartcontract/testdata/deploy/main.go index 42bf4c06f..c45b459e0 100644 --- a/cli/smartcontract/testdata/deploy/main.go +++ b/cli/smartcontract/testdata/deploy/main.go @@ -13,7 +13,7 @@ var key = "key" const mgmtKey = "mgmt" -func _deploy(data interface{}, isUpdate bool) { +func _deploy(data any, isUpdate bool) { var value string ctx := storage.GetContext() @@ -25,7 +25,7 @@ func _deploy(data interface{}, isUpdate bool) { storage.Put(ctx, mgmtKey, sh) if data != nil { - arr := data.([]interface{}) + arr := data.([]any) for i := 0; i < len(arr)-1; i += 2 { storage.Put(ctx, arr[i], arr[i+1]) } @@ -70,12 +70,12 @@ func GetValueWithKey(key string) string { } // TestFind finds items with the specified prefix. -func TestFind(f storage.FindFlags) []interface{} { +func TestFind(f storage.FindFlags) []any { ctx := storage.GetContext() storage.Put(ctx, "findkey1", "value1") storage.Put(ctx, "findkey2", "value2") - var result []interface{} + var result []any iter := storage.Find(ctx, "findkey", f) for iterator.Next(iter) { result = append(result, iterator.Value(iter)) diff --git a/cli/smartcontract/testdata/deploy/sub/put.go b/cli/smartcontract/testdata/deploy/sub/put.go index e21b3cbcf..08f634741 100644 --- a/cli/smartcontract/testdata/deploy/sub/put.go +++ b/cli/smartcontract/testdata/deploy/sub/put.go @@ -4,7 +4,7 @@ import "github.com/nspcc-dev/neo-go/pkg/interop/storage" var Key = "sub" -func _deploy(data interface{}, isUpdate bool) { +func _deploy(data any, isUpdate bool) { ctx := storage.GetContext() value := "sub create" if isUpdate { diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index d156d985c..efdfcabfe 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -27,11 +27,11 @@ type Actor interface { nep11.Actor - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) } @@ -155,14 +155,14 @@ func (c *Contract) AddRootUnsigned(root string) (*transaction.Transaction, error // SetPrice creates a transaction invoking `setPrice` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) SetPrice(priceList []interface{}) (util.Uint256, uint32, error) { +func (c *Contract) SetPrice(priceList []any) (util.Uint256, uint32, error) { return c.actor.SendCall(Hash, "setPrice", priceList) } // SetPriceTransaction creates a transaction invoking `setPrice` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. -func (c *Contract) SetPriceTransaction(priceList []interface{}) (*transaction.Transaction, error) { +func (c *Contract) SetPriceTransaction(priceList []any) (*transaction.Transaction, error) { return c.actor.MakeCall(Hash, "setPrice", priceList) } @@ -170,7 +170,7 @@ func (c *Contract) SetPriceTransaction(priceList []interface{}) (*transaction.Tr // This transaction is not signed, it's simply returned to the caller. // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) SetPriceUnsigned(priceList []interface{}) (*transaction.Transaction, error) { +func (c *Contract) SetPriceUnsigned(priceList []any) (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(Hash, "setPrice", nil, priceList) } diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 2ad6941db..4a4a46de4 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -24,11 +24,11 @@ type Actor interface { nep17.Actor - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) } @@ -168,14 +168,14 @@ func (c *Contract) MaxSupplyUnsigned() (*transaction.Transaction, error) { // Mint creates a transaction invoking `mint` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Mint(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data interface{}) (util.Uint256, uint32, error) { +func (c *Contract) Mint(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data any) (util.Uint256, uint32, error) { return c.actor.SendCall(Hash, "mint", from, to, amount, swapId, signature, data) } // MintTransaction creates a transaction invoking `mint` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. -func (c *Contract) MintTransaction(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data interface{}) (*transaction.Transaction, error) { +func (c *Contract) MintTransaction(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data any) (*transaction.Transaction, error) { return c.actor.MakeCall(Hash, "mint", from, to, amount, swapId, signature, data) } @@ -183,7 +183,7 @@ func (c *Contract) MintTransaction(from util.Uint160, to util.Uint160, amount *b // This transaction is not signed, it's simply returned to the caller. // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) MintUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data interface{}) (*transaction.Transaction, error) { +func (c *Contract) MintUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data any) (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(Hash, "mint", nil, from, to, amount, swapId, signature, data) } diff --git a/cli/smartcontract/testdata/nonepiter/iter.go b/cli/smartcontract/testdata/nonepiter/iter.go index c7323fb56..e04f6953c 100644 --- a/cli/smartcontract/testdata/nonepiter/iter.go +++ b/cli/smartcontract/testdata/nonepiter/iter.go @@ -14,8 +14,8 @@ var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xa // Invoker is used by ContractReader to call various safe methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) - CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) + CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) TerminateSession(sessionID uuid.UUID) error TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) } diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index a8330072b..cbe2a6e67 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -69,7 +69,7 @@ type LedgerTransactionSigner struct { // LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. type LedgerWitnessCondition struct { Type *big.Int - Value interface{} + Value any } // LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. @@ -114,7 +114,7 @@ type ManagementManifest struct { ABI *ManagementABI Permissions []*ManagementPermission Trusts []util.Uint160 - Extra interface{} + Extra any } // ManagementMethod is a contract-specific management.Method type used by its methods. @@ -156,7 +156,7 @@ type StructsInternal struct { } // Invoker is used by ContractReader to call various safe methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // ContractReader implements safe contract methods. diff --git a/cli/smartcontract/testdata/types/rpcbindings.out b/cli/smartcontract/testdata/types/rpcbindings.out index 2b419a2ad..e6a14ecea 100644 --- a/cli/smartcontract/testdata/types/rpcbindings.out +++ b/cli/smartcontract/testdata/types/rpcbindings.out @@ -18,7 +18,7 @@ var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xa // Invoker is used by ContractReader to call various safe methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // ContractReader implements safe contract methods. @@ -91,8 +91,8 @@ func (c *ContractReader) AAAStrings(s [][][]string) ([][][]string, error) { } // Any invokes `any` method of contract. -func (c *ContractReader) Any(a interface{}) (interface{}, error) { - return func (item stackitem.Item, err error) (interface{}, error) { +func (c *ContractReader) Any(a any) (any, error) { + return func (item stackitem.Item, err error) (any, error) { if err != nil { return nil, err } diff --git a/cli/smartcontract/testdata/types/types.go b/cli/smartcontract/testdata/types/types.go index f59aac0e8..c8d819dd5 100644 --- a/cli/smartcontract/testdata/types/types.go +++ b/cli/smartcontract/testdata/types/types.go @@ -20,7 +20,7 @@ func String(s string) string { return "" } -func Any(a interface{}) interface{} { +func Any(a any) any { return nil } diff --git a/cli/smartcontract/testdata/verify.go b/cli/smartcontract/testdata/verify.go index 3f399c9f6..dabc0ab7a 100644 --- a/cli/smartcontract/testdata/verify.go +++ b/cli/smartcontract/testdata/verify.go @@ -9,12 +9,12 @@ func Verify() bool { return true } -func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { +func OnNEP17Payment(from interop.Hash160, amount int, data any) { } // OnNEP11Payment notifies about NEP-11 payment. You don't call this method directly, // instead it's called by NEP-11 contract when you transfer funds from your address // to the address of this NFT contract. -func OnNEP11Payment(from interop.Hash160, amount int, token []byte, data interface{}) { +func OnNEP11Payment(from interop.Hash160, amount int, token []byte, data any) { runtime.Notify("OnNEP11Payment", from, amount, token, data) } diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index 8b8f07961..4a9af0156 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -12,11 +12,11 @@ var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xa // Actor is used by Contract to call state-changing methods. type Actor interface { - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) } diff --git a/cli/vm/cli.go b/cli/vm/cli.go index d7a3c07f8..a8c246b66 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -483,7 +483,7 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg shell: ctl, } - vmcli.shell.Metadata = map[string]interface{}{ + vmcli.shell.Metadata = map[string]any{ chainKey: chain, chainCfgKey: cfg, icKey: ic, diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index bd95b0df7..60f0647c3 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -180,9 +180,9 @@ func (e *executor) checkError(t *testing.T, expectedErr error) { require.True(t, strings.HasPrefix(line, expected), fmt.Errorf("expected `%s`, got `%s`", expected, line)) } -func (e *executor) checkStack(t *testing.T, items ...interface{}) { +func (e *executor) checkStack(t *testing.T, items ...any) { d := json.NewDecoder(e.out) - var actual interface{} + var actual any require.NoError(t, d.Decode(&actual)) rawActual, err := json.Marshal(actual) require.NoError(t, err) @@ -210,7 +210,7 @@ func (e *executor) checkEvents(t *testing.T, isKeywordExpected bool, events ...s e.checkNextLine(t, "Events:") } d := json.NewDecoder(e.out) - var actual interface{} + var actual any require.NoError(t, d.Decode(&actual)) rawActual, err := json.Marshal(actual) require.NoError(t, err) @@ -249,9 +249,9 @@ func (e *executor) checkChange(t *testing.T, c storageChange) { } } -func (e *executor) checkSlot(t *testing.T, items ...interface{}) { +func (e *executor) checkSlot(t *testing.T, items ...any) { d := json.NewDecoder(e.out) - var actual interface{} + var actual any require.NoError(t, d.Decode(&actual)) rawActual, err := json.Marshal(actual) require.NoError(t, err) @@ -532,7 +532,7 @@ func TestRunWithDifferentArguments(t *testing.T) { func GetString(arg string) string { return arg } - func GetArr(arg []interface{}) []interface{}{ + func GetArr(arg []any) []any{ return arg }` @@ -933,7 +933,7 @@ func TestEvents(t *testing.T) { script := io.NewBufBinWriter() h, err := e.cli.chain.GetContractScriptHash(2) // examples/runtime/runtime.go require.NoError(t, err) - emit.AppCall(script.BinWriter, h, "notify", callflag.All, []interface{}{true, 5}) + emit.AppCall(script.BinWriter, h, "notify", callflag.All, []any{true, 5}) e.runProg(t, "loadhex "+hex.EncodeToString(script.Bytes()), "run", diff --git a/examples/iterator/iterator.go b/examples/iterator/iterator.go index fe53881b8..f5e91ea37 100644 --- a/examples/iterator/iterator.go +++ b/examples/iterator/iterator.go @@ -7,7 +7,7 @@ import ( ) // _deploy primes contract's storage with some data to be used later. -func _deploy(_ interface{}, _ bool) { +func _deploy(_ any, _ bool) { ctx := storage.GetContext() // RW context. storage.Put(ctx, "foo1", "1") storage.Put(ctx, "foo2", "2") diff --git a/examples/nft-d/nft.go b/examples/nft-d/nft.go index 66afd2ef6..7a1d1e8f0 100644 --- a/examples/nft-d/nft.go +++ b/examples/nft-d/nft.go @@ -172,7 +172,7 @@ func tokensOf(ctx storage.Context, holder interop.Hash160) iterator.Iterator { // Transfer token from its owner to another user, if there's one owner of the token. // It will return false if token is shared between multiple owners. -func Transfer(to interop.Hash160, token []byte, data interface{}) bool { +func Transfer(to interop.Hash160, token []byte, data any) bool { if len(to) != interop.Hash160Len { panic("invalid 'to' address") } @@ -215,7 +215,7 @@ func Transfer(to interop.Hash160, token []byte, data interface{}) bool { } // postTransfer emits Transfer event and calls onNEP11Payment if needed. -func postTransfer(from interop.Hash160, to interop.Hash160, token []byte, amount int, data interface{}) { +func postTransfer(from interop.Hash160, to interop.Hash160, token []byte, amount int, data any) { runtime.Notify("Transfer", from, to, amount, token) if management.GetContract(to) != nil { contract.Call(to, "onNEP11Payment", contract.All, from, amount, token, data) @@ -263,7 +263,7 @@ func isTokenValid(ctx storage.Context, tokenID []byte) bool { // TransferDivisible token from its owner to another user, notice that it only has three // parameters because token owner can be deduced from token ID itself. -func TransferDivisible(from, to interop.Hash160, amount int, token []byte, data interface{}) bool { +func TransferDivisible(from, to interop.Hash160, amount int, token []byte, data any) bool { if len(from) != interop.Hash160Len { panic("invalid 'from' address") } @@ -350,7 +350,7 @@ func removeOwner(ctx storage.Context, token []byte, holder interop.Hash160) { // OnNEP17Payment mints tokens if at least 10 GAS is provided. You don't call // this method directly, instead it's called by GAS contract when you transfer // GAS from your address to the address of this NFT contract. -func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { +func OnNEP17Payment(from interop.Hash160, amount int, data any) { defer func() { if r := recover(); r != nil { runtime.Log(r.(string)) @@ -364,7 +364,7 @@ func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { if amount < 10_00000000 { panic("minting NFSO costs at least 10 GAS") } - tokenInfo := data.([]interface{}) + tokenInfo := data.([]any) if len(tokenInfo) != 2 { panic("invalid 'data'") } diff --git a/examples/nft-nd-nns/nns.go b/examples/nft-nd-nns/nns.go index 5a6800d47..b1dacb7a5 100644 --- a/examples/nft-nd-nns/nns.go +++ b/examples/nft-nd-nns/nns.go @@ -79,7 +79,7 @@ func Update(nef []byte, manifest string) { } // _deploy initializes defaults (total supply and registration price) on contract deploy. -func _deploy(data interface{}, isUpdate bool) { +func _deploy(data any, isUpdate bool) { if isUpdate { return } @@ -112,10 +112,10 @@ func OwnerOf(tokenID []byte) interop.Hash160 { } // Properties returns domain name and expiration date of the specified domain. -func Properties(tokenID []byte) map[string]interface{} { +func Properties(tokenID []byte) map[string]any { ctx := storage.GetReadOnlyContext() ns := getNameState(ctx, tokenID) - return map[string]interface{}{ + return map[string]any{ "name": ns.Name, "expiration": ns.Expiration, "admin": ns.Admin, @@ -151,7 +151,7 @@ func TokensOf(owner interop.Hash160) iterator.Iterator { } // Transfer transfers domain with the specified name to new owner. -func Transfer(to interop.Hash160, tokenID []byte, data interface{}) bool { +func Transfer(to interop.Hash160, tokenID []byte, data any) bool { if !isValid(to) { panic(`invalid receiver`) } @@ -398,7 +398,7 @@ func updateBalance(ctx storage.Context, tokenId []byte, acc interop.Hash160, dif // postTransfer sends Transfer notification to the network and calls onNEP11Payment // method. -func postTransfer(from, to interop.Hash160, tokenID []byte, data interface{}) { +func postTransfer(from, to interop.Hash160, tokenID []byte, data any) { runtime.Notify("Transfer", from, to, 1, tokenID) if management.GetContract(to) != nil { contract.Call(to, "onNEP11Payment", contract.All, from, 1, tokenID, data) diff --git a/examples/nft-nd-nns/nns_test.go b/examples/nft-nd-nns/nns_test.go index 9032bb9d2..5d4362105 100644 --- a/examples/nft-nd-nns/nns_test.go +++ b/examples/nft-nd-nns/nns_test.go @@ -190,8 +190,8 @@ func TestRegisterAndRenew(t *testing.T) { t.Run("invalid token ID", func(t *testing.T) { c.InvokeFail(t, "token not found", "properties", "not.exists") c.InvokeFail(t, "token not found", "ownerOf", "not.exists") - c.InvokeFail(t, "invalid conversion", "properties", []interface{}{}) - c.InvokeFail(t, "invalid conversion", "ownerOf", []interface{}{}) + c.InvokeFail(t, "invalid conversion", "properties", []any{}) + c.InvokeFail(t, "invalid conversion", "ownerOf", []any{}) }) // Renew @@ -294,7 +294,7 @@ func TestSetGetRecord(t *testing.T) { {Type: nns.AAAA, Name: "2001::13.1.68.3", ShouldFail: true}, } for _, testCase := range testCases { - args := []interface{}{"neo.com", int64(testCase.Type), testCase.Name} + args := []any{"neo.com", int64(testCase.Type), testCase.Name} t.Run(testCase.Name, func(t *testing.T) { if testCase.ShouldFail { c.InvokeFail(t, "", "setRecord", args...) @@ -377,7 +377,7 @@ func TestTransfer(t *testing.T) { ctr = neotest.CompileSource(t, e.CommitteeHash, strings.NewReader(`package foo import "github.com/nspcc-dev/neo-go/pkg/interop" - func OnNEP11Payment(from interop.Hash160, amount int, token []byte, data interface{}) {}`), + func OnNEP11Payment(from interop.Hash160, amount int, token []byte, data any) {}`), &compiler.Options{Name: "foo"}) e.DeployContract(t, ctr, nil) cTo.Invoke(t, true, "transfer", ctr.Hash, []byte("neo.com"), nil) @@ -404,7 +404,7 @@ func TestTokensOf(t *testing.T) { testTokensOf(t, c, [][]byte{}, util.Uint160{}.BytesBE()) // empty hash is a valid hash still } -func testTokensOf(t *testing.T, c *neotest.ContractInvoker, result [][]byte, args ...interface{}) { +func testTokensOf(t *testing.T, c *neotest.ContractInvoker, result [][]byte, args ...any) { method := "tokensOf" if len(args) == 0 { method = "tokens" diff --git a/examples/nft-nd/nft.go b/examples/nft-nd/nft.go index f4f87b743..d98646d10 100644 --- a/examples/nft-nd/nft.go +++ b/examples/nft-nd/nft.go @@ -173,7 +173,7 @@ func OwnerOf(token []byte) interop.Hash160 { // Transfer token from its owner to another user, notice that it only has three // parameters because token owner can be deduced from token ID itself. -func Transfer(to interop.Hash160, token []byte, data interface{}) bool { +func Transfer(to interop.Hash160, token []byte, data any) bool { if len(to) != 20 { panic("invalid 'to' address") } @@ -199,7 +199,7 @@ func Transfer(to interop.Hash160, token []byte, data interface{}) bool { } // postTransfer emits Transfer event and calls onNEP11Payment if needed. -func postTransfer(from interop.Hash160, to interop.Hash160, token []byte, data interface{}) { +func postTransfer(from interop.Hash160, to interop.Hash160, token []byte, data any) { runtime.Notify("Transfer", from, to, 1, token) if management.GetContract(to) != nil { contract.Call(to, "onNEP11Payment", contract.All, from, 1, token, data) @@ -209,7 +209,7 @@ func postTransfer(from interop.Hash160, to interop.Hash160, token []byte, data i // OnNEP17Payment mints tokens if at least 10 GAS is provided. You don't call // this method directly, instead it's called by GAS contract when you transfer // GAS from your address to the address of this NFT contract. -func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { +func OnNEP17Payment(from interop.Hash160, amount int, data any) { defer func() { if r := recover(); r != nil { runtime.Log(r.(string)) diff --git a/examples/oracle/oracle.go b/examples/oracle/oracle.go index 62e711454..5c5807351 100644 --- a/examples/oracle/oracle.go +++ b/examples/oracle/oracle.go @@ -23,7 +23,7 @@ func FilteredRequest(url string, filter []byte) { // OracleCallback is called by Oracle native contract when request is finished. // It either throws an error (if the result is not successful) or logs the data // got as a result. -func OracleCallback(url string, data interface{}, code int, res []byte) { +func OracleCallback(url string, data any, code int, res []byte) { // This function shouldn't be called directly, we only expect oracle native // contract to be calling it. callingHash := runtime.GetCallingScriptHash() diff --git a/examples/runtime/runtime.go b/examples/runtime/runtime.go index 9ecdd559d..0fc7df18d 100644 --- a/examples/runtime/runtime.go +++ b/examples/runtime/runtime.go @@ -22,7 +22,7 @@ func init() { // _deploy is called after contract deployment or update, it'll be called // in deployment transaction and if call update method of this contract. -func _deploy(_ interface{}, isUpdate bool) { +func _deploy(_ any, isUpdate bool) { if isUpdate { Log("_deploy method called after contract update") return @@ -46,7 +46,7 @@ func Log(message string) { } // Notify emits an event with the specified data. -func Notify(event interface{}) { +func Notify(event any) { runtime.Notify("Event", event) } diff --git a/examples/storage/storage.go b/examples/storage/storage.go index 7f7c1c267..42416dd82 100644 --- a/examples/storage/storage.go +++ b/examples/storage/storage.go @@ -29,12 +29,12 @@ func PutDefault(value []byte) []byte { } // Get returns the value at the passed key. -func Get(key []byte) interface{} { +func Get(key []byte) any { return storage.Get(ctx, key) } // GetDefault returns the value at the default key. -func GetDefault() interface{} { +func GetDefault() any { return storage.Get(ctx, defaultKey) } diff --git a/examples/timer/timer.go b/examples/timer/timer.go index 3e09d39ba..7898b90e0 100644 --- a/examples/timer/timer.go +++ b/examples/timer/timer.go @@ -25,7 +25,7 @@ func init() { ctx = storage.GetContext() } -func _deploy(_ interface{}, isUpdate bool) { +func _deploy(_ any, isUpdate bool) { if isUpdate { ticksLeft := storage.Get(ctx, ticksKey).(int) + 1 storage.Put(ctx, ticksKey, ticksLeft) diff --git a/examples/token/nep17/nep17.go b/examples/token/nep17/nep17.go index 7d4154766..dc4702d5a 100644 --- a/examples/token/nep17/nep17.go +++ b/examples/token/nep17/nep17.go @@ -46,7 +46,7 @@ func (t Token) BalanceOf(ctx storage.Context, holder []byte) int { } // Transfer token from one user to another -func (t Token) Transfer(ctx storage.Context, from, to interop.Hash160, amount int, data interface{}) bool { +func (t Token) Transfer(ctx storage.Context, from, to interop.Hash160, amount int, data any) bool { amountFrom := t.CanTransfer(ctx, from, to, amount) if amountFrom == -1 { return false diff --git a/examples/token/token.go b/examples/token/token.go index 7cede5d3f..e49970bda 100644 --- a/examples/token/token.go +++ b/examples/token/token.go @@ -53,7 +53,7 @@ func BalanceOf(holder interop.Hash160) int { } // Transfer token from one user to another -func Transfer(from interop.Hash160, to interop.Hash160, amount int, data interface{}) bool { +func Transfer(from interop.Hash160, to interop.Hash160, amount int, data any) bool { return token.Transfer(ctx, from, to, amount, data) } diff --git a/internal/basicchain/basic.go b/internal/basicchain/basic.go index ef9a3d9a4..370986563 100644 --- a/internal/basicchain/basic.go +++ b/internal/basicchain/basic.go @@ -187,7 +187,7 @@ func Init(t *testing.T, rootpath string, e *neotest.Executor) { _, _, _ = deployContractFromPriv0(t, verifyPath, "Verify", verifyCfg, VerifyContractID) // Block #8: deposit some GAS to notary contract for priv0. - transferTxH = gasPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, notaryHash, 10_0000_0000, []interface{}{priv0ScriptHash, int64(e.Chain.BlockHeight() + 1000)}) + transferTxH = gasPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, notaryHash, 10_0000_0000, []any{priv0ScriptHash, int64(e.Chain.BlockHeight() + 1000)}) t.Logf("notaryDepositTxPriv0: %v", transferTxH.StringLE()) // Block #9: designate new Notary node. @@ -195,7 +195,7 @@ func Init(t *testing.T, rootpath string, e *neotest.Executor) { require.NoError(t, err) require.NoError(t, ntr.Accounts[0].Decrypt("one", ntr.Scrypt)) designateSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", - int64(noderoles.P2PNotary), []interface{}{ntr.Accounts[0].PublicKey().Bytes()}) + int64(noderoles.P2PNotary), []any{ntr.Accounts[0].PublicKey().Bytes()}) t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PublicKey().Bytes())) // Block #10: push verification contract with arguments into the chain. @@ -252,7 +252,7 @@ func Init(t *testing.T, rootpath string, e *neotest.Executor) { containerID := util.Uint256{1, 2, 3} objectID := util.Uint256{4, 5, 6} txGas0toNFSH := gasPriv0Invoker.Invoke(t, true, "transfer", - priv0ScriptHash, nfsHash, 10_0000_0000, []interface{}{containerID.BytesBE(), objectID.BytesBE()}) // block #18 + priv0ScriptHash, nfsHash, 10_0000_0000, []any{containerID.BytesBE(), objectID.BytesBE()}) // block #18 res = e.GetTxExecResult(t, txGas0toNFSH) require.Equal(t, 2, len(res.Events)) // GAS transfer + NFSO transfer tokenID, err = res.Events[1].Item.Value().([]stackitem.Item)[3].TryBytes() diff --git a/internal/basicchain/testdata/storage/storage_contract.go b/internal/basicchain/testdata/storage/storage_contract.go index 9cb875c64..f98772b8e 100644 --- a/internal/basicchain/testdata/storage/storage_contract.go +++ b/internal/basicchain/testdata/storage/storage_contract.go @@ -16,7 +16,7 @@ const valuesCount = 255 // valuesPrefix is the prefix values are stored by. var valuesPrefix = []byte{0x01} -func _deploy(data interface{}, isUpdate bool) { +func _deploy(data any, isUpdate bool) { if !isUpdate { ctx := storage.GetContext() for i := 0; i < valuesCount; i++ { diff --git a/internal/basicchain/testdata/test_contract.go b/internal/basicchain/testdata/test_contract.go index e6b98ab57..8807779a0 100644 --- a/internal/basicchain/testdata/test_contract.go +++ b/internal/basicchain/testdata/test_contract.go @@ -27,7 +27,7 @@ func Init() bool { return true } -func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { +func OnNEP17Payment(from interop.Hash160, amount int, data any) { curr := runtime.GetExecutingScriptHash() balance := neo.BalanceOf(curr) if ledger.CurrentIndex() >= 100 { @@ -47,7 +47,7 @@ func Verify() bool { return true } -func Transfer(from, to interop.Hash160, amount int, data interface{}) bool { +func Transfer(from, to interop.Hash160, amount int, data any) bool { ctx := storage.GetContext() if len(from) != 20 { runtime.Log("invalid 'from' address") diff --git a/internal/contracts/oracle_contract/oracle.go b/internal/contracts/oracle_contract/oracle.go index da7ebe990..94e2b22ac 100644 --- a/internal/contracts/oracle_contract/oracle.go +++ b/internal/contracts/oracle_contract/oracle.go @@ -12,22 +12,22 @@ import ( // RequestURL accepts a complete set of parameters to make an oracle request and // performs it. -func RequestURL(url string, filter []byte, callback string, userData interface{}, gasForResponse int) { +func RequestURL(url string, filter []byte, callback string, userData any, gasForResponse int) { oracle.Request(url, filter, callback, userData, gasForResponse) } // Handle is a response handler that writes response data to the storage. -func Handle(url string, data interface{}, code int, res []byte) { +func Handle(url string, data any, code int, res []byte) { // ABORT if len(data) == 2, some tests use this feature. if data != nil && len(data.(string)) == 2 { util.Abort() } - params := []interface{}{url, data, code, res} + params := []any{url, data, code, res} storage.Put(storage.GetContext(), "lastOracleResponse", std.Serialize(params)) } // HandleRecursive invokes oracle.finish again to test Oracle reentrance. -func HandleRecursive(url string, data interface{}, code int, res []byte) { +func HandleRecursive(url string, data any, code int, res []byte) { // Regular safety check. callingHash := runtime.GetCallingScriptHash() if !callingHash.Equals(oracle.Hash) { diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 96296ac45..83f889f10 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -28,7 +28,7 @@ type FakeChain struct { blocksCh []chan *block.Block Blockheight uint32 PoolTxF func(*transaction.Transaction) error - poolTxWithData func(*transaction.Transaction, interface{}, *mempool.Pool) error + poolTxWithData func(*transaction.Transaction, any, *mempool.Pool) error blocks map[util.Uint256]*block.Block hdrHashes map[uint32]util.Uint256 txs map[util.Uint256]*transaction.Transaction @@ -64,7 +64,7 @@ func NewFakeChainWithCustomCfg(protocolCfg func(c *config.Blockchain)) *FakeChai return &FakeChain{ Pool: mempool.New(10, 0, false), PoolTxF: func(*transaction.Transaction) error { return nil }, - poolTxWithData: func(*transaction.Transaction, interface{}, *mempool.Pool) error { return nil }, + poolTxWithData: func(*transaction.Transaction, any, *mempool.Pool) error { return nil }, blocks: make(map[util.Uint256]*block.Block), hdrHashes: make(map[uint32]util.Uint256), txs: make(map[util.Uint256]*transaction.Transaction), @@ -149,7 +149,7 @@ func (chain *FakeChain) GetMaxVerificationGAS() int64 { } // PoolTxWithData implements the Blockchainer interface. -func (chain *FakeChain) PoolTxWithData(t *transaction.Transaction, data interface{}, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(t *transaction.Transaction, data interface{}) error) error { +func (chain *FakeChain) PoolTxWithData(t *transaction.Transaction, data any, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(t *transaction.Transaction, data any) error) error { return chain.poolTxWithData(t, data, mp) } diff --git a/internal/testserdes/testing.go b/internal/testserdes/testing.go index 3cec4801e..87645c176 100644 --- a/internal/testserdes/testing.go +++ b/internal/testserdes/testing.go @@ -12,7 +12,7 @@ import ( // MarshalUnmarshalJSON checks if the expected stays the same after // marshal/unmarshal via JSON. -func MarshalUnmarshalJSON(t *testing.T, expected, actual interface{}) { +func MarshalUnmarshalJSON(t *testing.T, expected, actual any) { data, err := json.Marshal(expected) require.NoError(t, err) require.NoError(t, json.Unmarshal(data, actual)) @@ -21,7 +21,7 @@ func MarshalUnmarshalJSON(t *testing.T, expected, actual interface{}) { // MarshalUnmarshalYAML checks if the expected stays the same after // marshal/unmarshal via YAML. -func MarshalUnmarshalYAML(t *testing.T, expected, actual interface{}) { +func MarshalUnmarshalYAML(t *testing.T, expected, actual any) { data, err := yaml.Marshal(expected) require.NoError(t, err) require.NoError(t, yaml.Unmarshal(data, actual)) diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index c8f67e2b3..60a45525c 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -122,7 +122,7 @@ func (c *codegen) fillImportMap(f *ast.File, pkg *packages.Package) { } } -func getBuildInfo(name string, src interface{}) (*buildInfo, error) { +func getBuildInfo(name string, src any) (*buildInfo, error) { dir, err := filepath.Abs(name) if err != nil { return nil, err diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index 142c33110..8a9ab207a 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -102,25 +102,25 @@ func TestOnPayableChecks(t *testing.T) { t.Run("NEP-11, good", func(t *testing.T) { src := `package payable import "github.com/nspcc-dev/neo-go/pkg/interop" - func OnNEP11Payment(from interop.Hash160, amount int, tokenID []byte, data interface{}) {}` + func OnNEP11Payment(from interop.Hash160, amount int, tokenID []byte, data any) {}` require.NoError(t, compileAndCheck(t, src)) }) t.Run("NEP-11, bad", func(t *testing.T) { src := `package payable import "github.com/nspcc-dev/neo-go/pkg/interop" - func OnNEP11Payment(from interop.Hash160, amount int, oldParam string, tokenID []byte, data interface{}) {}` + func OnNEP11Payment(from interop.Hash160, amount int, oldParam string, tokenID []byte, data any) {}` require.Error(t, compileAndCheck(t, src)) }) t.Run("NEP-17, good", func(t *testing.T) { src := `package payable import "github.com/nspcc-dev/neo-go/pkg/interop" - func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {}` + func OnNEP17Payment(from interop.Hash160, amount int, data any) {}` require.NoError(t, compileAndCheck(t, src)) }) t.Run("NEP-17, bad", func(t *testing.T) { src := `package payable import "github.com/nspcc-dev/neo-go/pkg/interop" - func OnNEP17Payment(from interop.Hash160, amount int, data interface{}, extra int) {}` + func OnNEP17Payment(from interop.Hash160, amount int, data any, extra int) {}` require.Error(t, compileAndCheck(t, src)) }) } @@ -234,7 +234,7 @@ func TestEventWarnings(t *testing.T) { src := `package payable import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" func Main() { - runtime.Notify("Event", []interface{}{1}...) + runtime.Notify("Event", []any{1}...) }` _, di, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src), nil) @@ -407,7 +407,7 @@ func TestUnnamedParameterCheck(t *testing.T) { t.Run("interface", func(t *testing.T) { src := ` package testcase - func OnNEP17Payment(h string, i int, _ interface{}){} + func OnNEP17Payment(h string, i int, _ any){} ` _, _, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) require.Error(t, err) @@ -416,7 +416,7 @@ func TestUnnamedParameterCheck(t *testing.T) { t.Run("a set of unnamed params", func(t *testing.T) { src := ` package testcase - func OnNEP17Payment(_ string, _ int, _ interface{}){} + func OnNEP17Payment(_ string, _ int, _ any){} ` _, _, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) require.Error(t, err) @@ -447,11 +447,19 @@ func TestUnnamedParameterCheck(t *testing.T) { _, _, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) require.NoError(t, err) }) + t.Run("good, use any keyword", func(t *testing.T) { + src := ` + package testcase + func OnNEP17Payment(s string, i int, iface any){} + ` + _, _, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) + require.NoError(t, err) + }) t.Run("method with unnamed params", func(t *testing.T) { src := ` package testcase type A int - func (rsv A) OnNEP17Payment(_ string, _ int, iface interface{}){} + func (rsv A) OnNEP17Payment(_ string, _ int, iface any){} ` _, _, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) require.NoError(t, err) // it's OK for exported method to have unnamed params as it won't be included into manifest diff --git a/pkg/compiler/convert_test.go b/pkg/compiler/convert_test.go index eba50b332..0995dc685 100644 --- a/pkg/compiler/convert_test.go +++ b/pkg/compiler/convert_test.go @@ -16,7 +16,7 @@ import ( type convertTestCase struct { returnType string argValue string - result interface{} + result any } func getFunctionName(typ string) string { @@ -85,7 +85,7 @@ func TestTypeAssertion(t *testing.T) { src := `package foo func Main() int { a := []byte{1} - var u interface{} + var u any u = a return u.(int) }` @@ -95,7 +95,7 @@ func TestTypeAssertion(t *testing.T) { src := `package foo func Main() int { a := []byte{1} - var u interface{} + var u any u = a var ret = u.(int) return ret @@ -106,7 +106,7 @@ func TestTypeAssertion(t *testing.T) { src := `package foo func Main() int { a := []byte{1} - var u interface{} + var u any u = a var ret int ret = u.(int) @@ -118,7 +118,7 @@ func TestTypeAssertion(t *testing.T) { src := `package foo func Main() int { a := []byte{1} - var u interface{} + var u any u = a ret := u.(int) return ret @@ -132,7 +132,7 @@ func TestTypeAssertionWithOK(t *testing.T) { src := `package foo func Main() bool { a := 1 - var u interface{} + var u any u = a var _, ok = u.(int) // *ast.GenDecl return ok @@ -145,7 +145,7 @@ func TestTypeAssertionWithOK(t *testing.T) { src := `package foo func Main() bool { a := 1 - var u interface{} + var u any u = a var ok bool _, ok = u.(int) // *ast.AssignStmt @@ -159,7 +159,7 @@ func TestTypeAssertionWithOK(t *testing.T) { src := `package foo func Main() bool { a := 1 - var u interface{} + var u any u = a _, ok := u.(int) // *ast.AssignStmt return ok @@ -231,7 +231,7 @@ func TestInterfaceTypeConversion(t *testing.T) { src := `package foo func Main() int { a := 1 - b := interface{}(a).(int) + b := any(a).(int) return b }` eval(t, src, big.NewInt(1)) diff --git a/pkg/compiler/debug.go b/pkg/compiler/debug.go index 9785de401..82e2e49f7 100644 --- a/pkg/compiler/debug.go +++ b/pkg/compiler/debug.go @@ -308,7 +308,7 @@ func scAndVMInteropTypeFromExpr(named *types.Named, isPointer bool) (smartcontra } return smartcontract.InteropInterfaceType, stackitem.InteropT, - binding.Override{TypeName: "interface{}"}, + binding.Override{TypeName: "any"}, &binding.ExtendedType{Base: smartcontract.InteropInterfaceType, Interface: "iterator"} // Temporarily all interops are iterators. } @@ -318,7 +318,7 @@ func (c *codegen) scAndVMTypeFromExpr(typ ast.Expr, exts map[string]binding.Exte func (c *codegen) scAndVMTypeFromType(t types.Type, exts map[string]binding.ExtendedType) (smartcontract.ParamType, stackitem.Type, binding.Override, *binding.ExtendedType) { if t == nil { - return smartcontract.AnyType, stackitem.AnyT, binding.Override{TypeName: "interface{}"}, nil + return smartcontract.AnyType, stackitem.AnyT, binding.Override{TypeName: "any"}, nil } var isPtr bool @@ -357,7 +357,7 @@ func (c *codegen) scAndVMTypeFromType(t types.Type, exts map[string]binding.Exte over.TypeName = "string" return smartcontract.StringType, stackitem.ByteArrayT, over, nil default: - over.TypeName = "interface{}" + over.TypeName = "any" return smartcontract.AnyType, stackitem.AnyT, over, nil } case *types.Map: @@ -412,7 +412,7 @@ func (c *codegen) scAndVMTypeFromType(t types.Type, exts map[string]binding.Exte } return smartcontract.ArrayType, stackitem.ArrayT, over, et default: - over.TypeName = "interface{}" + over.TypeName = "any" return smartcontract.AnyType, stackitem.AnyT, over, nil } } diff --git a/pkg/compiler/debug_test.go b/pkg/compiler/debug_test.go index dbe382561..4861e29b2 100644 --- a/pkg/compiler/debug_test.go +++ b/pkg/compiler/debug_test.go @@ -65,7 +65,7 @@ func MethodParams(addr interop.Hash160, h interop.Hash256, type MyStruct struct {} func (ms MyStruct) MethodOnStruct() { } func (ms *MyStruct) MethodOnPointerToStruct() { } -func _deploy(data interface{}, isUpdate bool) { x := 1; _ = x } +func _deploy(data any, isUpdate bool) { x := 1; _ = x } ` ne, d, err := CompileWithOptions("foo.go", strings.NewReader(src), nil) diff --git a/pkg/compiler/for_test.go b/pkg/compiler/for_test.go index c7bd36cc1..456678f92 100644 --- a/pkg/compiler/for_test.go +++ b/pkg/compiler/for_test.go @@ -32,7 +32,7 @@ func TestEntryPointWithArgs(t *testing.T) { src := ` package foo - func Main(args []interface{}) int { + func Main(args []any) int { return 2 + args[1].(int) } ` @@ -44,7 +44,7 @@ func TestEntryPointWithMethodAndArgs(t *testing.T) { src := ` package foo - func Main(method string, args []interface{}) int { + func Main(method string, args []any) int { if method == "foobar" { return 2 + args[1].(int) } diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index c409108be..0278c8801 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -173,6 +173,21 @@ func TestFunctionCallWithInterfaceType(t *testing.T) { eval(t, src, big.NewInt(10)) } +func TestFunctionCallWithAnyKeywordType(t *testing.T) { + src := ` + package testcase + func Main() any { + x := getSomeInteger(10) + return x + } + + func getSomeInteger(x any) any { + return x + } + ` + eval(t, src, big.NewInt(10)) +} + func TestFunctionCallMultiArg(t *testing.T) { src := ` package testcase @@ -312,7 +327,7 @@ func TestJumpOptimize(t *testing.T) { var a int _ = a } - func _deploy(_ interface{}, upd bool) { + func _deploy(_ any, upd bool) { if true {} else {} t := upd _ = t diff --git a/pkg/compiler/global_test.go b/pkg/compiler/global_test.go index 7b972dd5d..bc0a617c3 100644 --- a/pkg/compiler/global_test.go +++ b/pkg/compiler/global_test.go @@ -137,9 +137,9 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f() int { return 4 }` - eval(t, src, big.NewInt(4), []interface{}{opcode.INITSSLOT, []byte{2}}, // sslot for A and C + eval(t, src, big.NewInt(4), []any{opcode.INITSSLOT, []byte{2}}, // sslot for A and C opcode.PUSH1, opcode.STSFLD0, // store A - []interface{}{opcode.CALL, []byte{10}}, opcode.DROP, // evaluate B and drop + []any{opcode.CALL, []byte{10}}, opcode.DROP, // evaluate B and drop opcode.PUSH3, opcode.STSFLD1, opcode.RET, // store C opcode.LDSFLD0, opcode.LDSFLD1, opcode.ADD, opcode.RET, // Main opcode.PUSH4, opcode.RET) // f @@ -166,7 +166,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func Main() int { return A }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for A + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{1}}, // sslot for A opcode.PUSH1, opcode.STSFLD0, opcode.RET, // store A opcode.LDSFLD0, opcode.RET) // Main }) @@ -176,7 +176,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func Main() int { return A + B }` - eval(t, src, big.NewInt(4), []interface{}{opcode.INITSSLOT, []byte{2}}, // sslot for A and B + eval(t, src, big.NewInt(4), []any{opcode.INITSSLOT, []byte{2}}, // sslot for A and B opcode.PUSH1, opcode.STSFLD0, // store A opcode.PUSH3, opcode.STSFLD1, opcode.RET, // store B opcode.LDSFLD0, opcode.LDSFLD1, opcode.ADD, opcode.RET) // Main @@ -190,7 +190,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func Main() int { return A + B + C }` - eval(t, src, big.NewInt(4), []interface{}{opcode.INITSSLOT, []byte{3}}, // sslot for A, B, C + eval(t, src, big.NewInt(4), []any{opcode.INITSSLOT, []byte{3}}, // sslot for A, B, C opcode.PUSH1, opcode.STSFLD0, // store A opcode.PUSH3, opcode.STSFLD1, // store B opcode.PUSH0, opcode.STSFLD2, opcode.RET, // store C @@ -205,9 +205,9 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f() int { return 2 }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for A + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{1}}, // sslot for A opcode.PUSH1, opcode.STSFLD0, // store A - []interface{}{opcode.CALL, []byte{6}}, opcode.DROP, opcode.RET, // evaluate Unused1 (call to f) and drop its value + []any{opcode.CALL, []byte{6}}, opcode.DROP, opcode.RET, // evaluate Unused1 (call to f) and drop its value opcode.LDSFLD0, opcode.RET, // Main opcode.PUSH2, opcode.RET) // f }) @@ -221,7 +221,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f() int { return 2 }` - eval(t, src, big.NewInt(1), []interface{}{opcode.CALL, []byte{8}}, opcode.PUSH1, opcode.PACKSTRUCT, opcode.DROP, opcode.RET, // evaluate struct val + eval(t, src, big.NewInt(1), []any{opcode.CALL, []byte{8}}, opcode.PUSH1, opcode.PACKSTRUCT, opcode.DROP, opcode.RET, // evaluate struct val opcode.PUSH1, opcode.RET, // Main opcode.PUSH2, opcode.RET) // f }) @@ -319,11 +319,11 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f() int { return 2 }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{3}}, // sslot for A + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{3}}, // sslot for A opcode.PUSH1, opcode.STSFLD0, // store A opcode.LDSFLD0, opcode.PUSH1, opcode.ADD, opcode.STSFLD1, // store B opcode.PUSH3, opcode.STSFLD2, // store C - opcode.LDSFLD1, []interface{}{opcode.CALL, []byte{9}}, opcode.ADD, opcode.LDSFLD2, opcode.ADD, opcode.DROP, opcode.RET, // evaluate D and drop + opcode.LDSFLD1, []any{opcode.CALL, []byte{9}}, opcode.ADD, opcode.LDSFLD2, opcode.ADD, opcode.DROP, opcode.RET, // evaluate D and drop opcode.PUSH1, opcode.RET, // Main opcode.PUSH2, opcode.RET) // f }) @@ -337,11 +337,11 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f(a int) int { return a }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for A + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{1}}, // sslot for A opcode.PUSH1, opcode.STSFLD0, // store A - opcode.LDSFLD0, []interface{}{opcode.CALL, []byte{6}}, opcode.DROP, opcode.RET, // evaluate B and drop + opcode.LDSFLD0, []any{opcode.CALL, []byte{6}}, opcode.DROP, opcode.RET, // evaluate B and drop opcode.PUSH1, opcode.RET, // Main - []interface{}{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.RET) // f + []any{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.RET) // f }) t.Run("named, inside multi-specs and multi-vals var declaration", func(t *testing.T) { src := `package foo @@ -355,7 +355,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f() int { return 5 }` - eval(t, src, big.NewInt(1), opcode.PUSH3, []interface{}{opcode.CALL, []byte{7}}, opcode.ADD, opcode.DROP, opcode.RET, // evaluate and drop A + eval(t, src, big.NewInt(1), opcode.PUSH3, []any{opcode.CALL, []byte{7}}, opcode.ADD, opcode.DROP, opcode.RET, // evaluate and drop A opcode.PUSH1, opcode.RET, // Main opcode.PUSH5, opcode.RET) // f }) @@ -367,7 +367,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func Main() int { return A }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for A + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{1}}, // sslot for A opcode.PUSH1, opcode.STSFLD0, opcode.RET, // store A opcode.LDSFLD0, opcode.RET) // Main }) @@ -395,8 +395,8 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f() (int, int) { return 3, 4 }` - eval(t, src, big.NewInt(3), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for A - []interface{}{opcode.CALL, []byte{7}}, opcode.STSFLD0, opcode.DROP, opcode.RET, // evaluate and store A, drop B + eval(t, src, big.NewInt(3), []any{opcode.INITSSLOT, []byte{1}}, // sslot for A + []any{opcode.CALL, []byte{7}}, opcode.STSFLD0, opcode.DROP, opcode.RET, // evaluate and store A, drop B opcode.LDSFLD0, opcode.RET, // Main opcode.PUSH4, opcode.PUSH3, opcode.RET) // f }) @@ -460,12 +460,12 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f(a int) int { return a }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{2}}, // sslot for A, B + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{2}}, // sslot for A, B opcode.PUSH2, opcode.STSFLD0, // store A opcode.PUSH3, opcode.LDSFLD0, opcode.PUSH1, opcode.PUSH3, opcode.PACK, opcode.PUSH1, opcode.PICKITEM, opcode.STSFLD1, // evaluate B - opcode.PUSH1, []interface{}{opcode.CALL, []byte{8}}, opcode.LDSFLD1, opcode.ADD, opcode.DROP, opcode.RET, // evalute C and drop + opcode.PUSH1, []any{opcode.CALL, []byte{8}}, opcode.LDSFLD1, opcode.ADD, opcode.DROP, opcode.RET, // evalute C and drop opcode.PUSH1, opcode.RET, // Main - []interface{}{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.RET) // f + []any{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.RET) // f }) t.Run("index expression", func(t *testing.T) { src := `package foo @@ -477,13 +477,13 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func f(a int) int { return a }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for Unused + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{1}}, // sslot for Unused opcode.PUSH2, opcode.STSFLD0, // store Unused - opcode.PUSH1, []interface{}{opcode.CALL, []byte{14}}, // call f(1) + opcode.PUSH1, []any{opcode.CALL, []byte{14}}, // call f(1) opcode.PUSH3, opcode.PUSH2, opcode.PUSH1, opcode.PUSH3, opcode.PACK, opcode.LDSFLD0, opcode.PICKITEM, // eval index expression opcode.ADD, opcode.DROP, opcode.RET, // eval and drop A opcode.PUSH1, opcode.RET, // Main - []interface{}{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.RET) // f(a) + []any{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.RET) // f(a) }) t.Run("used via nested function calls", func(t *testing.T) { src := `package foo @@ -497,10 +497,10 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func g() int { return A }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for A + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{1}}, // sslot for A opcode.PUSH1, opcode.STSFLD0, opcode.RET, // store A - []interface{}{opcode.CALL, []byte{3}}, opcode.RET, // Main - []interface{}{opcode.CALL, []byte{3}}, opcode.RET, // f + []any{opcode.CALL, []byte{3}}, opcode.RET, // Main + []any{opcode.CALL, []byte{3}}, opcode.RET, // f opcode.LDSFLD0, opcode.RET) // g }) t.Run("struct field name matches global var name", func(t *testing.T) { @@ -511,7 +511,7 @@ func TestUnusedOptimizedGlobalVar(t *testing.T) { func Main() int { return str.Int }` - eval(t, src, big.NewInt(2), []interface{}{opcode.INITSSLOT, []byte{1}}, // sslot for str + eval(t, src, big.NewInt(2), []any{opcode.INITSSLOT, []byte{1}}, // sslot for str opcode.PUSH2, opcode.PUSH1, opcode.PACKSTRUCT, opcode.STSFLD0, opcode.RET, // store str opcode.LDSFLD0, opcode.PUSH0, opcode.PICKITEM, opcode.RET) // Main }) @@ -929,11 +929,11 @@ func TestUnderscoreGlobalVarDontEmitCode(t *testing.T) { func f(a, b int) (int, int, int) { return 8, 9, 10 }` - eval(t, src, big.NewInt(1), []interface{}{opcode.INITSSLOT, []byte{2}}, // sslot for A, B + eval(t, src, big.NewInt(1), []any{opcode.INITSSLOT, []byte{2}}, // sslot for A, B opcode.PUSH2, opcode.STSFLD0, // store A opcode.PUSH5, opcode.STSFLD1, // store B - opcode.LDSFLD0, opcode.LDSFLD1, opcode.SWAP, []interface{}{opcode.CALL, []byte{8}}, // evaluate f(A,B) + opcode.LDSFLD0, opcode.LDSFLD1, opcode.SWAP, []any{opcode.CALL, []byte{8}}, // evaluate f(A,B) opcode.DROP, opcode.DROP, opcode.DROP, opcode.RET, // drop result of f(A,B) opcode.PUSH1, opcode.RET, // Main - []interface{}{opcode.INITSLOT, []byte{0, 2}}, opcode.PUSH10, opcode.PUSH9, opcode.PUSH8, opcode.RET) // f + []any{opcode.INITSLOT, []byte{0, 2}}, opcode.PUSH10, opcode.PUSH9, opcode.PUSH8, opcode.RET) // f } diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 2ba7a5f2f..7e6fc9bd3 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -39,7 +39,7 @@ func TestTypeConstantSize(t *testing.T) { src := `package foo import "github.com/nspcc-dev/neo-go/pkg/interop" var a %T // type declaration is always ok - func Main() interface{} { + func Main() any { return %#v }` @@ -532,7 +532,7 @@ func TestCallWithVersion(t *testing.T) { "github.com/nspcc-dev/neo-go/pkg/interop/contract" util "github.com/nspcc-dev/neo-go/pkg/interop/lib/contract" ) - func CallWithVersion(hash interop.Hash160, version int, method string) interface{} { + func CallWithVersion(hash interop.Hash160, version int, method string) any { return util.CallWithVersion(hash, version, method, contract.All) }` ctr := neotest.CompileSource(t, e.CommitteeHash, strings.NewReader(src), &compiler.Options{Name: "Helper"}) @@ -569,7 +569,7 @@ func TestForcedNotifyArgumentsConversion(t *testing.T) { runtime.Notify("withoutEllipsis", arg0, arg1, arg2, arg3, arg4, 5, f(6)) // The fifth argument is basic literal. } func WithEllipsis() { - arg := []interface{}{0, 1, f(2), 3, 4, 5, 6} + arg := []any{0, 1, f(2), 3, 4, 5, 6} runtime.Notify("withEllipsis", arg...) } func f(i int) int { diff --git a/pkg/compiler/native_test.go b/pkg/compiler/native_test.go index 06db9f919..088d714b8 100644 --- a/pkg/compiler/native_test.go +++ b/pkg/compiler/native_test.go @@ -295,7 +295,7 @@ func addNativeTestCase(t *testing.T, srcBuilder *bytes.Buffer, ctr interop.Contr isVoid := md.MD.ReturnType == smartcontract.VoidType srcBuilder.WriteString("func F" + strconv.Itoa(i) + "() ") if !isVoid { - srcBuilder.WriteString("interface{} { return ") + srcBuilder.WriteString("any { return ") } else { srcBuilder.WriteString("{ ") } diff --git a/pkg/compiler/nilcheck_test.go b/pkg/compiler/nilcheck_test.go index 54f36e037..415a8f294 100644 --- a/pkg/compiler/nilcheck_test.go +++ b/pkg/compiler/nilcheck_test.go @@ -11,7 +11,7 @@ var nilTestCases = []testCase{ ` package foo func Main() int { - var t interface{} + var t any if t == nil { return 1 } @@ -39,7 +39,7 @@ var nilTestCases = []testCase{ ` package foo func Main() int { - var t interface{} + var t any if nil == t { return 1 } diff --git a/pkg/compiler/return_test.go b/pkg/compiler/return_test.go index ead69d2fb..437f7cd9b 100644 --- a/pkg/compiler/return_test.go +++ b/pkg/compiler/return_test.go @@ -124,7 +124,7 @@ func TestTypeAssertReturn(t *testing.T) { src := ` package main - func foo() interface{} { + func foo() any { return 5 } diff --git a/pkg/compiler/syscall_test.go b/pkg/compiler/syscall_test.go index ed0e655d6..fc56d6d0a 100644 --- a/pkg/compiler/syscall_test.go +++ b/pkg/compiler/syscall_test.go @@ -121,7 +121,7 @@ func TestSyscallExecution(t *testing.T) { if tc.isVoid { tmpl = "func %s() { %s(%s) }\n" } else { - tmpl = "func %s() interface{} { return %s(%s) }\n" + tmpl = "func %s() any { return %s(%s) }\n" } srcBuilder.WriteString(fmt.Sprintf(tmpl, realName, goName, strings.Join(tc.params, ", "))) } diff --git a/pkg/compiler/testdata/util/equals.go b/pkg/compiler/testdata/util/equals.go index 391fb74db..33f4b2e7a 100644 --- a/pkg/compiler/testdata/util/equals.go +++ b/pkg/compiler/testdata/util/equals.go @@ -1,6 +1,6 @@ package util // Equals is a mirror of `Equals` builtin. -func Equals(a, b interface{}) bool { +func Equals(a, b any) bool { return true } diff --git a/pkg/compiler/vardecl_test.go b/pkg/compiler/vardecl_test.go index 3759582b3..954b7a5ed 100644 --- a/pkg/compiler/vardecl_test.go +++ b/pkg/compiler/vardecl_test.go @@ -59,18 +59,18 @@ func TestUnderscoreLocalVarDontEmitCode(t *testing.T) { func (fo Foo) GetInt() int { return fo.Int }` - eval(t, src, big.NewInt(9), []interface{}{opcode.INITSLOT, []byte{5, 0}}, // local slot for A, B, C, D, fo + eval(t, src, big.NewInt(9), []any{opcode.INITSLOT, []byte{5, 0}}, // local slot for A, B, C, D, fo opcode.PUSH2, opcode.STLOC0, // store A opcode.PUSH5, opcode.STLOC1, // store B - opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []interface{}{opcode.CALL, []byte{27}}, // evaluate f() first time + opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []any{opcode.CALL, []byte{27}}, // evaluate f() first time opcode.DROP, opcode.DROP, opcode.DROP, // drop all values from f - opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []interface{}{opcode.CALL, []byte{19}}, // evaluate f() second time + opcode.LDLOC0, opcode.LDLOC1, opcode.SWAP, []any{opcode.CALL, []byte{19}}, // evaluate f() second time opcode.DROP, opcode.STLOC2, opcode.DROP, // store C opcode.PUSH7, opcode.STLOC3, // store D opcode.LDLOC3, opcode.DROP, // empty assignment opcode.PUSH3, opcode.PUSH1, opcode.PACKSTRUCT, opcode.STLOC4, // fo decl - opcode.LDLOC4, []interface{}{opcode.CALL, []byte{12}}, opcode.DROP, // fo.GetInt() + opcode.LDLOC4, []any{opcode.CALL, []byte{12}}, opcode.DROP, // fo.GetInt() opcode.LDLOC2, opcode.RET, // return C - []interface{}{opcode.INITSLOT, []byte{0, 2}}, opcode.PUSH10, opcode.PUSH9, opcode.PUSH8, opcode.RET, // f - []interface{}{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.PUSH0, opcode.PICKITEM, opcode.RET) // (fo Foo) GetInt() int + []any{opcode.INITSLOT, []byte{0, 2}}, opcode.PUSH10, opcode.PUSH9, opcode.PUSH8, opcode.RET, // f + []any{opcode.INITSLOT, []byte{0, 1}}, opcode.LDARG0, opcode.PUSH0, opcode.PICKITEM, opcode.RET) // (fo Foo) GetInt() int } diff --git a/pkg/compiler/vm_test.go b/pkg/compiler/vm_test.go index 58a4cda57..4ec7196a5 100644 --- a/pkg/compiler/vm_test.go +++ b/pkg/compiler/vm_test.go @@ -23,7 +23,7 @@ import ( type testCase struct { name string src string - result interface{} + result any } // testMainIdent is a method invoked in tests by default. @@ -35,7 +35,7 @@ func runTestCases(t *testing.T, tcases []testCase) { } } -func eval(t *testing.T, src string, result interface{}, expectedOps ...interface{}) []byte { +func eval(t *testing.T, src string, result any, expectedOps ...any) []byte { vm, _, script := vmAndCompileInterop(t, src) if len(expectedOps) != 0 { expected := io.NewBufBinWriter() @@ -43,7 +43,7 @@ func eval(t *testing.T, src string, result interface{}, expectedOps ...interface switch typ := op.(type) { case opcode.Opcode: emit.Opcodes(expected.BinWriter, typ) - case []interface{}: + case []any: emit.Instruction(expected.BinWriter, typ[0].(opcode.Opcode), typ[1].([]byte)) default: t.Fatalf("unexpected evaluation operation: %v", typ) @@ -64,14 +64,14 @@ func evalWithError(t *testing.T, src string, e string) []byte { return prog } -func runAndCheck(t *testing.T, v *vm.VM, result interface{}) { +func runAndCheck(t *testing.T, v *vm.VM, result any) { err := v.Run() require.NoError(t, err) assert.Equal(t, 1, v.Estack().Len(), "stack contains unexpected items") assertResult(t, v, result) } -func evalWithArgs(t *testing.T, src string, op []byte, args []stackitem.Item, result interface{}) { +func evalWithArgs(t *testing.T, src string, op []byte, args []stackitem.Item, result any) { vm := vmAndCompile(t, src) if len(args) > 0 { vm.Estack().PushVal(args) @@ -82,7 +82,7 @@ func evalWithArgs(t *testing.T, src string, op []byte, args []stackitem.Item, re runAndCheck(t, vm, result) } -func assertResult(t *testing.T, vm *vm.VM, result interface{}) { +func assertResult(t *testing.T, vm *vm.VM, result any) { assert.Equal(t, result, vm.PopResult()) assert.Nil(t, vm.Context()) } diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 915b51629..777f5d341 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -238,7 +238,7 @@ func NewPayload(m netmode.Magic, stateRootEnabled bool) *Payload { } } -func (s *service) newPayload(c *dbft.Context, t payload.MessageType, msg interface{}) payload.ConsensusPayload { +func (s *service) newPayload(c *dbft.Context, t payload.MessageType, msg any) payload.ConsensusPayload { cp := NewPayload(s.ProtocolConfiguration.Magic, s.ProtocolConfiguration.StateRootInHeader) cp.SetHeight(c.BlockIndex) cp.SetValidatorIndex(uint16(c.MyIndex)) diff --git a/pkg/consensus/payload.go b/pkg/consensus/payload.go index d9290c49f..aa100cf8c 100644 --- a/pkg/consensus/payload.go +++ b/pkg/consensus/payload.go @@ -65,12 +65,12 @@ func (p *Payload) SetType(t payload.MessageType) { } // Payload implements the payload.ConsensusPayload interface. -func (p Payload) Payload() interface{} { +func (p Payload) Payload() any { return p.payload } // SetPayload implements the payload.ConsensusPayload interface. -func (p *Payload) SetPayload(pl interface{}) { +func (p *Payload) SetPayload(pl any) { p.payload = pl.(io.Serializable) } diff --git a/pkg/core/block/block_test.go b/pkg/core/block/block_test.go index 0123e4819..90d434627 100644 --- a/pkg/core/block/block_test.go +++ b/pkg/core/block/block_test.go @@ -19,7 +19,7 @@ import ( "github.com/stretchr/testify/require" ) -func trim0x(value interface{}) string { +func trim0x(value any) string { s := value.(string) return strings.TrimPrefix(s, "0x") } @@ -42,15 +42,15 @@ func TestDecodeBlock1(t *testing.T) { assert.Equal(t, trim0x(data["merkleroot"]), block.MerkleRoot.StringLE()) assert.Equal(t, trim0x(data["nextconsensus"]), address.Uint160ToString(block.NextConsensus)) - scripts := data["witnesses"].([]interface{}) - script := scripts[0].(map[string]interface{}) + scripts := data["witnesses"].([]any) + script := scripts[0].(map[string]any) assert.Equal(t, script["invocation"].(string), base64.StdEncoding.EncodeToString(block.Script.InvocationScript)) assert.Equal(t, script["verification"].(string), base64.StdEncoding.EncodeToString(block.Script.VerificationScript)) - tx := data["tx"].([]interface{}) - tx0 := tx[0].(map[string]interface{}) + tx := data["tx"].([]any) + tx0 := tx[0].(map[string]any) assert.Equal(t, len(tx), len(block.Transactions)) - assert.Equal(t, len(tx0["attributes"].([]interface{})), len(block.Transactions[0].Attributes)) + assert.Equal(t, len(tx0["attributes"].([]any)), len(block.Transactions[0].Attributes)) } func TestTrimmedBlock(t *testing.T) { diff --git a/pkg/core/block/helper_test.go b/pkg/core/block/helper_test.go index 85be4903b..db61d299f 100644 --- a/pkg/core/block/helper_test.go +++ b/pkg/core/block/helper_test.go @@ -24,12 +24,12 @@ func getDecodedBlock(t *testing.T, i int) *Block { return block } -func getBlockData(i int) (map[string]interface{}, error) { +func getBlockData(i int) (map[string]any, error) { b, err := os.ReadFile(fmt.Sprintf("../test_data/block_%d.json", i)) if err != nil { return nil, err } - var data map[string]interface{} + var data map[string]any if err := json.Unmarshal(b, &data); err != nil { return nil, err } diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 2c28c06a3..bde36a856 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -183,8 +183,8 @@ type Blockchain struct { // Notification subsystem. events chan bcEvent - subCh chan interface{} - unsubCh chan interface{} + subCh chan any + unsubCh chan any } // StateRoot represents local state root module. @@ -312,8 +312,8 @@ func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger) (*Bl memPool: mempool.New(cfg.MemPoolSize, 0, false), log: log, events: make(chan bcEvent), - subCh: make(chan interface{}), - unsubCh: make(chan interface{}), + subCh: make(chan any), + unsubCh: make(chan any), contracts: *native.NewContracts(cfg.ProtocolConfiguration), } @@ -2334,7 +2334,7 @@ var ( // verifyAndPoolTx verifies whether a transaction is bonafide or not and tries // to add it to the mempool given. -func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.Pool, feer mempool.Feer, data ...interface{}) error { +func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.Pool, feer mempool.Feer, data ...any) error { // This code can technically be moved out of here, because it doesn't // really require a chain lock. err := vm.IsScriptCorrect(t.Script, nil) @@ -2552,7 +2552,7 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction, pools ...*mempool.Pool) } // PoolTxWithData verifies and tries to add given transaction with additional data into the mempool. -func (bc *Blockchain) PoolTxWithData(t *transaction.Transaction, data interface{}, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(tx *transaction.Transaction, data interface{}) error) error { +func (bc *Blockchain) PoolTxWithData(t *transaction.Transaction, data any, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(tx *transaction.Transaction, data any) error) error { bc.lock.RLock() defer bc.lock.RUnlock() diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index f71b8890b..488b3411a 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -1024,7 +1024,7 @@ func TestBlockchain_MPTDeleteNoKey(t *testing.T) { // native contract. func TestConfigNativeUpdateHistory(t *testing.T) { var prefixPath = filepath.Join("..", "..", "config") - check := func(t *testing.T, cfgFileSuffix interface{}) { + check := func(t *testing.T, cfgFileSuffix any) { cfgPath := filepath.Join(prefixPath, fmt.Sprintf("protocol.%s.yml", cfgFileSuffix)) cfg, err := config.LoadFile(cfgPath) require.NoError(t, err, fmt.Errorf("failed to load %s", cfgPath)) @@ -1038,7 +1038,7 @@ func TestConfigNativeUpdateHistory(t *testing.T) { "edit the test if the contract should be disabled", cfgPath, c.Metadata().Name)) } } - testCases := []interface{}{ + testCases := []any{ netmode.MainNet, netmode.PrivNet, netmode.TestNet, @@ -1390,7 +1390,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { checkErr(t, core.ErrInvalidAttribute, tx) }) - keys := make([]interface{}, 0, len(oraclePubs)) + keys := make([]any, 0, len(oraclePubs)) for _, p := range oraclePubs { keys = append(keys, p.Bytes()) } @@ -1612,7 +1612,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { notary, err := wallet.NewAccount() require.NoError(t, err) designateSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", - int64(noderoles.P2PNotary), []interface{}{notary.PublicKey().Bytes()}) + int64(noderoles.P2PNotary), []any{notary.PublicKey().Bytes()}) txSetNotary := transaction.New([]byte{byte(opcode.RET)}, 0) txSetNotary.Signers = []transaction.Signer{ { @@ -1861,7 +1861,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { } mp := mempool.New(10, 1, false) - verificationF := func(tx *transaction.Transaction, data interface{}) error { + verificationF := func(tx *transaction.Transaction, data any) error { if data.(int) > 5 { return errors.New("bad data") } @@ -1909,7 +1909,7 @@ func TestBlockchain_Bug1728(t *testing.T) { src := `package example import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" func init() { if true { } else { } } - func _deploy(_ interface{}, isUpdate bool) { + func _deploy(_ any, isUpdate bool) { runtime.Log("Deploy") }` c := neotest.CompileSource(t, acc.ScriptHash(), strings.NewReader(src), &compiler.Options{Name: "TestContract"}) diff --git a/pkg/core/interop/contract/account_test.go b/pkg/core/interop/contract/account_test.go index 2359c185e..bedb97730 100644 --- a/pkg/core/interop/contract/account_test.go +++ b/pkg/core/interop/contract/account_test.go @@ -63,7 +63,7 @@ func TestCreateMultisigAccount(t *testing.T) { e := neotest.NewExecutor(t, bc, acc, acc) w := io.NewBufBinWriter() - createScript := func(t *testing.T, pubs []interface{}, m int) []byte { + createScript := func(t *testing.T, pubs []any, m int) []byte { w.Reset() emit.Array(w.BinWriter, pubs...) emit.Int(w.BinWriter, int64(m)) @@ -74,7 +74,7 @@ func TestCreateMultisigAccount(t *testing.T) { t.Run("Good", func(t *testing.T) { m, n := 3, 5 pubs := make(keys.PublicKeys, n) - arr := make([]interface{}, n) + arr := make([]any, n) for i := range pubs { pk, err := keys.NewPrivateKey() require.NoError(t, err) @@ -94,13 +94,13 @@ func TestCreateMultisigAccount(t *testing.T) { require.Equal(t, hash.Hash160(expected), u) }) t.Run("InvalidKey", func(t *testing.T) { - script := createScript(t, []interface{}{[]byte{1, 2, 3}}, 1) + script := createScript(t, []any{[]byte{1, 2, 3}}, 1) e.InvokeScriptCheckFAULT(t, script, []neotest.Signer{acc}, "invalid prefix 1") }) t.Run("Invalid m", func(t *testing.T) { pk, err := keys.NewPrivateKey() require.NoError(t, err) - script := createScript(t, []interface{}{pk.PublicKey().Bytes()}, 2) + script := createScript(t, []any{pk.PublicKey().Bytes()}, 2) e.InvokeScriptCheckFAULT(t, script, []neotest.Signer{acc}, "length of the signatures (2) is higher then the number of public keys") }) t.Run("m overflows int32", func(t *testing.T) { @@ -131,7 +131,7 @@ func TestCreateAccount_Hardfork(t *testing.T) { pub := priv.PublicKey() w := io.NewBufBinWriter() - emit.Array(w.BinWriter, []interface{}{pub.Bytes(), pub.Bytes(), pub.Bytes()}...) + emit.Array(w.BinWriter, []any{pub.Bytes(), pub.Bytes(), pub.Bytes()}...) emit.Int(w.BinWriter, int64(2)) emit.Syscall(w.BinWriter, interopnames.SystemContractCreateMultisigAccount) require.NoError(t, w.Err) diff --git a/pkg/core/interop/contract/call_test.go b/pkg/core/interop/contract/call_test.go index 50648a4b6..6bcf575a7 100644 --- a/pkg/core/interop/contract/call_test.go +++ b/pkg/core/interop/contract/call_test.go @@ -90,7 +90,7 @@ func TestCall(t *testing.T) { require.Error(t, contract.Call(ic)) }) - runInvalid := func(args ...interface{}) func(t *testing.T) { + runInvalid := func(args ...any) func(t *testing.T) { return func(t *testing.T) { loadScriptWithHashAndFlags(ic, currScript, h, callflag.All, 42) for i := range args { @@ -591,7 +591,7 @@ func TestCALLL_from_VoidContext(t *testing.T) { ctrInvoker.Invoke(t, stackitem.Null{}, "callHasRet") } -func loadScript(ic *interop.Context, script []byte, args ...interface{}) { +func loadScript(ic *interop.Context, script []byte, args ...any) { ic.SpawnVM() ic.VM.LoadScriptWithFlags(script, callflag.AllowCall) for i := range args { @@ -600,7 +600,7 @@ func loadScript(ic *interop.Context, script []byte, args ...interface{}) { ic.VM.GasLimit = -1 } -func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f callflag.CallFlag, args ...interface{}) { +func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f callflag.CallFlag, args ...any) { ic.SpawnVM() ic.VM.LoadScriptWithHash(script, hash, f) for i := range args { diff --git a/pkg/core/interop/crypto/ecdsa_test.go b/pkg/core/interop/crypto/ecdsa_test.go index fc6f70bfd..a44c959ce 100644 --- a/pkg/core/interop/crypto/ecdsa_test.go +++ b/pkg/core/interop/crypto/ecdsa_test.go @@ -180,7 +180,7 @@ func TestCheckSig(t *testing.T) { verifyFunc := ECDSASecp256r1CheckSig d := dao.NewSimple(storage.NewMemoryStore(), false, false) ic := &interop.Context{Network: uint32(netmode.UnitTestNet), DAO: d} - runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) { + runCase := func(t *testing.T, isErr bool, result any, args ...any) { ic.SpawnVM() for i := range args { ic.VM.Estack().PushVal(args[i]) diff --git a/pkg/core/interop/runtime/engine_test.go b/pkg/core/interop/runtime/engine_test.go index 656a78dcb..646926d8a 100644 --- a/pkg/core/interop/runtime/engine_test.go +++ b/pkg/core/interop/runtime/engine_test.go @@ -21,7 +21,7 @@ import ( "go.uber.org/zap/zaptest" ) -func checkStack(t *testing.T, v *vm.VM, args ...interface{}) { +func checkStack(t *testing.T, v *vm.VM, args ...any) { require.Equal(t, len(args), v.Estack().Len()) for i := range args { require.Equal(t, stackitem.Make(args[i]), v.Estack().Pop().Item(), "%d", i) @@ -122,7 +122,7 @@ func TestLog(t *testing.T) { ls := buf.Lines() require.Equal(t, 1, len(ls)) - var logMsg map[string]interface{} + var logMsg map[string]any require.NoError(t, json.Unmarshal([]byte(ls[0]), &logMsg)) require.Equal(t, "info", logMsg["level"]) require.Equal(t, "hello", logMsg["msg"]) diff --git a/pkg/core/interop/runtime/ext_test.go b/pkg/core/interop/runtime/ext_test.go index d423ee701..64feb3ecb 100644 --- a/pkg/core/interop/runtime/ext_test.go +++ b/pkg/core/interop/runtime/ext_test.go @@ -71,7 +71,7 @@ func createVM(t testing.TB) (*vm.VM, *interop.Context, *core.Blockchain) { return v, ic, chain } -func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f callflag.CallFlag, args ...interface{}) { +func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f callflag.CallFlag, args ...any) { ic.SpawnVM() ic.VM.LoadScriptWithHash(script, hash, f) for i := range args { @@ -80,7 +80,7 @@ func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Ui ic.VM.GasLimit = -1 } -func wrapDynamicScript(t *testing.T, script []byte, flags callflag.CallFlag, args ...interface{}) []byte { +func wrapDynamicScript(t *testing.T, script []byte, flags callflag.CallFlag, args ...any) []byte { b := io.NewBufBinWriter() // Params. @@ -150,7 +150,7 @@ func TestCheckWitness(t *testing.T) { script := []byte{byte(opcode.RET)} scriptHash := hash.Hash160(script) - check := func(t *testing.T, ic *interop.Context, arg interface{}, shouldFail bool, expected ...bool) { + check := func(t *testing.T, ic *interop.Context, arg any, shouldFail bool, expected ...bool) { ic.VM.Estack().PushVal(arg) err := runtime.CheckWitness(ic) if shouldFail { @@ -632,7 +632,7 @@ func TestGetRandomCompatibility(t *testing.T) { func TestNotify(t *testing.T) { caller := random.Uint160() - newIC := func(name string, args interface{}) *interop.Context { + newIC := func(name string, args any) *interop.Context { _, _, bc, cs := getDeployedInternal(t) ic, err := bc.GetTestVM(trigger.Application, nil, nil) require.NoError(t, err) diff --git a/pkg/core/interop/storage/interops_test.go b/pkg/core/interop/storage/interops_test.go index 74795fc21..0ae492c9d 100644 --- a/pkg/core/interop/storage/interops_test.go +++ b/pkg/core/interop/storage/interops_test.go @@ -11,7 +11,7 @@ import ( ) func TestUnexpectedNonInterops(t *testing.T) { - vals := map[string]interface{}{ + vals := map[string]any{ "int": 1, "bool": false, "string": "smth", diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index d393f6e34..0faf79c96 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -41,7 +41,7 @@ var ( type item struct { txn *transaction.Transaction blockStamp uint32 - data interface{} + data any } // items is a slice of an item. @@ -70,7 +70,7 @@ type Pool struct { payerIndex int resendThreshold uint32 - resendFunc func(*transaction.Transaction, interface{}) + resendFunc func(*transaction.Transaction, any) // subscriptions for mempool events subscriptionsEnabled bool @@ -197,7 +197,7 @@ func checkBalance(tx *transaction.Transaction, balance utilityBalanceAndFees) (u } // Add tries to add the given transaction to the Pool. -func (mp *Pool) Add(t *transaction.Transaction, fee Feer, data ...interface{}) error { +func (mp *Pool) Add(t *transaction.Transaction, fee Feer, data ...any) error { var pItem = item{ txn: t, blockStamp: fee.BlockHeight(), @@ -441,7 +441,7 @@ func New(capacity int, payerIndex int, enableSubscriptions bool) *Pool { // SetResendThreshold sets a threshold after which the transaction will be considered stale // and returned for retransmission by `GetStaleTransactions`. -func (mp *Pool) SetResendThreshold(h uint32, f func(*transaction.Transaction, interface{})) { +func (mp *Pool) SetResendThreshold(h uint32, f func(*transaction.Transaction, any)) { mp.lock.Lock() defer mp.lock.Unlock() mp.resendThreshold = h @@ -466,7 +466,7 @@ func (mp *Pool) TryGetValue(hash util.Uint256) (*transaction.Transaction, bool) } // TryGetData returns data associated with the specified transaction if it exists in the memory pool. -func (mp *Pool) TryGetData(hash util.Uint256) (interface{}, bool) { +func (mp *Pool) TryGetData(hash util.Uint256) (any, bool) { mp.lock.RLock() defer mp.lock.RUnlock() if tx, ok := mp.verifiedMap[hash]; ok { diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index 20d571953..43a1f0cef 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -76,7 +76,7 @@ func TestMemPoolRemoveStale(t *testing.T) { } staleTxs := make(chan *transaction.Transaction, 5) - f := func(tx *transaction.Transaction, _ interface{}) { + f := func(tx *transaction.Transaction, _ any) { staleTxs <- tx } mp.SetResendThreshold(5, f) diff --git a/pkg/core/mempoolevent/event.go b/pkg/core/mempoolevent/event.go index d59c07c8e..85fc8436b 100644 --- a/pkg/core/mempoolevent/event.go +++ b/pkg/core/mempoolevent/event.go @@ -21,7 +21,7 @@ const ( type Event struct { Type Type Tx *transaction.Transaction - Data interface{} + Data any } // String is a Stringer implementation. diff --git a/pkg/core/mpt/empty.go b/pkg/core/mpt/empty.go index b3ceec873..7a25b0f7d 100644 --- a/pkg/core/mpt/empty.go +++ b/pkg/core/mpt/empty.go @@ -29,7 +29,7 @@ func (e EmptyNode) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements Node interface. func (e EmptyNode) UnmarshalJSON(bytes []byte) error { - var m map[string]interface{} + var m map[string]any err := json.Unmarshal(bytes, &m) if err != nil { return err diff --git a/pkg/core/mpt/extension.go b/pkg/core/mpt/extension.go index 49af8558b..c752e8aff 100644 --- a/pkg/core/mpt/extension.go +++ b/pkg/core/mpt/extension.go @@ -80,7 +80,7 @@ func (e *ExtensionNode) Size() int { // MarshalJSON implements the json.Marshaler. func (e *ExtensionNode) MarshalJSON() ([]byte, error) { - m := map[string]interface{}{ + m := map[string]any{ "key": hex.EncodeToString(e.key), "next": e.next, } diff --git a/pkg/core/native/crypto_test.go b/pkg/core/native/crypto_test.go index 727c160a9..11cc87db7 100644 --- a/pkg/core/native/crypto_test.go +++ b/pkg/core/native/crypto_test.go @@ -91,7 +91,7 @@ func testECDSAVerify(t *testing.T, curve NamedCurve) { } require.NoError(t, err) - runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) { + runCase := func(t *testing.T, isErr bool, result any, args ...any) { argsArr := make([]stackitem.Item, len(args)) for i := range args { argsArr[i] = stackitem.Make(args[i]) diff --git a/pkg/core/native/native_test/common_test.go b/pkg/core/native/native_test/common_test.go index 53a927a52..4957291f6 100644 --- a/pkg/core/native/native_test/common_test.go +++ b/pkg/core/native/native_test/common_test.go @@ -113,7 +113,7 @@ func testGetSetCache(t *testing.T, c *neotest.ContractInvoker, name string, defa } func setNodesByRole(t *testing.T, designateInvoker *neotest.ContractInvoker, ok bool, r noderoles.Role, nodes keys.PublicKeys) { - pubs := make([]interface{}, len(nodes)) + pubs := make([]any, len(nodes)) for i := range nodes { pubs[i] = nodes[i].Bytes() } diff --git a/pkg/core/native/native_test/designate_test.go b/pkg/core/native/native_test/designate_test.go index 98d3c362b..5bb7e47d0 100644 --- a/pkg/core/native/native_test/designate_test.go +++ b/pkg/core/native/native_test/designate_test.go @@ -106,11 +106,11 @@ func TestDesignate_Cache(t *testing.T) { } privGood, err := keys.NewPrivateKey() require.NoError(t, err) - pubsGood := []interface{}{privGood.PublicKey().Bytes()} + pubsGood := []any{privGood.PublicKey().Bytes()} privBad, err := keys.NewPrivateKey() require.NoError(t, err) - pubsBad := []interface{}{privBad.PublicKey().Bytes()} + pubsBad := []any{privBad.PublicKey().Bytes()} // Firstly, designate good Oracle node and check that OracleService callback was called during PostPersist. e.Chain.SetOracle(oracleServ) diff --git a/pkg/core/native/native_test/gas_test.go b/pkg/core/native/native_test/gas_test.go index 3c08fbf30..e92f9097b 100644 --- a/pkg/core/native/native_test/gas_test.go +++ b/pkg/core/native/native_test/gas_test.go @@ -78,7 +78,7 @@ func TestGAS_RewardWithP2PSigExtensionsEnabled(t *testing.T) { // set Notary nodes and check their balance notaryNodes := make([]*keys.PrivateKey, nNotaries) - notaryNodesPublicKeys := make([]interface{}, nNotaries) + notaryNodesPublicKeys := make([]any, nNotaries) var err error for i := range notaryNodes { notaryNodes[i], err = keys.NewPrivateKey() @@ -92,7 +92,7 @@ func TestGAS_RewardWithP2PSigExtensionsEnabled(t *testing.T) { // deposit GAS for `signer` with lock until the next block depositAmount := 100_0000 + (2+int64(nKeys))*notaryServiceFeePerKey // sysfee + netfee of the next transaction - gasCommitteeInvoker.Invoke(t, true, "transfer", e.CommitteeHash, notaryHash, depositAmount, []interface{}{e.CommitteeHash, e.Chain.BlockHeight() + 1}) + gasCommitteeInvoker.Invoke(t, true, "transfer", e.CommitteeHash, notaryHash, depositAmount, []any{e.CommitteeHash, e.Chain.BlockHeight() + 1}) // save initial GAS total supply getGASTS := func(t *testing.T) int64 { diff --git a/pkg/core/native/native_test/management_test.go b/pkg/core/native/native_test/management_test.go index dd5535cdb..a5525fb0b 100644 --- a/pkg/core/native/native_test/management_test.go +++ b/pkg/core/native/native_test/management_test.go @@ -98,7 +98,7 @@ func TestManagement_ContractDeploy(t *testing.T) { managementInvoker.InvokeFail(t, "invalid NEF file", "deploy", []byte{}, manifestBytes) }) t.Run("array for NEF", func(t *testing.T) { - managementInvoker.InvokeFail(t, "invalid NEF file", "deploy", []interface{}{int64(1)}, manifestBytes) + managementInvoker.InvokeFail(t, "invalid NEF file", "deploy", []any{int64(1)}, manifestBytes) }) t.Run("bad script in NEF", func(t *testing.T) { nf, err := nef.FileFromBytes(nefBytes) // make a full copy @@ -116,7 +116,7 @@ func TestManagement_ContractDeploy(t *testing.T) { managementInvoker.InvokeFail(t, "invalid manifest", "deploy", nefBytes, []byte{}) }) t.Run("array for manifest", func(t *testing.T) { - managementInvoker.InvokeFail(t, "invalid manifest", "deploy", nefBytes, []interface{}{int64(1)}) + managementInvoker.InvokeFail(t, "invalid manifest", "deploy", nefBytes, []any{int64(1)}) }) t.Run("non-utf8 manifest", func(t *testing.T) { manifestBad := bytes.Replace(manifestBytes, []byte("TestMain"), []byte("\xff\xfe\xfd"), 1) // Replace name. @@ -549,7 +549,7 @@ func TestManagement_GetContract(t *testing.T) { managementInvoker.Invoke(t, si, "deploy", nefBytes, manifestBytes) t.Run("bad parameter type", func(t *testing.T) { - managementInvoker.InvokeFail(t, "invalid conversion: Array/ByteString", "getContract", []interface{}{int64(1)}) + managementInvoker.InvokeFail(t, "invalid conversion: Array/ByteString", "getContract", []any{int64(1)}) }) t.Run("not a hash", func(t *testing.T) { managementInvoker.InvokeFail(t, "expected byte size of 20 got 3", "getContract", []byte{1, 2, 3}) @@ -558,7 +558,7 @@ func TestManagement_GetContract(t *testing.T) { managementInvoker.Invoke(t, si, "getContract", cs1.Hash.BytesBE()) }) t.Run("by ID, bad parameter type", func(t *testing.T) { - managementInvoker.InvokeFail(t, "invalid conversion: Array/Integer", "getContractById", []interface{}{int64(1)}) + managementInvoker.InvokeFail(t, "invalid conversion: Array/Integer", "getContractById", []any{int64(1)}) }) t.Run("by ID, bad num", func(t *testing.T) { managementInvoker.InvokeFail(t, "id is not a correct int32", "getContractById", []byte{1, 2, 3, 4, 5}) diff --git a/pkg/core/native/native_test/notary_test.go b/pkg/core/native/native_test/notary_test.go index 85e3914fb..c4a58ac71 100644 --- a/pkg/core/native/native_test/notary_test.go +++ b/pkg/core/native/native_test/notary_test.go @@ -75,19 +75,19 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, false, "lockDepositUntil", multisigHash, int64(depositLock+1)) // `onPayment`: bad token - neoCommitteeInvoker.InvokeFail(t, "only GAS can be accepted for deposit", "transfer", multisigHash, notaryHash, int64(1), []interface{}{nil, int64(depositLock)}) + neoCommitteeInvoker.InvokeFail(t, "only GAS can be accepted for deposit", "transfer", multisigHash, notaryHash, int64(1), []any{nil, int64(depositLock)}) // `onPayment`: insufficient first deposit - gasCommitteeInvoker.InvokeFail(t, "first deposit can not be less then", "transfer", multisigHash, notaryHash, int64(2*feePerKey-1), []interface{}{nil, int64(depositLock)}) + gasCommitteeInvoker.InvokeFail(t, "first deposit can not be less then", "transfer", multisigHash, notaryHash, int64(2*feePerKey-1), []any{nil, int64(depositLock)}) // `onPayment`: invalid `data` (missing `till` parameter) - gasCommitteeInvoker.InvokeFail(t, "`data` parameter should be an array of 2 elements", "transfer", multisigHash, notaryHash, 2*feePerKey, []interface{}{nil}) + gasCommitteeInvoker.InvokeFail(t, "`data` parameter should be an array of 2 elements", "transfer", multisigHash, notaryHash, 2*feePerKey, []any{nil}) // `onPayment`: invalid `data` (outdated `till` parameter) - gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, 2*feePerKey, []interface{}{nil, int64(0)}) + gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, 2*feePerKey, []any{nil, int64(0)}) // `onPayment`: good - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, []interface{}{nil, int64(depositLock)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, []any{nil, int64(depositLock)}) checkBalanceOf(t, notaryHash, 2*feePerKey) // `expirationOf`: check `till` was set @@ -97,7 +97,7 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, 2*feePerKey, "balanceOf", multisigHash) // `onPayment`: good second deposit and explicit `to` paramenter - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, []interface{}{multisigHash, int64(depositLock + 1)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, []any{multisigHash, int64(depositLock + 1)}) checkBalanceOf(t, notaryHash, 3*feePerKey) // `balanceOf`: check deposited amount for the multisig account @@ -107,17 +107,17 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, depositLock+1, "expirationOf", multisigHash) // `onPayment`: empty payment, should fail because `till` less then the previous one - gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the previous value", "transfer", multisigHash, notaryHash, int64(0), []interface{}{multisigHash, int64(depositLock)}) + gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the previous value", "transfer", multisigHash, notaryHash, int64(0), []any{multisigHash, int64(depositLock)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, depositLock+1, "expirationOf", multisigHash) // `onPayment`: empty payment, should fail because `till` less then the chain height - gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, int64(0), []interface{}{multisigHash, int64(1)}) + gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, int64(0), []any{multisigHash, int64(1)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, depositLock+1, "expirationOf", multisigHash) // `onPayment`: empty payment, should successfully update `till` - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, int64(0), []interface{}{multisigHash, int64(depositLock + 2)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, int64(0), []any{multisigHash, int64(depositLock + 2)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, depositLock+2, "expirationOf", multisigHash) @@ -159,12 +159,12 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, false, "withdraw", multisigHash, accHash) // `onPayment`: good first deposit to other account, should set default `till` even if other `till` value is provided - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, []interface{}{accHash, int64(math.MaxUint32 - 1)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, []any{accHash, int64(math.MaxUint32 - 1)}) checkBalanceOf(t, notaryHash, 2*feePerKey) notaryCommitteeInvoker.Invoke(t, 5760+e.Chain.BlockHeight()-1, "expirationOf", accHash) // `onPayment`: good second deposit to other account, shouldn't update `till` even if other `till` value is provided - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, []interface{}{accHash, int64(math.MaxUint32 - 1)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, []any{accHash, int64(math.MaxUint32 - 1)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, 5760+e.Chain.BlockHeight()-3, "expirationOf", accHash) } @@ -184,7 +184,7 @@ func TestNotary_NotaryNodesReward(t *testing.T) { // set Notary nodes and check their balance notaryNodes := make([]*keys.PrivateKey, nNotaryNodes) - notaryNodesPublicKeys := make([]interface{}, nNotaryNodes) + notaryNodesPublicKeys := make([]any, nNotaryNodes) for i := range notaryNodes { notaryNodes[i], err = keys.NewPrivateKey() require.NoError(t, err) @@ -201,7 +201,7 @@ func TestNotary_NotaryNodesReward(t *testing.T) { if !spendFullDeposit { depositAmount += 1_0000 } - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, depositAmount, []interface{}{multisigHash, e.Chain.BlockHeight() + 1}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, depositAmount, []any{multisigHash, e.Chain.BlockHeight() + 1}) // send transaction with Notary contract as a sender tx := transaction.New([]byte{byte(opcode.PUSH1)}, 1_000_000) diff --git a/pkg/core/native/native_test/oracle_test.go b/pkg/core/native/native_test/oracle_test.go index f7ce224f3..54ad6569c 100644 --- a/pkg/core/native/native_test/oracle_test.go +++ b/pkg/core/native/native_test/oracle_test.go @@ -36,7 +36,7 @@ func TestOracle_GetSetPriceCache(t *testing.T) { func putOracleRequest(t *testing.T, oracleInvoker *neotest.ContractInvoker, url string, filter *string, cb string, userData []byte, gas int64, errStr ...string) { - var filtItem interface{} + var filtItem any if filter != nil { filtItem = *filter } @@ -71,7 +71,7 @@ func TestOracle_Request(t *testing.T) { // Designate single Oracle node. oracleNode := e.NewAccount(t) - designationCommitteeInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int(noderoles.Oracle), []interface{}{oracleNode.(neotest.SingleSigner).Account().PublicKey().Bytes()}) + designationCommitteeInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int(noderoles.Oracle), []any{oracleNode.(neotest.SingleSigner).Account().PublicKey().Bytes()}) err = oracleNode.(neotest.SingleSigner).Account().ConvertMultisig(1, []*keys.PublicKey{oracleNode.(neotest.SingleSigner).Account().PublicKey()}) require.NoError(t, err) oracleNodeMulti := neotest.NewMultiSigner(oracleNode.(neotest.SingleSigner).Account()) diff --git a/pkg/core/native/oracle_types_test.go b/pkg/core/native/oracle_types_test.go index cba0e20b1..ac640151d 100644 --- a/pkg/core/native/oracle_types_test.go +++ b/pkg/core/native/oracle_types_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func getInvalidTestFunc(actual stackitem.Convertible, value interface{}) func(t *testing.T) { +func getInvalidTestFunc(actual stackitem.Convertible, value any) func(t *testing.T) { return func(t *testing.T) { it := stackitem.Make(value) require.Error(t, actual.FromStackItem(it)) diff --git a/pkg/core/native/std_test.go b/pkg/core/native/std_test.go index 48b81b526..dc1461328 100644 --- a/pkg/core/native/std_test.go +++ b/pkg/core/native/std_test.go @@ -306,7 +306,7 @@ func TestStdLibSerializeDeserialize(t *testing.T) { ic := &interop.Context{VM: vm.New(), DAO: &dao.Simple{}} var actual stackitem.Item - checkSerializeDeserialize := func(t *testing.T, value interface{}, expected stackitem.Item) { + checkSerializeDeserialize := func(t *testing.T, value any, expected stackitem.Item) { require.NotPanics(t, func() { actual = s.serialize(ic, []stackitem.Item{stackitem.Make(value)}) }) @@ -427,7 +427,7 @@ func TestMemorySearch(t *testing.T) { s := newStd() ic := &interop.Context{VM: vm.New()} - check := func(t *testing.T, result int64, args ...interface{}) { + check := func(t *testing.T, result int64, args ...any) { items := make([]stackitem.Item, len(args)) for i := range args { items[i] = stackitem.Make(args[i]) @@ -519,7 +519,7 @@ func TestStringSplit(t *testing.T) { s := newStd() ic := &interop.Context{VM: vm.New()} - check := func(t *testing.T, result []string, str, sep string, remove interface{}) { + check := func(t *testing.T, result []string, str, sep string, remove any) { args := []stackitem.Item{stackitem.Make(str), stackitem.Make(sep)} var actual stackitem.Item if remove == nil { diff --git a/pkg/core/transaction/attribute.go b/pkg/core/transaction/attribute.go index 91f8b66e5..0044f4b5f 100644 --- a/pkg/core/transaction/attribute.go +++ b/pkg/core/transaction/attribute.go @@ -17,7 +17,7 @@ type Attribute struct { // Anonymous interface fields are not considered anonymous by // json lib and marshaling Value together with type makes code // harder to follow. - toJSONMap(map[string]interface{}) + toJSONMap(map[string]any) } } @@ -70,7 +70,7 @@ func (attr *Attribute) EncodeBinary(bw *io.BinWriter) { // MarshalJSON implements the json Marshaller interface. func (attr *Attribute) MarshalJSON() ([]byte, error) { - m := map[string]interface{}{"type": attr.Type.String()} + m := map[string]any{"type": attr.Type.String()} if attr.Value != nil { attr.Value.toJSONMap(m) } diff --git a/pkg/core/transaction/conflicts.go b/pkg/core/transaction/conflicts.go index 01b62e441..50005fb21 100644 --- a/pkg/core/transaction/conflicts.go +++ b/pkg/core/transaction/conflicts.go @@ -20,6 +20,6 @@ func (c *Conflicts) EncodeBinary(w *io.BinWriter) { c.Hash.EncodeBinary(w) } -func (c *Conflicts) toJSONMap(m map[string]interface{}) { +func (c *Conflicts) toJSONMap(m map[string]any) { m["hash"] = c.Hash } diff --git a/pkg/core/transaction/not_valid_before.go b/pkg/core/transaction/not_valid_before.go index 232009f3d..6fe9b7b56 100644 --- a/pkg/core/transaction/not_valid_before.go +++ b/pkg/core/transaction/not_valid_before.go @@ -19,6 +19,6 @@ func (n *NotValidBefore) EncodeBinary(w *io.BinWriter) { w.WriteU32LE(n.Height) } -func (n *NotValidBefore) toJSONMap(m map[string]interface{}) { +func (n *NotValidBefore) toJSONMap(m map[string]any) { m["height"] = n.Height } diff --git a/pkg/core/transaction/notary_assisted.go b/pkg/core/transaction/notary_assisted.go index 5a7de29a4..747711165 100644 --- a/pkg/core/transaction/notary_assisted.go +++ b/pkg/core/transaction/notary_assisted.go @@ -19,6 +19,6 @@ func (n *NotaryAssisted) EncodeBinary(w *io.BinWriter) { w.WriteB(n.NKeys) } -func (n *NotaryAssisted) toJSONMap(m map[string]interface{}) { +func (n *NotaryAssisted) toJSONMap(m map[string]any) { m["nkeys"] = n.NKeys } diff --git a/pkg/core/transaction/oracle.go b/pkg/core/transaction/oracle.go index 2d396d2f7..68459ef56 100644 --- a/pkg/core/transaction/oracle.go +++ b/pkg/core/transaction/oracle.go @@ -111,7 +111,7 @@ func (r *OracleResponse) EncodeBinary(w *io.BinWriter) { w.WriteVarBytes(r.Result) } -func (r *OracleResponse) toJSONMap(m map[string]interface{}) { +func (r *OracleResponse) toJSONMap(m map[string]any) { m["id"] = r.ID m["code"] = r.Code m["result"] = r.Result diff --git a/pkg/core/transaction/oracle_test.go b/pkg/core/transaction/oracle_test.go index f0ec24a09..afc61f441 100644 --- a/pkg/core/transaction/oracle_test.go +++ b/pkg/core/transaction/oracle_test.go @@ -68,7 +68,7 @@ func TestOracleResponse_toJSONMap(t *testing.T) { b1, err := json.Marshal(r) require.NoError(t, err) - m := map[string]interface{}{} + m := map[string]any{} r.toJSONMap(m) b2, err := json.Marshal(m) require.NoError(t, err) diff --git a/pkg/core/transaction/reserved.go b/pkg/core/transaction/reserved.go index cc622c708..677458aa3 100644 --- a/pkg/core/transaction/reserved.go +++ b/pkg/core/transaction/reserved.go @@ -19,6 +19,6 @@ func (e *Reserved) EncodeBinary(w *io.BinWriter) { w.WriteVarBytes(e.Value) } -func (e *Reserved) toJSONMap(m map[string]interface{}) { +func (e *Reserved) toJSONMap(m map[string]any) { m["value"] = e.Value } diff --git a/pkg/core/transaction/witness_condition.go b/pkg/core/transaction/witness_condition.go index 65a73b09e..b34a8d389 100644 --- a/pkg/core/transaction/witness_condition.go +++ b/pkg/core/transaction/witness_condition.go @@ -631,7 +631,7 @@ func unmarshalConditionJSON(data []byte, maxDepth int) (WitnessCondition, error) return res, nil } -func condToStackItem(typ WitnessConditionType, c interface{}) stackitem.Item { +func condToStackItem(typ WitnessConditionType, c any) stackitem.Item { res := make([]stackitem.Item, 0, 2) res = append(res, stackitem.NewBigInteger(big.NewInt(int64(typ)))) switch typ { diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 674ca8e76..c1bf5c3b0 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -181,7 +181,7 @@ func (p *PublicKey) UncompressedBytes() []byte { func NewPublicKeyFromASN1(data []byte) (*PublicKey, error) { var ( err error - pubkey interface{} + pubkey any ) if pubkey, err = x509.ParsePKIXPublicKey(data); err != nil { return nil, err diff --git a/pkg/encoding/fixedn/fixed8.go b/pkg/encoding/fixedn/fixed8.go index 3bea85b3a..ad28d5133 100644 --- a/pkg/encoding/fixedn/fixed8.go +++ b/pkg/encoding/fixedn/fixed8.go @@ -85,7 +85,7 @@ func (f *Fixed8) UnmarshalJSON(data []byte) error { } // UnmarshalYAML implements the yaml unmarshaler interface. -func (f *Fixed8) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (f *Fixed8) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) if err != nil { @@ -109,7 +109,7 @@ func (f Fixed8) MarshalJSON() ([]byte, error) { } // MarshalYAML implements the yaml marshaller interface. -func (f Fixed8) MarshalYAML() (interface{}, error) { +func (f Fixed8) MarshalYAML() (any, error) { return f.String(), nil } diff --git a/pkg/interop/contract/contract.go b/pkg/interop/contract/contract.go index 2f3843ee3..0b4ad6b58 100644 --- a/pkg/interop/contract/contract.go +++ b/pkg/interop/contract/contract.go @@ -47,6 +47,6 @@ func GetCallFlags() CallFlag { // (20 bytes in BE form) using the provided arguments and call flags. // It returns whatever this contract returns. This function uses // `System.Contract.Call` syscall. -func Call(scriptHash interop.Hash160, method string, f CallFlag, args ...interface{}) interface{} { +func Call(scriptHash interop.Hash160, method string, f CallFlag, args ...any) any { return neogointernal.Syscall4("System.Contract.Call", scriptHash, method, f, args) } diff --git a/pkg/interop/convert/convert.go b/pkg/interop/convert/convert.go index 653f55ca1..0f4eb8dc0 100644 --- a/pkg/interop/convert/convert.go +++ b/pkg/interop/convert/convert.go @@ -2,21 +2,21 @@ package convert // ToInteger converts it's argument to an Integer. -func ToInteger(v interface{}) int { +func ToInteger(v any) int { return v.(int) } // ToBytes converts it's argument to a Buffer VM type. -func ToBytes(v interface{}) []byte { +func ToBytes(v any) []byte { return v.([]byte) } // ToString converts it's argument to a ByteString VM type. -func ToString(v interface{}) string { +func ToString(v any) string { return v.(string) } // ToBool converts it's argument to a Boolean. -func ToBool(v interface{}) bool { +func ToBool(v any) bool { return v.(bool) } diff --git a/pkg/interop/doc.go b/pkg/interop/doc.go index a78d25b72..b9d083500 100644 --- a/pkg/interop/doc.go +++ b/pkg/interop/doc.go @@ -14,6 +14,7 @@ correspond to smartcontract and VM types: []byte - ByteArray (Buffer in VM) string - String (ByteString in VM) (interface{})(nil) - Any + (any)(nil) - Any non-byte slice - Array map[K]V - map diff --git a/pkg/interop/iterator/iterator.go b/pkg/interop/iterator/iterator.go index 391e64cf3..243d02851 100644 --- a/pkg/interop/iterator/iterator.go +++ b/pkg/interop/iterator/iterator.go @@ -24,6 +24,6 @@ func Next(it Iterator) bool { // For slices, the result is just value. // For maps, the result can be cast to a slice of 2 elements: a key and a value. // For storage iterators, refer to `storage.FindFlags` documentation. -func Value(it Iterator) interface{} { +func Value(it Iterator) any { return neogointernal.Syscall1("System.Iterator.Value", it) } diff --git a/pkg/interop/lib/contract/contract.go b/pkg/interop/lib/contract/contract.go index 735db00ba..8011ae6f9 100644 --- a/pkg/interop/lib/contract/contract.go +++ b/pkg/interop/lib/contract/contract.go @@ -11,7 +11,7 @@ import ( // (20 bytes in BE form) using the provided arguments and call flags. It fails // if the contract has version mismatch. It returns whatever this contract // returns. This function uses `System.Contract.Call` syscall. -func CallWithVersion(scriptHash interop.Hash160, version int, method string, f contract.CallFlag, args ...interface{}) interface{} { +func CallWithVersion(scriptHash interop.Hash160, version int, method string, f contract.CallFlag, args ...any) any { cs := management.GetContract(scriptHash) if cs == nil { panic("unknown contract") diff --git a/pkg/interop/native/gas/gas.go b/pkg/interop/native/gas/gas.go index 538ac0a36..338a6f99d 100644 --- a/pkg/interop/native/gas/gas.go +++ b/pkg/interop/native/gas/gas.go @@ -34,7 +34,7 @@ func BalanceOf(addr interop.Hash160) int { } // Transfer represents `transfer` method of GAS native contract. -func Transfer(from, to interop.Hash160, amount int, data interface{}) bool { +func Transfer(from, to interop.Hash160, amount int, data any) bool { return neogointernal.CallWithToken(Hash, "transfer", int(contract.All), from, to, amount, data).(bool) } diff --git a/pkg/interop/native/ledger/block.go b/pkg/interop/native/ledger/block.go index 84e1a6407..0164803cb 100644 --- a/pkg/interop/native/ledger/block.go +++ b/pkg/interop/native/ledger/block.go @@ -51,5 +51,5 @@ type BlockSR struct { // ToBlockSR converts Block into BlockSR for chains with StateRootInHeader option. func (b *Block) ToBlockSR() *BlockSR { - return interface{}(b).(*BlockSR) + return any(b).(*BlockSR) } diff --git a/pkg/interop/native/ledger/ledger.go b/pkg/interop/native/ledger/ledger.go index f26a15fa4..591dccaea 100644 --- a/pkg/interop/native/ledger/ledger.go +++ b/pkg/interop/native/ledger/ledger.go @@ -39,7 +39,7 @@ func CurrentIndex() int { } // GetBlock represents `getBlock` method of Ledger native contract. -func GetBlock(indexOrHash interface{}) *Block { +func GetBlock(indexOrHash any) *Block { return neogointernal.CallWithToken(Hash, "getBlock", int(contract.ReadStates), indexOrHash).(*Block) } @@ -54,7 +54,7 @@ func GetTransactionHeight(hash interop.Hash256) int { } // GetTransactionFromBlock represents `getTransactionFromBlock` method of Ledger native contract. -func GetTransactionFromBlock(indexOrHash interface{}, txIndex int) *Transaction { +func GetTransactionFromBlock(indexOrHash any, txIndex int) *Transaction { return neogointernal.CallWithToken(Hash, "getTransactionFromBlock", int(contract.ReadStates), indexOrHash, txIndex).(*Transaction) } diff --git a/pkg/interop/native/ledger/transaction_signer.go b/pkg/interop/native/ledger/transaction_signer.go index 04f04772b..05270faf6 100644 --- a/pkg/interop/native/ledger/transaction_signer.go +++ b/pkg/interop/native/ledger/transaction_signer.go @@ -82,7 +82,7 @@ type WitnessCondition struct { // WitnessCalledByContract -> interop.Hash160 // WitnessCalledByGroup -> interop.PublicKey // WitnessCalledByEntry -> doesn't have value, thus, an attempt to access the Value leads to runtime exception. - Value interface{} + Value any } // WitnessConditionType represents the type of rule-based witness condition. diff --git a/pkg/interop/native/management/contract.go b/pkg/interop/native/management/contract.go index 31778e2e4..b05fc66bc 100644 --- a/pkg/interop/native/management/contract.go +++ b/pkg/interop/native/management/contract.go @@ -40,7 +40,7 @@ type Manifest struct { ABI ABI Permissions []Permission Trusts []interop.Hash160 - Extra interface{} + Extra any } // ABI represents contract's ABI. diff --git a/pkg/interop/native/management/management.go b/pkg/interop/native/management/management.go index 8f6517242..9e7a632c3 100644 --- a/pkg/interop/native/management/management.go +++ b/pkg/interop/native/management/management.go @@ -29,7 +29,7 @@ func Deploy(script, manifest []byte) *Contract { } // DeployWithData represents `deploy` method of Management native contract. -func DeployWithData(script, manifest []byte, data interface{}) *Contract { +func DeployWithData(script, manifest []byte, data any) *Contract { return neogointernal.CallWithToken(Hash, "deploy", int(contract.All), script, manifest, data).(*Contract) } @@ -80,7 +80,7 @@ func Update(script, manifest []byte) { } // UpdateWithData represents `update` method of Management native contract. -func UpdateWithData(script, manifest []byte, data interface{}) { +func UpdateWithData(script, manifest []byte, data any) { neogointernal.CallWithTokenNoRet(Hash, "update", int(contract.All), script, manifest, data) } diff --git a/pkg/interop/native/neo/neo.go b/pkg/interop/native/neo/neo.go index 4c5e4c9b0..dac6dae9d 100644 --- a/pkg/interop/native/neo/neo.go +++ b/pkg/interop/native/neo/neo.go @@ -44,7 +44,7 @@ func BalanceOf(addr interop.Hash160) int { } // Transfer represents `transfer` method of NEO native contract. -func Transfer(from, to interop.Hash160, amount int, data interface{}) bool { +func Transfer(from, to interop.Hash160, amount int, data any) bool { return neogointernal.CallWithToken(Hash, "transfer", int(contract.All), from, to, amount, data).(bool) } diff --git a/pkg/interop/native/oracle/oracle.go b/pkg/interop/native/oracle/oracle.go index 46a627a17..14155b5df 100644 --- a/pkg/interop/native/oracle/oracle.go +++ b/pkg/interop/native/oracle/oracle.go @@ -50,7 +50,7 @@ const MinimumResponseGas = 10_000_000 // of the same contract that invokes Request and it must have the following // signature for correct invocation: // -// - Method(url string, userData interface{}, code int, result []byte) +// - Method(url string, userData any, code int, result []byte) // where url is the same url specified for Request, userData is anything // passed in the next parameter, code is the status of the reply and // result is the data returned from the request if any. @@ -64,7 +64,7 @@ const MinimumResponseGas = 10_000_000 // GAS is used for oracle transaction's network and system fees, // so it should be enough to pay for reply data as well as // its processing. -func Request(url string, filter []byte, cb string, userData interface{}, gasForResponse int) { +func Request(url string, filter []byte, cb string, userData any, gasForResponse int) { neogointernal.CallWithTokenNoRet(Hash, "request", int(contract.States|contract.AllowNotify), url, filter, cb, userData, gasForResponse) diff --git a/pkg/interop/native/std/std.go b/pkg/interop/native/std/std.go index 10d7ddd47..e79e32d3d 100644 --- a/pkg/interop/native/std/std.go +++ b/pkg/interop/native/std/std.go @@ -16,14 +16,14 @@ const Hash = "\xc0\xef\x39\xce\xe0\xe4\xe9\x25\xc6\xc2\xa0\x6a\x79\xe1\x44\x0d\x // any given item into a byte slice. It works for all regular VM types (not ones // from interop package) and allows to save them in the storage or pass them into Notify // and then Deserialize them on the next run or in the external event receiver. -func Serialize(item interface{}) []byte { +func Serialize(item any) []byte { return neogointernal.CallWithToken(Hash, "serialize", int(contract.NoneFlag), item).([]byte) } // Deserialize calls `deserialize` method of StdLib native contract and unpacks // a previously serialized value from a byte slice, it's the opposite of Serialize. -func Deserialize(b []byte) interface{} { +func Deserialize(b []byte) any { return neogointernal.CallWithToken(Hash, "deserialize", int(contract.NoneFlag), b) } @@ -37,8 +37,9 @@ func Deserialize(b []byte) interface{} { // string -> base64 encoded sequence of underlying bytes // (u)int* -> integer, only value in -2^53..2^53 are allowed // []interface{} -> json array +// []any -> json array // map[type1]type2 -> json object with string keys marshaled as strings (not base64). -func JSONSerialize(item interface{}) []byte { +func JSONSerialize(item any) []byte { return neogointernal.CallWithToken(Hash, "jsonSerialize", int(contract.NoneFlag), item).([]byte) } @@ -52,7 +53,7 @@ func JSONSerialize(item interface{}) []byte { // null -> interface{}(nil) // arrays -> []interface{} // maps -> map[string]interface{} -func JSONDeserialize(data []byte) interface{} { +func JSONDeserialize(data []byte) any { return neogointernal.CallWithToken(Hash, "jsonDeserialize", int(contract.NoneFlag), data) } diff --git a/pkg/interop/neogointernal/call.go b/pkg/interop/neogointernal/call.go index 0309bfe94..f32e65fad 100644 --- a/pkg/interop/neogointernal/call.go +++ b/pkg/interop/neogointernal/call.go @@ -3,10 +3,10 @@ package neogointernal // CallWithToken performs contract call using CALLT instruction. It only works // for static script hashes and methods, requiring additional metadata compared to // ordinary contract.Call. It's more efficient though. -func CallWithToken(scriptHash string, method string, flags int, args ...interface{}) interface{} { +func CallWithToken(scriptHash string, method string, flags int, args ...any) any { return nil } // CallWithTokenNoRet is a version of CallWithToken that does not return anything. -func CallWithTokenNoRet(scriptHash string, method string, flags int, args ...interface{}) { +func CallWithTokenNoRet(scriptHash string, method string, flags int, args ...any) { } diff --git a/pkg/interop/neogointernal/opcode.go b/pkg/interop/neogointernal/opcode.go index 1667c5e05..a64e85733 100644 --- a/pkg/interop/neogointernal/opcode.go +++ b/pkg/interop/neogointernal/opcode.go @@ -5,20 +5,20 @@ func Opcode0NoReturn(op string) { } // Opcode1 emits opcode with 1 argument. -func Opcode1(op string, arg interface{}) interface{} { +func Opcode1(op string, arg any) any { return nil } // Opcode2 emits opcode with 2 arguments. -func Opcode2(op string, arg1, arg2 interface{}) interface{} { +func Opcode2(op string, arg1, arg2 any) any { return nil } // Opcode2NoReturn emits opcode with 2 arguments. -func Opcode2NoReturn(op string, arg1, arg2 interface{}) { +func Opcode2NoReturn(op string, arg1, arg2 any) { } // Opcode3 emits opcode with 3 arguments. -func Opcode3(op string, arg1, arg2, arg3 interface{}) interface{} { +func Opcode3(op string, arg1, arg2, arg3 any) any { return nil } diff --git a/pkg/interop/neogointernal/syscall.go b/pkg/interop/neogointernal/syscall.go index f42ed2735..d106d2c1a 100644 --- a/pkg/interop/neogointernal/syscall.go +++ b/pkg/interop/neogointernal/syscall.go @@ -1,7 +1,7 @@ package neogointernal // Syscall0 performs syscall with 0 arguments. -func Syscall0(name string) interface{} { +func Syscall0(name string) any { return nil } @@ -10,37 +10,37 @@ func Syscall0NoReturn(name string) { } // Syscall1 performs syscall with 1 arguments. -func Syscall1(name string, arg interface{}) interface{} { +func Syscall1(name string, arg any) any { return nil } // Syscall1NoReturn performs syscall with 1 arguments. -func Syscall1NoReturn(name string, arg interface{}) { +func Syscall1NoReturn(name string, arg any) { } // Syscall2 performs syscall with 2 arguments. -func Syscall2(name string, arg1, arg2 interface{}) interface{} { +func Syscall2(name string, arg1, arg2 any) any { return nil } // Syscall2NoReturn performs syscall with 2 arguments. -func Syscall2NoReturn(name string, arg1, arg2 interface{}) { +func Syscall2NoReturn(name string, arg1, arg2 any) { } // Syscall3 performs syscall with 3 arguments. -func Syscall3(name string, arg1, arg2, arg3 interface{}) interface{} { +func Syscall3(name string, arg1, arg2, arg3 any) any { return nil } // Syscall3NoReturn performs syscall with 3 arguments. -func Syscall3NoReturn(name string, arg1, arg2, arg3 interface{}) { +func Syscall3NoReturn(name string, arg1, arg2, arg3 any) { } // Syscall4 performs syscall with 4 arguments. -func Syscall4(name string, arg1, arg2, arg3, arg4 interface{}) interface{} { +func Syscall4(name string, arg1, arg2, arg3, arg4 any) any { return nil } // Syscall4NoReturn performs syscall with 4 arguments. -func Syscall4NoReturn(name string, arg1, arg2, arg3, arg4 interface{}) { +func Syscall4NoReturn(name string, arg1, arg2, arg3, arg4 any) { } diff --git a/pkg/interop/runtime/runtime.go b/pkg/interop/runtime/runtime.go index ab8415fb2..a23039473 100644 --- a/pkg/interop/runtime/runtime.go +++ b/pkg/interop/runtime/runtime.go @@ -41,7 +41,7 @@ func CheckWitness(hashOrKey []byte) bool { // script can ABORT the transaction or THROW an exception, make sure you // appropriately handle exceptions if bytecode comes from untrusted source. // This function uses `System.Runtime.LoadScript` syscall. -func LoadScript(script []byte, f contract.CallFlag, args ...interface{}) interface{} { +func LoadScript(script []byte, f contract.CallFlag, args ...any) any { return neogointernal.Syscall3("System.Runtime.LoadScript", script, f, args) } @@ -58,7 +58,7 @@ func Log(message string) { // part of contract's API to external systems, these events can be monitored // from outside and act upon accordingly. This function uses // `System.Runtime.Notify` syscall. -func Notify(name string, args ...interface{}) { +func Notify(name string, args ...any) { neogointernal.Syscall2NoReturn("System.Runtime.Notify", name, args) } @@ -105,8 +105,8 @@ func GasLeft() int { // 'nil' literal means no filtering. It returns slice consisting of following elements: // [ scripthash of notification's contract , emitted item ]. // This function uses `System.Runtime.GetNotifications` syscall. -func GetNotifications(h interop.Hash160) [][]interface{} { - return neogointernal.Syscall1("System.Runtime.GetNotifications", h).([][]interface{}) +func GetNotifications(h interop.Hash160) [][]any { + return neogointernal.Syscall1("System.Runtime.GetNotifications", h).([][]any) } // GetInvocationCounter returns how many times current contract was invoked during current tx execution. diff --git a/pkg/interop/storage/storage.go b/pkg/interop/storage/storage.go index 15f5de118..146e32104 100644 --- a/pkg/interop/storage/storage.go +++ b/pkg/interop/storage/storage.go @@ -61,25 +61,25 @@ func GetReadOnlyContext() Context { } // Put saves given value with given key in the storage using given Context. -// Even though it accepts interface{} for both, you can only pass simple types -// there like string, []byte, int or bool (not structures or slices of more -// complex types). To put more complex types there serialize them first using -// runtime.Serialize. This function uses `System.Storage.Put` syscall. -func Put(ctx Context, key interface{}, value interface{}) { +// Even though it accepts interface{} hidden under `any` for both, you can only +// pass simple types there like string, []byte, int or bool (not structures or +// slices of more complex types). To put more complex types there serialize them +// first using runtime.Serialize. This function uses `System.Storage.Put` syscall. +func Put(ctx Context, key any, value any) { neogointernal.Syscall3NoReturn("System.Storage.Put", ctx, key, value) } // Get retrieves value stored for the given key using given Context. See Put // documentation on possible key and value types. If the value is not present in // the database it returns nil. This function uses `System.Storage.Get` syscall. -func Get(ctx Context, key interface{}) interface{} { +func Get(ctx Context, key any) any { return neogointernal.Syscall2("System.Storage.Get", ctx, key) } // Delete removes key-value pair from storage by the given key using given // Context. See Put documentation on possible key types. This function uses // `System.Storage.Delete` syscall. -func Delete(ctx Context, key interface{}) { +func Delete(ctx Context, key any) { neogointernal.Syscall2NoReturn("System.Storage.Delete", ctx, key) } @@ -87,6 +87,6 @@ func Delete(ctx Context, key interface{}) { // that match the given key (contain it as a prefix). See Put documentation on // possible key types and iterator package documentation on how to use the // returned value. This function uses `System.Storage.Find` syscall. -func Find(ctx Context, key interface{}, options FindFlags) iterator.Iterator { +func Find(ctx Context, key any, options FindFlags) iterator.Iterator { return neogointernal.Syscall3("System.Storage.Find", ctx, key, options).(iterator.Iterator) } diff --git a/pkg/interop/types.go b/pkg/interop/types.go index c0ffd4ece..a99dcd413 100644 --- a/pkg/interop/types.go +++ b/pkg/interop/types.go @@ -36,14 +36,14 @@ type PublicKey []byte // Interface represents interop interface type which is needed for // transparent handling of VM-internal types (e.g. storage.Context). -type Interface interface{} +type Interface any // Equals compares Hash160 with the provided stackitem using EQUAL opcode. // The provided stackitem `b` must be either one of the primitive type (int, // bool, string, []byte) or derived from the primitive type, otherwise Equals // will fail on .(string) conversion. -func (a Hash160) Equals(b interface{}) bool { - ha := interface{}(a) +func (a Hash160) Equals(b any) bool { + ha := any(a) return bytesEquals(ha, b) } @@ -51,8 +51,8 @@ func (a Hash160) Equals(b interface{}) bool { // The provided stackitem `b` must be either one of the primitive type (int, // bool, string, []byte) or derived from the primitive type, otherwise Equals // will fail on .(string) conversion. -func (a Hash256) Equals(b interface{}) bool { - ha := interface{}(a) +func (a Hash256) Equals(b any) bool { + ha := any(a) return bytesEquals(ha, b) } @@ -60,8 +60,8 @@ func (a Hash256) Equals(b interface{}) bool { // The provided stackitem `b` must be either one of the primitive type (int, // bool, string, []byte) or derived from the primitive type, otherwise Equals // will fail on .(string) conversion. -func (a PublicKey) Equals(b interface{}) bool { - ha := interface{}(a) +func (a PublicKey) Equals(b any) bool { + ha := any(a) return bytesEquals(ha, b) } @@ -69,14 +69,14 @@ func (a PublicKey) Equals(b interface{}) bool { // The provided stackitem `b` must be either one of the primitive types (int, // bool, string, []byte) or derived from the primitive type, otherwise Equals // will fail on .(string) conversion. -func (a Signature) Equals(b interface{}) bool { - ha := interface{}(a) +func (a Signature) Equals(b any) bool { + ha := any(a) return bytesEquals(ha, b) } // bytesEquals is an internal helper function allowed to compare types that can be // converted to ByteString. -func bytesEquals(a interface{}, b interface{}) bool { +func bytesEquals(a any, b any) bool { return (a == nil && b == nil) || (a != nil && b != nil && neogointernal.Opcode2("EQUAL", a.(string), b.(string)).(bool)) } diff --git a/pkg/interop/util/util.go b/pkg/interop/util/util.go index 038b17aa9..dcd85f14c 100644 --- a/pkg/interop/util/util.go +++ b/pkg/interop/util/util.go @@ -27,12 +27,12 @@ func FromAddress(address string) interop.Hash160 { // Equals compares a with b and will return true when a and b are equal. It's // implemented as an EQUAL VM opcode, so the rules of comparison are those // of EQUAL. -func Equals(a, b interface{}) bool { +func Equals(a, b any) bool { return neogointernal.Opcode2("EQUAL", a, b).(bool) } // Remove removes element with index i from slice. // This is done in place and slice must have type other than `[]byte`. -func Remove(slice interface{}, i int) { +func Remove(slice any, i int) { neogointernal.Opcode2NoReturn("REMOVE", slice, i) } diff --git a/pkg/io/binaryReader.go b/pkg/io/binaryReader.go index 34abd7976..642eae245 100644 --- a/pkg/io/binaryReader.go +++ b/pkg/io/binaryReader.go @@ -100,7 +100,7 @@ func (r *BinReader) ReadBool() bool { // ReadArray reads an array into a value which must be // a pointer to a slice. -func (r *BinReader) ReadArray(t interface{}, maxSize ...int) { +func (r *BinReader) ReadArray(t any, maxSize ...int) { value := reflect.ValueOf(t) if value.Kind() != reflect.Ptr || value.Elem().Kind() != reflect.Slice { panic(value.Type().String() + " is not a pointer to a slice") diff --git a/pkg/io/binaryWriter.go b/pkg/io/binaryWriter.go index 6188a70d8..9abadb7cf 100644 --- a/pkg/io/binaryWriter.go +++ b/pkg/io/binaryWriter.go @@ -68,7 +68,7 @@ func (w *BinWriter) WriteBool(b bool) { // WriteArray writes a slice or an array arr into w. Note that nil slices and // empty slices are gonna be treated the same resulting in an equal zero-length // array encoded. -func (w *BinWriter) WriteArray(arr interface{}) { +func (w *BinWriter) WriteArray(arr any) { switch val := reflect.ValueOf(arr); val.Kind() { case reflect.Slice, reflect.Array: if w.Err != nil { diff --git a/pkg/io/size.go b/pkg/io/size.go index ba83a403e..25dd51686 100644 --- a/pkg/io/size.go +++ b/pkg/io/size.go @@ -38,7 +38,7 @@ func getVarIntSize(value int) int { // them with variable-length encoding that is used in Neo), strings, pointers to Serializable structures, // slices and arrays of ints/uints or Serializable structures. It's similar to GetVarSize(this T[] value) // used in C#, but differs in that it also supports things like Uint160 or Uint256. -func GetVarSize(value interface{}) int { +func GetVarSize(value any) int { v := reflect.ValueOf(value) switch v.Kind() { case reflect.String: diff --git a/pkg/io/size_test.go b/pkg/io/size_test.go index 26af4c026..66223838b 100644 --- a/pkg/io/size_test.go +++ b/pkg/io/size_test.go @@ -31,7 +31,7 @@ func (*smthNotReallySerializable) EncodeBinary(bw *io.BinWriter) { func TestVarSize(t *testing.T) { testCases := []struct { - variable interface{} + variable any name string expected int }{ @@ -189,7 +189,7 @@ func TestVarSize(t *testing.T) { } } -func panicVarSize(t *testing.T, v interface{}) { +func panicVarSize(t *testing.T, v any) { defer func() { r := recover() assert.NotNil(t, r) diff --git a/pkg/neorpc/result/validate_address.go b/pkg/neorpc/result/validate_address.go index 12c092afc..468a94cab 100644 --- a/pkg/neorpc/result/validate_address.go +++ b/pkg/neorpc/result/validate_address.go @@ -4,6 +4,6 @@ package result // Address is an interface{} here because the server echoes back whatever address // value a user has sent to it, even if it's not a string. type ValidateAddress struct { - Address interface{} `json:"address"` - IsValid bool `json:"isvalid"` + Address any `json:"address"` + IsValid bool `json:"isvalid"` } diff --git a/pkg/neorpc/rpcevent/filter.go b/pkg/neorpc/rpcevent/filter.go index 049943498..ecba3e199 100644 --- a/pkg/neorpc/rpcevent/filter.go +++ b/pkg/neorpc/rpcevent/filter.go @@ -13,13 +13,13 @@ type ( // filter notifications. Comparator interface { EventID() neorpc.EventID - Filter() interface{} + Filter() any } // Container is an interface required from notification event to be able to // pass filter. Container interface { EventID() neorpc.EventID - EventPayload() interface{} + EventPayload() any } ) diff --git a/pkg/neorpc/rpcevent/filter_test.go b/pkg/neorpc/rpcevent/filter_test.go index 6afd20d13..de56a08fc 100644 --- a/pkg/neorpc/rpcevent/filter_test.go +++ b/pkg/neorpc/rpcevent/filter_test.go @@ -17,24 +17,24 @@ import ( type ( testComparator struct { id neorpc.EventID - filter interface{} + filter any } testContainer struct { id neorpc.EventID - pld interface{} + pld any } ) func (c testComparator) EventID() neorpc.EventID { return c.id } -func (c testComparator) Filter() interface{} { +func (c testComparator) Filter() any { return c.filter } func (c testContainer) EventID() neorpc.EventID { return c.id } -func (c testContainer) EventPayload() interface{} { +func (c testContainer) EventPayload() any { return c.pld } diff --git a/pkg/neorpc/types.go b/pkg/neorpc/types.go index 223cd591c..40db91878 100644 --- a/pkg/neorpc/types.go +++ b/pkg/neorpc/types.go @@ -35,7 +35,7 @@ type ( // used by the method implementation on the server side. While JSON-RPC // technically allows it to be an object, all Neo calls expect params // to be an array. - Params []interface{} `json:"params"` + Params []any `json:"params"` // ID is an identifier associated with this request. JSON-RPC itself allows // any strings to be used for it as well, but NeoGo RPC client uses numeric // identifiers. @@ -66,9 +66,9 @@ type ( // special in that they look like requests but they don't have IDs and their // "method" is actually an event name. Notification struct { - JSONRPC string `json:"jsonrpc"` - Event EventID `json:"method"` - Payload []interface{} `json:"params"` + JSONRPC string `json:"jsonrpc"` + Event EventID `json:"method"` + Payload []any `json:"params"` } // SignerWithWitness represents transaction's signer with the corresponding witness. @@ -139,6 +139,6 @@ func (n *Notification) EventID() EventID { // EventPayload implements EventContainer interface and returns notification // object. -func (n *Notification) EventPayload() interface{} { +func (n *Notification) EventPayload() any { return n.Payload[0] } diff --git a/pkg/neotest/basic.go b/pkg/neotest/basic.go index 8c1c5b307..ce6ed44b1 100644 --- a/pkg/neotest/basic.go +++ b/pkg/neotest/basic.go @@ -80,7 +80,7 @@ func (e *Executor) NativeID(t testing.TB, name string) int32 { } // NewUnsignedTx creates a new unsigned transaction which invokes the method of the contract with the hash. -func (e *Executor) NewUnsignedTx(t testing.TB, hash util.Uint160, method string, args ...interface{}) *transaction.Transaction { +func (e *Executor) NewUnsignedTx(t testing.TB, hash util.Uint160, method string, args ...any) *transaction.Transaction { script, err := smartcontract.CreateCallScript(hash, method, args...) require.NoError(t, err) @@ -93,7 +93,7 @@ func (e *Executor) NewUnsignedTx(t testing.TB, hash util.Uint160, method string, // NewTx creates a new transaction which invokes the contract method. // The transaction is signed by the signers. func (e *Executor) NewTx(t testing.TB, signers []Signer, - hash util.Uint160, method string, args ...interface{}) *transaction.Transaction { + hash util.Uint160, method string, args ...any) *transaction.Transaction { tx := e.NewUnsignedTx(t, hash, method, args...) return e.SignTx(t, tx, -1, signers...) } @@ -137,7 +137,7 @@ func (e *Executor) NewAccount(t testing.TB, expectedGASBalance ...int64) Signer // the precalculated contract hash matches the actual one. // data is an optional argument to `_deploy`. // It returns the hash of the deploy transaction. -func (e *Executor) DeployContract(t testing.TB, c *Contract, data interface{}) util.Uint256 { +func (e *Executor) DeployContract(t testing.TB, c *Contract, data any) util.Uint256 { return e.DeployContractBy(t, e.Validator, c, data) } @@ -145,7 +145,7 @@ func (e *Executor) DeployContract(t testing.TB, c *Contract, data interface{}) u // It also checks that the precalculated contract hash matches the actual one. // data is an optional argument to `_deploy`. // It returns the hash of the deploy transaction. -func (e *Executor) DeployContractBy(t testing.TB, signer Signer, c *Contract, data interface{}) util.Uint256 { +func (e *Executor) DeployContractBy(t testing.TB, signer Signer, c *Contract, data any) util.Uint256 { tx := NewDeployTxBy(t, e.Chain, signer, c, data) e.AddNewBlock(t, tx) e.CheckHalt(t, tx.Hash()) @@ -164,7 +164,7 @@ func (e *Executor) DeployContractBy(t testing.TB, signer Signer, c *Contract, da // DeployContractCheckFAULT compiles and deploys a contract to the bc using the validator // account. It checks that the deploy transaction FAULTed with the specified error. -func (e *Executor) DeployContractCheckFAULT(t testing.TB, c *Contract, data interface{}, errMessage string) { +func (e *Executor) DeployContractCheckFAULT(t testing.TB, c *Contract, data any, errMessage string) { tx := e.NewDeployTx(t, e.Chain, c, data) e.AddNewBlock(t, tx) e.CheckFault(t, tx.Hash(), errMessage) @@ -253,12 +253,12 @@ func (e *Executor) EnsureGASBalance(t testing.TB, acc util.Uint160, isOk func(ba } // NewDeployTx returns a new deployment tx for the contract signed by the committee. -func (e *Executor) NewDeployTx(t testing.TB, bc *core.Blockchain, c *Contract, data interface{}) *transaction.Transaction { +func (e *Executor) NewDeployTx(t testing.TB, bc *core.Blockchain, c *Contract, data any) *transaction.Transaction { return NewDeployTxBy(t, bc, e.Validator, c, data) } // NewDeployTxBy returns a new deployment tx for the contract signed by the specified signer. -func NewDeployTxBy(t testing.TB, bc *core.Blockchain, signer Signer, c *Contract, data interface{}) *transaction.Transaction { +func NewDeployTxBy(t testing.TB, bc *core.Blockchain, signer Signer, c *Contract, data any) *transaction.Transaction { rawManifest, err := json.Marshal(c.Manifest) require.NoError(t, err) diff --git a/pkg/neotest/client.go b/pkg/neotest/client.go index 25ac8c158..9596c12cb 100644 --- a/pkg/neotest/client.go +++ b/pkg/neotest/client.go @@ -48,7 +48,7 @@ func (e *Executor) ValidatorInvoker(h util.Uint160) *ContractInvoker { } // TestInvoke creates test the VM and invokes the method with the args. -func (c *ContractInvoker) TestInvoke(t testing.TB, method string, args ...interface{}) (*vm.Stack, error) { +func (c *ContractInvoker) TestInvoke(t testing.TB, method string, args ...any) (*vm.Stack, error) { tx := c.PrepareInvokeNoSign(t, method, args...) b := c.NewUnsignedBlock(t, tx) ic, err := c.Chain.GetTestVM(trigger.Application, tx, b) @@ -70,18 +70,18 @@ func (c *ContractInvoker) WithSigners(signers ...Signer) *ContractInvoker { } // PrepareInvoke creates a new invocation transaction. -func (c *ContractInvoker) PrepareInvoke(t testing.TB, method string, args ...interface{}) *transaction.Transaction { +func (c *ContractInvoker) PrepareInvoke(t testing.TB, method string, args ...any) *transaction.Transaction { return c.Executor.NewTx(t, c.Signers, c.Hash, method, args...) } // PrepareInvokeNoSign creates a new unsigned invocation transaction. -func (c *ContractInvoker) PrepareInvokeNoSign(t testing.TB, method string, args ...interface{}) *transaction.Transaction { +func (c *ContractInvoker) PrepareInvokeNoSign(t testing.TB, method string, args ...any) *transaction.Transaction { return c.Executor.NewUnsignedTx(t, c.Hash, method, args...) } // Invoke invokes the method with the args, persists the transaction and checks the result. // Returns transaction hash. -func (c *ContractInvoker) Invoke(t testing.TB, result interface{}, method string, args ...interface{}) util.Uint256 { +func (c *ContractInvoker) Invoke(t testing.TB, result any, method string, args ...any) util.Uint256 { tx := c.PrepareInvoke(t, method, args...) c.AddNewBlock(t, tx) c.CheckHalt(t, tx.Hash(), stackitem.Make(result)) @@ -90,7 +90,7 @@ func (c *ContractInvoker) Invoke(t testing.TB, result interface{}, method string // InvokeAndCheck invokes the method with the args, persists the transaction and checks the result // using the provided function. It returns the transaction hash. -func (c *ContractInvoker) InvokeAndCheck(t testing.TB, checkResult func(t testing.TB, stack []stackitem.Item), method string, args ...interface{}) util.Uint256 { +func (c *ContractInvoker) InvokeAndCheck(t testing.TB, checkResult func(t testing.TB, stack []stackitem.Item), method string, args ...any) util.Uint256 { tx := c.PrepareInvoke(t, method, args...) c.AddNewBlock(t, tx) aer, err := c.Chain.GetAppExecResults(tx.Hash(), trigger.Application) @@ -103,7 +103,7 @@ func (c *ContractInvoker) InvokeAndCheck(t testing.TB, checkResult func(t testin } // InvokeWithFeeFail is like InvokeFail but sets the custom system fee for the transaction. -func (c *ContractInvoker) InvokeWithFeeFail(t testing.TB, message string, sysFee int64, method string, args ...interface{}) util.Uint256 { +func (c *ContractInvoker) InvokeWithFeeFail(t testing.TB, message string, sysFee int64, method string, args ...any) util.Uint256 { tx := c.PrepareInvokeNoSign(t, method, args...) c.Executor.SignTx(t, tx, sysFee, c.Signers...) c.AddNewBlock(t, tx) @@ -113,7 +113,7 @@ func (c *ContractInvoker) InvokeWithFeeFail(t testing.TB, message string, sysFee // InvokeFail invokes the method with the args, persists the transaction and checks the error message. // It returns the transaction hash. -func (c *ContractInvoker) InvokeFail(t testing.TB, message string, method string, args ...interface{}) util.Uint256 { +func (c *ContractInvoker) InvokeFail(t testing.TB, message string, method string, args ...any) util.Uint256 { tx := c.PrepareInvoke(t, method, args...) c.AddNewBlock(t, tx) c.CheckFault(t, tx.Hash(), message) diff --git a/pkg/network/server.go b/pkg/network/server.go index ca37d774f..0ce3697d5 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -73,7 +73,7 @@ type ( HeaderHeight() uint32 P2PSigExtensionsEnabled() bool PoolTx(t *transaction.Transaction, pools ...*mempool.Pool) error - PoolTxWithData(t *transaction.Transaction, data interface{}, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(t *transaction.Transaction, data interface{}) error) error + PoolTxWithData(t *transaction.Transaction, data any, mp *mempool.Pool, feer mempool.Feer, verificationFunction func(t *transaction.Transaction, data any) error) error RegisterPostBlock(f func(func(*transaction.Transaction, *mempool.Pool, bool) bool, *mempool.Pool, *block.Block)) SubscribeForBlocks(ch chan *block.Block) UnsubscribeFromBlocks(ch chan *block.Block) @@ -1189,7 +1189,7 @@ func (s *Server) verifyAndPoolNotaryRequest(r *payload.P2PNotaryRequest) error { } // verifyNotaryRequest is a function for state-dependant P2PNotaryRequest payload verification which is executed before ordinary blockchain's verification. -func (s *Server) verifyNotaryRequest(_ *transaction.Transaction, data interface{}) error { +func (s *Server) verifyNotaryRequest(_ *transaction.Transaction, data any) error { r := data.(*payload.P2PNotaryRequest) payer := r.FallbackTransaction.Signers[1].Account if _, err := s.chain.VerifyWitness(payer, r, &r.Witness, s.chain.GetMaxVerificationGAS()); err != nil { @@ -1206,7 +1206,7 @@ func (s *Server) verifyNotaryRequest(_ *transaction.Transaction, data interface{ return nil } -func (s *Server) broadcastP2PNotaryRequestPayload(_ *transaction.Transaction, data interface{}) { +func (s *Server) broadcastP2PNotaryRequestPayload(_ *transaction.Transaction, data any) { r := data.(*payload.P2PNotaryRequest) // we can guarantee that cast is successful msg := NewMessage(CMDInv, payload.NewInventory(payload.P2PNotaryRequestType, []util.Uint256{r.FallbackTransaction.Hash()})) s.broadcastMessage(msg) @@ -1592,7 +1592,7 @@ func (s *Server) RelayTxn(t *transaction.Transaction) error { } // broadcastTX broadcasts an inventory message about new transaction. -func (s *Server) broadcastTX(t *transaction.Transaction, _ interface{}) { +func (s *Server) broadcastTX(t *transaction.Transaction, _ any) { select { case s.transactions <- t: case <-s.quit: diff --git a/pkg/rpcclient/actor/actor.go b/pkg/rpcclient/actor/actor.go index f8926a958..35ae9346a 100644 --- a/pkg/rpcclient/actor/actor.go +++ b/pkg/rpcclient/actor/actor.go @@ -245,7 +245,7 @@ func (a *Actor) sendWrapper(tx *transaction.Transaction, err error) (util.Uint25 // SendCall creates a transaction that calls the given method of the given // contract with the given parameters (see also MakeCall) and sends it to the // network. -func (a *Actor) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (a *Actor) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return a.sendWrapper(a.MakeCall(contract, method, params...)) } @@ -253,7 +253,7 @@ func (a *Actor) SendCall(contract util.Uint160, method string, params ...interfa // contract with the given parameters (see also MakeTunedCall) and attributes, // allowing to check for execution results of this call and modify transaction // before it's signed; this transaction is then sent to the network. -func (a *Actor) SendTunedCall(contract util.Uint160, method string, attrs []transaction.Attribute, txHook TransactionCheckerModifier, params ...interface{}) (util.Uint256, uint32, error) { +func (a *Actor) SendTunedCall(contract util.Uint160, method string, attrs []transaction.Attribute, txHook TransactionCheckerModifier, params ...any) (util.Uint256, uint32, error) { return a.sendWrapper(a.MakeTunedCall(contract, method, attrs, txHook, params...)) } diff --git a/pkg/rpcclient/actor/maker.go b/pkg/rpcclient/actor/maker.go index d185dd1fd..38b9d92fe 100644 --- a/pkg/rpcclient/actor/maker.go +++ b/pkg/rpcclient/actor/maker.go @@ -52,7 +52,7 @@ func DefaultCheckerModifier(r *result.Invoke, t *transaction.Transaction) error // Actor-configured TransactionCheckerModifier. The resulting transaction has // Actor-configured attributes added as well. If you need to override attributes // and/or TransactionCheckerModifier use MakeTunedCall. -func (a *Actor) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (a *Actor) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return a.MakeTunedCall(contract, method, nil, nil, params...) } @@ -61,7 +61,7 @@ func (a *Actor) MakeCall(contract util.Uint160, method string, params ...interfa // parameters. It's filtered through the provided callback (or Actor default // one's if nil, see TransactionCheckerModifier documentation also), so the // process can be aborted and transaction can be modified before signing. -func (a *Actor) MakeTunedCall(contract util.Uint160, method string, attrs []transaction.Attribute, txHook TransactionCheckerModifier, params ...interface{}) (*transaction.Transaction, error) { +func (a *Actor) MakeTunedCall(contract util.Uint160, method string, attrs []transaction.Attribute, txHook TransactionCheckerModifier, params ...any) (*transaction.Transaction, error) { r, err := a.Call(contract, method, params...) return a.makeUncheckedWrapper(r, err, attrs, txHook) } @@ -130,7 +130,7 @@ func (a *Actor) MakeUncheckedRun(script []byte, sysfee int64, attrs []transactio // transaction returned has correct SystemFee and NetworkFee values. // TransactionModifier is not applied to the result of this method, but default // attributes are used if attrs is nil. -func (a *Actor) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (a *Actor) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { r, err := a.Call(contract, method, params...) return a.makeUnsignedWrapper(r, err, attrs) } diff --git a/pkg/rpcclient/actor/waiter.go b/pkg/rpcclient/actor/waiter.go index 8de06a6a8..d37b4383b 100644 --- a/pkg/rpcclient/actor/waiter.go +++ b/pkg/rpcclient/actor/waiter.go @@ -331,10 +331,10 @@ func (w *EventWaiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Ui case unsubErr := <-unsubErrs: if unsubErr != nil { errFmt := "unsubscription error: %v" - errArgs := []interface{}{unsubErr} + errArgs := []any{unsubErr} if waitErr != nil { errFmt = "%w; " + errFmt - errArgs = append([]interface{}{waitErr}, errArgs...) + errArgs = append([]any{waitErr}, errArgs...) } waitErr = fmt.Errorf(errFmt, errArgs...) } diff --git a/pkg/rpcclient/client.go b/pkg/rpcclient/client.go index 67cf3f10d..9c67ad43a 100644 --- a/pkg/rpcclient/client.go +++ b/pkg/rpcclient/client.go @@ -181,9 +181,9 @@ func (c *Client) Close() { c.cli.CloseIdleConnections() } -func (c *Client) performRequest(method string, p []interface{}, v interface{}) error { +func (c *Client) performRequest(method string, p []any, v any) error { if p == nil { - p = []interface{}{} // neo-project/neo-modules#742 + p = []any{} // neo-project/neo-modules#742 } var r = neorpc.Request{ JSONRPC: neorpc.JSONRPCVersion, diff --git a/pkg/rpcclient/gas/gas_test.go b/pkg/rpcclient/gas/gas_test.go index eb49affda..3ca49e5c5 100644 --- a/pkg/rpcclient/gas/gas_test.go +++ b/pkg/rpcclient/gas/gas_test.go @@ -17,7 +17,7 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { diff --git a/pkg/rpcclient/helper.go b/pkg/rpcclient/helper.go index 587816c93..af394cde9 100644 --- a/pkg/rpcclient/helper.go +++ b/pkg/rpcclient/helper.go @@ -36,7 +36,7 @@ func (c *Client) InvokeAndPackIteratorResults(contract util.Uint160, operation s if err != nil { return nil, fmt.Errorf("expanding params to emitable: %w", err) } - bytes, err := smartcontract.CreateCallAndUnwrapIteratorScript(contract, operation, max, values.([]interface{})...) + bytes, err := smartcontract.CreateCallAndUnwrapIteratorScript(contract, operation, max, values.([]any)...) if err != nil { return nil, fmt.Errorf("failed to create iterator unwrapper script: %w", err) } diff --git a/pkg/rpcclient/invoker/invoker.go b/pkg/rpcclient/invoker/invoker.go index dfab2c803..a56be5942 100644 --- a/pkg/rpcclient/invoker/invoker.go +++ b/pkg/rpcclient/invoker/invoker.go @@ -139,7 +139,7 @@ func (h *historicConverter) TraverseIterator(sessionID, iteratorID uuid.UUID, ma // Call invokes a method of the contract with the given parameters (and // Invoker-specific list of signers) and returns the result as is. -func (v *Invoker) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (v *Invoker) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { ps, err := smartcontract.NewParametersFromValues(params...) if err != nil { return nil, err @@ -155,7 +155,7 @@ func (v *Invoker) Call(contract util.Uint160, operation string, params ...interf // result of the whole script is an array containing up to maxResultItems elements // from the iterator returned from the contract's method call. This script is executed // using regular JSON-API (according to the way Iterator is set up). -func (v *Invoker) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) { +func (v *Invoker) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { bytes, err := smartcontract.CreateCallAndUnwrapIteratorScript(contract, method, maxItems, params...) if err != nil { return nil, fmt.Errorf("iterator unwrapper script: %w", err) @@ -165,7 +165,7 @@ func (v *Invoker) CallAndExpandIterator(contract util.Uint160, method string, ma // Verify invokes contract's verify method in the verification context with // Invoker-specific signers and given witnesses and parameters. -func (v *Invoker) Verify(contract util.Uint160, witnesses []transaction.Witness, params ...interface{}) (*result.Invoke, error) { +func (v *Invoker) Verify(contract util.Uint160, witnesses []transaction.Witness, params ...any) (*result.Invoke, error) { ps, err := smartcontract.NewParametersFromValues(params...) if err != nil { return nil, err diff --git a/pkg/rpcclient/local.go b/pkg/rpcclient/local.go index 19e67ceaa..345566d71 100644 --- a/pkg/rpcclient/local.go +++ b/pkg/rpcclient/local.go @@ -34,7 +34,7 @@ func NewInternal(ctx context.Context, register InternalHook) (*Internal, error) done: make(chan struct{}), closeCalled: *atomic.NewBool(false), subscriptions: make(map[string]notificationReceiver), - receivers: make(map[interface{}][]string), + receivers: make(map[any][]string), }, events: make(chan neorpc.Notification), } diff --git a/pkg/rpcclient/management/management.go b/pkg/rpcclient/management/management.go index 6c8e375f9..c6d2e77ef 100644 --- a/pkg/rpcclient/management/management.go +++ b/pkg/rpcclient/management/management.go @@ -27,8 +27,8 @@ import ( // Invoker is used by ContractReader to call various methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) - CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) + CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) TerminateSession(sessionID uuid.UUID) error TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) } @@ -37,11 +37,11 @@ type Invoker interface { type Actor interface { Invoker - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) } @@ -222,7 +222,7 @@ func (c *ContractReader) HasMethod(hash util.Uint160, method string, pcount int) // to the invocation and will be used for "_deploy" method invocation done by // the ContractManagement contract. If successful, this method returns deployed // contract state that can be retrieved from the stack after execution. -func (c *Contract) Deploy(exe *nef.File, manif *manifest.Manifest, data interface{}) (util.Uint256, uint32, error) { +func (c *Contract) Deploy(exe *nef.File, manif *manifest.Manifest, data any) (util.Uint256, uint32, error) { script, err := mkDeployScript(exe, manif, data) if err != nil { return util.Uint256{}, 0, err @@ -235,7 +235,7 @@ func (c *Contract) Deploy(exe *nef.File, manif *manifest.Manifest, data interfac // to the invocation and will be used for "_deploy" method invocation done by // the ContractManagement contract. If successful, this method returns deployed // contract state that can be retrieved from the stack after execution. -func (c *Contract) DeployTransaction(exe *nef.File, manif *manifest.Manifest, data interface{}) (*transaction.Transaction, error) { +func (c *Contract) DeployTransaction(exe *nef.File, manif *manifest.Manifest, data any) (*transaction.Transaction, error) { script, err := mkDeployScript(exe, manif, data) if err != nil { return nil, err @@ -248,7 +248,7 @@ func (c *Contract) DeployTransaction(exe *nef.File, manif *manifest.Manifest, da // to the invocation and will be used for "_deploy" method invocation done by // the ContractManagement contract. If successful, this method returns deployed // contract state that can be retrieved from the stack after execution. -func (c *Contract) DeployUnsigned(exe *nef.File, manif *manifest.Manifest, data interface{}) (*transaction.Transaction, error) { +func (c *Contract) DeployUnsigned(exe *nef.File, manif *manifest.Manifest, data any) (*transaction.Transaction, error) { script, err := mkDeployScript(exe, manif, data) if err != nil { return nil, err @@ -256,7 +256,7 @@ func (c *Contract) DeployUnsigned(exe *nef.File, manif *manifest.Manifest, data return c.actor.MakeUnsignedRun(script, nil) } -func mkDeployScript(exe *nef.File, manif *manifest.Manifest, data interface{}) ([]byte, error) { +func mkDeployScript(exe *nef.File, manif *manifest.Manifest, data any) ([]byte, error) { exeB, err := exe.Bytes() if err != nil { return nil, fmt.Errorf("bad NEF: %w", err) diff --git a/pkg/rpcclient/management/management_test.go b/pkg/rpcclient/management/management_test.go index 31a54484d..f30531972 100644 --- a/pkg/rpcclient/management/management_test.go +++ b/pkg/rpcclient/management/management_test.go @@ -23,16 +23,16 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } -func (t *testAct) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { @@ -44,7 +44,7 @@ func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } -func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) TerminateSession(sessionID uuid.UUID) error { @@ -283,7 +283,7 @@ func TestDeploy(t *testing.T) { _, _, err := man.Deploy(nefFile, manif, nil) require.Error(t, err) - for _, m := range []func(exe *nef.File, manif *manifest.Manifest, data interface{}) (*transaction.Transaction, error){ + for _, m := range []func(exe *nef.File, manif *manifest.Manifest, data any) (*transaction.Transaction, error){ man.DeployTransaction, man.DeployUnsigned, } { @@ -301,7 +301,7 @@ func TestDeploy(t *testing.T) { require.Equal(t, ta.vub, vub) ta.tx = transaction.New([]byte{1, 2, 3}, 100500) - for _, m := range []func(exe *nef.File, manif *manifest.Manifest, data interface{}) (*transaction.Transaction, error){ + for _, m := range []func(exe *nef.File, manif *manifest.Manifest, data any) (*transaction.Transaction, error){ man.DeployTransaction, man.DeployUnsigned, } { diff --git a/pkg/rpcclient/neo/neo.go b/pkg/rpcclient/neo/neo.go index b9b17ed33..3da8b47a0 100644 --- a/pkg/rpcclient/neo/neo.go +++ b/pkg/rpcclient/neo/neo.go @@ -33,7 +33,7 @@ const ( type Invoker interface { nep17.Invoker - CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) + CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) TerminateSession(sessionID uuid.UUID) error TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) } @@ -44,10 +44,10 @@ type Actor interface { Invoker Run(script []byte) (*result.Invoke, error) - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedUncheckedRun(script []byte, sysFee int64, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) Sign(tx *transaction.Transaction) error SignAndSend(tx *transaction.Transaction) (util.Uint256, uint32, error) } @@ -398,7 +398,7 @@ func (c *Contract) VoteUnsigned(account util.Uint160, voteTo *keys.PublicKey) (* } func voteScript(account util.Uint160, voteTo *keys.PublicKey) []byte { - var param interface{} + var param any if voteTo != nil { param = voteTo.Bytes() diff --git a/pkg/rpcclient/neo/neo_test.go b/pkg/rpcclient/neo/neo_test.go index 5cf7e8235..d99dc86f9 100644 --- a/pkg/rpcclient/neo/neo_test.go +++ b/pkg/rpcclient/neo/neo_test.go @@ -27,7 +27,7 @@ type testAct struct { inv *result.Invoke } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { @@ -39,13 +39,13 @@ func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } -func (t *testAct) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } func (t *testAct) Run(script []byte) (*result.Invoke, error) { @@ -60,7 +60,7 @@ func (t *testAct) Sign(tx *transaction.Transaction) error { func (t *testAct) SignAndSend(tx *transaction.Transaction) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } -func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { return t.inv, t.err } func (t *testAct) TerminateSession(sessionID uuid.UUID) error { diff --git a/pkg/rpcclient/nep.go b/pkg/rpcclient/nep.go index 4b2497315..3fa41a913 100644 --- a/pkg/rpcclient/nep.go +++ b/pkg/rpcclient/nep.go @@ -25,7 +25,7 @@ func (c *Client) nepTotalSupply(tokenHash util.Uint160) (int64, error) { // nepBalanceOf invokes `balanceOf` NEP* method on the specified contract. func (c *Client) nepBalanceOf(tokenHash, acc util.Uint160, tokenID []byte) (int64, error) { - params := []interface{}{acc} + params := []any{acc} if tokenID != nil { params = append(params, tokenID) } diff --git a/pkg/rpcclient/nep11.go b/pkg/rpcclient/nep11.go index 723922759..e80999c04 100644 --- a/pkg/rpcclient/nep11.go +++ b/pkg/rpcclient/nep11.go @@ -62,7 +62,7 @@ func (c *Client) NEP11TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) { // 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 interface{}, gas int64, cosigners []SignerAccount) (util.Uint256, error) { + 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 @@ -82,7 +82,7 @@ func (c *Client) TransferNEP11(acc *wallet.Account, to util.Uint160, // 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 ...interface{}) (*transaction.Transaction, error) { + 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) @@ -142,7 +142,7 @@ func (c *Client) NEP11NDOwnerOf(tokenHash util.Uint160, tokenID []byte) (util.Ui // 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 interface{}, gas int64, cosigners []SignerAccount) (util.Uint256, error) { + 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 diff --git a/pkg/rpcclient/nep11/base.go b/pkg/rpcclient/nep11/base.go index 71c75ef7a..ed30df2af 100644 --- a/pkg/rpcclient/nep11/base.go +++ b/pkg/rpcclient/nep11/base.go @@ -28,7 +28,7 @@ import ( type Invoker interface { neptoken.Invoker - CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) + CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) TerminateSession(sessionID uuid.UUID) error TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) } @@ -149,7 +149,7 @@ func (t *BaseReader) TokensOfExpanded(account util.Uint160, num int) ([][]byte, // transaction if it's not true. It works for divisible NFTs only when there is // one owner for the particular token. The returned values are transaction hash, // its ValidUntilBlock value and an error if any. -func (t *BaseWriter) Transfer(to util.Uint160, id []byte, data interface{}) (util.Uint256, uint32, error) { +func (t *BaseWriter) Transfer(to util.Uint160, id []byte, data any) (util.Uint256, uint32, error) { script, err := t.transferScript(to, id, data) if err != nil { return util.Uint256{}, 0, err @@ -162,7 +162,7 @@ func (t *BaseWriter) Transfer(to util.Uint160, id []byte, data interface{}) (uti // transaction if it's not true. It works for divisible NFTs only when there is // one owner for the particular token. This transaction is signed, but not sent // to the network, instead it's returned to the caller. -func (t *BaseWriter) TransferTransaction(to util.Uint160, id []byte, data interface{}) (*transaction.Transaction, error) { +func (t *BaseWriter) TransferTransaction(to util.Uint160, id []byte, data any) (*transaction.Transaction, error) { script, err := t.transferScript(to, id, data) if err != nil { return nil, err @@ -175,7 +175,7 @@ func (t *BaseWriter) TransferTransaction(to util.Uint160, id []byte, data interf // transaction if it's not true. It works for divisible NFTs only when there is // one owner for the particular token. This transaction is not signed and just // returned to the caller. -func (t *BaseWriter) TransferUnsigned(to util.Uint160, id []byte, data interface{}) (*transaction.Transaction, error) { +func (t *BaseWriter) TransferUnsigned(to util.Uint160, id []byte, data any) (*transaction.Transaction, error) { script, err := t.transferScript(to, id, data) if err != nil { return nil, err @@ -183,7 +183,7 @@ func (t *BaseWriter) TransferUnsigned(to util.Uint160, id []byte, data interface return t.actor.MakeUnsignedRun(script, nil) } -func (t *BaseWriter) transferScript(params ...interface{}) ([]byte, error) { +func (t *BaseWriter) transferScript(params ...any) ([]byte, error) { return smartcontract.CreateCallWithAssertScript(t.hash, "transfer", params...) } diff --git a/pkg/rpcclient/nep11/base_test.go b/pkg/rpcclient/nep11/base_test.go index 33938c0aa..9ba9b3aa2 100644 --- a/pkg/rpcclient/nep11/base_test.go +++ b/pkg/rpcclient/nep11/base_test.go @@ -21,7 +21,7 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { @@ -33,7 +33,7 @@ func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } -func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) TerminateSession(sessionID uuid.UUID) error { @@ -241,7 +241,7 @@ func TestTokenTransferTransaction(t *testing.T) { ta := new(testAct) tok := NewBase(ta, util.Uint160{1, 2, 3}) - for _, fun := range []func(to util.Uint160, token []byte, data interface{}) (*transaction.Transaction, error){ + for _, fun := range []func(to util.Uint160, token []byte, data any) (*transaction.Transaction, error){ tok.TransferTransaction, tok.TransferUnsigned, } { diff --git a/pkg/rpcclient/nep11/divisible.go b/pkg/rpcclient/nep11/divisible.go index d558ab05b..59600048a 100644 --- a/pkg/rpcclient/nep11/divisible.go +++ b/pkg/rpcclient/nep11/divisible.go @@ -79,7 +79,7 @@ func (t *DivisibleReader) BalanceOfD(owner util.Uint160, token []byte) (*big.Int // method call using the given parameters and checks for this call result, // failing the transaction if it's not true. The returned values are transaction // hash, its ValidUntilBlock value and an error if any. -func (t *DivisibleWriter) TransferD(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (util.Uint256, uint32, error) { +func (t *DivisibleWriter) TransferD(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (util.Uint256, uint32, error) { script, err := t.transferScript(from, to, amount, id, data) if err != nil { return util.Uint256{}, 0, err @@ -92,7 +92,7 @@ func (t *DivisibleWriter) TransferD(from util.Uint160, to util.Uint160, amount * // `transfer` method call using the given parameters and checks for this call // result, failing the transaction if it's not true. This transaction is signed, // but not sent to the network, instead it's returned to the caller. -func (t *DivisibleWriter) TransferDTransaction(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error) { +func (t *DivisibleWriter) TransferDTransaction(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (*transaction.Transaction, error) { script, err := t.transferScript(from, to, amount, id, data) if err != nil { return nil, err @@ -105,7 +105,7 @@ func (t *DivisibleWriter) TransferDTransaction(from util.Uint160, to util.Uint16 // `transfer` method call using the given parameters and checks for this call // result, failing the transaction if it's not true. This transaction is not // signed and just returned to the caller. -func (t *DivisibleWriter) TransferDUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error) { +func (t *DivisibleWriter) TransferDUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (*transaction.Transaction, error) { script, err := t.transferScript(from, to, amount, id, data) if err != nil { return nil, err diff --git a/pkg/rpcclient/nep11/divisible_test.go b/pkg/rpcclient/nep11/divisible_test.go index f44e83c31..dd9a1e26d 100644 --- a/pkg/rpcclient/nep11/divisible_test.go +++ b/pkg/rpcclient/nep11/divisible_test.go @@ -198,7 +198,7 @@ func TestDivisibleTransferTransaction(t *testing.T) { ta := new(testAct) tok := NewDivisible(ta, util.Uint160{1, 2, 3}) - for _, fun := range []func(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data interface{}) (*transaction.Transaction, error){ + for _, fun := range []func(from util.Uint160, to util.Uint160, amount *big.Int, id []byte, data any) (*transaction.Transaction, error){ tok.TransferDTransaction, tok.TransferDUnsigned, } { diff --git a/pkg/rpcclient/nep17.go b/pkg/rpcclient/nep17.go index aa73a8c28..ea2c5c894 100644 --- a/pkg/rpcclient/nep17.go +++ b/pkg/rpcclient/nep17.go @@ -15,7 +15,7 @@ type TransferTarget struct { Token util.Uint160 Address util.Uint160 Amount int64 - Data interface{} + Data any } // SignerAccount represents combination of the transaction.Signer and the @@ -75,7 +75,7 @@ func (c *Client) NEP17TokenInfo(tokenHash util.Uint160) (*wallet.Token, error) { // 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 interface{}, cosigners []SignerAccount) (*transaction.Transaction, error) { + token util.Uint160, amount int64, gas int64, data any, cosigners []SignerAccount) (*transaction.Transaction, error) { return c.CreateNEP17MultiTransferTx(acc, gas, []TransferTarget{ {Token: token, Address: to, @@ -164,7 +164,7 @@ func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, // 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 interface{}, cosigners []SignerAccount) (util.Uint256, error) { + 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 diff --git a/pkg/rpcclient/nep17/nep17.go b/pkg/rpcclient/nep17/nep17.go index e2f1d71e4..f91488e82 100644 --- a/pkg/rpcclient/nep17/nep17.go +++ b/pkg/rpcclient/nep17/nep17.go @@ -63,7 +63,7 @@ type TransferParameters struct { From util.Uint160 To util.Uint160 Amount *big.Int - Data interface{} + Data any } // NewReader creates an instance of TokenReader for contract with the given @@ -82,7 +82,7 @@ func New(actor Actor, hash util.Uint160) *Token { // call using the given parameters and checks for this call result, failing the // transaction if it's not true. The returned values are transaction hash, its // ValidUntilBlock value and an error if any. -func (t *TokenWriter) Transfer(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (util.Uint256, uint32, error) { +func (t *TokenWriter) Transfer(from util.Uint160, to util.Uint160, amount *big.Int, data any) (util.Uint256, uint32, error) { return t.MultiTransfer([]TransferParameters{{from, to, amount, data}}) } @@ -90,7 +90,7 @@ func (t *TokenWriter) Transfer(from util.Uint160, to util.Uint160, amount *big.I // call using the given parameters and checks for this call result, failing the // transaction if it's not true. This transaction is signed, but not sent to the // network, instead it's returned to the caller. -func (t *TokenWriter) TransferTransaction(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) { +func (t *TokenWriter) TransferTransaction(from util.Uint160, to util.Uint160, amount *big.Int, data any) (*transaction.Transaction, error) { return t.MultiTransferTransaction([]TransferParameters{{from, to, amount, data}}) } @@ -98,7 +98,7 @@ func (t *TokenWriter) TransferTransaction(from util.Uint160, to util.Uint160, am // call using the given parameters and checks for this call result, failing the // transaction if it's not true. This transaction is not signed and just returned // to the caller. -func (t *TokenWriter) TransferUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) { +func (t *TokenWriter) TransferUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, data any) (*transaction.Transaction, error) { return t.MultiTransferUnsigned([]TransferParameters{{from, to, amount, data}}) } diff --git a/pkg/rpcclient/nep17/nep17_test.go b/pkg/rpcclient/nep17/nep17_test.go index b14e84dda..0fe260cbd 100644 --- a/pkg/rpcclient/nep17/nep17_test.go +++ b/pkg/rpcclient/nep17/nep17_test.go @@ -20,7 +20,7 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { @@ -66,9 +66,9 @@ func TestTokenTransfer(t *testing.T) { ta := new(testAct) tok := New(ta, util.Uint160{1, 2, 3}) - for name, fun := range map[string]func(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (util.Uint256, uint32, error){ + for name, fun := range map[string]func(from util.Uint160, to util.Uint160, amount *big.Int, data any) (util.Uint256, uint32, error){ "Tranfer": tok.Transfer, - "MultiTransfer": func(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (util.Uint256, uint32, error) { + "MultiTransfer": func(from util.Uint160, to util.Uint160, amount *big.Int, data any) (util.Uint256, uint32, error) { return tok.MultiTransfer([]TransferParameters{{from, to, amount, data}, {from, to, amount, data}}) }, } { @@ -99,13 +99,13 @@ func TestTokenTransferTransaction(t *testing.T) { ta := new(testAct) tok := New(ta, util.Uint160{1, 2, 3}) - for name, fun := range map[string]func(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error){ + for name, fun := range map[string]func(from util.Uint160, to util.Uint160, amount *big.Int, data any) (*transaction.Transaction, error){ "TransferTransaction": tok.TransferTransaction, "TransferUnsigned": tok.TransferUnsigned, - "MultiTransferTransaction": func(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) { + "MultiTransferTransaction": func(from util.Uint160, to util.Uint160, amount *big.Int, data any) (*transaction.Transaction, error) { return tok.MultiTransferTransaction([]TransferParameters{{from, to, amount, data}, {from, to, amount, data}}) }, - "MultiTransferUnsigned": func(from util.Uint160, to util.Uint160, amount *big.Int, data interface{}) (*transaction.Transaction, error) { + "MultiTransferUnsigned": func(from util.Uint160, to util.Uint160, amount *big.Int, data any) (*transaction.Transaction, error) { return tok.MultiTransferUnsigned([]TransferParameters{{from, to, amount, data}, {from, to, amount, data}}) }, } { diff --git a/pkg/rpcclient/neptoken/base.go b/pkg/rpcclient/neptoken/base.go index 610e2be8e..57b504f0a 100644 --- a/pkg/rpcclient/neptoken/base.go +++ b/pkg/rpcclient/neptoken/base.go @@ -24,7 +24,7 @@ const ( // Invoker is used by Base to call various methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // Base is a reader interface for common NEP-11 and NEP-17 methods built diff --git a/pkg/rpcclient/neptoken/base_test.go b/pkg/rpcclient/neptoken/base_test.go index 7f7320d7c..f1c85332e 100644 --- a/pkg/rpcclient/neptoken/base_test.go +++ b/pkg/rpcclient/neptoken/base_test.go @@ -16,7 +16,7 @@ type testInv struct { res *result.Invoke } -func (t *testInv) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testInv) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } diff --git a/pkg/rpcclient/nns/contract_test.go b/pkg/rpcclient/nns/contract_test.go index f69079e68..98a4ef20d 100644 --- a/pkg/rpcclient/nns/contract_test.go +++ b/pkg/rpcclient/nns/contract_test.go @@ -16,10 +16,10 @@ type testAct struct { res *result.Invoke } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } -func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) TerminateSession(sessionID uuid.UUID) error { diff --git a/pkg/rpcclient/notary/contract.go b/pkg/rpcclient/notary/contract.go index 9bf3b6373..749003f1c 100644 --- a/pkg/rpcclient/notary/contract.go +++ b/pkg/rpcclient/notary/contract.go @@ -27,18 +27,18 @@ const ( // ContractInvoker is used by ContractReader to perform read-only calls. type ContractInvoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // ContractActor is used by Contract to create and send transactions. type ContractActor interface { ContractInvoker - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) } diff --git a/pkg/rpcclient/notary/contract_test.go b/pkg/rpcclient/notary/contract_test.go index c8498ffbf..1e50f8db5 100644 --- a/pkg/rpcclient/notary/contract_test.go +++ b/pkg/rpcclient/notary/contract_test.go @@ -20,7 +20,7 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { @@ -32,13 +32,13 @@ func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } -func (t *testAct) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } diff --git a/pkg/rpcclient/oracle/oracle.go b/pkg/rpcclient/oracle/oracle.go index fe3a79964..39a12e023 100644 --- a/pkg/rpcclient/oracle/oracle.go +++ b/pkg/rpcclient/oracle/oracle.go @@ -19,16 +19,16 @@ import ( // Invoker is used by ContractReader to call various methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // Actor is used by Contract to create and send transactions. type Actor interface { Invoker - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) } // Hash stores the hash of the native OracleContract contract. diff --git a/pkg/rpcclient/oracle/oracle_test.go b/pkg/rpcclient/oracle/oracle_test.go index 25e960d67..aad3386f3 100644 --- a/pkg/rpcclient/oracle/oracle_test.go +++ b/pkg/rpcclient/oracle/oracle_test.go @@ -20,16 +20,16 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } -func (t *testAct) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } diff --git a/pkg/rpcclient/policy/policy.go b/pkg/rpcclient/policy/policy.go index 2f583db0a..52dd6ba5b 100644 --- a/pkg/rpcclient/policy/policy.go +++ b/pkg/rpcclient/policy/policy.go @@ -18,18 +18,18 @@ import ( // Invoker is used by ContractReader to call various methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // Actor is used by Contract to create and send transactions. type Actor interface { Invoker - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) } diff --git a/pkg/rpcclient/policy/policy_test.go b/pkg/rpcclient/policy/policy_test.go index aed3dcd16..458c77efd 100644 --- a/pkg/rpcclient/policy/policy_test.go +++ b/pkg/rpcclient/policy/policy_test.go @@ -19,16 +19,16 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } -func (t *testAct) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { diff --git a/pkg/rpcclient/rolemgmt/roles.go b/pkg/rpcclient/rolemgmt/roles.go index c7593e4b5..5bb8dbb91 100644 --- a/pkg/rpcclient/rolemgmt/roles.go +++ b/pkg/rpcclient/rolemgmt/roles.go @@ -19,16 +19,16 @@ import ( // Invoker is used by ContractReader to call various methods. type Invoker interface { - Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) } // Actor is used by Contract to create and send transactions. type Actor interface { Invoker - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) } // Hash stores the hash of the native RoleManagement contract. diff --git a/pkg/rpcclient/rolemgmt/roles_test.go b/pkg/rpcclient/rolemgmt/roles_test.go index f1899ed80..ffb764fac 100644 --- a/pkg/rpcclient/rolemgmt/roles_test.go +++ b/pkg/rpcclient/rolemgmt/roles_test.go @@ -21,16 +21,16 @@ type testAct struct { vub uint32 } -func (t *testAct) Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) { +func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { return t.res, t.err } -func (t *testAct) MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) { +func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { return t.tx, t.err } -func (t *testAct) SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) { +func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { return t.txh, t.vub, t.err } diff --git a/pkg/rpcclient/rpc.go b/pkg/rpcclient/rpc.go index 6b97c8895..07cfbe077 100644 --- a/pkg/rpcclient/rpc.go +++ b/pkg/rpcclient/rpc.go @@ -39,7 +39,7 @@ var errNetworkNotInitialized = errors.New("RPC client network is not initialized // filled for standard sig/multisig signers. func (c *Client) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { var ( - params = []interface{}{tx.Bytes()} + params = []any{tx.Bytes()} resp = new(result.NetworkFee) ) if err := c.performRequest("calculatenetworkfee", params, resp); err != nil { @@ -51,7 +51,7 @@ func (c *Client) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) // GetApplicationLog returns a contract log based on the specified txid. func (c *Client) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { var ( - params = []interface{}{hash.StringLE()} + params = []any{hash.StringLE()} resp = new(result.ApplicationLog) ) if trig != nil { @@ -93,13 +93,13 @@ func (c *Client) GetBlockByHash(hash util.Uint256) (*block.Block, error) { return c.getBlock(hash.StringLE()) } -func (c *Client) getBlock(param interface{}) (*block.Block, error) { +func (c *Client) getBlock(param any) (*block.Block, error) { var ( resp []byte err error b *block.Block ) - if err = c.performRequest("getblock", []interface{}{param}, &resp); err != nil { + if err = c.performRequest("getblock", []any{param}, &resp); err != nil { return nil, err } r := io.NewBinReaderFromBuf(resp) @@ -130,9 +130,9 @@ func (c *Client) GetBlockByHashVerbose(hash util.Uint256) (*result.Block, error) return c.getBlockVerbose(hash.StringLE()) } -func (c *Client) getBlockVerbose(param interface{}) (*result.Block, error) { +func (c *Client) getBlockVerbose(param any) (*result.Block, error) { var ( - params = []interface{}{param, 1} // 1 for verbose. + params = []any{param, 1} // 1 for verbose. resp = &result.Block{} err error ) @@ -150,7 +150,7 @@ func (c *Client) getBlockVerbose(param interface{}) (*result.Block, error) { // GetBlockHash returns the hash value of the corresponding block based on the specified index. func (c *Client) GetBlockHash(index uint32) (util.Uint256, error) { var ( - params = []interface{}{index} + params = []any{index} resp = util.Uint256{} ) if err := c.performRequest("getblockhash", params, &resp); err != nil { @@ -164,7 +164,7 @@ func (c *Client) GetBlockHash(index uint32) (util.Uint256, error) { // initialized with Init before calling this method. func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) { var ( - params = []interface{}{hash.StringLE()} + params = []any{hash.StringLE()} resp []byte h *block.Header ) @@ -199,7 +199,7 @@ func (c *Client) GetBlockHeaderCount() (uint32, error) { // initialized with Init before calling this method. func (c *Client) GetBlockHeaderVerbose(hash util.Uint256) (*result.Header, error) { var ( - params = []interface{}{hash.StringLE(), 1} + params = []any{hash.StringLE(), 1} resp = &result.Header{} ) if err := c.performRequest("getblockheader", params, resp); err != nil { @@ -212,7 +212,7 @@ func (c *Client) GetBlockHeaderVerbose(hash util.Uint256) (*result.Header, error // This method is only supported by NeoGo servers. func (c *Client) GetBlockSysFee(index uint32) (fixedn.Fixed8, error) { var ( - params = []interface{}{index} + params = []any{index} resp fixedn.Fixed8 ) if err := c.performRequest("getblocksysfee", params, &resp); err != nil { @@ -261,9 +261,9 @@ func (c *Client) GetContractStateByID(id int32) (*state.Contract, error) { } // getContractState is an internal representation of GetContractStateBy* methods. -func (c *Client) getContractState(param interface{}) (*state.Contract, error) { +func (c *Client) getContractState(param any) (*state.Contract, error) { var ( - params = []interface{}{param} + params = []any{param} resp = &state.Contract{} ) if err := c.performRequest("getcontractstate", params, resp); err != nil { @@ -291,7 +291,7 @@ func (c *Client) GetNativeContracts() ([]state.NativeContract, error) { // GetNEP11Balances is a wrapper for getnep11balances RPC. func (c *Client) GetNEP11Balances(address util.Uint160) (*result.NEP11Balances, error) { - params := []interface{}{address.StringLE()} + params := []any{address.StringLE()} resp := new(result.NEP11Balances) if err := c.performRequest("getnep11balances", params, resp); err != nil { return nil, err @@ -301,7 +301,7 @@ func (c *Client) GetNEP11Balances(address util.Uint160) (*result.NEP11Balances, // GetNEP17Balances is a wrapper for getnep17balances RPC. func (c *Client) GetNEP17Balances(address util.Uint160) (*result.NEP17Balances, error) { - params := []interface{}{address.StringLE()} + params := []any{address.StringLE()} resp := new(result.NEP17Balances) if err := c.performRequest("getnep17balances", params, resp); err != nil { return nil, err @@ -314,9 +314,9 @@ func (c *Client) GetNEP17Balances(address util.Uint160) (*result.NEP17Balances, // This method is provided mostly for the sake of completeness. For well-known // attributes like "description", "image", "name" and "tokenURI" it returns strings, // while for all others []byte (which can be nil). -func (c *Client) GetNEP11Properties(asset util.Uint160, token []byte) (map[string]interface{}, error) { - params := []interface{}{asset.StringLE(), hex.EncodeToString(token)} - resp := make(map[string]interface{}) +func (c *Client) GetNEP11Properties(asset util.Uint160, token []byte) (map[string]any, error) { + params := []any{asset.StringLE(), hex.EncodeToString(token)} + resp := make(map[string]any) if err := c.performRequest("getnep11properties", params, &resp); err != nil { return nil, err } @@ -355,8 +355,8 @@ func (c *Client) GetNEP11Transfers(address util.Uint160, start, stop *uint64, li return resp, nil } -func packTransfersParams(address util.Uint160, start, stop *uint64, limit, page *int) ([]interface{}, error) { - params := []interface{}{address.StringLE()} +func packTransfersParams(address util.Uint160, start, stop *uint64, limit, page *int) ([]any, error) { + params := []any{address.StringLE()} if start != nil { params = append(params, *start) if stop != nil { @@ -418,7 +418,7 @@ func (c *Client) GetRawMemPool() ([]util.Uint256, error) { // GetRawTransaction returns a transaction by hash. func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction, error) { var ( - params = []interface{}{hash.StringLE()} + params = []any{hash.StringLE()} resp []byte err error ) @@ -437,7 +437,7 @@ func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction, // NOTE: to get transaction.ID and transaction.Size, use t.Hash() and io.GetVarSize(t) respectively. func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.TransactionOutputRaw, error) { var ( - params = []interface{}{hash.StringLE(), 1} // 1 for verbose. + params = []any{hash.StringLE(), 1} // 1 for verbose. resp = &result.TransactionOutputRaw{} err error ) @@ -451,7 +451,7 @@ func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.Transactio // historical contract hash and historical item key. func (c *Client) GetProof(stateroot util.Uint256, historicalContractHash util.Uint160, historicalKey []byte) (*result.ProofWithKey, error) { var ( - params = []interface{}{stateroot.StringLE(), historicalContractHash.StringLE(), historicalKey} + params = []any{stateroot.StringLE(), historicalContractHash.StringLE(), historicalKey} resp = &result.ProofWithKey{} ) if err := c.performRequest("getproof", params, resp); err != nil { @@ -463,7 +463,7 @@ func (c *Client) GetProof(stateroot util.Uint256, historicalContractHash util.Ui // VerifyProof returns value by the given stateroot and proof. func (c *Client) VerifyProof(stateroot util.Uint256, proof *result.ProofWithKey) ([]byte, error) { var ( - params = []interface{}{stateroot.StringLE(), proof.String()} + params = []any{stateroot.StringLE(), proof.String()} resp []byte ) if err := c.performRequest("verifyproof", params, &resp); err != nil { @@ -476,7 +476,7 @@ func (c *Client) VerifyProof(stateroot util.Uint256, proof *result.ProofWithKey) // historical contract hash and historical item key. func (c *Client) GetState(stateroot util.Uint256, historicalContractHash util.Uint160, historicalKey []byte) ([]byte, error) { var ( - params = []interface{}{stateroot.StringLE(), historicalContractHash.StringLE(), historicalKey} + params = []any{stateroot.StringLE(), historicalContractHash.StringLE(), historicalKey} resp []byte ) if err := c.performRequest("getstate", params, &resp); err != nil { @@ -495,7 +495,7 @@ func (c *Client) FindStates(stateroot util.Uint256, historicalContractHash util. historicalPrefix = []byte{} } var ( - params = []interface{}{stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix} + params = []any{stateroot.StringLE(), historicalContractHash.StringLE(), historicalPrefix} resp result.FindStates ) if start == nil && maxCount != nil { @@ -523,9 +523,9 @@ func (c *Client) GetStateRootByBlockHash(hash util.Uint256) (*state.MPTRoot, err return c.getStateRoot(hash) } -func (c *Client) getStateRoot(param interface{}) (*state.MPTRoot, error) { +func (c *Client) getStateRoot(param any) (*state.MPTRoot, error) { var resp = new(state.MPTRoot) - if err := c.performRequest("getstateroot", []interface{}{param}, resp); err != nil { + if err := c.performRequest("getstateroot", []any{param}, resp); err != nil { return nil, err } return resp, nil @@ -543,15 +543,15 @@ func (c *Client) GetStateHeight() (*result.StateHeight, error) { // GetStorageByID returns the stored value according to the contract ID and the stored key. func (c *Client) GetStorageByID(id int32, key []byte) ([]byte, error) { - return c.getStorage([]interface{}{id, key}) + return c.getStorage([]any{id, key}) } // GetStorageByHash returns the stored value according to the contract script hash and the stored key. func (c *Client) GetStorageByHash(hash util.Uint160, key []byte) ([]byte, error) { - return c.getStorage([]interface{}{hash.StringLE(), key}) + return c.getStorage([]any{hash.StringLE(), key}) } -func (c *Client) getStorage(params []interface{}) ([]byte, error) { +func (c *Client) getStorage(params []any) ([]byte, error) { var resp []byte if err := c.performRequest("getstorage", params, &resp); err != nil { return nil, err @@ -562,7 +562,7 @@ func (c *Client) getStorage(params []interface{}) ([]byte, error) { // GetTransactionHeight returns the block index where the transaction is found. func (c *Client) GetTransactionHeight(hash util.Uint256) (uint32, error) { var ( - params = []interface{}{hash.StringLE()} + params = []any{hash.StringLE()} resp uint32 ) if err := c.performRequest("gettransactionheight", params, &resp); err != nil { @@ -574,7 +574,7 @@ func (c *Client) GetTransactionHeight(hash util.Uint256) (uint32, error) { // GetUnclaimedGas returns the unclaimed GAS amount for the specified address. func (c *Client) GetUnclaimedGas(address string) (result.UnclaimedGas, error) { var ( - params = []interface{}{address} + params = []any{address} resp result.UnclaimedGas ) if err := c.performRequest("getunclaimedgas", params, &resp); err != nil { @@ -617,7 +617,7 @@ func (c *Client) GetVersion() (*result.Version, error) { // InvokeScript returns the result of the given script after running it true the VM. // NOTE: This is a test invoke and will not affect the blockchain. func (c *Client) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { - var p = []interface{}{script} + var p = []any{script} return c.invokeSomething("invokescript", p, signers) } @@ -626,7 +626,7 @@ func (c *Client) InvokeScript(script []byte, signers []transaction.Signer) (*res // height. // NOTE: This is a test invoke and will not affect the blockchain. func (c *Client) InvokeScriptAtHeight(height uint32, script []byte, signers []transaction.Signer) (*result.Invoke, error) { - var p = []interface{}{height, script} + var p = []any{height, script} return c.invokeSomething("invokescripthistoric", p, signers) } @@ -635,7 +635,7 @@ func (c *Client) InvokeScriptAtHeight(height uint32, script []byte, signers []tr // state root or block hash. // NOTE: This is a test invoke and will not affect the blockchain. func (c *Client) InvokeScriptWithState(stateOrBlock util.Uint256, script []byte, signers []transaction.Signer) (*result.Invoke, error) { - var p = []interface{}{stateOrBlock.StringLE(), script} + var p = []any{stateOrBlock.StringLE(), script} return c.invokeSomething("invokescripthistoric", p, signers) } @@ -643,7 +643,7 @@ func (c *Client) InvokeScriptWithState(stateOrBlock util.Uint256, script []byte, // with the given operation and parameters. // NOTE: this is test invoke and will not affect the blockchain. func (c *Client) InvokeFunction(contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) { - var p = []interface{}{contract.StringLE(), operation, params} + var p = []any{contract.StringLE(), operation, params} return c.invokeSomething("invokefunction", p, signers) } @@ -652,7 +652,7 @@ func (c *Client) InvokeFunction(contract util.Uint160, operation string, params // specified by the blockchain height. // NOTE: this is test invoke and will not affect the blockchain. func (c *Client) InvokeFunctionAtHeight(height uint32, contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) { - var p = []interface{}{height, contract.StringLE(), operation, params} + var p = []any{height, contract.StringLE(), operation, params} return c.invokeSomething("invokefunctionhistoric", p, signers) } @@ -661,7 +661,7 @@ func (c *Client) InvokeFunctionAtHeight(height uint32, contract util.Uint160, op // by the specified state root or block hash. // NOTE: this is test invoke and will not affect the blockchain. func (c *Client) InvokeFunctionWithState(stateOrBlock util.Uint256, contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) { - var p = []interface{}{stateOrBlock.StringLE(), contract.StringLE(), operation, params} + var p = []any{stateOrBlock.StringLE(), contract.StringLE(), operation, params} return c.invokeSomething("invokefunctionhistoric", p, signers) } @@ -669,7 +669,7 @@ func (c *Client) InvokeFunctionWithState(stateOrBlock util.Uint256, contract uti // with the given parameters under verification trigger type. // NOTE: this is test invoke and will not affect the blockchain. func (c *Client) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) { - var p = []interface{}{contract.StringLE(), params} + var p = []any{contract.StringLE(), params} return c.invokeSomething("invokecontractverify", p, signers, witnesses...) } @@ -678,7 +678,7 @@ func (c *Client) InvokeContractVerify(contract util.Uint160, params []smartcontr // at the blockchain state specified by the blockchain height. // NOTE: this is test invoke and will not affect the blockchain. func (c *Client) InvokeContractVerifyAtHeight(height uint32, contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) { - var p = []interface{}{height, contract.StringLE(), params} + var p = []any{height, contract.StringLE(), params} return c.invokeSomething("invokecontractverifyhistoric", p, signers, witnesses...) } @@ -687,12 +687,12 @@ func (c *Client) InvokeContractVerifyAtHeight(height uint32, contract util.Uint1 // at the blockchain state specified by the state root or block hash. // NOTE: this is test invoke and will not affect the blockchain. func (c *Client) InvokeContractVerifyWithState(stateOrBlock util.Uint256, contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) { - var p = []interface{}{stateOrBlock.StringLE(), contract.StringLE(), params} + var p = []any{stateOrBlock.StringLE(), contract.StringLE(), params} return c.invokeSomething("invokecontractverifyhistoric", p, signers, witnesses...) } // invokeSomething is an inner wrapper for Invoke* functions. -func (c *Client) invokeSomething(method string, p []interface{}, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) { +func (c *Client) invokeSomething(method string, p []any, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) { var resp = new(result.Invoke) if signers != nil { if witnesses == nil { @@ -722,7 +722,7 @@ func (c *Client) invokeSomething(method string, p []interface{}, signers []trans // hash returned from server, when not it's a locally calculated rawTX hash. func (c *Client) SendRawTransaction(rawTX *transaction.Transaction) (util.Uint256, error) { var ( - params = []interface{}{rawTX.Bytes()} + params = []any{rawTX.Bytes()} resp = new(result.RelayResult) ) if err := c.performRequest("sendrawtransaction", params, resp); err != nil { @@ -734,7 +734,7 @@ func (c *Client) SendRawTransaction(rawTX *transaction.Transaction) (util.Uint25 // SubmitBlock broadcasts a raw block over the NEO network. func (c *Client) SubmitBlock(b block.Block) (util.Uint256, error) { var ( - params []interface{} + params []any resp = new(result.RelayResult) ) buf := io.NewBufBinWriter() @@ -742,7 +742,7 @@ func (c *Client) SubmitBlock(b block.Block) (util.Uint256, error) { if err := buf.Err; err != nil { return util.Uint256{}, err } - params = []interface{}{buf.Bytes()} + params = []any{buf.Bytes()} if err := c.performRequest("submitblock", params, resp); err != nil { return util.Uint256{}, err @@ -752,7 +752,7 @@ func (c *Client) SubmitBlock(b block.Block) (util.Uint256, error) { // SubmitRawOracleResponse submits a raw oracle response to the oracle node. // Raw params are used to avoid excessive marshalling. -func (c *Client) SubmitRawOracleResponse(ps []interface{}) error { +func (c *Client) SubmitRawOracleResponse(ps []any) error { return c.performRequest("submitoracleresponse", ps, new(result.RelayResult)) } @@ -991,7 +991,7 @@ func (c *Client) SubmitP2PNotaryRequest(req *payload.P2PNotaryRequest) (util.Uin if err != nil { return util.Uint256{}, fmt.Errorf("failed to encode request: %w", err) } - params := []interface{}{bytes} + params := []any{bytes} if err := c.performRequest("submitnotaryrequest", params, resp); err != nil { return util.Uint256{}, err } @@ -1002,7 +1002,7 @@ func (c *Client) SubmitP2PNotaryRequest(req *payload.P2PNotaryRequest) (util.Uin // Consider using [address] package instead to do it locally. func (c *Client) ValidateAddress(address string) error { var ( - params = []interface{}{address} + params = []any{address} resp = &result.ValidateAddress{} ) @@ -1168,7 +1168,7 @@ func (c *Client) TraverseIterator(sessionID, iteratorID uuid.UUID, maxItemsCount maxItemsCount = config.DefaultMaxIteratorResultItems } var ( - params = []interface{}{sessionID.String(), iteratorID.String(), maxItemsCount} + params = []any{sessionID.String(), iteratorID.String(), maxItemsCount} resp []json.RawMessage ) if err := c.performRequest("traverseiterator", params, &resp); err != nil { @@ -1190,7 +1190,7 @@ func (c *Client) TraverseIterator(sessionID, iteratorID uuid.UUID, maxItemsCount // the specified session was found on server. func (c *Client) TerminateSession(sessionID uuid.UUID) (bool, error) { var resp bool - params := []interface{}{sessionID.String()} + params := []any{sessionID.String()} if err := c.performRequest("terminatesession", params, &resp); err != nil { return false, err } diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index 9458e0830..87092343d 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -44,11 +44,11 @@ import ( type rpcClientTestCase struct { name string - invoke func(c *Client) (interface{}, error) + invoke func(c *Client) (any, error) fails bool serverResponse string - result func(c *Client) interface{} - check func(t *testing.T, c *Client, result interface{}) + result func(c *Client) any + check func(t *testing.T, c *Client, result any) } const base64B1 = "AAAAAMSdeyVO3QCekJTbQ4D7YEEGFv2nXPd6CfO5Kn3htI8P9tVA4+VXLyyMG12BUj6qB3CZ+JIFwWCcDF+KBHH0VSjJICSkegEAAAAAAAAAAAAAAQAAAABouegejA5skHm0udEF6HinbT8iPwHGDEBg0hpK90iZlB4ZSCG7BOr7BsvPXGDax360lvqKeNFuzaGI1RYNH50/dhQLxocy90JdsIOyodd1sOJGEjZIt7ztDEAHc2avJzz6tK+FOQMIZO/FEEikJdLJX0+iZXFcsmDRpB7lo2wWMSQbcoTXNg7leuR0VeDsKJ+YdvCuTG5WbiqWDECa6Yjj+bK4te5KR5jdLF5kLt03csyozZcd/X7NPt89IsX01zpX8ec3e+B2qySJIOhEf3cK0i+5U5wyXiFcRI8xkxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOgIAAgAAAMDYpwAAAAAADHlDAAAAAACwBAAAAWi56B6MDmyQebS50QXoeKdtPyI/AQBbCwIY3fUFDBTunqIsJ+NL0BSPxBCOCPdOj1BIsgwUaLnoHowObJB5tLnRBeh4p20/Ij8UwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQHGDEC8InWg8rQHWjklRojobu7kn4r0xZY2xWYs15ggVX4PQyEHpNTU6vZHT2TXRdPXAOKHhgWAttO0oTvo+9VZAjIVDEBF0qvBMlvmYJIYLqSoCjhBykcSN78UXrBjO5BKL8BpHtejWCld1VT6Z7nYrEBLgySD6HeMcp/fa6vqHzU220e/DECXtm5AA1jy9GFA7t8U6a+1uPrQFk4Ufp0UyXsun0PvN0NdhrHc37xm8k9Z0dB85V/7WLtkMaLLyjVNVIKImC76kxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOgADAAAAwNinAAAAAACsiEMAAAAAALAEAAABaLnoHowObJB5tLnRBeh4p20/Ij8BAF8LAwDodkgXAAAADBTunqIsJ+NL0BSPxBCOCPdOj1BIsgwUaLnoHowObJB5tLnRBeh4p20/Ij8UwB8MCHRyYW5zZmVyDBTPduKL0AYsSkeO41VhARMZ88+k0kFifVtSOQHGDEDgj/SQT84EbWRZ4ZKhyjJTuLwVPDgVlQO3CGmgacItvni9nziJvTxziZXBG/0Hqkv68ddS1EH94RtWlqLQWRCjDEAWZUeSQ8KskILSvoWPN3836xpg/TYzOGiFVoePv91CFnap4fRFxdbporBgnZ/sUsjFZ74U8f+r0riqtvkdMMyGDEDx5iho79oDVYOCwIDH3K1UeDjAT6Hq9YsD9SCfJSE1rRsAdJPh2StYxdh9Jah1lwGbW0U+Wu6zpbVFf5CS6fFckxMMIQIQOn990BZVhZf3lg0nxRakOU/ZaLnmUVXrSwE+QEBAbgwhAqe8Vf6GhOARl2jRBLoweVvcyGYZ6GSt0mFWcj7Rhc1iDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIMIQPZDAffY+aQzneRLhCrUazJRLZoYCN7YIxPj4MJ5x7mmRRBntDcOg==" @@ -116,11 +116,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getapplicationlog": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetApplicationLog(util.Uint256{}, nil) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"txid":"0x17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521","executions":[{"trigger":"Application","vmstate":"HALT","gasconsumed":"1","stack":[{"type":"Integer","value":"1"}],"notifications":[]}]}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { txHash, err := util.Uint256DecodeStringLE("17145a039fca704fcdbeb46e6b210af98a1a9e5b9768e46ffc38f71c79ac2521") if err != nil { panic(err) @@ -143,11 +143,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getbestblockhash": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBestBlockHash() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"0x773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { result, err := util.Uint256DecodeStringLE("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e") if err != nil { panic(err) @@ -159,29 +159,29 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getblock": { { name: "byIndex_positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndex(1) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64B1 + `"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { b := getResultBlock1() return &b.Block }, }, { name: "byIndex_verbose_positive", - invoke: func(c *Client) (i interface{}, err error) { + invoke: func(c *Client) (i any, err error) { return c.GetBlockByIndexVerbose(1) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + b1Verbose + `}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { res := getResultBlock1() return res }, }, { name: "byHash_positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("d151651e86680a7ecbc87babf3346a42e7bc9974414ce192c9c22ac4f2e9d043") if err != nil { panic(err) @@ -189,14 +189,14 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetBlockByHash(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64B1 + `"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { b := getResultBlock1() return &b.Block }, }, { name: "byHash_verbose_positive", - invoke: func(c *Client) (i interface{}, err error) { + invoke: func(c *Client) (i any, err error) { hash, err := util.Uint256DecodeStringLE("86fe1061140b2ea791b0739fb9732abc6e5e47de4927228a1ac41de3d93eb7cb") if err != nil { panic(err) @@ -204,7 +204,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetBlockByHashVerbose(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + b1Verbose + `}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { res := getResultBlock1() return res }, @@ -213,11 +213,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getblockcount": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockCount() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":991991}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return uint32(991991) }, }, @@ -225,11 +225,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getblockhash": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHash(1) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { hash, err := util.Uint256DecodeStringLE("4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2") if err != nil { panic(err) @@ -241,7 +241,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getblockheader": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("68e4bd688b852e807eef13a0ff7da7b02223e359a35153667e88f9cb4a3b0801") if err != nil { panic(err) @@ -249,14 +249,14 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetBlockHeader(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64Header1 + `"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { b := getResultBlock1() return &b.Header }, }, { name: "verbose_positive", - invoke: func(c *Client) (i interface{}, err error) { + invoke: func(c *Client) (i any, err error) { hash, err := util.Uint256DecodeStringLE("cbb73ed9e31dc41a8a222749de475e6ebc2a73b99f73b091a72e0b146110fe86") if err != nil { panic(err) @@ -264,7 +264,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetBlockHeaderVerbose(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + header1Verbose + `}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { b := getResultBlock1() return &result.Header{ Header: b.Header, @@ -280,11 +280,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getblockheadercount": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHeaderCount() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":2021}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return uint32(2021) }, }, @@ -292,11 +292,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getblocksysfee": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockSysFee(1) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"195500"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return fixedn.Fixed8FromInt64(195500) }, }, @@ -304,11 +304,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getcommittee": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetCommittee() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":["02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e"]}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { member, err := keys.NewPublicKeyFromString("02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e") if err != nil { panic(fmt.Errorf("failed to decode public key: %w", err)) @@ -320,11 +320,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getconnectioncount": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetConnectionCount() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":10}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return 10 }, }, @@ -332,7 +332,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getcontractstate": { { name: "positive, by hash", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("1b4357bff5a01bdf2a6581247cf9ed1e24629176") if err != nil { panic(err) @@ -340,7 +340,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetContractStateByHash(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"features":{},"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { panic(err) @@ -359,11 +359,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "positive, by address", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetContractStateByAddressOrName("NWiu5oejTu925aeL9Hc1LX8SvaJhE23h15") }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"features":{},"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { panic(err) @@ -382,11 +382,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "positive, by id", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetContractStateByID(0) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"features":{},"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { panic(err) @@ -407,11 +407,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getFeePerByte": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(1000) }, }, @@ -419,11 +419,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getExecFeeFactor": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(1000) }, }, @@ -431,11 +431,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getStoragePrice": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(100000) }, }, @@ -443,11 +443,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getOraclePrice": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(10000000) }, }, @@ -455,11 +455,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getNNSPrice": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(1000000) }, }, @@ -467,11 +467,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getGasPerBlock": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(500000000) }, }, @@ -479,11 +479,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getCandidateRegisterPrice": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(100000000000) }, }, @@ -491,11 +491,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getDesignatedByRole": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { pk1Bytes, _ := base64.StdEncoding.DecodeString("Aw0WkQoDc8WqpG18xPMTEgfHO6gRTVtMN0Mw6zw06fzl") pk1, err := keys.NewPublicKeyFromBytes(pk1Bytes, elliptic.P256()) if err != nil { @@ -513,11 +513,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getMaxNotValidBeforeDelta": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return int64(262144) }, }, @@ -525,11 +525,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "isBlocked": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + 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) interface{} { + result: func(c *Client) any { return false }, }, @@ -537,7 +537,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getnep11balances": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("1aada0032aba1ef6d1f07bbd8bec1d85f5380fb3") if err != nil { panic(err) @@ -545,7 +545,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetNEP11Balances(hash) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"balance":[{"assethash":"a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8","symbol":"SOME","decimals":"42","name":"Contract","tokens":[{"tokenid":"abcdef","amount":"1","lastupdatedblock":251604}]}],"address":"NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { hash, err := util.Uint160DecodeStringLE("a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8") if err != nil { panic(err) @@ -570,7 +570,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getnep17balances": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("1aada0032aba1ef6d1f07bbd8bec1d85f5380fb3") if err != nil { panic(err) @@ -578,7 +578,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetNEP17Balances(hash) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"balance":[{"assethash":"a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8","symbol":"N17","decimals":"8","name":"Token","amount":"50000000000","lastupdatedblock":251604}],"address":"AY6eqWjsUFCzsVELG7yG72XDukKvC34p2w"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { hash, err := util.Uint160DecodeStringLE("a48b6e1291ba24211ad11bb90ae2a10bf1fcd5a8") if err != nil { panic(err) @@ -600,7 +600,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getnep11properties": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("1aada0032aba1ef6d1f07bbd8bec1d85f5380fb3") if err != nil { panic(err) @@ -608,8 +608,8 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetNEP11Properties(hash, []byte("abcdef")) }, // NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"name":"sometoken","field1":"c29tZXRoaW5n","field2":null}}`, - result: func(c *Client) interface{} { - return map[string]interface{}{ + result: func(c *Client) any { + return map[string]any{ "name": "sometoken", "field1": []byte("something"), "field2": nil, @@ -620,7 +620,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getnep11transfers": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := address.StringToUint160("NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe") if err != nil { panic(err) @@ -628,7 +628,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetNEP11Transfers(hash, nil, nil, nil, nil) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sent":[],"received":[{"timestamp":1555651816,"assethash":"600c4f5200db36177e3e8a09e9f18e2fc7d12a0f","transferaddress":"NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP","amount":"1","tokenid":"abcdef","blockindex":436036,"transfernotifyindex":0,"txhash":"df7683ece554ecfb85cf41492c5f143215dd43ef9ec61181a28f922da06aba58"}],"address":"NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { assetHash, err := util.Uint160DecodeStringLE("600c4f5200db36177e3e8a09e9f18e2fc7d12a0f") if err != nil { panic(err) @@ -659,7 +659,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getnep17transfers": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := address.StringToUint160("NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe") if err != nil { panic(err) @@ -667,7 +667,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetNEP17Transfers(hash, nil, nil, nil, nil) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"sent":[],"received":[{"timestamp":1555651816,"assethash":"600c4f5200db36177e3e8a09e9f18e2fc7d12a0f","transferaddress":"AYwgBNMepiv5ocGcyNT4mA8zPLTQ8pDBis","amount":"1000000","blockindex":436036,"transfernotifyindex":0,"txhash":"df7683ece554ecfb85cf41492c5f143215dd43ef9ec61181a28f922da06aba58"}],"address":"NcEkNmgWmf7HQVQvzhxpengpnt4DXjmZLe"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { assetHash, err := util.Uint160DecodeStringLE("600c4f5200db36177e3e8a09e9f18e2fc7d12a0f") if err != nil { panic(err) @@ -697,11 +697,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getpeers": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetPeers() }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"unconnected":[{"address":"172.200.0.1","port":"20333"}],"connected":[{"address":"127.0.0.1","port":"20335"}],"bad":[{"address":"172.200.0.254","port":"20332"}]}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return &result.GetPeers{ Unconnected: result.Peers{ { @@ -728,11 +728,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getrawmempool": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetRawMemPool() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":["0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"]}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { hash, err := util.Uint256DecodeStringLE("9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e") if err != nil { panic(err) @@ -744,7 +744,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getrawtransaction": { { name: "positive", - invoke: func(c *Client) (i interface{}, err error) { + invoke: func(c *Client) (i any, err error) { hash, err := util.Uint256DecodeStringLE("f5fbd303799f24ba247529d7544d4276cca54ea79f4b98095f2b0557313c5275") if err != nil { panic(err) @@ -752,14 +752,14 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetRawTransaction(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + base64TxMoveNeo + `"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { tx := getTxMoveNeo() return &tx.Transaction }, }, { name: "verbose_positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("f5fbd303799f24ba247529d7544d4276cca54ea79f4b98095f2b0557313c5275") if err != nil { panic(err) @@ -772,7 +772,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return out, nil }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":` + txMoveNeoVerbose + `}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return getTxMoveNeo() }, }, @@ -780,11 +780,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getstateroot": { { name: "positive, by height", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetStateRootByHeight(5) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"version":0,"index":5,"roothash":"0x65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686","witnesses":[]}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { h, err := util.Uint256DecodeStringLE("65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686") if err != nil { panic(err) @@ -799,7 +799,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "positive, by hash", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("86fe1061140b2ea791b0739fb9732abc6e5e47de4927228a1ac41de3d93eb7cb") if err != nil { panic(err) @@ -807,7 +807,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetStateRootByBlockHash(hash) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"version":0,"index":5,"roothash":"0x65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686","witnesses":[]}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { h, _ := util.Uint256DecodeStringLE("65d19151694321e70c6d184b37a2bcf7af4a2c60c099af332a4f7815e3670686") return &state.MPTRoot{ Version: 0, @@ -821,13 +821,13 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getstate": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170") cHash, _ := util.Uint160DecodeStringLE("5c9e40a12055c6b9e3f72271c9779958c842135d") return c.GetState(root, cHash, []byte("testkey")) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"dGVzdHZhbHVl"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return []byte("testvalue") }, }, @@ -835,14 +835,14 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getproof": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") cHash, _ := util.Uint160DecodeStringLE("cc5e4edd9f5f8dba8bb65734541df7a1c081c67b") key := []byte{10} return c.GetProof(root, cHash, key) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD") proof := &result.ProofWithKey{} r := io.NewBinReaderFromBuf(b) @@ -852,7 +852,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "not found", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") cHash, _ := util.Uint160DecodeStringLE("cc5e4edd9f5f8dba8bb65734541df7a1c081c67b") key := []byte{01} @@ -865,7 +865,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "verifyproof": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD") proof := &result.ProofWithKey{} @@ -874,13 +874,13 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.VerifyProof(root, proof) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"6AM="}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return bigint.ToPreallocatedBytes(big.NewInt(1000), nil) }, }, { name: "fail", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { root, _ := util.Uint256DecodeStringLE("272002b11a6a39035c719defec3e4e6a8d1f4ae37a995b44734911413fcc2ba5") b, _ := base64.StdEncoding.DecodeString("Bfn///8KBiQBAQ8DogBnMdiiPTEW05A6bJPmQ2TNVpuca/nB1rJRdQX7R4SyAAQEBAQEBAQDHvo5Rc9v\u002BWSpfsnMXM75ku\u002BZjvbLJhWXn/lh6L\u002B1yB0EA4k\u002Bsx4f7IgmdHNm3wRMpj5kTU4l0gChSGppo5p5wZyWA2\u002BKSFn16W6tRrGSfJob\u002BgqJukLcNDk0DBFYW2wIS2/NAzkugdLfZRXHOLqq5XJr89ElzlqyXU1o9D87l9YOcXjGBAQEA7oDTOxuU4iMAKPuhn5eJjzsM56bQrx3uORa8LKm42oDBCkBBg8PDw8PDwN96s39UOSCwMJmMQZzNjfNAPCbRRyke1B4VRKqOZ0NHlIAA2woQ13XO4Ug2aQ/cW4WBricVcUVqobFUU0dnRPtfIHeAxuYERXsV6HwdGjW\u002BhtpM0FEkw/mllbH5pyhn\u002BBx4r8wBAQEBAQEBAQEBAQEBAQEJAEBCgPXvpMqBogTeGhXjtFY4Rsn9bY/PgNX0l4iYOHMzUBQQgQCAugD") proof := &result.ProofWithKey{} @@ -895,14 +895,14 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "findstates": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { root, _ := util.Uint256DecodeStringLE("252e9d73d49c95c7618d40650da504e05183a1b2eed0685e42c360413c329170") cHash, _ := util.Uint160DecodeStringLE("5c9e40a12055c6b9e3f72271c9779958c842135d") count := 1 return c.FindStates(root, cHash, []byte("aa"), []byte("aa00"), &count) }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"results":[{"key":"YWExMA==","value":"djI="}],"firstProof":"CAEAAABhYTEwCXIAA5KNHjQ1+LFX4lQBLjMAhaLtTJnfuI86O7WnNdlshsYWBAQEBAQEBAQDTzD7MJp2KW6E8BNVjjjgZMTAjI/GI3ZrTmR2UUOtSeIEBAQEBAPKPqb0qnb4Ywz6gqpNKCUNQsfBmAnKc5p3dxokSQRpwgRSAAQDPplG1wee4KOfkehaF94R5uoKSgvQL1j5gkFTN4ywYaIEBAOhOyI39MZfoKc940g57XeqwRnxh7P62fKjnfEtBzQxHQQEBAQEBAQEBAQEBCkBBgAAAAAAAAM6A1UrwFYZAEMfe6go3jX25xz2sHsovQ2UO/UHqZZOXLIABAOwg7pkXyaTR85yQIvYnoGaG/OVRLRHOj+nhZnXb6dVtAQEBAPnciBUp3uspLQTajKTlAxgrNe+3tlqlbwlNRkz0eNmhQMzoMcWOFi9nCyn+eM5lA6Pq67DxzTQDlHljh8g8kRtJAPq9hxzTgreK0qDTavsethixguZYfV7wDmKfumMglnoqQQEBAQEBAM1x2dVBdf5BJ0Xvw2qqhvpKqxdHb8/HMFWiXkJj1uAAQQEJgEDAQYBA5kV2WLkgey9C5z6gZT69VLKcEuwyY8P853rNtGhT3NeUgAEBAQDiX59K9PuJ5RE7Z1uj7q/QJ8FGf8avLdWM7hwmWkVH2gEBAQEBAQEBAQEBAQD1SubX5XhFHcUOWdUzg1bXmDwWJwt+wpU3FOdFkU1PXBSAAQDHCzfEQyqwOO263EE6HER1vWDrwz8JiEHEOXfZ3kX7NYEBAQDEH++Hy8wBcniKuWVevaAwzHCh60kzncU30E5fDC3gJsEBAQEBAQEBAQEBCUBAgMAA1wt18LbxMKdYcJ+nEDMMWZbRsu550l8HGhcYhpl6DjSBAICdjI=","truncated":true}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { proofB, _ := base64.StdEncoding.DecodeString("CAEAAABhYTEwCXIAA5KNHjQ1+LFX4lQBLjMAhaLtTJnfuI86O7WnNdlshsYWBAQEBAQEBAQDTzD7MJp2KW6E8BNVjjjgZMTAjI/GI3ZrTmR2UUOtSeIEBAQEBAPKPqb0qnb4Ywz6gqpNKCUNQsfBmAnKc5p3dxokSQRpwgRSAAQDPplG1wee4KOfkehaF94R5uoKSgvQL1j5gkFTN4ywYaIEBAOhOyI39MZfoKc940g57XeqwRnxh7P62fKjnfEtBzQxHQQEBAQEBAQEBAQEBCkBBgAAAAAAAAM6A1UrwFYZAEMfe6go3jX25xz2sHsovQ2UO/UHqZZOXLIABAOwg7pkXyaTR85yQIvYnoGaG/OVRLRHOj+nhZnXb6dVtAQEBAPnciBUp3uspLQTajKTlAxgrNe+3tlqlbwlNRkz0eNmhQMzoMcWOFi9nCyn+eM5lA6Pq67DxzTQDlHljh8g8kRtJAPq9hxzTgreK0qDTavsethixguZYfV7wDmKfumMglnoqQQEBAQEBAM1x2dVBdf5BJ0Xvw2qqhvpKqxdHb8/HMFWiXkJj1uAAQQEJgEDAQYBA5kV2WLkgey9C5z6gZT69VLKcEuwyY8P853rNtGhT3NeUgAEBAQDiX59K9PuJ5RE7Z1uj7q/QJ8FGf8avLdWM7hwmWkVH2gEBAQEBAQEBAQEBAQD1SubX5XhFHcUOWdUzg1bXmDwWJwt+wpU3FOdFkU1PXBSAAQDHCzfEQyqwOO263EE6HER1vWDrwz8JiEHEOXfZ3kX7NYEBAQDEH++Hy8wBcniKuWVevaAwzHCh60kzncU30E5fDC3gJsEBAQEBAQEBAQEBCUBAgMAA1wt18LbxMKdYcJ+nEDMMWZbRsu550l8HGhcYhpl6DjSBAICdjI=") proof := &result.ProofWithKey{} r := io.NewBinReaderFromBuf(proofB) @@ -918,11 +918,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getstateheight": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetStateHeight() }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"localrootindex":11646,"validatedrootindex":11645}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return &result.StateHeight{ Local: 11646, Validated: 11645, @@ -933,7 +933,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getstorage": { { name: "by hash, positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("03febccf81ac85e3d795bc5cbd4e84e907812aa3") if err != nil { panic(err) @@ -945,7 +945,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetStorageByHash(hash, key) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { value, err := hex.DecodeString("4c696e") if err != nil { panic(err) @@ -955,7 +955,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "by ID, positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { key, err := hex.DecodeString("5065746572") if err != nil { panic(err) @@ -963,7 +963,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetStorageByID(-1, key) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":"TGlu"}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { value, err := hex.DecodeString("4c696e") if err != nil { panic(err) @@ -975,7 +975,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "gettransactionheight": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("cb6ddb5f99d6af4c94a6c396d5294472f2eebc91a2c933e0f527422296fa9fb2") if err != nil { panic(err) @@ -983,7 +983,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.GetTransactionHeight(hash) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":1}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return uint32(1) }, }, @@ -991,11 +991,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getunclaimedgas": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetUnclaimedGas("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB") }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB","unclaimed":"897299680935"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { addr, err := address.StringToUint160("NMipL5VsNoLUBUJKPKLhxaEbPQVCZnyJyB") if err != nil { panic(fmt.Errorf("failed to parse UnclaimedGas address: %w", err)) @@ -1010,12 +1010,12 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getcandidates": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetCandidates() }, serverResponse: `{"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}]}`, - result: func(c *Client) interface{} { return []result.Candidate{} }, - check: func(t *testing.T, c *Client, uns interface{}) { + result: func(c *Client) any { return []result.Candidate{} }, + check: func(t *testing.T, c *Client, uns any) { res, ok := uns.([]result.Candidate) require.True(t, ok) assert.Equal(t, 4, len(res)) @@ -1025,12 +1025,12 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getvalidators": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNextBlockValidators() }, serverResponse: `{"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}]}`, - result: func(c *Client) interface{} { return []result.Validator{} }, - check: func(t *testing.T, c *Client, uns interface{}) { + result: func(c *Client) any { return []result.Validator{} }, + check: func(t *testing.T, c *Client, uns any) { res, ok := uns.([]result.Validator) require.True(t, ok) assert.Equal(t, 4, len(res)) @@ -1040,11 +1040,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "getversion": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetVersion() }, serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"tcpport":20332,"wsport":20342,"nonce":2153672787,"useragent":"/NEO-GO:0.73.1-pre-273-ge381358/"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return &result.Version{ TCPPort: uint16(20332), WSPort: uint16(20342), @@ -1060,7 +1060,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "invokefunction": { { name: "positive, by scripthash", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("91b83e96f2a7c4fdf0c1688441ec61986c7cae26") if err != nil { panic(err) @@ -1079,10 +1079,10 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }}) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv","state":"HALT","gasconsumed":"31100000","stack":[{"type":"ByteString","value":"JivsCEQy"}],"tx":"AAgAAACAlpgAAAAAAAIEEwAAAAAAsAQAAAGqis+FnU/kArNOZz8hVoIXlqSI6wEAVwHoAwwUqorPhZ1P5AKzTmc/IVaCF5akiOsMFOeetm08E0pKd27oB9LluEbdpP2wE8AMCHRyYW5zZmVyDBTnnrZtPBNKSndu6AfS5bhG3aT9sEFifVtSOAFCDEDYNAh3TUvYsZrocFYdBvJ0Trdnj1jRuQzy9Q6YroP2Cwgk4v7q3vbeZBikz8Q7vB+RbDPsWUy+ZiqdkkeG4XoUKQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CC0GVRA14"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return &result.Invoke{} }, - check: func(t *testing.T, c *Client, uns interface{}) { + check: func(t *testing.T, c *Client, uns any) { res, ok := uns.(*result.Invoke) require.True(t, ok) bytes, err := hex.DecodeString("262bec084432") @@ -1102,7 +1102,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "positive, FAULT state", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("91b83e96f2a7c4fdf0c1688441ec61986c7cae26") if err != nil { panic(err) @@ -1121,10 +1121,10 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }}) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv","state":"FAULT","gasconsumed":"31100000","stack":[{"type":"ByteString","value":"JivsCEQy"}],"tx":"AAgAAACAlpgAAAAAAAIEEwAAAAAAsAQAAAGqis+FnU/kArNOZz8hVoIXlqSI6wEAVwHoAwwUqorPhZ1P5AKzTmc/IVaCF5akiOsMFOeetm08E0pKd27oB9LluEbdpP2wE8AMCHRyYW5zZmVyDBTnnrZtPBNKSndu6AfS5bhG3aT9sEFifVtSOAFCDEDYNAh3TUvYsZrocFYdBvJ0Trdnj1jRuQzy9Q6YroP2Cwgk4v7q3vbeZBikz8Q7vB+RbDPsWUy+ZiqdkkeG4XoUKQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CC0GVRA14","exception":"gas limit exceeded"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return &result.Invoke{} }, - check: func(t *testing.T, c *Client, uns interface{}) { + check: func(t *testing.T, c *Client, uns any) { res, ok := uns.(*result.Invoke) require.True(t, ok) bytes, err := hex.DecodeString("262bec084432") @@ -1146,7 +1146,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "invokescript": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { script, err := base64.StdEncoding.DecodeString("AARuYW1lZyQFjl4bYAiEfNZicoVJCIqe6CGR") if err != nil { panic(err) @@ -1156,7 +1156,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }}) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"AARuYW1lZyQFjl4bYAiEfNZicoVJCIqe6CGR","state":"HALT","gasconsumed":"16100000","stack":[{"type":"ByteString","value":"TkVQNSBHQVM="}],"tx":null}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { bytes, err := hex.DecodeString("4e45503520474153") if err != nil { panic(err) @@ -1177,7 +1177,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "invokecontractverify": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { contr, err := util.Uint160DecodeStringLE("af7c7328eee5a275a3bcaee2bf0cf662b5e739be") if err != nil { panic(err) @@ -1185,10 +1185,10 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ return c.InvokeContractVerify(contr, nil, []transaction.Signer{{Account: util.Uint160{1, 2, 3}}}, transaction.Witness{InvocationScript: []byte{1, 2, 3}}) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"script":"FCaufGyYYexBhGjB8P3Ep/KWPriRUcEJYmFsYW5jZU9mZ74557Vi9gy/4q68o3Wi5e4oc3yv","state":"HALT","gasconsumed":"31100000","stack":[{"type":"ByteString","value":"JivsCEQy"}],"tx":"AAgAAACAlpgAAAAAAAIEEwAAAAAAsAQAAAGqis+FnU/kArNOZz8hVoIXlqSI6wEAVwHoAwwUqorPhZ1P5AKzTmc/IVaCF5akiOsMFOeetm08E0pKd27oB9LluEbdpP2wE8AMCHRyYW5zZmVyDBTnnrZtPBNKSndu6AfS5bhG3aT9sEFifVtSOAFCDEDYNAh3TUvYsZrocFYdBvJ0Trdnj1jRuQzy9Q6YroP2Cwgk4v7q3vbeZBikz8Q7vB+RbDPsWUy+ZiqdkkeG4XoUKQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CC0GVRA14"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { return &result.Invoke{} }, - check: func(t *testing.T, c *Client, uns interface{}) { + check: func(t *testing.T, c *Client, uns any) { res, ok := uns.(*result.Invoke) require.True(t, ok) bytes, err := hex.DecodeString("262bec084432") @@ -1208,7 +1208,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, { name: "bad witness number", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.InvokeContractVerify(util.Uint160{}, nil, []transaction.Signer{{}}, []transaction.Witness{{}, {}}...) }, fails: true, @@ -1217,11 +1217,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "sendrawtransaction": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0)) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { h, err := util.Uint256DecodeStringLE("72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875") if err != nil { panic(fmt.Errorf("can't decode `sendrawtransaction` result hash: %w", err)) @@ -1233,7 +1233,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "submitblock": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SubmitBlock(block.Block{ Header: block.Header{}, Transactions: nil, @@ -1241,7 +1241,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x1bdea8f80eb5bd97fade38d5e7fb93b02c9d3e01394e9f4324218132293f7ea6"}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { h, err := util.Uint256DecodeStringLE("1bdea8f80eb5bd97fade38d5e7fb93b02c9d3e01394e9f4324218132293f7ea6") if err != nil { panic(fmt.Errorf("can't decode `submitblock` result hash: %w", err)) @@ -1253,11 +1253,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ "validateaddress": { { name: "positive", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return nil, c.ValidateAddress("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i") }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"address":"AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i","isvalid":true}}`, - result: func(c *Client) interface{} { + result: func(c *Client) any { // no error expected return nil }, @@ -1267,14 +1267,14 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ type rpcClientErrorCase struct { name string - invoke func(c *Client) (interface{}, error) + invoke func(c *Client) (any, error) } var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{"jsonrpc":"2.0","id":1,"result":{"name":"name","bad":42}}`: { { name: "getnep11properties_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Properties(util.Uint160{}, []byte{}) }, }, @@ -1282,7 +1282,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{"jsonrpc":"2.0","id":1,"result":{"name":100500,"good":"c29tZXRoaW5n"}}`: { { name: "getnep11properties_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Properties(util.Uint160{}, []byte{}) }, }, @@ -1290,13 +1290,13 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{"jsonrpc":"2.0","id":1,"result":"not-a-hex-string"}`: { { name: "getblock_not_a_hex_response", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndex(1) }, }, { name: "getblockheader_not_a_hex_response", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c") if err != nil { panic(err) @@ -1306,7 +1306,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "getrawtransaction_not_a_hex_response", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c") if err != nil { panic(err) @@ -1316,7 +1316,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "getstoragebyhash_not_a_hex_response", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint160DecodeStringLE("03febccf81ac85e3d795bc5cbd4e84e907812aa3") if err != nil { panic(err) @@ -1330,7 +1330,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "getstoragebyid_not_a_hex_response", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { key, err := hex.DecodeString("5065746572") if err != nil { panic(err) @@ -1342,13 +1342,13 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{"jsonrpc":"2.0","id":1,"result":"01"}`: { { name: "getblock_decodebin_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndex(1) }, }, { name: "getheader_decodebin_err", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c") if err != nil { panic(err) @@ -1358,7 +1358,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "getrawtransaction_decodebin_err", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { hash, err := util.Uint256DecodeStringLE("e93d17a52967f9e69314385482bf86f85260e811b46bf4d4b261a7f4135a623c") if err != nil { panic(err) @@ -1370,13 +1370,13 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{"jsonrpc":"2.0","id":1,"result":false}`: { { name: "sendrawtransaction_bad_server_answer", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0)) }, }, { name: "submitblock_bad_server_answer", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SubmitBlock(block.Block{ Header: block.Header{}, Transactions: nil, @@ -1386,7 +1386,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "validateaddress_bad_server_answer", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return nil, c.ValidateAddress("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i") }, }, @@ -1394,116 +1394,116 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{"id":1,"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid Params"}}`: { { name: "getapplicationlog_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetApplicationLog(util.Uint256{}, nil) }, }, { name: "getbestblockhash_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBestBlockHash() }, }, { name: "getblock_byindex_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndex(1) }, }, { name: "getblock_byindex_verbose_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndexVerbose(1) }, }, { name: "getblock_byhash_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByHash(util.Uint256{}) }, }, { name: "getblock_byhash_verbose_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByHashVerbose(util.Uint256{}) }, }, { name: "getblockhash_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHash(0) }, }, { name: "getblockheader_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHeader(util.Uint256{}) }, }, { name: "getblockheader_verbose_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHeaderVerbose(util.Uint256{}) }, }, { name: "getblocksysfee_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockSysFee(1) }, }, { name: "getconnectioncount_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetConnectionCount() }, }, { name: "getcontractstate_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetContractStateByHash(util.Uint160{}) }, }, { name: "getnep11balances_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Balances(util.Uint160{}) }, }, { name: "getnep17balances_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP17Balances(util.Uint160{}) }, }, { name: "getnep11properties_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Properties(util.Uint160{}, []byte{}) }, }, { name: "getnep11transfers_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Transfers(util.Uint160{}, nil, nil, nil, nil) }, }, { name: "getnep17transfers_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP17Transfers(util.Uint160{}, nil, nil, nil, nil) }, }, { name: "getnep17transfers_invalid_params_error 2", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { var stop uint64 return c.GetNEP17Transfers(util.Uint160{}, nil, &stop, nil, nil) }, }, { name: "getnep17transfers_invalid_params_error 3", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { var start uint64 var limit int return c.GetNEP17Transfers(util.Uint160{}, &start, nil, &limit, nil) @@ -1511,7 +1511,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "getnep17transfers_invalid_params_error 4", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { var start, stop uint64 var page int return c.GetNEP17Transfers(util.Uint160{}, &start, &stop, nil, &page) @@ -1519,67 +1519,67 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "getrawtransaction_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetRawTransaction(util.Uint256{}) }, }, { name: "getrawtransaction_verbose_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetRawTransactionVerbose(util.Uint256{}) }, }, { name: "getstoragebyhash_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetStorageByHash(util.Uint160{}, []byte{}) }, }, { name: "getstoragebyid_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetStorageByID(-1, []byte{}) }, }, { name: "gettransactionheight_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetTransactionHeight(util.Uint256{}) }, }, { name: "getunclaimedgas_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetUnclaimedGas("") }, }, { name: "invokefunction_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.InvokeFunction(util.Uint160{}, "", []smartcontract.Parameter{}, nil) }, }, { name: "invokescript_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.InvokeScript([]byte{}, nil) }, }, { name: "sendrawtransaction_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SendRawTransaction(&transaction.Transaction{}) }, }, { name: "submitblock_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SubmitBlock(block.Block{}) }, }, { name: "validateaddress_invalid_params_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return nil, c.ValidateAddress("") }, }, @@ -1587,193 +1587,193 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ `{}`: { { name: "getapplicationlog_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetApplicationLog(util.Uint256{}, nil) }, }, { name: "getbestblockhash_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBestBlockHash() }, }, { name: "getblock_byindex_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndex(1) }, }, { name: "getblock_byindex_verbose_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByIndexVerbose(1) }, }, { name: "getblock_byhash_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByHash(util.Uint256{}) }, }, { name: "getblock_byhash_verbose_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockByHashVerbose(util.Uint256{}) }, }, { name: "getblockcount_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockCount() }, }, { name: "getblockhash_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHash(1) }, }, { name: "getblockheader_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHeader(util.Uint256{}) }, }, { name: "getblockheader_verbose_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockHeaderVerbose(util.Uint256{}) }, }, { name: "getblocksysfee_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetBlockSysFee(1) }, }, { name: "getcommittee_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetCommittee() }, }, { name: "getconnectioncount_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetConnectionCount() }, }, { name: "getcontractstate_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetContractStateByHash(util.Uint160{}) }, }, { name: "getnep11balances_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Balances(util.Uint160{}) }, }, { name: "getnep17balances_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP17Balances(util.Uint160{}) }, }, { name: "getnep11transfers_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP11Transfers(util.Uint160{}, nil, nil, nil, nil) }, }, { name: "getnep17transfers_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNEP17Transfers(util.Uint160{}, nil, nil, nil, nil) }, }, { name: "getpeers_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetPeers() }, }, { name: "getrawmempool_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetRawMemPool() }, }, { name: "getrawtransaction_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetRawTransaction(util.Uint256{}) }, }, { name: "getrawtransaction_verbose_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetRawTransactionVerbose(util.Uint256{}) }, }, { name: "getstoragebyhash_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetStorageByHash(util.Uint160{}, []byte{}) }, }, { name: "getstoragebyid_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetStorageByID(-1, []byte{}) }, }, { name: "gettransactionheight_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetTransactionHeight(util.Uint256{}) }, }, { name: "getunclaimedgas_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetUnclaimedGas("") }, }, { name: "getcandidates_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetCandidates() }, }, { name: "getvalidators_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.GetNextBlockValidators() }, }, { name: "invokefunction_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.InvokeFunction(util.Uint160{}, "", []smartcontract.Parameter{}, nil) }, }, { name: "invokescript_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.InvokeScript([]byte{}, nil) }, }, { name: "sendrawtransaction_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0)) }, }, { name: "submitblock_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return c.SubmitBlock(block.Block{ Header: block.Header{}, Transactions: nil, @@ -1783,7 +1783,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ }, { name: "validateaddress_unmarshalling_error", - invoke: func(c *Client) (interface{}, error) { + invoke: func(c *Client) (any, error) { return nil, c.ValidateAddress("") }, }, diff --git a/pkg/rpcclient/unwrap/unwrap_test.go b/pkg/rpcclient/unwrap/unwrap_test.go index b26876a58..9ec9f3cc0 100644 --- a/pkg/rpcclient/unwrap/unwrap_test.go +++ b/pkg/rpcclient/unwrap/unwrap_test.go @@ -15,66 +15,66 @@ import ( ) func TestStdErrors(t *testing.T) { - funcs := []func(r *result.Invoke, err error) (interface{}, error){ - func(r *result.Invoke, err error) (interface{}, error) { + funcs := []func(r *result.Invoke, err error) (any, error){ + func(r *result.Invoke, err error) (any, error) { return BigInt(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Bool(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Int64(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return LimitedInt64(r, err, 0, 1) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Bytes(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return UTF8String(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return PrintableASCIIString(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Uint160(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Uint256(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return PublicKey(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { _, _, err = SessionIterator(r, err) return nil, err }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Array(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfBools(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfBigInts(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfBytes(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfUTF8Strings(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfUint160(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfUint256(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return ArrayOfPublicKeys(r, err) }, - func(r *result.Invoke, err error) (interface{}, error) { + func(r *result.Invoke, err error) (any, error) { return Map(r, err) }, } diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index 2234260fc..c3f6172a1 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -79,7 +79,7 @@ type WSClient struct { // It must be accessed with subscriptionsLock taken. Its keys must be used to deliver // notifications, if channel is not in the receivers list and corresponding subscription // still exists, notification must not be sent. - receivers map[interface{}][]string + receivers map[any][]string respLock sync.RWMutex respChannels map[uint64]chan *neorpc.Response @@ -91,7 +91,7 @@ type notificationReceiver interface { // Comparator provides notification filtering functionality. rpcevent.Comparator // Receiver returns notification receiver channel. - Receiver() interface{} + Receiver() any // TrySend checks whether notification passes receiver filter and sends it // to the underlying channel if so. TrySend(ntf Notification) bool @@ -111,7 +111,7 @@ func (r *blockReceiver) EventID() neorpc.EventID { } // Filter implements neorpc.Comparator interface. -func (r *blockReceiver) Filter() interface{} { +func (r *blockReceiver) Filter() any { if r.filter == nil { return nil } @@ -119,7 +119,7 @@ func (r *blockReceiver) Filter() interface{} { } // Receiver implements notificationReceiver interface. -func (r *blockReceiver) Receiver() interface{} { +func (r *blockReceiver) Receiver() any { return r.ch } @@ -149,7 +149,7 @@ func (r *txReceiver) EventID() neorpc.EventID { } // Filter implements neorpc.Comparator interface. -func (r *txReceiver) Filter() interface{} { +func (r *txReceiver) Filter() any { if r.filter == nil { return nil } @@ -157,7 +157,7 @@ func (r *txReceiver) Filter() interface{} { } // Receiver implements notificationReceiver interface. -func (r *txReceiver) Receiver() interface{} { +func (r *txReceiver) Receiver() any { return r.ch } @@ -187,7 +187,7 @@ func (r *executionNotificationReceiver) EventID() neorpc.EventID { } // Filter implements neorpc.Comparator interface. -func (r *executionNotificationReceiver) Filter() interface{} { +func (r *executionNotificationReceiver) Filter() any { if r.filter == nil { return nil } @@ -195,7 +195,7 @@ func (r *executionNotificationReceiver) Filter() interface{} { } // Receiver implements notificationReceiver interface. -func (r *executionNotificationReceiver) Receiver() interface{} { +func (r *executionNotificationReceiver) Receiver() any { return r.ch } @@ -225,7 +225,7 @@ func (r *executionReceiver) EventID() neorpc.EventID { } // Filter implements neorpc.Comparator interface. -func (r *executionReceiver) Filter() interface{} { +func (r *executionReceiver) Filter() any { if r.filter == nil { return nil } @@ -233,7 +233,7 @@ func (r *executionReceiver) Filter() interface{} { } // Receiver implements notificationReceiver interface. -func (r *executionReceiver) Receiver() interface{} { +func (r *executionReceiver) Receiver() any { return r.ch } @@ -263,7 +263,7 @@ func (r *notaryRequestReceiver) EventID() neorpc.EventID { } // Filter implements neorpc.Comparator interface. -func (r *notaryRequestReceiver) Filter() interface{} { +func (r *notaryRequestReceiver) Filter() any { if r.filter == nil { return nil } @@ -271,7 +271,7 @@ func (r *notaryRequestReceiver) Filter() interface{} { } // Receiver implements notificationReceiver interface. -func (r *notaryRequestReceiver) Receiver() interface{} { +func (r *notaryRequestReceiver) Receiver() any { return r.ch } @@ -295,7 +295,7 @@ func (r *notaryRequestReceiver) Close() { // Deprecated: this receiver must be removed after outdated subscriptions API removal. type naiveReceiver struct { eventID neorpc.EventID - filter interface{} + filter any ch chan<- Notification } @@ -305,12 +305,12 @@ func (r *naiveReceiver) EventID() neorpc.EventID { } // Filter implements neorpc.Comparator interface. -func (r *naiveReceiver) Filter() interface{} { +func (r *naiveReceiver) Filter() any { return r.filter } // Receiver implements notificationReceiver interface. -func (r *naiveReceiver) Receiver() interface{} { +func (r *naiveReceiver) Receiver() any { return r.ch } @@ -335,7 +335,7 @@ func (r *naiveReceiver) Close() { // *transaction.Transaction or *subscriptions.NotaryRequestEvent based on Type. type Notification struct { Type neorpc.EventID - Value interface{} + Value any } // EventID implements Container interface and returns notification ID. @@ -345,7 +345,7 @@ func (n Notification) EventID() neorpc.EventID { // EventPayload implements Container interface and returns notification // object. -func (n Notification) EventPayload() interface{} { +func (n Notification) EventPayload() any { return n.Value } @@ -410,7 +410,7 @@ func NewWS(ctx context.Context, endpoint string, opts Options) (*WSClient, error respChannels: make(map[uint64]chan *neorpc.Response), requests: make(chan *neorpc.Request), subscriptions: make(map[string]notificationReceiver), - receivers: make(map[interface{}][]string), + receivers: make(map[any][]string), } err = initClient(ctx, &wsc.Client, endpoint, opts) @@ -644,7 +644,7 @@ func (c *WSClient) makeWsRequest(r *neorpc.Request) (*neorpc.Response, error) { } } -func (c *WSClient) performSubscription(params []interface{}, rcvr notificationReceiver) (string, error) { +func (c *WSClient) performSubscription(params []any, rcvr notificationReceiver) (string, error) { var resp string if err := c.performRequest("subscribe", params, &resp); err != nil { @@ -666,12 +666,12 @@ func (c *WSClient) performSubscription(params []interface{}, rcvr notificationRe // // Deprecated: please, use ReceiveBlocks. This method will be removed in future versions. func (c *WSClient) SubscribeForNewBlocks(primary *int) (string, error) { - var flt interface{} + var flt any if primary != nil { var f = neorpc.BlockFilter{Primary: primary} flt = *f.Copy() } - params := []interface{}{"block_added"} + params := []any{"block_added"} if flt != nil { params = append(params, flt) } @@ -690,7 +690,7 @@ func (c *WSClient) ReceiveBlocks(flt *neorpc.BlockFilter, rcvr chan<- *block.Blo if rcvr == nil { return "", ErrNilNotificationReceiver } - params := []interface{}{"block_added"} + params := []any{"block_added"} if flt != nil { flt = flt.Copy() params = append(params, *flt) @@ -708,12 +708,12 @@ func (c *WSClient) ReceiveBlocks(flt *neorpc.BlockFilter, rcvr chan<- *block.Blo // // Deprecated: please, use ReceiveTransactions. This method will be removed in future versions. func (c *WSClient) SubscribeForNewTransactions(sender *util.Uint160, signer *util.Uint160) (string, error) { - var flt interface{} + var flt any if sender != nil || signer != nil { var f = neorpc.TxFilter{Sender: sender, Signer: signer} flt = *f.Copy() } - params := []interface{}{"transaction_added"} + params := []any{"transaction_added"} if flt != nil { params = append(params, flt) } @@ -732,7 +732,7 @@ func (c *WSClient) ReceiveTransactions(flt *neorpc.TxFilter, rcvr chan<- *transa if rcvr == nil { return "", ErrNilNotificationReceiver } - params := []interface{}{"transaction_added"} + params := []any{"transaction_added"} if flt != nil { flt = flt.Copy() params = append(params, *flt) @@ -751,12 +751,12 @@ func (c *WSClient) ReceiveTransactions(flt *neorpc.TxFilter, rcvr chan<- *transa // // Deprecated: please, use ReceiveExecutionNotifications. This method will be removed in future versions. func (c *WSClient) SubscribeForExecutionNotifications(contract *util.Uint160, name *string) (string, error) { - var flt interface{} + var flt any if contract != nil || name != nil { var f = neorpc.NotificationFilter{Contract: contract, Name: name} flt = *f.Copy() } - params := []interface{}{"notification_from_execution"} + params := []any{"notification_from_execution"} if flt != nil { params = append(params, flt) } @@ -775,7 +775,7 @@ func (c *WSClient) ReceiveExecutionNotifications(flt *neorpc.NotificationFilter, if rcvr == nil { return "", ErrNilNotificationReceiver } - params := []interface{}{"notification_from_execution"} + params := []any{"notification_from_execution"} if flt != nil { flt = flt.Copy() params = append(params, *flt) @@ -794,7 +794,7 @@ func (c *WSClient) ReceiveExecutionNotifications(flt *neorpc.NotificationFilter, // // Deprecated: please, use ReceiveExecutions. This method will be removed in future versions. func (c *WSClient) SubscribeForTransactionExecutions(state *string) (string, error) { - var flt interface{} + var flt any if state != nil { if *state != "HALT" && *state != "FAULT" { return "", errors.New("bad state parameter") @@ -802,7 +802,7 @@ func (c *WSClient) SubscribeForTransactionExecutions(state *string) (string, err var f = neorpc.ExecutionFilter{State: state} flt = *f.Copy() } - params := []interface{}{"transaction_executed"} + params := []any{"transaction_executed"} if flt != nil { params = append(params, flt) } @@ -822,7 +822,7 @@ func (c *WSClient) ReceiveExecutions(flt *neorpc.ExecutionFilter, rcvr chan<- *s if rcvr == nil { return "", ErrNilNotificationReceiver } - params := []interface{}{"transaction_executed"} + params := []any{"transaction_executed"} if flt != nil { if flt.State != nil { if *flt.State != "HALT" && *flt.State != "FAULT" { @@ -846,12 +846,12 @@ func (c *WSClient) ReceiveExecutions(flt *neorpc.ExecutionFilter, rcvr chan<- *s // // Deprecated: please, use ReceiveNotaryRequests. This method will be removed in future versions. func (c *WSClient) SubscribeForNotaryRequests(sender *util.Uint160, mainSigner *util.Uint160) (string, error) { - var flt interface{} + var flt any if sender != nil || mainSigner != nil { var f = neorpc.TxFilter{Sender: sender, Signer: mainSigner} flt = *f.Copy() } - params := []interface{}{"notary_request_event"} + params := []any{"notary_request_event"} if flt != nil { params = append(params, flt) } @@ -872,7 +872,7 @@ func (c *WSClient) ReceiveNotaryRequests(flt *neorpc.TxFilter, rcvr chan<- *resu if rcvr == nil { return "", ErrNilNotificationReceiver } - params := []interface{}{"notary_request_event"} + params := []any{"notary_request_event"} if flt != nil { flt = flt.Copy() params = append(params, *flt) @@ -918,10 +918,10 @@ func (c *WSClient) UnsubscribeAll() error { err := c.performUnsubscription(id) if err != nil { errFmt := "failed to unsubscribe from feed %d: %v" - errArgs := []interface{}{err} + errArgs := []any{err} if resErr != nil { errFmt = "%w; " + errFmt - errArgs = append([]interface{}{resErr}, errArgs...) + errArgs = append([]any{resErr}, errArgs...) } resErr = fmt.Errorf(errFmt, errArgs...) } @@ -935,7 +935,7 @@ func (c *WSClient) UnsubscribeAll() error { // may still receive WS notifications. func (c *WSClient) performUnsubscription(id string) error { var resp bool - if err := c.performRequest("unsubscribe", []interface{}{id}, &resp); err != nil { + if err := c.performRequest("unsubscribe", []any{id}, &resp); err != nil { return err } if !resp { diff --git a/pkg/services/helpers/rpcbroadcaster/broadcaster.go b/pkg/services/helpers/rpcbroadcaster/broadcaster.go index 2738f3b47..33464f0fd 100644 --- a/pkg/services/helpers/rpcbroadcaster/broadcaster.go +++ b/pkg/services/helpers/rpcbroadcaster/broadcaster.go @@ -10,7 +10,7 @@ import ( type RPCBroadcaster struct { Clients map[string]*RPCClient Log *zap.Logger - Responses chan []interface{} + Responses chan []any close chan struct{} finished chan struct{} @@ -24,7 +24,7 @@ func NewRPCBroadcaster(log *zap.Logger, sendTimeout time.Duration) *RPCBroadcast Log: log, close: make(chan struct{}), finished: make(chan struct{}), - Responses: make(chan []interface{}), + Responses: make(chan []any), sendTimeout: sendTimeout, } } @@ -65,7 +65,7 @@ drain: } // SendParams sends a request using all clients if the broadcaster is active. -func (r *RPCBroadcaster) SendParams(params []interface{}) { +func (r *RPCBroadcaster) SendParams(params []any) { select { case <-r.close: case r.Responses <- params: diff --git a/pkg/services/helpers/rpcbroadcaster/client.go b/pkg/services/helpers/rpcbroadcaster/client.go index 43c4e97c2..841336d43 100644 --- a/pkg/services/helpers/rpcbroadcaster/client.go +++ b/pkg/services/helpers/rpcbroadcaster/client.go @@ -14,17 +14,17 @@ type RPCClient struct { addr string close chan struct{} finished chan struct{} - responses chan []interface{} + responses chan []any log *zap.Logger sendTimeout time.Duration method SendMethod } // SendMethod represents an rpc method for sending data to other nodes. -type SendMethod func(*rpcclient.Client, []interface{}) error +type SendMethod func(*rpcclient.Client, []any) error // NewRPCClient returns a new rpc client for the provided address and method. -func (r *RPCBroadcaster) NewRPCClient(addr string, method SendMethod, timeout time.Duration, ch chan []interface{}) *RPCClient { +func (r *RPCBroadcaster) NewRPCClient(addr string, method SendMethod, timeout time.Duration, ch chan []any) *RPCClient { return &RPCClient{ addr: addr, close: r.close, diff --git a/pkg/services/notary/core_test.go b/pkg/services/notary/core_test.go index c383c39be..657a2bc90 100644 --- a/pkg/services/notary/core_test.go +++ b/pkg/services/notary/core_test.go @@ -154,7 +154,7 @@ func TestNotary(t *testing.T) { mp1.StopSubscriptions() }) - notaryNodes := []interface{}{acc1.PublicKey().Bytes(), acc2.PrivateKey().PublicKey().Bytes()} + notaryNodes := []any{acc1.PublicKey().Bytes(), acc2.PrivateKey().PublicKey().Bytes()} designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(noderoles.P2PNotary), notaryNodes) @@ -721,9 +721,9 @@ func TestNotary(t *testing.T) { requester1, _ := wallet.NewAccount() requester2, _ := wallet.NewAccount() amount := int64(100_0000_0000) - gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []interface{}{requester1.ScriptHash(), int64(bc.BlockHeight() + 50)}) + gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []any{requester1.ScriptHash(), int64(bc.BlockHeight() + 50)}) e.CheckGASBalance(t, notaryHash, big.NewInt(amount)) - gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []interface{}{requester2.ScriptHash(), int64(bc.BlockHeight() + 50)}) + gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []any{requester2.ScriptHash(), int64(bc.BlockHeight() + 50)}) e.CheckGASBalance(t, notaryHash, big.NewInt(2*amount)) // create request for 2 standard signatures => main tx should be completed after the second request is added to the pool diff --git a/pkg/services/oracle/broadcaster/oracle.go b/pkg/services/oracle/broadcaster/oracle.go index 0655580b6..b5e5cd2aa 100644 --- a/pkg/services/oracle/broadcaster/oracle.go +++ b/pkg/services/oracle/broadcaster/oracle.go @@ -34,7 +34,7 @@ func New(cfg config.OracleConfiguration, log *zap.Logger) *OracleBroadcaster { } for i := range cfg.Nodes { r.Clients[cfg.Nodes[i]] = r.NewRPCClient(cfg.Nodes[i], (*rpcclient.Client).SubmitRawOracleResponse, - cfg.ResponseTimeout, make(chan []interface{}, defaultChanCapacity)) + cfg.ResponseTimeout, make(chan []any, defaultChanCapacity)) } return r } @@ -44,7 +44,7 @@ func (r *OracleBroadcaster) SendResponse(priv *keys.PrivateKey, resp *transactio pub := priv.PublicKey() data := GetMessage(pub.Bytes(), resp.ID, txSig) msgSig := priv.Sign(data) - params := []interface{}{ + params := []any{ base64.StdEncoding.EncodeToString(pub.Bytes()), resp.ID, base64.StdEncoding.EncodeToString(txSig), diff --git a/pkg/services/oracle/filter.go b/pkg/services/oracle/filter.go index 5c13030a8..2c92f3d0d 100644 --- a/pkg/services/oracle/filter.go +++ b/pkg/services/oracle/filter.go @@ -19,7 +19,7 @@ func filter(value []byte, path string) ([]byte, error) { d := json.NewDecoder(buf) d.UseOrderedObject() - var v interface{} + var v any if err := d.Decode(&v); err != nil { return nil, err } diff --git a/pkg/services/oracle/jsonpath/jsonpath.go b/pkg/services/oracle/jsonpath/jsonpath.go index 18b1294ac..7ccf41bf7 100644 --- a/pkg/services/oracle/jsonpath/jsonpath.go +++ b/pkg/services/oracle/jsonpath/jsonpath.go @@ -40,9 +40,9 @@ const ( // Get returns substructures of value selected by path. // The result is always non-nil unless the path is invalid. -func Get(path string, value interface{}) ([]interface{}, bool) { +func Get(path string, value any) ([]any, bool) { if path == "" { - return []interface{}{value}, true + return []any{value}, true } p := pathParser{ @@ -55,7 +55,7 @@ func Get(path string, value interface{}) ([]interface{}, bool) { return nil, false } - objs := []interface{}{value} + objs := []any{value} for p.i < len(p.s) { var ok bool @@ -72,7 +72,7 @@ func Get(path string, value interface{}) ([]interface{}, bool) { } if objs == nil { - objs = []interface{}{} + objs = []any{} } return objs, true } @@ -173,7 +173,7 @@ func (p *pathParser) parseNumber() (string, int, bool) { // processDot handles `.` operator. // It either descends 1 level down or performs recursive descent. -func (p *pathParser) processDot(objs []interface{}) ([]interface{}, bool) { +func (p *pathParser) processDot(objs []any) ([]any, bool) { typ, value := p.nextToken() switch typ { case pathAsterisk: @@ -189,16 +189,16 @@ func (p *pathParser) processDot(objs []interface{}) ([]interface{}, bool) { // descend descends 1 level down. // It flattens arrays and returns map values for maps. -func (p *pathParser) descend(objs []interface{}) ([]interface{}, bool) { +func (p *pathParser) descend(objs []any) ([]any, bool) { if p.depth <= 0 { return nil, false } p.depth-- - var values []interface{} + var values []any for i := range objs { switch obj := objs[i].(type) { - case []interface{}: + case []any: if maxObjects < len(values)+len(obj) { return nil, false } @@ -217,13 +217,13 @@ func (p *pathParser) descend(objs []interface{}) ([]interface{}, bool) { } // descendRecursive performs recursive descent. -func (p *pathParser) descendRecursive(objs []interface{}) ([]interface{}, bool) { +func (p *pathParser) descendRecursive(objs []any) ([]any, bool) { typ, val := p.nextToken() if typ != pathIdentifier { return nil, false } - var values []interface{} + var values []any for len(objs) > 0 { newObjs, _ := p.descendByIdentAux(objs, false, val) @@ -238,11 +238,11 @@ func (p *pathParser) descendRecursive(objs []interface{}) ([]interface{}, bool) } // descendByIdent performs map's field access by name. -func (p *pathParser) descendByIdent(objs []interface{}, names ...string) ([]interface{}, bool) { +func (p *pathParser) descendByIdent(objs []any, names ...string) ([]any, bool) { return p.descendByIdentAux(objs, true, names...) } -func (p *pathParser) descendByIdentAux(objs []interface{}, checkDepth bool, names ...string) ([]interface{}, bool) { +func (p *pathParser) descendByIdentAux(objs []any, checkDepth bool, names ...string) ([]any, bool) { if checkDepth { if p.depth <= 0 { return nil, false @@ -250,7 +250,7 @@ func (p *pathParser) descendByIdentAux(objs []interface{}, checkDepth bool, name p.depth-- } - var values []interface{} + var values []any for i := range objs { obj, ok := objs[i].(json.OrderedObject) if !ok { @@ -273,15 +273,15 @@ func (p *pathParser) descendByIdentAux(objs []interface{}, checkDepth bool, name } // descendByIndex performs array access by index. -func (p *pathParser) descendByIndex(objs []interface{}, indices ...int) ([]interface{}, bool) { +func (p *pathParser) descendByIndex(objs []any, indices ...int) ([]any, bool) { if p.depth <= 0 { return nil, false } p.depth-- - var values []interface{} + var values []any for i := range objs { - obj, ok := objs[i].([]interface{}) + obj, ok := objs[i].([]any) if !ok { continue } @@ -304,7 +304,7 @@ func (p *pathParser) descendByIndex(objs []interface{}, indices ...int) ([]inter // processLeftBracket processes index expressions which can be either // array/map access, array sub-slice or union of indices. -func (p *pathParser) processLeftBracket(objs []interface{}) ([]interface{}, bool) { +func (p *pathParser) processLeftBracket(objs []any) ([]any, bool) { typ, value := p.nextToken() switch typ { case pathAsterisk: @@ -360,7 +360,7 @@ func (p *pathParser) processLeftBracket(objs []interface{}) ([]interface{}, bool // processUnion processes union of multiple indices. // firstTyp is assumed to be either pathNumber or pathString. -func (p *pathParser) processUnion(objs []interface{}, firstTyp pathTokenType, firstVal string) ([]interface{}, bool) { +func (p *pathParser) processUnion(objs []any, firstTyp pathTokenType, firstVal string) ([]any, bool) { items := []string{firstVal} for { typ, val := p.nextToken() @@ -403,7 +403,7 @@ func (p *pathParser) processUnion(objs []interface{}, firstTyp pathTokenType, fi } // processSlice processes a slice with the specified start index. -func (p *pathParser) processSlice(objs []interface{}, start int) ([]interface{}, bool) { +func (p *pathParser) processSlice(objs []any, start int) ([]any, bool) { typ, val := p.nextToken() switch typ { case pathNumber: @@ -426,15 +426,15 @@ func (p *pathParser) processSlice(objs []interface{}, start int) ([]interface{}, } // descendByRange is similar to descend but skips maps and returns sub-slices for arrays. -func (p *pathParser) descendByRange(objs []interface{}, start, end int) ([]interface{}, bool) { +func (p *pathParser) descendByRange(objs []any, start, end int) ([]any, bool) { if p.depth <= 0 { return nil, false } p.depth-- - var values []interface{} + var values []any for i := range objs { - arr, ok := objs[i].([]interface{}) + arr, ok := objs[i].([]any) if !ok { continue } diff --git a/pkg/services/oracle/jsonpath/jsonpath_test.go b/pkg/services/oracle/jsonpath/jsonpath_test.go index eaeacbe2d..e537fb1db 100644 --- a/pkg/services/oracle/jsonpath/jsonpath_test.go +++ b/pkg/services/oracle/jsonpath/jsonpath_test.go @@ -16,8 +16,8 @@ type pathTestCase struct { result string } -func unmarshalGet(t *testing.T, js string, path string) ([]interface{}, bool) { - var v interface{} +func unmarshalGet(t *testing.T, js string, path string) ([]any, bool) { + var v any buf := bytes.NewBuffer([]byte(js)) d := json.NewDecoder(buf) d.UseOrderedObject() diff --git a/pkg/services/oracle/oracle_test.go b/pkg/services/oracle/oracle_test.go index 9cc43bcee..acc0f6509 100644 --- a/pkg/services/oracle/oracle_test.go +++ b/pkg/services/oracle/oracle_test.go @@ -41,7 +41,7 @@ var pathToInternalContracts = filepath.Join("..", "..", "..", "internal", "contr func putOracleRequest(t *testing.T, oracleValidatorInvoker *neotest.ContractInvoker, url string, filter *string, cb string, userData []byte, gas int64) util.Uint256 { - var filtItem interface{} + var filtItem any if filter != nil { filtItem = *filter } @@ -153,7 +153,7 @@ func TestOracle(t *testing.T) { oracleNodes := keys.PublicKeys{acc1.PublicKey(), acc2.PrivateKey().PublicKey()} // Must be set in native contract for tx verification. designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", - int64(roles.Oracle), []interface{}{oracleNodes[0].Bytes(), oracleNodes[1].Bytes()}) + int64(roles.Oracle), []any{oracleNodes[0].Bytes(), oracleNodes[1].Bytes()}) orc1.UpdateOracleNodes(oracleNodes.Copy()) orc2.UpdateOracleNodes(oracleNodes.Copy()) @@ -357,7 +357,7 @@ func TestOracleFull(t *testing.T) { }) designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", - int64(roles.Oracle), []interface{}{acc.PublicKey().Bytes()}) + int64(roles.Oracle), []any{acc.PublicKey().Bytes()}) cs := contracts.GetOracleContractState(t, pathToInternalContracts, validator.ScriptHash(), 0) e.DeployContract(t, &neotest.Contract{ @@ -391,7 +391,7 @@ func TestNotYetRunningOracle(t *testing.T) { t.Cleanup(bc.Close) designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", - int64(roles.Oracle), []interface{}{acc.PublicKey().Bytes()}) + int64(roles.Oracle), []any{acc.PublicKey().Bytes()}) var req state.OracleRequest var reqs = make(map[uint64]*state.OracleRequest) diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 86d8c7346..de0606f8d 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -2298,7 +2298,7 @@ func testSubClientWaitWithMissedEvent(t *testing.T, local bool) { overNotification := neorpc.Notification{ JSONRPC: neorpc.JSONRPCVersion, Event: neorpc.MissedEventID, - Payload: make([]interface{}, 0), + Payload: make([]any, 0), } overEvent, err := json.Marshal(overNotification) require.NoError(t, err) diff --git a/pkg/services/rpcsrv/error.go b/pkg/services/rpcsrv/error.go index 819b40b8a..89fb64538 100644 --- a/pkg/services/rpcsrv/error.go +++ b/pkg/services/rpcsrv/error.go @@ -17,7 +17,7 @@ type abstractResult interface { type abstract struct { neorpc.Header Error *neorpc.Error `json:"error,omitempty"` - Result interface{} `json:"result,omitempty"` + Result any `json:"result,omitempty"` } // RunForErrors implements abstractResult interface. diff --git a/pkg/services/rpcsrv/params/param.go b/pkg/services/rpcsrv/params/param.go index db392d58d..e0a56db3f 100644 --- a/pkg/services/rpcsrv/params/param.go +++ b/pkg/services/rpcsrv/params/param.go @@ -25,7 +25,7 @@ type ( // the client. Param struct { json.RawMessage - cache interface{} + cache any } // FuncParam represents a function argument parameter used in the @@ -193,7 +193,7 @@ func (p *Param) GetIntStrict() (int, error) { return 0, errNotAnInt } -func (p *Param) fillIntCache() (interface{}, error) { +func (p *Param) fillIntCache() (any, error) { if p.cache != nil { return p.cache, nil } diff --git a/pkg/services/rpcsrv/params/params.go b/pkg/services/rpcsrv/params/params.go index 23e5fe189..805625856 100644 --- a/pkg/services/rpcsrv/params/params.go +++ b/pkg/services/rpcsrv/params/params.go @@ -12,7 +12,7 @@ type ( // FromAny allows to create Params for a slice of abstract values (by // JSON-marshaling them). -func FromAny(arr []interface{}) (Params, error) { +func FromAny(arr []any) (Params, error) { var res Params for i := range arr { b, err := json.Marshal(arr[i]) diff --git a/pkg/services/rpcsrv/params/params_test.go b/pkg/services/rpcsrv/params/params_test.go index 8fd066951..415203182 100644 --- a/pkg/services/rpcsrv/params/params_test.go +++ b/pkg/services/rpcsrv/params/params_test.go @@ -10,7 +10,7 @@ import ( func TestParamsFromAny(t *testing.T) { str := "jajaja" - ps, err := FromAny([]interface{}{str, smartcontract.Parameter{Type: smartcontract.StringType, Value: str}}) + ps, err := FromAny([]any{str, smartcontract.Parameter{Type: smartcontract.StringType, Value: str}}) require.NoError(t, err) require.Equal(t, 2, len(ps)) @@ -26,6 +26,6 @@ func TestParamsFromAny(t *testing.T) { require.Equal(t, resStr, str) // Invalid item. - _, err = FromAny([]interface{}{smartcontract.Parameter{Type: smartcontract.IntegerType, Value: str}}) + _, err = FromAny([]any{smartcontract.Parameter{Type: smartcontract.IntegerType, Value: str}}) require.Error(t, err) } diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index 6531ccaf8..88fb38942 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -195,7 +195,7 @@ const ( defaultSessionPoolSize = 20 ) -var rpcHandlers = map[string]func(*Server, params.Params) (interface{}, *neorpc.Error){ +var rpcHandlers = map[string]func(*Server, params.Params) (any, *neorpc.Error){ "calculatenetworkfee": (*Server).calculateNetworkFee, "findstates": (*Server).findStates, "getapplicationlog": (*Server).getApplicationLog, @@ -244,7 +244,7 @@ var rpcHandlers = map[string]func(*Server, params.Params) (interface{}, *neorpc. "verifyproof": (*Server).verifyProof, } -var rpcWsHandlers = map[string]func(*Server, params.Params, *subscriber) (interface{}, *neorpc.Error){ +var rpcWsHandlers = map[string]func(*Server, params.Params, *subscriber) (any, *neorpc.Error){ "subscribe": (*Server).subscribe, "unsubscribe": (*Server).unsubscribe, } @@ -534,7 +534,7 @@ func (s *Server) handleRequest(req *params.Request, sub *subscriber) abstractRes // handleInternal is an experimental interface to handle client requests directly. func (s *Server) handleInternal(req *neorpc.Request, sub *subscriber) (*neorpc.Response, error) { var ( - res interface{} + res any rpcRes = &neorpc.Response{ HeaderAndError: neorpc.HeaderAndError{ Header: neorpc.Header{ @@ -577,7 +577,7 @@ func (s *Server) handleInternal(req *neorpc.Request, sub *subscriber) (*neorpc.R } func (s *Server) handleIn(req *params.In, sub *subscriber) abstract { - var res interface{} + var res any var resErr *neorpc.Error if req.JSONRPC != neorpc.JSONRPCVersion { return s.packResponse(req, nil, neorpc.NewInvalidParamsError(fmt.Sprintf("problem parsing JSON: invalid version, expected 2.0 got '%s'", req.JSONRPC))) @@ -721,19 +721,19 @@ func (s *Server) dropSubscriber(subscr *subscriber) { s.subsCounterLock.Unlock() } -func (s *Server) getBestBlockHash(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBestBlockHash(_ params.Params) (any, *neorpc.Error) { return "0x" + s.chain.CurrentBlockHash().StringLE(), nil } -func (s *Server) getBlockCount(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBlockCount(_ params.Params) (any, *neorpc.Error) { return s.chain.BlockHeight() + 1, nil } -func (s *Server) getBlockHeaderCount(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBlockHeaderCount(_ params.Params) (any, *neorpc.Error) { return s.chain.HeaderHeight() + 1, nil } -func (s *Server) getConnectionCount(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getConnectionCount(_ params.Params) (any, *neorpc.Error) { return s.coreServer.PeerCount(), nil } @@ -769,7 +769,7 @@ func (s *Server) fillBlockMetadata(obj io.Serializable, h *block.Header) result. return res } -func (s *Server) getBlock(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBlock(reqParams params.Params) (any, *neorpc.Error) { param := reqParams.Value(0) hash, respErr := s.blockHashFromParam(param) if respErr != nil { @@ -793,7 +793,7 @@ func (s *Server) getBlock(reqParams params.Params) (interface{}, *neorpc.Error) return writer.Bytes(), nil } -func (s *Server) getBlockHash(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBlockHash(reqParams params.Params) (any, *neorpc.Error) { num, err := s.blockHeightFromParam(reqParams.Value(0)) if err != nil { return nil, neorpc.ErrInvalidParams @@ -802,7 +802,7 @@ func (s *Server) getBlockHash(reqParams params.Params) (interface{}, *neorpc.Err return s.chain.GetHeaderHash(num), nil } -func (s *Server) getVersion(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getVersion(_ params.Params) (any, *neorpc.Error) { port, err := s.coreServer.Port(nil) // any port will suite if err != nil { return nil, neorpc.NewInternalServerError(fmt.Sprintf("cannot fetch tcp port: %s", err)) @@ -832,7 +832,7 @@ func (s *Server) getVersion(_ params.Params) (interface{}, *neorpc.Error) { }, nil } -func (s *Server) getPeers(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getPeers(_ params.Params) (any, *neorpc.Error) { peers := result.NewGetPeers() peers.AddUnconnected(s.coreServer.UnconnectedPeers()) peers.AddConnected(s.coreServer.ConnectedPeers()) @@ -840,7 +840,7 @@ func (s *Server) getPeers(_ params.Params) (interface{}, *neorpc.Error) { return peers, nil } -func (s *Server) getRawMempool(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getRawMempool(reqParams params.Params) (any, *neorpc.Error) { verbose, _ := reqParams.Value(0).GetBoolean() mp := s.chain.GetMemPool() hashList := make([]util.Uint256, 0) @@ -857,7 +857,7 @@ func (s *Server) getRawMempool(reqParams params.Params) (interface{}, *neorpc.Er }, nil } -func (s *Server) validateAddress(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) validateAddress(reqParams params.Params) (any, *neorpc.Error) { param, err := reqParams.Value(0).GetString() if err != nil { return nil, neorpc.ErrInvalidParams @@ -870,7 +870,7 @@ func (s *Server) validateAddress(reqParams params.Params) (interface{}, *neorpc. } // calculateNetworkFee calculates network fee for the transaction. -func (s *Server) calculateNetworkFee(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) calculateNetworkFee(reqParams params.Params) (any, *neorpc.Error) { if len(reqParams) < 1 { return 0, neorpc.ErrInvalidParams } @@ -938,7 +938,7 @@ func (s *Server) calculateNetworkFee(reqParams params.Params) (interface{}, *neo } // getApplicationLog returns the contract log based on the specified txid or blockid. -func (s *Server) getApplicationLog(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getApplicationLog(reqParams params.Params) (any, *neorpc.Error) { hash, err := reqParams.Value(0).GetUint256() if err != nil { return nil, neorpc.ErrInvalidParams @@ -964,7 +964,7 @@ func (s *Server) getApplicationLog(reqParams params.Params) (interface{}, *neorp } func (s *Server) getNEP11Tokens(h util.Uint160, acc util.Uint160, bw *io.BufBinWriter) ([]stackitem.Item, string, int, error) { - items, finalize, err := s.invokeReadOnlyMulti(bw, h, []string{"tokensOf", "symbol", "decimals"}, [][]interface{}{{acc}, nil, nil}) + items, finalize, err := s.invokeReadOnlyMulti(bw, h, []string{"tokensOf", "symbol", "decimals"}, [][]any{{acc}, nil, nil}) if err != nil { return nil, "", 0, err } @@ -987,7 +987,7 @@ func (s *Server) getNEP11Tokens(h util.Uint160, acc util.Uint160, bw *io.BufBinW return vals, sym, int(dec.Int64()), nil } -func (s *Server) getNEP11Balances(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNEP11Balances(ps params.Params) (any, *neorpc.Error) { u, err := ps.Value(0).GetUint160FromAddressOrHex() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1076,7 +1076,7 @@ func (s *Server) invokeNEP11Properties(h util.Uint160, id []byte, bw *io.BufBinW return item.Value().([]stackitem.MapElement), nil } -func (s *Server) getNEP11Properties(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNEP11Properties(ps params.Params) (any, *neorpc.Error) { asset, err := ps.Value(0).GetUint160FromAddressOrHex() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1089,13 +1089,13 @@ func (s *Server) getNEP11Properties(ps params.Params) (interface{}, *neorpc.Erro if err != nil { return nil, neorpc.NewRPCError("Failed to get NEP-11 properties", err.Error()) } - res := make(map[string]interface{}) + res := make(map[string]any) for _, kv := range props { key, err := kv.Key.TryBytes() if err != nil { continue } - var val interface{} + var val any if result.KnownNEP11Properties[string(key)] || kv.Value.Type() != stackitem.AnyT { v, err := kv.Value.TryBytes() if err != nil { @@ -1112,7 +1112,7 @@ func (s *Server) getNEP11Properties(ps params.Params) (interface{}, *neorpc.Erro return res, nil } -func (s *Server) getNEP17Balances(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNEP17Balances(ps params.Params) (any, *neorpc.Error) { u, err := ps.Value(0).GetUint160FromAddressOrHex() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1160,15 +1160,15 @@ func (s *Server) getNEP17Balances(ps params.Params) (interface{}, *neorpc.Error) return bs, nil } -func (s *Server) invokeReadOnly(bw *io.BufBinWriter, h util.Uint160, method string, params ...interface{}) (stackitem.Item, func(), error) { - r, f, err := s.invokeReadOnlyMulti(bw, h, []string{method}, [][]interface{}{params}) +func (s *Server) invokeReadOnly(bw *io.BufBinWriter, h util.Uint160, method string, params ...any) (stackitem.Item, func(), error) { + r, f, err := s.invokeReadOnlyMulti(bw, h, []string{method}, [][]any{params}) if err != nil { return nil, nil, err } return r[0], f, nil } -func (s *Server) invokeReadOnlyMulti(bw *io.BufBinWriter, h util.Uint160, methods []string, params [][]interface{}) ([]stackitem.Item, func(), error) { +func (s *Server) invokeReadOnlyMulti(bw *io.BufBinWriter, h util.Uint160, methods []string, params [][]any) ([]stackitem.Item, func(), error) { if bw == nil { bw = io.NewBufBinWriter() } else { @@ -1205,7 +1205,7 @@ func (s *Server) invokeReadOnlyMulti(bw *io.BufBinWriter, h util.Uint160, method } func (s *Server) getNEP17TokenBalance(h util.Uint160, acc util.Uint160, bw *io.BufBinWriter) (*big.Int, string, int, error) { - items, finalize, err := s.invokeReadOnlyMulti(bw, h, []string{"balanceOf", "symbol", "decimals"}, [][]interface{}{{acc}, nil, nil}) + items, finalize, err := s.invokeReadOnlyMulti(bw, h, []string{"balanceOf", "symbol", "decimals"}, [][]any{{acc}, nil, nil}) if err != nil { return nil, "", 0, err } @@ -1291,15 +1291,15 @@ func getTimestampsAndLimit(ps params.Params, index int) (uint64, uint64, int, in return start, end, limit, page, nil } -func (s *Server) getNEP11Transfers(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNEP11Transfers(ps params.Params) (any, *neorpc.Error) { return s.getTokenTransfers(ps, true) } -func (s *Server) getNEP17Transfers(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNEP17Transfers(ps params.Params) (any, *neorpc.Error) { return s.getTokenTransfers(ps, false) } -func (s *Server) getTokenTransfers(ps params.Params, isNEP11 bool) (interface{}, *neorpc.Error) { +func (s *Server) getTokenTransfers(ps params.Params, isNEP11 bool) (any, *neorpc.Error) { u, err := ps.Value(0).GetUint160FromAddressOrHex() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1312,8 +1312,8 @@ func (s *Server) getTokenTransfers(ps params.Params, isNEP11 bool) (interface{}, bs := &tokenTransfers{ Address: address.Uint160ToString(u), - Received: []interface{}{}, - Sent: []interface{}{}, + Received: []any{}, + Sent: []any{}, } cache := make(map[int32]util.Uint160) var resCount, frameCount int @@ -1478,7 +1478,7 @@ func makeStorageKey(id int32, key []byte) []byte { var errKeepOnlyLatestState = errors.New("'KeepOnlyLatestState' setting is enabled") -func (s *Server) getProof(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getProof(ps params.Params) (any, *neorpc.Error) { if s.chain.GetConfig().Ledger.KeepOnlyLatestState { return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'getproof' is not supported: %s", errKeepOnlyLatestState)) } @@ -1509,7 +1509,7 @@ func (s *Server) getProof(ps params.Params) (interface{}, *neorpc.Error) { }, nil } -func (s *Server) verifyProof(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) verifyProof(ps params.Params) (any, *neorpc.Error) { if s.chain.GetConfig().Ledger.KeepOnlyLatestState { return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'verifyproof' is not supported: %s", errKeepOnlyLatestState)) } @@ -1533,7 +1533,7 @@ func (s *Server) verifyProof(ps params.Params) (interface{}, *neorpc.Error) { return vp, nil } -func (s *Server) getState(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getState(ps params.Params) (any, *neorpc.Error) { root, err := ps.Value(0).GetUint256() if err != nil { return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot") @@ -1567,7 +1567,7 @@ func (s *Server) getState(ps params.Params) (interface{}, *neorpc.Error) { return res, nil } -func (s *Server) findStates(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) findStates(ps params.Params) (any, *neorpc.Error) { root, err := ps.Value(0).GetUint256() if err != nil { return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot") @@ -1675,7 +1675,7 @@ func (s *Server) getHistoricalContractState(root util.Uint256, csHash util.Uint1 return contract, nil } -func (s *Server) getStateHeight(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getStateHeight(_ params.Params) (any, *neorpc.Error) { var height = s.chain.BlockHeight() var stateHeight = s.chain.GetStateModule().CurrentValidatedHeight() if s.chain.GetConfig().StateRootInHeader { @@ -1687,7 +1687,7 @@ func (s *Server) getStateHeight(_ params.Params) (interface{}, *neorpc.Error) { }, nil } -func (s *Server) getStateRoot(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getStateRoot(ps params.Params) (any, *neorpc.Error) { p := ps.Value(0) if p == nil { return nil, neorpc.NewInvalidParamsError("missing stateroot identifier") @@ -1713,7 +1713,7 @@ func (s *Server) getStateRoot(ps params.Params) (interface{}, *neorpc.Error) { return rt, nil } -func (s *Server) getStorage(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getStorage(ps params.Params) (any, *neorpc.Error) { id, rErr := s.contractIDFromParam(ps.Value(0)) if rErr == neorpc.ErrUnknown { return nil, nil @@ -1735,7 +1735,7 @@ func (s *Server) getStorage(ps params.Params) (interface{}, *neorpc.Error) { return []byte(item), nil } -func (s *Server) getrawtransaction(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getrawtransaction(reqParams params.Params) (any, *neorpc.Error) { txHash, err := reqParams.Value(0).GetUint256() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1774,7 +1774,7 @@ func (s *Server) getrawtransaction(reqParams params.Params) (interface{}, *neorp return tx.Bytes(), nil } -func (s *Server) getTransactionHeight(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getTransactionHeight(ps params.Params) (any, *neorpc.Error) { h, err := ps.Value(0).GetUint256() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1790,7 +1790,7 @@ func (s *Server) getTransactionHeight(ps params.Params) (interface{}, *neorpc.Er // getContractState returns contract state (contract information, according to the contract script hash, // contract id or native contract name). -func (s *Server) getContractState(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getContractState(reqParams params.Params) (any, *neorpc.Error) { scriptHash, err := s.contractScriptHashFromParam(reqParams.Value(0)) if err != nil { return nil, err @@ -1802,12 +1802,12 @@ func (s *Server) getContractState(reqParams params.Params) (interface{}, *neorpc return cs, nil } -func (s *Server) getNativeContracts(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNativeContracts(_ params.Params) (any, *neorpc.Error) { return s.chain.GetNatives(), nil } // getBlockSysFee returns the system fees of the block, based on the specified index. -func (s *Server) getBlockSysFee(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBlockSysFee(reqParams params.Params) (any, *neorpc.Error) { num, err := s.blockHeightFromParam(reqParams.Value(0)) if err != nil { return 0, neorpc.NewRPCError("Invalid height", "invalid block identifier") @@ -1828,7 +1828,7 @@ func (s *Server) getBlockSysFee(reqParams params.Params) (interface{}, *neorpc.E } // getBlockHeader returns the corresponding block header information according to the specified script hash. -func (s *Server) getBlockHeader(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getBlockHeader(reqParams params.Params) (any, *neorpc.Error) { param := reqParams.Value(0) hash, respErr := s.blockHashFromParam(param) if respErr != nil { @@ -1858,7 +1858,7 @@ func (s *Server) getBlockHeader(reqParams params.Params) (interface{}, *neorpc.E } // getUnclaimedGas returns unclaimed GAS amount of the specified address. -func (s *Server) getUnclaimedGas(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getUnclaimedGas(ps params.Params) (any, *neorpc.Error) { u, err := ps.Value(0).GetUint160FromAddressOrHex() if err != nil { return nil, neorpc.ErrInvalidParams @@ -1881,7 +1881,7 @@ func (s *Server) getUnclaimedGas(ps params.Params) (interface{}, *neorpc.Error) } // getCandidates returns the current list of candidates with their active/inactive voting status. -func (s *Server) getCandidates(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getCandidates(_ params.Params) (any, *neorpc.Error) { var validators keys.PublicKeys validators, err := s.chain.GetNextBlockValidators() @@ -1904,7 +1904,7 @@ func (s *Server) getCandidates(_ params.Params) (interface{}, *neorpc.Error) { } // getNextBlockValidators returns validators for the next block with voting status. -func (s *Server) getNextBlockValidators(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getNextBlockValidators(_ params.Params) (any, *neorpc.Error) { var validators keys.PublicKeys validators, err := s.chain.GetNextBlockValidators() @@ -1929,7 +1929,7 @@ func (s *Server) getNextBlockValidators(_ params.Params) (interface{}, *neorpc.E } // getCommittee returns the current list of NEO committee members. -func (s *Server) getCommittee(_ params.Params) (interface{}, *neorpc.Error) { +func (s *Server) getCommittee(_ params.Params) (any, *neorpc.Error) { keys, err := s.chain.GetCommittee() if err != nil { return nil, neorpc.NewInternalServerError(fmt.Sprintf("can't get committee members: %s", err)) @@ -1938,7 +1938,7 @@ func (s *Server) getCommittee(_ params.Params) (interface{}, *neorpc.Error) { } // invokeFunction implements the `invokeFunction` RPC call. -func (s *Server) invokeFunction(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) invokeFunction(reqParams params.Params) (any, *neorpc.Error) { tx, verbose, respErr := s.getInvokeFunctionParams(reqParams) if respErr != nil { return nil, respErr @@ -1947,7 +1947,7 @@ func (s *Server) invokeFunction(reqParams params.Params) (interface{}, *neorpc.E } // invokeFunctionHistoric implements the `invokeFunctionHistoric` RPC call. -func (s *Server) invokeFunctionHistoric(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) invokeFunctionHistoric(reqParams params.Params) (any, *neorpc.Error) { nextH, respErr := s.getHistoricParams(reqParams) if respErr != nil { return nil, respErr @@ -2005,7 +2005,7 @@ func (s *Server) getInvokeFunctionParams(reqParams params.Params) (*transaction. } // invokescript implements the `invokescript` RPC call. -func (s *Server) invokescript(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) invokescript(reqParams params.Params) (any, *neorpc.Error) { tx, verbose, respErr := s.getInvokeScriptParams(reqParams) if respErr != nil { return nil, respErr @@ -2014,7 +2014,7 @@ func (s *Server) invokescript(reqParams params.Params) (interface{}, *neorpc.Err } // invokescripthistoric implements the `invokescripthistoric` RPC call. -func (s *Server) invokescripthistoric(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) invokescripthistoric(reqParams params.Params) (any, *neorpc.Error) { nextH, respErr := s.getHistoricParams(reqParams) if respErr != nil { return nil, respErr @@ -2059,7 +2059,7 @@ func (s *Server) getInvokeScriptParams(reqParams params.Params) (*transaction.Tr } // invokeContractVerify implements the `invokecontractverify` RPC call. -func (s *Server) invokeContractVerify(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) invokeContractVerify(reqParams params.Params) (any, *neorpc.Error) { scriptHash, tx, invocationScript, respErr := s.getInvokeContractVerifyParams(reqParams) if respErr != nil { return nil, respErr @@ -2068,7 +2068,7 @@ func (s *Server) invokeContractVerify(reqParams params.Params) (interface{}, *ne } // invokeContractVerifyHistoric implements the `invokecontractverifyhistoric` RPC call. -func (s *Server) invokeContractVerifyHistoric(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) invokeContractVerifyHistoric(reqParams params.Params) (any, *neorpc.Error) { nextH, respErr := s.getHistoricParams(reqParams) if respErr != nil { return nil, respErr @@ -2312,7 +2312,7 @@ func (s *Server) registerOrDumpIterator(item stackitem.Item) (stackitem.Item, uu return stackitem.NewInterop(resIterator), iterID } -func (s *Server) traverseIterator(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) traverseIterator(reqParams params.Params) (any, *neorpc.Error) { if !s.config.SessionEnabled { return nil, neorpc.NewInvalidRequestError("sessions are disabled") } @@ -2369,7 +2369,7 @@ func (s *Server) traverseIterator(reqParams params.Params) (interface{}, *neorpc return result, nil } -func (s *Server) terminateSession(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) terminateSession(reqParams params.Params) (any, *neorpc.Error) { if !s.config.SessionEnabled { return nil, neorpc.NewInvalidRequestError("sessions are disabled") } @@ -2396,7 +2396,7 @@ func (s *Server) terminateSession(reqParams params.Params) (interface{}, *neorpc } // submitBlock broadcasts a raw block over the Neo network. -func (s *Server) submitBlock(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) submitBlock(reqParams params.Params) (any, *neorpc.Error) { blockBytes, err := reqParams.Value(0).GetBytesBase64() if err != nil { return nil, neorpc.NewInvalidParamsError(fmt.Sprintf("missing parameter or not a base64: %s", err)) @@ -2422,7 +2422,7 @@ func (s *Server) submitBlock(reqParams params.Params) (interface{}, *neorpc.Erro } // submitNotaryRequest broadcasts P2PNotaryRequest over the Neo network. -func (s *Server) submitNotaryRequest(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) submitNotaryRequest(ps params.Params) (any, *neorpc.Error) { if !s.chain.P2PSigExtensionsEnabled() { return nil, neorpc.NewRPCError("P2PSignatureExtensions are disabled", "") } @@ -2439,7 +2439,7 @@ func (s *Server) submitNotaryRequest(ps params.Params) (interface{}, *neorpc.Err } // getRelayResult returns successful relay result or an error. -func getRelayResult(err error, hash util.Uint256) (interface{}, *neorpc.Error) { +func getRelayResult(err error, hash util.Uint256) (any, *neorpc.Error) { switch { case err == nil: return result.RelayResult{ @@ -2456,7 +2456,7 @@ func getRelayResult(err error, hash util.Uint256) (interface{}, *neorpc.Error) { } } -func (s *Server) submitOracleResponse(ps params.Params) (interface{}, *neorpc.Error) { +func (s *Server) submitOracleResponse(ps params.Params) (any, *neorpc.Error) { oracle := s.oracle.Load().(*OracleHandler) if oracle == nil || *oracle == nil { return nil, neorpc.NewRPCError("Oracle is not enabled", "") @@ -2489,7 +2489,7 @@ func (s *Server) submitOracleResponse(ps params.Params) (interface{}, *neorpc.Er return json.RawMessage([]byte("{}")), nil } -func (s *Server) sendrawtransaction(reqParams params.Params) (interface{}, *neorpc.Error) { +func (s *Server) sendrawtransaction(reqParams params.Params) (any, *neorpc.Error) { if len(reqParams) < 1 { return nil, neorpc.NewInvalidParamsError("not enough parameters") } @@ -2505,7 +2505,7 @@ func (s *Server) sendrawtransaction(reqParams params.Params) (interface{}, *neor } // subscribe handles subscription requests from websocket clients. -func (s *Server) subscribe(reqParams params.Params, sub *subscriber) (interface{}, *neorpc.Error) { +func (s *Server) subscribe(reqParams params.Params, sub *subscriber) (any, *neorpc.Error) { streamName, err := reqParams.Value(0).GetString() if err != nil { return nil, neorpc.ErrInvalidParams @@ -2518,7 +2518,7 @@ func (s *Server) subscribe(reqParams params.Params, sub *subscriber) (interface{ return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "P2PSigExtensions are disabled") } // Optional filter. - var filter interface{} + var filter any if p := reqParams.Value(1); p != nil { param := *p jd := json.NewDecoder(bytes.NewReader(param.RawMessage)) @@ -2611,7 +2611,7 @@ func (s *Server) subscribeToChannel(event neorpc.EventID) { } // unsubscribe handles unsubscription requests from websocket clients. -func (s *Server) unsubscribe(reqParams params.Params, sub *subscriber) (interface{}, *neorpc.Error) { +func (s *Server) unsubscribe(reqParams params.Params, sub *subscriber) (any, *neorpc.Error) { id, err := reqParams.Value(0).GetInt() if err != nil || id < 0 { return nil, neorpc.ErrInvalidParams @@ -2669,7 +2669,7 @@ func (s *Server) handleSubEvents() { var overflowEvent = neorpc.Notification{ JSONRPC: neorpc.JSONRPCVersion, Event: neorpc.MissedEventID, - Payload: make([]interface{}, 0), + Payload: make([]any, 0), } b, err := json.Marshal(overflowEvent) if err != nil { @@ -2685,7 +2685,7 @@ chloop: for { var resp = neorpc.Notification{ JSONRPC: neorpc.JSONRPCVersion, - Payload: make([]interface{}, 1), + Payload: make([]any, 1), } var msg *websocket.PreparedMessage select { @@ -2798,7 +2798,7 @@ func (s *Server) blockHeightFromParam(param *params.Param) (uint32, *neorpc.Erro return uint32(num), nil } -func (s *Server) packResponse(r *params.In, result interface{}, respErr *neorpc.Error) abstract { +func (s *Server) packResponse(r *params.In, result any, respErr *neorpc.Error) abstract { resp := abstract{ Header: neorpc.Header{ JSONRPC: r.JSONRPC, @@ -2882,7 +2882,7 @@ func (s *Server) writeHTTPServerResponse(r *params.Request, w http.ResponseWrite // validateAddress verifies that the address is a correct Neo address // see https://docs.neo.org/en-us/node/cli/2.9.4/api/validateaddress.html -func validateAddress(addr interface{}) bool { +func validateAddress(addr any) bool { if addr, ok := addr.(string); ok { _, err := address.StringToUint160(addr) return err == nil diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 08d636d07..c5be0f3e0 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -62,8 +62,8 @@ type rpcTestCase struct { name string params string fail bool - result func(e *executor) interface{} - check func(t *testing.T, e *executor, result interface{}) + result func(e *executor) any + check func(t *testing.T, e *executor, result any) } const genesisBlockHash = "0f8fb4e17d2ab9f3097af75ca7fd16064160fb8043db94909e00dd4e257b9dc4" @@ -97,8 +97,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + deploymentTxHash + `"]`, - result: func(e *executor) interface{} { return &result.ApplicationLog{} }, - check: func(t *testing.T, e *executor, acc interface{}) { + result: func(e *executor) any { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc any) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) expectedTxHash, err := util.Uint256DecodeStringLE(deploymentTxHash) @@ -112,8 +112,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, genesis block", params: `["` + genesisBlockHash + `"]`, - result: func(e *executor) interface{} { return &result.ApplicationLog{} }, - check: func(t *testing.T, e *executor, acc interface{}) { + result: func(e *executor) any { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc any) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) assert.Equal(t, genesisBlockHash, res.Container.StringLE()) @@ -126,8 +126,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, genesis block, postPersist", params: `["` + genesisBlockHash + `", "PostPersist"]`, - result: func(e *executor) interface{} { return &result.ApplicationLog{} }, - check: func(t *testing.T, e *executor, acc interface{}) { + result: func(e *executor) any { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc any) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) assert.Equal(t, genesisBlockHash, res.Container.StringLE()) @@ -139,8 +139,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, genesis block, onPersist", params: `["` + genesisBlockHash + `", "OnPersist"]`, - result: func(e *executor) interface{} { return &result.ApplicationLog{} }, - check: func(t *testing.T, e *executor, acc interface{}) { + result: func(e *executor) any { return &result.ApplicationLog{} }, + check: func(t *testing.T, e *executor, acc any) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) assert.Equal(t, genesisBlockHash, res.Container.StringLE()) @@ -174,8 +174,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by hash", params: fmt.Sprintf(`["%s"]`, testContractHash), - result: func(e *executor) interface{} { return &state.Contract{} }, - check: func(t *testing.T, e *executor, cs interface{}) { + result: func(e *executor) any { return &state.Contract{} }, + check: func(t *testing.T, e *executor, cs any) { res, ok := cs.(*state.Contract) require.True(t, ok) assert.Equal(t, testContractHash, res.Hash.StringLE()) @@ -184,8 +184,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by id", params: `[1]`, - result: func(e *executor) interface{} { return &state.Contract{} }, - check: func(t *testing.T, e *executor, cs interface{}) { + result: func(e *executor) any { return &state.Contract{} }, + check: func(t *testing.T, e *executor, cs any) { res, ok := cs.(*state.Contract) require.True(t, ok) assert.Equal(t, int32(1), res.ID) @@ -194,8 +194,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, native by id", params: `[-3]`, - result: func(e *executor) interface{} { return &state.Contract{} }, - check: func(t *testing.T, e *executor, cs interface{}) { + result: func(e *executor) any { return &state.Contract{} }, + check: func(t *testing.T, e *executor, cs any) { res, ok := cs.(*state.Contract) require.True(t, ok) assert.Equal(t, int32(-3), res.ID) @@ -204,8 +204,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, native by name", params: `["PolicyContract"]`, - result: func(e *executor) interface{} { return &state.Contract{} }, - check: func(t *testing.T, e *executor, cs interface{}) { + result: func(e *executor) any { return &state.Contract{} }, + check: func(t *testing.T, e *executor, cs any) { res, ok := cs.(*state.Contract) require.True(t, ok) assert.Equal(t, int32(-7), res.ID) @@ -251,13 +251,13 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + testchain.PrivateKeyByID(0).GetScriptHash().StringLE() + `"]`, - result: func(e *executor) interface{} { return &result.NEP11Balances{} }, + result: func(e *executor) any { return &result.NEP11Balances{} }, check: checkNep11Balances, }, { name: "positive_address", params: `["` + address.Uint160ToString(testchain.PrivateKeyByID(0).GetScriptHash()) + `"]`, - result: func(e *executor) interface{} { return &result.NEP11Balances{} }, + result: func(e *executor) any { return &result.NEP11Balances{} }, check: checkNep11Balances, }, }, @@ -285,8 +285,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + nnsContractHash + `", "6e656f2e636f6d"]`, - result: func(e *executor) interface{} { - return &map[string]interface{}{ + result: func(e *executor) any { + return &map[string]any{ "name": "neo.com", "expiration": "lhbLRl0B", "admin": nil, @@ -318,7 +318,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + testchain.PrivateKeyByID(0).Address() + `", 0]`, - result: func(e *executor) interface{} { return &result.NEP11Transfers{} }, + result: func(e *executor) any { return &result.NEP11Transfers{} }, check: checkNep11Transfers, }, }, @@ -336,13 +336,13 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + testchain.PrivateKeyByID(0).GetScriptHash().StringLE() + `"]`, - result: func(e *executor) interface{} { return &result.NEP17Balances{} }, + result: func(e *executor) any { return &result.NEP17Balances{} }, check: checkNep17Balances, }, { name: "positive_address", params: `["` + address.Uint160ToString(testchain.PrivateKeyByID(0).GetScriptHash()) + `"]`, - result: func(e *executor) interface{} { return &result.NEP17Balances{} }, + result: func(e *executor) any { return &result.NEP17Balances{} }, check: checkNep17Balances, }, }, @@ -395,13 +395,13 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + testchain.PrivateKeyByID(0).Address() + `", 0]`, - result: func(e *executor) interface{} { return &result.NEP17Transfers{} }, + result: func(e *executor) any { return &result.NEP17Transfers{} }, check: checkNep17Transfers, }, { name: "positive_hash", params: `["` + testchain.PrivateKeyByID(0).GetScriptHash().StringLE() + `", 0]`, - result: func(e *executor) interface{} { return &result.NEP17Transfers{} }, + result: func(e *executor) any { return &result.NEP17Transfers{} }, check: checkNep17Transfers, }, }, @@ -495,8 +495,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `[]`, - result: func(_ *executor) interface{} { return new(result.StateHeight) }, - check: func(t *testing.T, e *executor, res interface{}) { + result: func(_ *executor) any { return new(result.StateHeight) }, + check: func(t *testing.T, e *executor, res any) { sh, ok := res.(*result.StateHeight) require.True(t, ok) @@ -521,7 +521,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: fmt.Sprintf(`["%s", "dGVzdGtleQ=="]`, testContractHash), - result: func(e *executor) interface{} { + result: func(e *executor) any { v := base64.StdEncoding.EncodeToString([]byte("newtestvalue")) return &v }, @@ -529,7 +529,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "missing key", params: fmt.Sprintf(`["%s", "dGU="]`, testContractHash), - result: func(e *executor) interface{} { + result: func(e *executor) any { v := "" return &v }, @@ -558,7 +558,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getbestblockhash": { { params: "[]", - result: func(e *executor) interface{} { + result: func(e *executor) any { v := "0x" + e.chain.CurrentBlockHash().StringLE() return &v }, @@ -568,8 +568,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: "[3, 1]", - result: func(_ *executor) interface{} { return &result.Block{} }, - check: func(t *testing.T, e *executor, blockRes interface{}) { + result: func(_ *executor) any { return &result.Block{} }, + check: func(t *testing.T, e *executor, blockRes any) { res, ok := blockRes.(*result.Block) require.True(t, ok) @@ -614,7 +614,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getblockcount": { { params: "[]", - result: func(e *executor) interface{} { + result: func(e *executor) any { v := int(e.chain.BlockHeight() + 1) return &v }, @@ -623,7 +623,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getblockhash": { { params: "[1]", - result: func(e *executor) interface{} { + result: func(e *executor) any { // We don't have `t` here for proper handling, but // error here would lead to panic down below. block, _ := e.chain.GetBlock(e.chain.GetHeaderHash(1)) @@ -667,7 +667,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getblockheadercount": { { params: "[]", - result: func(e *executor) interface{} { + result: func(e *executor) any { v := int(e.chain.HeaderHeight() + 1) return &v }, @@ -677,7 +677,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: "[1]", - result: func(e *executor) interface{} { + result: func(e *executor) any { block, _ := e.chain.GetBlock(e.chain.GetHeaderHash(1)) var expectedBlockSysFee int64 @@ -706,7 +706,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getcommittee": { { params: "[]", - result: func(e *executor) interface{} { + result: func(e *executor) any { expected, _ := e.chain.GetCommittee() sort.Sort(expected) return &expected @@ -716,7 +716,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getconnectioncount": { { params: "[]", - result: func(*executor) interface{} { + result: func(*executor) any { v := 0 return &v }, @@ -725,10 +725,10 @@ var rpcTestCases = map[string][]rpcTestCase{ "getnativecontracts": { { params: "[]", - result: func(e *executor) interface{} { + result: func(e *executor) any { return new([]state.NativeContract) }, - check: func(t *testing.T, e *executor, res interface{}) { + check: func(t *testing.T, e *executor, res any) { lst := res.(*[]state.NativeContract) for i := range *lst { cs := e.chain.GetContractState((*lst)[i].Hash) @@ -742,7 +742,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getpeers": { { params: "[]", - result: func(*executor) interface{} { + result: func(*executor) any { return &result.GetPeers{ Unconnected: []result.Peer{}, Connected: []result.Peer{}, @@ -772,11 +772,11 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + deploymentTxHash + `"]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { h := 0 return &h }, - check: func(t *testing.T, e *executor, resp interface{}) { + check: func(t *testing.T, e *executor, resp any) { h, ok := resp.(*int) require.True(t, ok) assert.Equal(t, 2, *h) @@ -812,10 +812,10 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["` + testchain.MultisigAddress() + `"]`, - result: func(*executor) interface{} { + result: func(*executor) any { return &result.UnclaimedGas{} }, - check: func(t *testing.T, e *executor, resp interface{}) { + check: func(t *testing.T, e *executor, resp any) { actual, ok := resp.(*result.UnclaimedGas) require.True(t, ok) expected := result.UnclaimedGas{ @@ -829,7 +829,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getcandidates": { { params: "[]", - result: func(*executor) interface{} { + result: func(*executor) any { return &[]result.Candidate{} }, }, @@ -837,11 +837,11 @@ var rpcTestCases = map[string][]rpcTestCase{ "getnextblockvalidators": { { params: "[]", - result: func(*executor) interface{} { + result: func(*executor) any { return &[]result.Validator{} }, /* preview3 doesn't return any validators until there is a vote - check: func(t *testing.T, e *executor, validators interface{}) { + check: func(t *testing.T, e *executor, validators any) { var expected []result.Validator sBValidators := e.chain.GetStandByValidators() for _, sbValidator := range sBValidators { @@ -863,8 +863,8 @@ var rpcTestCases = map[string][]rpcTestCase{ "getversion": { { params: "[]", - result: func(*executor) interface{} { return &result.Version{} }, - check: func(t *testing.T, e *executor, ver interface{}) { + result: func(*executor) any { return &result.Version{} }, + check: func(t *testing.T, e *executor, ver any) { resp, ok := ver.(*result.Version) require.True(t, ok) require.Equal(t, "/NEO-GO:0.98.6-test/", resp.UserAgent) @@ -891,8 +891,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotNil(t, res.Script) @@ -903,7 +903,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with notifications", params: `["` + nnsContractHash + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"neo.com"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { script := append([]byte{0x0b, 0x0c, 0x07, 0x6e, 0x65, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x0c, 0x14, 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb, 0x13, 0xc0, 0x1f, 0xc, 0x8, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0xc, 0x14}, nnsHash.BytesBE()...) script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52) return &result.Invoke{ @@ -927,8 +927,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with storage changes", params: `["0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", "transfer", [{"type":"Hash160", "value":"0xb248508f4ef7088e10c48f14d04be3272ca29eee"},{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"Integer", "value":1},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"],true]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotNil(t, res.Script) @@ -959,7 +959,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, verbose", params: `["` + nnsContractHash + `", "resolve", [{"type":"String", "value":"neo.com"},{"type":"Integer","value":1}], [], true]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { script := append([]byte{0x11, 0xc, 0x7, 0x6e, 0x65, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x12, 0xc0, 0x1f, 0xc, 0x7, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0xc, 0x14}, nnsHash.BytesBE()...) script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52) stdHash, _ := e.chain.GetNativeContractScriptHash(nativenames.StdLib) @@ -1026,8 +1026,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by index", params: `[20, "50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotNil(t, res.Script) @@ -1038,8 +1038,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by stateroot", params: `["` + block20StateRootLE + `", "50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotNil(t, res.Script) @@ -1050,7 +1050,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with notifications", params: `[20, "` + nnsContractHash + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"neo.com"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { script := append([]byte{0x0b, 0x0c, 0x07, 0x6e, 0x65, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x0c, 0x14, 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb, 0x13, 0xc0, 0x1f, 0xc, 0x8, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0xc, 0x14}, nnsHash.BytesBE()...) script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52) return &result.Invoke{ @@ -1074,7 +1074,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, verbose", params: `[20, "` + nnsContractHash + `", "resolve", [{"type":"String", "value":"neo.com"},{"type":"Integer","value":1}], [], true]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { script := append([]byte{0x11, 0xc, 0x7, 0x6e, 0x65, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x12, 0xc0, 0x1f, 0xc, 0x7, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0xc, 0x14}, nnsHash.BytesBE()...) script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52) stdHash, _ := e.chain.GetNativeContractScriptHash(nativenames.StdLib) @@ -1156,8 +1156,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotEqual(t, "", res.Script) @@ -1168,7 +1168,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive,verbose", params: `["UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY=",[],true]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { script := []byte{0x51, 0xc5, 0x6b, 0xd, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x68, 0xf, 0x4e, 0x65, 0x6f, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x61, 0x6c, 0x75, 0x66} return &result.Invoke{ State: "FAULT", @@ -1190,8 +1190,8 @@ var rpcTestCases = map[string][]rpcTestCase{ name: "positive, good witness", // script is base64-encoded `invokescript_contract.avm` representation, hashes are hex-encoded LE bytes of hashes used in the contract with `0x` prefix params: fmt.Sprintf(`["%s",["0x0000000009070e030d0f0e020d0c06050e030c01","0x090c060e00010205040307030102000902030f0d"]]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1202,8 +1202,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, bad witness of second hash", params: fmt.Sprintf(`["%s",["0x0000000009070e030d0f0e020d0c06050e030c01"]]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1214,8 +1214,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, no good hashes", params: fmt.Sprintf(`["%s"]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1226,8 +1226,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, bad hashes witness", params: fmt.Sprintf(`["%s",["0x0000000009070e030d0f0e020d0c06050e030c02"]]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1255,8 +1255,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by index", params: `[20,"UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotEqual(t, "", res.Script) @@ -1267,8 +1267,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by stateroot", params: `["` + block20StateRootLE + `","UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="]`, - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.NotEqual(t, "", res.Script) @@ -1279,7 +1279,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive,verbose", params: `[20, "UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY=",[],true]`, - result: func(e *executor) interface{} { + result: func(e *executor) any { script := []byte{0x51, 0xc5, 0x6b, 0xd, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x68, 0xf, 0x4e, 0x65, 0x6f, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x61, 0x6c, 0x75, 0x66} return &result.Invoke{ State: "FAULT", @@ -1301,8 +1301,8 @@ var rpcTestCases = map[string][]rpcTestCase{ name: "positive, good witness", // script is base64-encoded `invokescript_contract.avm` representation, hashes are hex-encoded LE bytes of hashes used in the contract with `0x` prefix params: fmt.Sprintf(`[20,"%s",["0x0000000009070e030d0f0e020d0c06050e030c01","0x090c060e00010205040307030102000902030f0d"]]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1313,8 +1313,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, bad witness of second hash", params: fmt.Sprintf(`[20,"%s",["0x0000000009070e030d0f0e020d0c06050e030c01"]]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1325,8 +1325,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, no good hashes", params: fmt.Sprintf(`[20,"%s"]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1337,8 +1337,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, bad hashes witness", params: fmt.Sprintf(`[20,"%s",["0x0000000009070e030d0f0e020d0c06050e030c02"]]`, invokescriptContractAVM), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Equal(t, "HALT", res.State) @@ -1381,8 +1381,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: fmt.Sprintf(`["%s", [], [{"account":"%s"}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) // empty witness invocation script (pushes args of `verify` on stack, but this `verify` don't have args) @@ -1394,8 +1394,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, no signers", params: fmt.Sprintf(`["%s", []]`, verifyContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) @@ -1407,8 +1407,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, no arguments", params: fmt.Sprintf(`["%s"]`, verifyContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) @@ -1420,8 +1420,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with signers and scripts", params: fmt.Sprintf(`["%s", [], [{"account":"%s", "invocation":"MQo=", "verification": ""}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) @@ -1433,8 +1433,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with arguments, result=true", params: fmt.Sprintf(`["%s", [{"type": "String", "value": "good_string"}, {"type": "Integer", "value": "4"}, {"type":"Boolean", "value": false}]]`, verifyWithArgsContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) expectedInvScript := io.NewBufBinWriter() @@ -1451,8 +1451,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with arguments, result=false", params: fmt.Sprintf(`["%s", [{"type": "String", "value": "invalid_string"}, {"type": "Integer", "value": "4"}, {"type":"Boolean", "value": false}]]`, verifyWithArgsContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) expectedInvScript := io.NewBufBinWriter() @@ -1486,8 +1486,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by index", params: fmt.Sprintf(`[20,"%s", [], [{"account":"%s"}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) // empty witness invocation script (pushes args of `verify` on stack, but this `verify` don't have args) @@ -1499,8 +1499,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, by stateroot", params: fmt.Sprintf(`["`+block20StateRootLE+`","%s", [], [{"account":"%s"}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) // empty witness invocation script (pushes args of `verify` on stack, but this `verify` don't have args) @@ -1512,8 +1512,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, no signers", params: fmt.Sprintf(`[20,"%s", []]`, verifyContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) @@ -1525,8 +1525,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, no arguments", params: fmt.Sprintf(`[20,"%s"]`, verifyContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) @@ -1538,8 +1538,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with signers and scripts", params: fmt.Sprintf(`[20,"%s", [], [{"account":"%s", "invocation":"MQo=", "verification": ""}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) assert.Nil(t, res.Script) @@ -1551,8 +1551,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with arguments, result=true", params: fmt.Sprintf(`[20,"%s", [{"type": "String", "value": "good_string"}, {"type": "Integer", "value": "4"}, {"type":"Boolean", "value": false}]]`, verifyWithArgsContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) expectedInvScript := io.NewBufBinWriter() @@ -1569,8 +1569,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive, with arguments, result=false", params: fmt.Sprintf(`[20, "%s", [{"type": "String", "value": "invalid_string"}, {"type": "Integer", "value": "4"}, {"type":"Boolean", "value": false}]]`, verifyWithArgsContractHash), - result: func(e *executor) interface{} { return &result.Invoke{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.Invoke{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) require.True(t, ok) expectedInvScript := io.NewBufBinWriter() @@ -1609,8 +1609,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["AB0AAACWP5gAAAAAAEDaEgAAAAAAGAAAAAHunqIsJ+NL0BSPxBCOCPdOj1BIsoAAXgsDAOh2SBcAAAAMFBEmW7QXJQBBvgTo+iQOOPV8HlabDBTunqIsJ+NL0BSPxBCOCPdOj1BIshTAHwwIdHJhbnNmZXIMFPVj6kC8KD1NDgXEjqMFs/Kgc0DvQWJ9W1IBQgxAJ6norhWoZxp+Hj1JFhi+Z3qI9DUkLSbfsbaLSaJIqxTfdmPbNFDVK1G+oa+LWmpRp/bj9+QZM7yC+S6HXUI7rigMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwkFW57Mn"]`, - result: func(e *executor) interface{} { return &result.RelayResult{} }, - check: func(t *testing.T, e *executor, inv interface{}) { + result: func(e *executor) any { return &result.RelayResult{} }, + check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.RelayResult) require.True(t, ok) expectedHash := "c11861dec1dd0f188608b725095041fcfc90abe51eea044993f122f22472753e" @@ -1673,8 +1673,8 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", params: `["Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2"]`, - result: func(*executor) interface{} { return &result.ValidateAddress{} }, - check: func(t *testing.T, e *executor, va interface{}) { + result: func(*executor) any { return &result.ValidateAddress{} }, + check: func(t *testing.T, e *executor, va any) { res, ok := va.(*result.ValidateAddress) require.True(t, ok) assert.Equal(t, "Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2", res.Address) @@ -1684,7 +1684,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "negative", params: "[1]", - result: func(*executor) interface{} { + result: func(*executor) any { return &result.ValidateAddress{ Address: float64(1), IsValid: false, @@ -2266,7 +2266,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] testHeaderHash := chain.GetHeaderHash(1).StringLE() hdr := e.getHeader(testHeaderHash) - runCase := func(t *testing.T, rpc string, expected, actual interface{}) { + runCase := func(t *testing.T, rpc string, expected, actual any) { body := doRPCCall(rpc, httpSrv.URL, t) data := checkErrGetResult(t, body, false) require.NoError(t, json.Unmarshal(data, actual)) @@ -2616,7 +2616,7 @@ func encodeBlock(t *testing.T, b *block.Block) string { return base64.StdEncoding.EncodeToString(w.Bytes()) } -func (tc rpcTestCase) getResultPair(e *executor) (expected interface{}, res interface{}) { +func (tc rpcTestCase) getResultPair(e *executor) (expected any, res any) { expected = tc.result(e) resVal := reflect.New(reflect.TypeOf(expected).Elem()) res = resVal.Interface() @@ -2682,7 +2682,7 @@ func doRPCCallOverHTTP(rpcCall string, url string, t *testing.T) []byte { return bytes.TrimSpace(body) } -func checkNep11Balances(t *testing.T, e *executor, acc interface{}) { +func checkNep11Balances(t *testing.T, e *executor, acc any) { res, ok := acc.(*result.NEP11Balances) require.True(t, ok) @@ -2720,7 +2720,7 @@ func checkNep11Balances(t *testing.T, e *executor, acc interface{}) { require.ElementsMatch(t, expected.Balances, res.Balances) } -func checkNep17Balances(t *testing.T, e *executor, acc interface{}) { +func checkNep17Balances(t *testing.T, e *executor, acc any) { res, ok := acc.(*result.NEP17Balances) require.True(t, ok) rubles, err := util.Uint160DecodeStringLE(testContractHash) @@ -2756,11 +2756,11 @@ func checkNep17Balances(t *testing.T, e *executor, acc interface{}) { require.ElementsMatch(t, expected.Balances, res.Balances) } -func checkNep11Transfers(t *testing.T, e *executor, acc interface{}) { +func checkNep11Transfers(t *testing.T, e *executor, acc any) { checkNep11TransfersAux(t, e, acc, []int{0}, []int{0, 1, 2}) } -func checkNep11TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcvd []int) { +func checkNep11TransfersAux(t *testing.T, e *executor, acc any, sent, rcvd []int) { res, ok := acc.(*result.NEP11Transfers) require.True(t, ok) @@ -2858,11 +2858,11 @@ func checkNep11TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rc require.Equal(t, arr, res.Received) } -func checkNep17Transfers(t *testing.T, e *executor, acc interface{}) { +func checkNep17Transfers(t *testing.T, e *executor, acc any) { checkNep17TransfersAux(t, e, acc, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, []int{0, 1, 2, 3, 4, 5, 6, 7, 8}) } -func checkNep17TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcvd []int) { +func checkNep17TransfersAux(t *testing.T, e *executor, acc any, sent, rcvd []int) { res, ok := acc.(*result.NEP17Transfers) require.True(t, ok) rublesHash, err := util.Uint160DecodeStringLE(testContractHash) diff --git a/pkg/services/rpcsrv/subscription.go b/pkg/services/rpcsrv/subscription.go index 511aed2ef..e8f2336cc 100644 --- a/pkg/services/rpcsrv/subscription.go +++ b/pkg/services/rpcsrv/subscription.go @@ -27,7 +27,7 @@ type ( // feed stores subscriber's desired event ID with filter. feed struct { event neorpc.EventID - filter interface{} + filter any } ) @@ -37,7 +37,7 @@ func (f feed) EventID() neorpc.EventID { } // Filter implements neorpc.EventComparator interface and returns notification filter. -func (f feed) Filter() interface{} { +func (f feed) Filter() any { return f.filter } diff --git a/pkg/services/rpcsrv/subscription_test.go b/pkg/services/rpcsrv/subscription_test.go index 752ed03fa..2aece5b6e 100644 --- a/pkg/services/rpcsrv/subscription_test.go +++ b/pkg/services/rpcsrv/subscription_test.go @@ -171,7 +171,7 @@ func TestFilteredSubscriptions(t *testing.T) { "tx matching sender": { params: `["transaction_added", {"sender":"` + goodSender.StringLE() + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.TransactionEventID, resp.Event) sender := rmap["sender"].(string) require.Equal(t, address.Uint160ToString(goodSender), sender) @@ -180,10 +180,10 @@ func TestFilteredSubscriptions(t *testing.T) { "tx matching signer": { params: `["transaction_added", {"signer":"` + goodSender.StringLE() + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.TransactionEventID, resp.Event) - signers := rmap["signers"].([]interface{}) - signer0 := signers[0].(map[string]interface{}) + signers := rmap["signers"].([]any) + signer0 := signers[0].(map[string]any) signer0acc := signer0["account"].(string) require.Equal(t, "0x"+goodSender.StringLE(), signer0acc) }, @@ -191,12 +191,12 @@ func TestFilteredSubscriptions(t *testing.T) { "tx matching sender and signer": { params: `["transaction_added", {"sender":"` + goodSender.StringLE() + `", "signer":"` + goodSender.StringLE() + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.TransactionEventID, resp.Event) sender := rmap["sender"].(string) require.Equal(t, address.Uint160ToString(goodSender), sender) - signers := rmap["signers"].([]interface{}) - signer0 := signers[0].(map[string]interface{}) + signers := rmap["signers"].([]any) + signer0 := signers[0].(map[string]any) signer0acc := signer0["account"].(string) require.Equal(t, "0x"+goodSender.StringLE(), signer0acc) }, @@ -204,7 +204,7 @@ func TestFilteredSubscriptions(t *testing.T) { "notification matching contract hash": { params: `["notification_from_execution", {"contract":"` + testContractHash + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.NotificationEventID, resp.Event) c := rmap["contract"].(string) require.Equal(t, "0x"+testContractHash, c) @@ -213,7 +213,7 @@ func TestFilteredSubscriptions(t *testing.T) { "notification matching name": { params: `["notification_from_execution", {"name":"my_pretty_notification"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.NotificationEventID, resp.Event) n := rmap["name"].(string) require.Equal(t, "my_pretty_notification", n) @@ -222,7 +222,7 @@ func TestFilteredSubscriptions(t *testing.T) { "notification matching contract hash and name": { params: `["notification_from_execution", {"contract":"` + testContractHash + `", "name":"my_pretty_notification"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.NotificationEventID, resp.Event) c := rmap["contract"].(string) require.Equal(t, "0x"+testContractHash, c) @@ -233,7 +233,7 @@ func TestFilteredSubscriptions(t *testing.T) { "execution matching state": { params: `["transaction_executed", {"state":"HALT"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.ExecutionEventID, resp.Event) st := rmap["vmstate"].(string) require.Equal(t, "HALT", st) @@ -242,7 +242,7 @@ func TestFilteredSubscriptions(t *testing.T) { "execution matching container": { params: `["transaction_executed", {"container":"` + deploymentTxHash + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.ExecutionEventID, resp.Event) tx := rmap["container"].(string) require.Equal(t, "0x"+deploymentTxHash, tx) @@ -251,7 +251,7 @@ func TestFilteredSubscriptions(t *testing.T) { "execution matching state and container": { params: `["transaction_executed", {"state":"HALT", "container":"` + deploymentTxHash + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.ExecutionEventID, resp.Event) tx := rmap["container"].(string) require.Equal(t, "0x"+deploymentTxHash, tx) @@ -299,7 +299,7 @@ func TestFilteredSubscriptions(t *testing.T) { for { resp := getNotification(t, respMsgs) - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) if resp.Event == neorpc.BlockEventID { index := rmap["index"].(float64) if uint32(index) == lastBlock { @@ -331,25 +331,25 @@ func TestFilteredNotaryRequestSubscriptions(t *testing.T) { "matching sender": { params: `["notary_request_event", {"sender":"` + goodSender.StringLE() + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.NotaryRequestEventID, resp.Event) require.Equal(t, "added", rmap["type"].(string)) - req := rmap["notaryrequest"].(map[string]interface{}) - fbTx := req["fallbacktx"].(map[string]interface{}) - sender := fbTx["signers"].([]interface{})[1].(map[string]interface{})["account"].(string) + req := rmap["notaryrequest"].(map[string]any) + fbTx := req["fallbacktx"].(map[string]any) + sender := fbTx["signers"].([]any)[1].(map[string]any)["account"].(string) require.Equal(t, "0x"+goodSender.StringLE(), sender) }, }, "matching signer": { params: `["notary_request_event", {"signer":"` + goodSender.StringLE() + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.NotaryRequestEventID, resp.Event) require.Equal(t, "added", rmap["type"].(string)) - req := rmap["notaryrequest"].(map[string]interface{}) - mainTx := req["maintx"].(map[string]interface{}) - signers := mainTx["signers"].([]interface{}) - signer0 := signers[0].(map[string]interface{}) + req := rmap["notaryrequest"].(map[string]any) + mainTx := req["maintx"].(map[string]any) + signers := mainTx["signers"].([]any) + signer0 := signers[0].(map[string]any) signer0acc := signer0["account"].(string) require.Equal(t, "0x"+goodSender.StringLE(), signer0acc) }, @@ -357,16 +357,16 @@ func TestFilteredNotaryRequestSubscriptions(t *testing.T) { "matching sender and signer": { params: `["notary_request_event", {"sender":"` + goodSender.StringLE() + `", "signer":"` + goodSender.StringLE() + `"}]`, check: func(t *testing.T, resp *neorpc.Notification) { - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) require.Equal(t, neorpc.NotaryRequestEventID, resp.Event) require.Equal(t, "added", rmap["type"].(string)) - req := rmap["notaryrequest"].(map[string]interface{}) - mainTx := req["maintx"].(map[string]interface{}) - fbTx := req["fallbacktx"].(map[string]interface{}) - sender := fbTx["signers"].([]interface{})[1].(map[string]interface{})["account"].(string) + req := rmap["notaryrequest"].(map[string]any) + mainTx := req["maintx"].(map[string]any) + fbTx := req["fallbacktx"].(map[string]any) + sender := fbTx["signers"].([]any)[1].(map[string]any)["account"].(string) require.Equal(t, "0x"+goodSender.StringLE(), sender) - signers := mainTx["signers"].([]interface{}) - signer0 := signers[0].(map[string]interface{}) + signers := mainTx["signers"].([]any) + signer0 := signers[0].(map[string]any) signer0acc := signer0["account"].(string) require.Equal(t, "0x"+goodSender.StringLE(), signer0acc) }, @@ -443,7 +443,7 @@ func TestFilteredBlockSubscriptions(t *testing.T) { } require.Equal(t, neorpc.BlockEventID, resp.Event) - rmap := resp.Payload[0].(map[string]interface{}) + rmap := resp.Payload[0].(map[string]any) primary := rmap["primary"].(float64) require.Equal(t, 3, int(primary)) } diff --git a/pkg/services/rpcsrv/tokens.go b/pkg/services/rpcsrv/tokens.go index 4844a85d4..38530fa95 100644 --- a/pkg/services/rpcsrv/tokens.go +++ b/pkg/services/rpcsrv/tokens.go @@ -6,9 +6,9 @@ import ( // tokenTransfers is a generic type used to represent NEP-11 and NEP-17 transfers. type tokenTransfers struct { - Sent []interface{} `json:"sent"` - Received []interface{} `json:"received"` - Address string `json:"address"` + Sent []any `json:"sent"` + Received []any `json:"received"` + Address string `json:"address"` } // nep17TransferToNEP11 adds an ID to the provided NEP-17 transfer and returns a new diff --git a/pkg/services/stateroot/service_test.go b/pkg/services/stateroot/service_test.go index d71c2f101..544e30d24 100644 --- a/pkg/services/stateroot/service_test.go +++ b/pkg/services/stateroot/service_test.go @@ -85,7 +85,7 @@ func TestStateRoot(t *testing.T) { gasValidatorInvoker := e.ValidatorInvoker(e.NativeHash(t, nativenames.Gas)) h, pubs, accs := newMajorityMultisigWithGAS(t, 2) - validatorNodes := []interface{}{pubs[0].Bytes(), pubs[1].Bytes()} + validatorNodes := []any{pubs[0].Bytes(), pubs[1].Bytes()} designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(roles.StateValidator), validatorNodes) updateIndex := bc.BlockHeight() @@ -166,7 +166,7 @@ func TestStateRootInitNonZeroHeight(t *testing.T) { designationSuperInvoker := e.NewInvoker(e.NativeHash(t, nativenames.Designation), validator, committee) gasValidatorInvoker := e.ValidatorInvoker(e.NativeHash(t, nativenames.Gas)) - validatorNodes := []interface{}{pubs[0].Bytes(), pubs[1].Bytes()} + validatorNodes := []any{pubs[0].Bytes(), pubs[1].Bytes()} designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(roles.StateValidator), validatorNodes) gasValidatorInvoker.Invoke(t, true, "transfer", validator.ScriptHash(), h, 1_0000_0000, nil) @@ -244,7 +244,7 @@ func TestStateRootFull(t *testing.T) { srv.Start() t.Cleanup(srv.Shutdown) - validatorNodes := []interface{}{pubs[0].Bytes(), pubs[1].Bytes()} + validatorNodes := []any{pubs[0].Bytes(), pubs[1].Bytes()} designationSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(roles.StateValidator), validatorNodes) gasValidatorInvoker.Invoke(t, true, "transfer", validator.ScriptHash(), h, 1_0000_0000, nil) diff --git a/pkg/smartcontract/binding/generate.go b/pkg/smartcontract/binding/generate.go index 62733b7ac..c02bbd49a 100644 --- a/pkg/smartcontract/binding/generate.go +++ b/pkg/smartcontract/binding/generate.go @@ -126,7 +126,7 @@ func scTypeToGo(name string, typ smartcontract.ParamType, cfg *Config) (string, switch typ { case smartcontract.AnyType: - return "interface{}", "" + return "any", "" case smartcontract.BoolType: return "bool", "" case smartcontract.IntegerType: @@ -144,11 +144,11 @@ func scTypeToGo(name string, typ smartcontract.ParamType, cfg *Config) (string, case smartcontract.SignatureType: return "interop.Signature", "github.com/nspcc-dev/neo-go/pkg/interop" case smartcontract.ArrayType: - return "[]interface{}", "" + return "[]any", "" case smartcontract.MapType: - return "map[string]interface{}", "" + return "map[string]any", "" case smartcontract.InteropInterfaceType: - return "interface{}", "" + return "any", "" case smartcontract.VoidType: return "", "" default: diff --git a/pkg/smartcontract/binding/override.go b/pkg/smartcontract/binding/override.go index 366bd562e..ed861a026 100644 --- a/pkg/smartcontract/binding/override.go +++ b/pkg/smartcontract/binding/override.go @@ -48,7 +48,7 @@ func NewOverrideFromString(s string) Override { } // UnmarshalYAML implements the YAML Unmarshaler interface. -func (o *Override) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (o *Override) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) @@ -61,7 +61,7 @@ func (o *Override) UnmarshalYAML(unmarshal func(interface{}) error) error { } // MarshalYAML implements the YAML marshaler interface. -func (o Override) MarshalYAML() (interface{}, error) { +func (o Override) MarshalYAML() (any, error) { if o.Package == "" { return o.TypeName, nil } diff --git a/pkg/smartcontract/builder.go b/pkg/smartcontract/builder.go index 369be1b64..6d5d03331 100644 --- a/pkg/smartcontract/builder.go +++ b/pkg/smartcontract/builder.go @@ -44,7 +44,7 @@ func NewBuilder() *Builder { // contract. The correctness of this invocation (number and type of parameters) is // out of scope of this method, as well as return value, if contract's method returns // something this value just remains on the execution stack. -func (b *Builder) InvokeMethod(contract util.Uint160, method string, params ...interface{}) { +func (b *Builder) InvokeMethod(contract util.Uint160, method string, params ...any) { emit.AppCall(b.bw.BinWriter, contract, method, callflag.All, params...) } @@ -61,7 +61,7 @@ func (b *Builder) Assert() { // that as well as NEO's 'vote'. The ASSERT then allow to simplify transaction // status checking, if action is successful then transaction is successful as // well, if it went wrong than whole transaction fails (ends with vmstate.FAULT). -func (b *Builder) InvokeWithAssert(contract util.Uint160, method string, params ...interface{}) { +func (b *Builder) InvokeWithAssert(contract util.Uint160, method string, params ...any) { b.InvokeMethod(contract, method, params...) b.Assert() } diff --git a/pkg/smartcontract/callflag/call_flags.go b/pkg/smartcontract/callflag/call_flags.go index 224077c4b..03eebd0aa 100644 --- a/pkg/smartcontract/callflag/call_flags.go +++ b/pkg/smartcontract/callflag/call_flags.go @@ -119,12 +119,12 @@ func (f *CallFlag) UnmarshalJSON(data []byte) error { } // MarshalYAML implements the YAML marshaler interface. -func (f CallFlag) MarshalYAML() (interface{}, error) { +func (f CallFlag) MarshalYAML() (any, error) { return f.String(), nil } // UnmarshalYAML implements the YAML unmarshaler interface. -func (f *CallFlag) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (f *CallFlag) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) diff --git a/pkg/smartcontract/entry.go b/pkg/smartcontract/entry.go index c6f6b211a..99caed055 100644 --- a/pkg/smartcontract/entry.go +++ b/pkg/smartcontract/entry.go @@ -18,7 +18,7 @@ import ( // processed this way (and this number can't exceed VM limits), the result of the // script is an array containing extracted value elements. This script can be useful // for interactions with RPC server that have iterator sessions disabled. -func CreateCallAndUnwrapIteratorScript(contract util.Uint160, operation string, maxIteratorResultItems int, params ...interface{}) ([]byte, error) { +func CreateCallAndUnwrapIteratorScript(contract util.Uint160, operation string, maxIteratorResultItems int, params ...any) ([]byte, error) { script := io.NewBufBinWriter() emit.Int(script.BinWriter, int64(maxIteratorResultItems)) emit.AppCall(script.BinWriter, contract, operation, callflag.All, params...) // The System.Contract.Call itself, it will push Iterator on estack. @@ -71,7 +71,7 @@ func CreateCallAndUnwrapIteratorScript(contract util.Uint160, operation string, // CreateCallScript returns a script that calls contract's method with // the specified parameters. Whatever this method returns remains on the stack. // See also (*Builder).InvokeMethod. -func CreateCallScript(contract util.Uint160, method string, params ...interface{}) ([]byte, error) { +func CreateCallScript(contract util.Uint160, method string, params ...any) ([]byte, error) { b := NewBuilder() b.InvokeMethod(contract, method, params...) return b.Script() @@ -80,7 +80,7 @@ func CreateCallScript(contract util.Uint160, method string, params ...interface{ // CreateCallWithAssertScript returns a script that calls contract's method with // the specified parameters expecting a Boolean value to be return that then is // used for ASSERT. See also (*Builder).InvokeWithAssert. -func CreateCallWithAssertScript(contract util.Uint160, method string, params ...interface{}) ([]byte, error) { +func CreateCallWithAssertScript(contract util.Uint160, method string, params ...any) ([]byte, error) { b := NewBuilder() b.InvokeWithAssert(contract, method, params...) return b.Script() diff --git a/pkg/smartcontract/manifest/manifest.go b/pkg/smartcontract/manifest/manifest.go index ba391a657..c4e88e9b0 100644 --- a/pkg/smartcontract/manifest/manifest.go +++ b/pkg/smartcontract/manifest/manifest.go @@ -182,7 +182,7 @@ func extraToStackItem(rawExtra []byte) stackitem.Item { // Prevent accidental precision loss. d.UseNumber() - var obj interface{} + var obj any // The error can't really occur because `json.RawMessage` is already a valid json. _ = d.Decode(&obj) diff --git a/pkg/smartcontract/manifest/permission.go b/pkg/smartcontract/manifest/permission.go index 0859871db..260c73b14 100644 --- a/pkg/smartcontract/manifest/permission.go +++ b/pkg/smartcontract/manifest/permission.go @@ -27,7 +27,7 @@ const ( // PermissionDesc is a permission descriptor. type PermissionDesc struct { Type PermissionType - Value interface{} + Value any } // Permission describes which contracts may be invoked and which methods are called. @@ -45,13 +45,13 @@ type permissionAux struct { } // NewPermission returns a new permission of the given type. -func NewPermission(typ PermissionType, args ...interface{}) *Permission { +func NewPermission(typ PermissionType, args ...any) *Permission { return &Permission{ Contract: *newPermissionDesc(typ, args...), } } -func newPermissionDesc(typ PermissionType, args ...interface{}) *PermissionDesc { +func newPermissionDesc(typ PermissionType, args ...any) *PermissionDesc { desc := &PermissionDesc{Type: typ} switch typ { case PermissionWildcard: diff --git a/pkg/smartcontract/manifest/permission_test.go b/pkg/smartcontract/manifest/permission_test.go index 1016bb542..16fa923cc 100644 --- a/pkg/smartcontract/manifest/permission_test.go +++ b/pkg/smartcontract/manifest/permission_test.go @@ -144,7 +144,7 @@ func TestPermissionDesc_MarshalJSON(t *testing.T) { }) } -func testMarshalUnmarshal(t *testing.T, expected, actual interface{}) { +func testMarshalUnmarshal(t *testing.T, expected, actual any) { data, err := json.Marshal(expected) require.NoError(t, err) require.NoError(t, json.Unmarshal(data, actual)) diff --git a/pkg/smartcontract/param_type.go b/pkg/smartcontract/param_type.go index c6d640ae5..403a48649 100644 --- a/pkg/smartcontract/param_type.go +++ b/pkg/smartcontract/param_type.go @@ -123,12 +123,12 @@ func (pt *ParamType) UnmarshalJSON(data []byte) error { } // MarshalYAML implements the YAML Marshaler interface. -func (pt ParamType) MarshalYAML() (interface{}, error) { +func (pt ParamType) MarshalYAML() (any, error) { return pt.String(), nil } // UnmarshalYAML implements the YAML Unmarshaler interface. -func (pt *ParamType) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (pt *ParamType) UnmarshalYAML(unmarshal func(any) error) error { var name string err := unmarshal(&name) @@ -275,7 +275,7 @@ func ParseParamType(typ string) (ParamType, error) { } // adjustValToType is a value type-checker and converter. -func adjustValToType(typ ParamType, val string) (interface{}, error) { +func adjustValToType(typ ParamType, val string) (any, error) { switch typ { case SignatureType: b, err := hex.DecodeString(val) diff --git a/pkg/smartcontract/param_type_test.go b/pkg/smartcontract/param_type_test.go index 88ac51fd6..9d3e51d2f 100644 --- a/pkg/smartcontract/param_type_test.go +++ b/pkg/smartcontract/param_type_test.go @@ -171,7 +171,7 @@ func TestAdjustValToType(t *testing.T) { var inouts = []struct { typ ParamType val string - out interface{} + out any err bool }{{ typ: SignatureType, diff --git a/pkg/smartcontract/parameter.go b/pkg/smartcontract/parameter.go index 06556eca1..afe48dba6 100644 --- a/pkg/smartcontract/parameter.go +++ b/pkg/smartcontract/parameter.go @@ -22,7 +22,7 @@ type Parameter struct { // Type of the parameter. Type ParamType `json:"type"` // The actual value of the parameter. - Value interface{} `json:"value"` + Value any `json:"value"` } // ParameterPair represents a key-value pair, a slice of which is stored in @@ -259,7 +259,7 @@ func NewParameterFromString(in string) (*Parameter, error) { // the value if needed. It does not copy the value if it can avoid doing so. All // regular integers, util.*, keys.PublicKey*, string and bool types are supported, // slice of byte slices is accepted and converted as well. -func NewParameterFromValue(value interface{}) (Parameter, error) { +func NewParameterFromValue(value any) (Parameter, error) { var result = Parameter{ Value: value, } @@ -353,7 +353,7 @@ func NewParameterFromValue(value interface{}) (Parameter, error) { } result.Type = ArrayType result.Value = arr - case []interface{}: + case []any: arr, err := NewParametersFromValues(v...) if err != nil { return result, err @@ -369,7 +369,7 @@ func NewParameterFromValue(value interface{}) (Parameter, error) { // NewParametersFromValues is similar to NewParameterFromValue except that it // works with multiple values and returns a simple slice of Parameter. -func NewParametersFromValues(values ...interface{}) ([]Parameter, error) { +func NewParametersFromValues(values ...any) ([]Parameter, error) { res := make([]Parameter, 0, len(values)) for i := range values { elem, err := NewParameterFromValue(values[i]) @@ -384,12 +384,12 @@ func NewParametersFromValues(values ...interface{}) ([]Parameter, error) { // ExpandParameterToEmitable converts a parameter to a type which can be handled as // an array item by emit.Array. It correlates with the way an RPC server handles // FuncParams for invoke* calls inside the request.ExpandArrayIntoScript function. -func ExpandParameterToEmitable(param Parameter) (interface{}, error) { +func ExpandParameterToEmitable(param Parameter) (any, error) { var err error switch t := param.Type; t { case ArrayType: arr := param.Value.([]Parameter) - res := make([]interface{}, len(arr)) + res := make([]any, len(arr)) for i := range arr { res[i], err = ExpandParameterToEmitable(arr[i]) if err != nil { diff --git a/pkg/smartcontract/parameter_test.go b/pkg/smartcontract/parameter_test.go index 295ed8f93..1150e9cbc 100644 --- a/pkg/smartcontract/parameter_test.go +++ b/pkg/smartcontract/parameter_test.go @@ -452,7 +452,7 @@ func TestExpandParameterToEmitableToStackitem(t *testing.T) { pk, _ := keys.NewPrivateKey() testCases := []struct { In Parameter - Expected interface{} + Expected any ExpectedStackitem stackitem.Item }{ { @@ -520,7 +520,7 @@ func TestExpandParameterToEmitableToStackitem(t *testing.T) { }, }, }}, - Expected: []interface{}{big.NewInt(123), []byte{1, 2, 3}, []interface{}{true}}, + Expected: []any{big.NewInt(123), []byte{1, 2, 3}, []any{true}}, ExpectedStackitem: stackitem.NewArray([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(123)), stackitem.NewByteArray([]byte{1, 2, 3}), @@ -558,9 +558,9 @@ func TestParameterFromValue(t *testing.T) { pk1, _ := keys.NewPrivateKey() pk2, _ := keys.NewPrivateKey() items := []struct { - value interface{} + value any expType ParamType - expVal interface{} + expVal any }{ { value: []byte{1, 2, 3}, @@ -723,7 +723,7 @@ func TestParameterFromValue(t *testing.T) { }}, }, { - value: []interface{}{-42, "random", []byte{1, 2, 3}}, + value: []any{-42, "random", []byte{1, 2, 3}}, expType: ArrayType, expVal: []Parameter{{ Type: IntegerType, @@ -748,7 +748,7 @@ func TestParameterFromValue(t *testing.T) { } _, err := NewParameterFromValue(make(map[string]int)) require.Error(t, err) - _, err = NewParameterFromValue([]interface{}{1, 2, make(map[string]int)}) + _, err = NewParameterFromValue([]any{1, 2, make(map[string]int)}) require.Error(t, err) } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index b8f53d91a..3db076bd7 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -121,9 +121,9 @@ type Invoker interface { {{if or .IsNep11D .IsNep11ND}} nep11.Invoker {{else -}} {{ if .IsNep17}} nep17.Invoker -{{else if len .SafeMethods}} Call(contract util.Uint160, operation string, params ...interface{}) (*result.Invoke, error) +{{else if len .SafeMethods}} Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) {{end -}} -{{if .HasIterator}} CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...interface{}) (*result.Invoke, error) +{{if .HasIterator}} CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) TerminateSession(sessionID uuid.UUID) error TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) {{end -}} @@ -142,11 +142,11 @@ type Actor interface { nep17.Actor {{end}} {{- if len .Methods}} - MakeCall(contract util.Uint160, method string, params ...interface{}) (*transaction.Transaction, error) + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...interface{}) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...interface{}) (util.Uint256, uint32, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) SendRun(script []byte) (util.Uint256, uint32, error) {{end -}} } @@ -358,7 +358,7 @@ func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest. func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.ExtendedType) (string, string) { switch et.Base { case smartcontract.AnyType: - return "interface{}", "" + return "any", "" case smartcontract.BoolType: return "bool", "" case smartcontract.IntegerType: @@ -385,14 +385,14 @@ func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.Extended sub, pkg := extendedTypeToGo(*et.Value, named) return "[]" + sub, pkg } - return "[]interface{}", "" + return "[]any", "" case smartcontract.MapType: kt, _ := extendedTypeToGo(binding.ExtendedType{Base: et.Key}, named) vt, _ := extendedTypeToGo(*et.Value, named) return "map[" + kt + "]" + vt, "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" case smartcontract.InteropInterfaceType: - return "interface{}", "" + return "any", "" case smartcontract.VoidType: return "", "" } @@ -554,7 +554,7 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st for i := range ctr.SafeMethods { switch ctr.SafeMethods[i].ReturnType { - case "interface{}": + case "any": abim := cfg.Manifest.ABI.GetMethod(ctr.SafeMethods[i].NameABI, len(ctr.SafeMethods[i].Arguments)) if abim.ReturnType == smartcontract.InteropInterfaceType { imports["github.com/google/uuid"] = struct{}{} @@ -565,7 +565,7 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st ctr.HasIterator = true } else { imports["github.com/nspcc-dev/neo-go/pkg/vm/stackitem"] = struct{}{} - ctr.SafeMethods[i].ReturnType = "interface{}" + ctr.SafeMethods[i].ReturnType = "any" ctr.SafeMethods[i].Unwrapper = "Item" } case "bool": @@ -582,7 +582,7 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st ctr.SafeMethods[i].Unwrapper = "PublicKey" case "[]byte": ctr.SafeMethods[i].Unwrapper = "Bytes" - case "[]interface{}": + case "[]any": imports["github.com/nspcc-dev/neo-go/pkg/vm/stackitem"] = struct{}{} ctr.SafeMethods[i].ReturnType = "[]stackitem.Item" ctr.SafeMethods[i].Unwrapper = "Array" diff --git a/pkg/util/uint160.go b/pkg/util/uint160.go index 2f107e05e..ddb992a98 100644 --- a/pkg/util/uint160.go +++ b/pkg/util/uint160.go @@ -141,7 +141,7 @@ func (u Uint160) MarshalJSON() ([]byte, error) { } // UnmarshalYAML implements the YAML Unmarshaler interface. -func (u *Uint160) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (u *Uint160) UnmarshalYAML(unmarshal func(any) error) error { var s string err := unmarshal(&s) @@ -155,7 +155,7 @@ func (u *Uint160) UnmarshalYAML(unmarshal func(interface{}) error) error { } // MarshalYAML implements the YAML marshaller interface. -func (u Uint160) MarshalYAML() (interface{}, error) { +func (u Uint160) MarshalYAML() (any, error) { return "0x" + u.StringLE(), nil } diff --git a/pkg/vm/emit/emit.go b/pkg/vm/emit/emit.go index 8292aa30e..b79fcdeac 100644 --- a/pkg/vm/emit/emit.go +++ b/pkg/vm/emit/emit.go @@ -99,14 +99,14 @@ func bigInt(w *io.BinWriter, n *big.Int, trySmall bool) { } // Array emits an array of elements to the given buffer. -func Array(w *io.BinWriter, es ...interface{}) { +func Array(w *io.BinWriter, es ...any) { if len(es) == 0 { Opcodes(w, opcode.NEWARRAY0) return } for i := len(es) - 1; i >= 0; i-- { switch e := es[i].(type) { - case []interface{}: + case []any: Array(w, e...) case int64: Int(w, e) @@ -225,7 +225,7 @@ func AppCallNoArgs(w *io.BinWriter, scriptHash util.Uint160, operation string, f } // AppCall emits SYSCALL with System.Contract.Call parameter for given contract, operation, call flag and arguments. -func AppCall(w *io.BinWriter, scriptHash util.Uint160, operation string, f callflag.CallFlag, args ...interface{}) { +func AppCall(w *io.BinWriter, scriptHash util.Uint160, operation string, f callflag.CallFlag, args ...any) { Array(w, args...) AppCallNoArgs(w, scriptHash, operation, f) } diff --git a/pkg/vm/emit/emit_test.go b/pkg/vm/emit/emit_test.go index a585161b4..63b35cfdb 100644 --- a/pkg/vm/emit/emit_test.go +++ b/pkg/vm/emit/emit_test.go @@ -224,7 +224,7 @@ func TestEmitArray(t *testing.T) { veryBig := new(big.Int).SetUint64(math.MaxUint64) veryBig.Add(veryBig, big.NewInt(1)) Array(buf.BinWriter, p160, p256, &u160, &u256, u160, u256, big.NewInt(0), veryBig, - []interface{}{int64(1), int64(2)}, nil, int64(1), "str", false, true, []byte{0xCA, 0xFE}) + []any{int64(1), int64(2)}, nil, int64(1), "str", false, true, []byte{0xCA, 0xFE}) require.NoError(t, buf.Err) res := buf.Bytes() diff --git a/pkg/vm/exception.go b/pkg/vm/exception.go index 61c509931..5498e9b44 100644 --- a/pkg/vm/exception.go +++ b/pkg/vm/exception.go @@ -45,7 +45,7 @@ func (c *exceptionHandlingContext) String() string { } // Value implements the stackitem.Item interface. -func (c *exceptionHandlingContext) Value() interface{} { +func (c *exceptionHandlingContext) Value() any { return c } diff --git a/pkg/vm/json_test.go b/pkg/vm/json_test.go index ada80b499..8df690145 100644 --- a/pkg/vm/json_test.go +++ b/pkg/vm/json_test.go @@ -54,7 +54,7 @@ type ( vmUTStackItem struct { Type vmUTStackItemType - Value interface{} + Value any } vmUTStep struct { diff --git a/pkg/vm/opcodebench_test.go b/pkg/vm/opcodebench_test.go index 1494dbd9a..e64405e78 100644 --- a/pkg/vm/opcodebench_test.go +++ b/pkg/vm/opcodebench_test.go @@ -43,11 +43,11 @@ func opParamVM(op opcode.Opcode, param []byte) func() *VM { return opParamPushVM(op, param) } -func opParamPushVM(op opcode.Opcode, param []byte, items ...interface{}) func() *VM { +func opParamPushVM(op opcode.Opcode, param []byte, items ...any) func() *VM { return opParamSlotsPushVM(op, param, 0, 0, 0, items...) } -func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int, slotarg int, items ...interface{}) func() *VM { +func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int, slotarg int, items ...any) func() *VM { return func() *VM { script := []byte{byte(op)} script = append(script, param...) @@ -75,7 +75,7 @@ func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int, } } -func exceptParamPushVM(op opcode.Opcode, param []byte, ilen int, elen int, exception bool, items ...interface{}) func() *VM { +func exceptParamPushVM(op opcode.Opcode, param []byte, ilen int, elen int, exception bool, items ...any) func() *VM { return func() *VM { regVMF := opParamPushVM(op, param, items...) v := regVMF() @@ -136,8 +136,8 @@ func arrayOfOnes(size int) []stackitem.Item { return elems } -func arrayOfIfaces(size int) []interface{} { - var elems = make([]interface{}, size) +func arrayOfIfaces(size int) []any { + var elems = make([]any, size) for i := range elems { elems[i] = 1 } @@ -388,14 +388,14 @@ func BenchmarkOpcodes(t *testing.B) { if cp.op == opcode.PICK { name += "/" + strconv.Itoa(cp.pos) } - var getitems = func(element interface{}) []interface{} { + var getitems = func(element any) []any { l := cp.l pos := cp.pos if cp.op == opcode.PICK { pos++ l++ } - var items = make([]interface{}, l) + var items = make([]any, l) for i := range items { items[i] = 0 } @@ -461,12 +461,12 @@ func BenchmarkOpcodes(t *testing.B) { if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { name += "/" + strconv.Itoa(sw.num) } - var getitems = func(element interface{}) []interface{} { + var getitems = func(element any) []any { l := sw.num if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { l++ } - var items = make([]interface{}, l) + var items = make([]any, l) for i := range items { items[i] = element } @@ -656,7 +656,7 @@ func BenchmarkOpcodes(t *testing.B) { var nums = []int{1, 255, 1024} for _, n := range nums { t.Run(strconv.Itoa(n), func(t *testing.B) { - var elems = make([]interface{}, n+1) + var elems = make([]any, n+1) for i := range elems { elems[i] = 0 } diff --git a/pkg/vm/stack.go b/pkg/vm/stack.go index 9e609766e..bd83fba6a 100644 --- a/pkg/vm/stack.go +++ b/pkg/vm/stack.go @@ -22,7 +22,7 @@ type Element struct { // NewElement returns a new Element object, with its underlying value inferred // to the corresponding type. -func NewElement(v interface{}) Element { +func NewElement(v any) Element { return Element{stackitem.Make(v)} } @@ -32,7 +32,7 @@ func (e Element) Item() stackitem.Item { } // Value returns the value of the Item contained in the element. -func (e Element) Value() interface{} { +func (e Element) Value() any { return e.value.Value() } @@ -185,7 +185,7 @@ func (s *Stack) PushItem(i stackitem.Item) { // PushVal pushes the given value on the stack. It will infer the // underlying Item to its corresponding type. -func (s *Stack) PushVal(v interface{}) { +func (s *Stack) PushVal(v any) { s.Push(NewElement(v)) } diff --git a/pkg/vm/stackitem/item.go b/pkg/vm/stackitem/item.go index 6e645bf28..8e5952a46 100644 --- a/pkg/vm/stackitem/item.go +++ b/pkg/vm/stackitem/item.go @@ -36,7 +36,7 @@ const ( // Item represents the "real" value that is pushed on the stack. type Item interface { fmt.Stringer - Value() interface{} + Value() any // Dup duplicates current Item. Dup() Item // TryBool converts Item to a boolean value. @@ -88,7 +88,7 @@ func mkInvConversion(from Item, to Type) error { // Make tries to make an appropriate stack item from the provided value. // It will panic if it's not possible. -func Make(v interface{}) Item { +func Make(v any) Item { switch val := v.(type) { case int: return (*BigInteger)(big.NewInt(int64(val))) @@ -122,7 +122,7 @@ func Make(v interface{}) Item { a = append(a, Make(i)) } return Make(a) - case []interface{}: + case []any: res := make([]Item, len(val)) for i := range val { res[i] = Make(val[i]) @@ -210,7 +210,7 @@ func NewStruct(items []Item) *Struct { } // Value implements the Item interface. -func (i *Struct) Value() interface{} { +func (i *Struct) Value() any { return i.value } @@ -374,7 +374,7 @@ func (i Null) String() string { } // Value implements the Item interface. -func (i Null) Value() interface{} { +func (i Null) Value() any { return nil } @@ -483,7 +483,7 @@ func (i *BigInteger) Equals(s Item) bool { } // Value implements the Item interface. -func (i *BigInteger) Value() interface{} { +func (i *BigInteger) Value() any { return i.Big() } @@ -519,7 +519,7 @@ func NewBool(val bool) Bool { } // Value implements the Item interface. -func (i Bool) Value() interface{} { +func (i Bool) Value() any { return bool(i) } @@ -589,7 +589,7 @@ func NewByteArray(b []byte) *ByteArray { } // Value implements the Item interface. -func (i *ByteArray) Value() interface{} { +func (i *ByteArray) Value() any { return []byte(*i) } @@ -697,7 +697,7 @@ func NewArray(items []Item) *Array { } // Value implements the Item interface. -func (i *Array) Value() interface{} { +func (i *Array) Value() any { return i.value } @@ -818,7 +818,7 @@ func NewMapWithValue(value []MapElement) *Map { } // Value implements the Item interface. -func (i *Map) Value() interface{} { +func (i *Map) Value() any { return i.value } @@ -937,18 +937,18 @@ func IsValidMapKey(key Item) error { // Interop represents interop data on the stack. type Interop struct { - value interface{} + value any } // NewInterop returns a new Interop object. -func NewInterop(value interface{}) *Interop { +func NewInterop(value any) *Interop { return &Interop{ value: value, } } // Value implements the Item interface. -func (i *Interop) Value() interface{} { +func (i *Interop) Value() any { return i.value } @@ -1041,7 +1041,7 @@ func (p *Pointer) String() string { } // Value implements the Item interface. -func (p *Pointer) Value() interface{} { +func (p *Pointer) Value() any { return p.pos } @@ -1114,7 +1114,7 @@ func NewBuffer(b []byte) *Buffer { } // Value implements the Item interface. -func (i *Buffer) Value() interface{} { +func (i *Buffer) Value() any { return []byte(*i) } diff --git a/pkg/vm/stackitem/item_test.go b/pkg/vm/stackitem/item_test.go index 210f0a83d..c90763b84 100644 --- a/pkg/vm/stackitem/item_test.go +++ b/pkg/vm/stackitem/item_test.go @@ -10,7 +10,7 @@ import ( ) var makeStackItemTestCases = []struct { - input interface{} + input any result Item }{ { @@ -84,7 +84,7 @@ var makeStackItemTestCases = []struct { } var makeStackItemErrorCases = []struct { - input interface{} + input any }{ { input: map[int]int{1: 2}, diff --git a/pkg/vm/stackitem/json_test.go b/pkg/vm/stackitem/json_test.go index c68db70f0..45227feaf 100644 --- a/pkg/vm/stackitem/json_test.go +++ b/pkg/vm/stackitem/json_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func getTestDecodeFunc(js string, expected ...interface{}) func(t *testing.T) { +func getTestDecodeFunc(js string, expected ...any) func(t *testing.T) { return func(t *testing.T) { actual, err := FromJSON([]byte(js), 20) if expected[0] == nil { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 950dfed7e..5541e25b8 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -30,14 +30,14 @@ import ( type errorAtInstruct struct { ip int op opcode.Opcode - err interface{} + err any } func (e *errorAtInstruct) Error() string { return fmt.Sprintf("at instruction %d (%s): %s", e.ip, e.op, e.err) } -func newError(ip int, op opcode.Opcode, err interface{}) *errorAtInstruct { +func newError(ip int, op opcode.Opcode, err any) *errorAtInstruct { return &errorAtInstruct{ip: ip, op: op, err: err} } @@ -379,7 +379,7 @@ func (v *VM) Context() *Context { // PopResult is used to pop the first item of the evaluation stack. This allows // us to test the compiler and the vm in a bi-directional way. -func (v *VM) PopResult() interface{} { +func (v *VM) PopResult() any { if v.estack.Len() == 0 { return nil } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index d78ab22c3..67af89618 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -471,7 +471,7 @@ func TestPushData4BigN(t *testing.T) { checkVMFailed(t, vm) } -func getTestCallFlagsFunc(syscall []byte, flags callflag.CallFlag, result interface{}) func(t *testing.T) { +func getTestCallFlagsFunc(syscall []byte, flags callflag.CallFlag, result any) func(t *testing.T) { return func(t *testing.T) { script := append([]byte{byte(opcode.SYSCALL)}, syscall...) v := newTestVM() @@ -535,7 +535,7 @@ func getJMPProgram(op opcode.Opcode) []byte { return append(prog, byte(opcode.PUSH1), byte(opcode.RET), byte(opcode.PUSH2), byte(opcode.RET)) } -func testJMP(t *testing.T, op opcode.Opcode, res interface{}, items ...interface{}) { +func testJMP(t *testing.T, op opcode.Opcode, res any, items ...any) { prog := getJMPProgram(op) v := load(prog) for i := range items { @@ -552,35 +552,35 @@ func testJMP(t *testing.T, op opcode.Opcode, res interface{}, items ...interface func TestJMPs(t *testing.T) { testCases := []struct { name string - items []interface{} + items []any }{ { name: "no condition", }, { name: "single item (true)", - items: []interface{}{true}, + items: []any{true}, }, { name: "single item (false)", - items: []interface{}{false}, + items: []any{false}, }, { name: "24 and 42", - items: []interface{}{24, 42}, + items: []any{24, 42}, }, { name: "42 and 24", - items: []interface{}{42, 24}, + items: []any{42, 24}, }, { name: "42 and 42", - items: []interface{}{42, 42}, + items: []any{42, 42}, }, } // 2 is true, 1 is false - results := map[opcode.Opcode][]interface{}{ + results := map[opcode.Opcode][]any{ opcode.JMP: {2, 2, 2, 2, 2, 2}, opcode.JMPIF: {nil, 2, 1, 2, 2, 2}, opcode.JMPIFNOT: {nil, 1, 2, 1, 1, 1}, @@ -896,11 +896,11 @@ func TestEQUALByteArrayWithLimit(t *testing.T) { }) } -func runWithArgs(t *testing.T, prog []byte, result interface{}, args ...interface{}) { +func runWithArgs(t *testing.T, prog []byte, result any, args ...any) { getTestFuncForVM(prog, result, args...)(t) } -func getCustomTestFuncForVM(prog []byte, check func(t *testing.T, v *VM), args ...interface{}) func(t *testing.T) { +func getCustomTestFuncForVM(prog []byte, check func(t *testing.T, v *VM), args ...any) func(t *testing.T) { return func(t *testing.T) { v := load(prog) for i := range args { @@ -915,7 +915,7 @@ func getCustomTestFuncForVM(prog []byte, check func(t *testing.T, v *VM), args . } } -func getTestFuncForVM(prog []byte, result interface{}, args ...interface{}) func(t *testing.T) { +func getTestFuncForVM(prog []byte, result any, args ...any) func(t *testing.T) { var f func(t *testing.T, v *VM) if result != nil { f = func(t *testing.T, v *VM) { @@ -1057,7 +1057,7 @@ func getTRYProgram(tryBlock, catchBlock, finallyBlock []byte) []byte { return prog } -func getTRYTestFunc(result interface{}, tryBlock, catchBlock, finallyBlock []byte) func(t *testing.T) { +func getTRYTestFunc(result any, tryBlock, catchBlock, finallyBlock []byte) func(t *testing.T) { return func(t *testing.T) { prog := getTRYProgram(tryBlock, catchBlock, finallyBlock) runWithArgs(t, prog, result) @@ -1695,7 +1695,7 @@ func TestROLLGood(t *testing.T) { assert.Equal(t, stackitem.Make(1), vm.estack.Pop().value) } -func getCheckEStackFunc(items ...interface{}) func(t *testing.T, v *VM) { +func getCheckEStackFunc(items ...any) func(t *testing.T, v *VM) { return func(t *testing.T, v *VM) { require.Equal(t, len(items), v.estack.Len()) for i := 0; i < len(items); i++ { @@ -2255,7 +2255,7 @@ func TestCLEARITEMS(t *testing.T) { } func TestPOPITEM(t *testing.T) { - testPOPITEM := func(t *testing.T, item, elem, arr interface{}) { + testPOPITEM := func(t *testing.T, item, elem, arr any) { prog := makeProgram(opcode.DUP, opcode.POPITEM) v := load(prog) v.estack.PushVal(item) @@ -2351,51 +2351,51 @@ func TestDupBool(t *testing.T) { var opcodesTestCases = map[opcode.Opcode][]struct { name string - args []interface{} - expected interface{} - actual func(vm *VM) interface{} + args []any + expected any + actual func(vm *VM) any }{ opcode.AND: { { name: "1_1", - args: []interface{}{1, 1}, + args: []any{1, 1}, expected: int64(1), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "1_0", - args: []interface{}{1, 0}, + args: []any{1, 0}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0_1", - args: []interface{}{0, 1}, + args: []any{0, 1}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0_0", - args: []interface{}{0, 0}, + args: []any{0, 0}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "random_values", - args: []interface{}{ + args: []any{ []byte{1, 0, 1, 0, 1, 0, 1, 1}, []byte{1, 1, 0, 0, 0, 0, 0, 1}, }, expected: []byte{1, 0, 0, 0, 0, 0, 0, 1}, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bytes() }, }, @@ -2403,44 +2403,44 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.OR: { { name: "1_1", - args: []interface{}{1, 1}, + args: []any{1, 1}, expected: int64(1), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0_0", - args: []interface{}{0, 0}, + args: []any{0, 0}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0_1", - args: []interface{}{0, 1}, + args: []any{0, 1}, expected: int64(1), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "1_0", - args: []interface{}{1, 0}, + args: []any{1, 0}, expected: int64(1), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "random_values", - args: []interface{}{ + args: []any{ []byte{1, 0, 1, 0, 1, 0, 1, 1}, []byte{1, 1, 0, 0, 0, 0, 0, 1}, }, expected: []byte{1, 1, 1, 0, 1, 0, 1, 1}, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bytes() }, }, @@ -2448,44 +2448,44 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.XOR: { { name: "1_1", - args: []interface{}{1, 1}, + args: []any{1, 1}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0_0", - args: []interface{}{0, 0}, + args: []any{0, 0}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0_1", - args: []interface{}{0, 1}, + args: []any{0, 1}, expected: int64(1), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "1_0", - args: []interface{}{1, 0}, + args: []any{1, 0}, expected: int64(1), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "random_values", - args: []interface{}{ + args: []any{ []byte{1, 0, 1, 0, 1, 0, 1, 1}, []byte{1, 1, 0, 0, 0, 0, 0, 1}, }, expected: []byte{0, 1, 1, 0, 1, 0, 1}, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bytes() }, }, @@ -2493,33 +2493,33 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.BOOLOR: { { name: "1_1", - args: []interface{}{true, true}, + args: []any{true, true}, expected: true, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, { name: "0_0", - args: []interface{}{false, false}, + args: []any{false, false}, expected: false, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, { name: "0_1", - args: []interface{}{false, true}, + args: []any{false, true}, expected: true, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, { name: "1_0", - args: []interface{}{true, false}, + args: []any{true, false}, expected: true, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, @@ -2527,25 +2527,25 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.MIN: { { name: "3_5", - args: []interface{}{3, 5}, + args: []any{3, 5}, expected: int64(3), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "5_3", - args: []interface{}{5, 3}, + args: []any{5, 3}, expected: int64(3), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "3_3", - args: []interface{}{3, 3}, + args: []any{3, 3}, expected: int64(3), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, @@ -2553,25 +2553,25 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.MAX: { { name: "3_5", - args: []interface{}{3, 5}, + args: []any{3, 5}, expected: int64(5), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "5_3", - args: []interface{}{5, 3}, + args: []any{5, 3}, expected: int64(5), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "3_3", - args: []interface{}{3, 3}, + args: []any{3, 3}, expected: int64(3), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, @@ -2579,25 +2579,25 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.WITHIN: { { name: "within", - args: []interface{}{4, 3, 5}, + args: []any{4, 3, 5}, expected: true, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, { name: "less", - args: []interface{}{2, 3, 5}, + args: []any{2, 3, 5}, expected: false, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, { name: "more", - args: []interface{}{6, 3, 5}, + args: []any{6, 3, 5}, expected: false, - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().Bool() }, }, @@ -2605,25 +2605,25 @@ var opcodesTestCases = map[opcode.Opcode][]struct { opcode.NEGATE: { { name: "3", - args: []interface{}{3}, + args: []any{3}, expected: int64(-3), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "-3", - args: []interface{}{-3}, + args: []any{-3}, expected: int64(3), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, { name: "0", - args: []interface{}{0}, + args: []any{0}, expected: int64(0), - actual: func(vm *VM) interface{} { + actual: func(vm *VM) any { return vm.estack.Pop().BigInt().Int64() }, }, From 4ab6d1e31a2e98ffa20d77530f377deaec6fddb9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 4 Apr 2023 12:18:38 +0300 Subject: [PATCH 014/125] go.mod: fetch dbft update Minimum required go version of dbft has been changed from 1.17 to 1.18. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 66a0024df..cfe1c61c5 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/holiman/uint256 v1.2.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/mr-tron/base58 v1.2.0 - github.com/nspcc-dev/dbft v0.0.0-20230315155759-60347b1563e7 + github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 diff --git a/go.sum b/go.sum index 5b0ca7430..eaad5aa6b 100644 --- a/go.sum +++ b/go.sum @@ -250,8 +250,8 @@ github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= -github.com/nspcc-dev/dbft v0.0.0-20230315155759-60347b1563e7 h1:XP4vSXovxQHgbjHwmrbT/2sPFhSwzEy/HbcNs3kMzIo= -github.com/nspcc-dev/dbft v0.0.0-20230315155759-60347b1563e7/go.mod h1:IsUsZqxQkav23pFrCyZEibz0VukpI787XnbcsFkekI8= +github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd h1:PYJbdSrB4S2Sp5e28CD0pxGE5xsCGO/6DZVQtBnllRc= +github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= From 115ec4d8dd885a5e267357770a118477d4f01c2d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 17 Mar 2023 18:38:38 +0300 Subject: [PATCH 015/125] core: add BLS12_381 interops --- go.mod | 4 + go.sum | 11 + pkg/core/native/crypto.go | 320 ++++++++++++++++ pkg/core/native/crypto_test.go | 61 +++ pkg/core/native/native_test/cryptolib_test.go | 352 ++++++++++++++++++ pkg/neotest/basic.go | 7 +- pkg/neotest/client.go | 23 +- pkg/services/rpcsrv/server_test.go | 2 +- 8 files changed, 777 insertions(+), 3 deletions(-) create mode 100644 pkg/core/native/native_test/cryptolib_test.go diff --git a/go.mod b/go.mod index cfe1c61c5..1f5255334 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/nspcc-dev/neo-go require ( github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e + github.com/consensys/gnark-crypto v0.9.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/google/uuid v1.2.0 @@ -36,10 +37,12 @@ require ( github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/nspcc-dev/hrw v1.0.9 // indirect github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 // indirect github.com/nspcc-dev/neofs-crypto v0.4.0 // indirect @@ -58,6 +61,7 @@ require ( google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect google.golang.org/grpc v1.41.0 // indirect google.golang.org/protobuf v1.28.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) go 1.18 diff --git a/go.sum b/go.sum index eaad5aa6b..0b24180df 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.9.1 h1:mru55qKdWl3E035hAoh1jj9d7hVnYY5pfb6tmovSmII= +github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -183,6 +187,7 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -226,6 +231,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -235,6 +241,9 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -729,3 +738,5 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/pkg/core/native/crypto.go b/pkg/core/native/crypto.go index 0228bc9cc..323a8ed21 100644 --- a/pkg/core/native/crypto.go +++ b/pkg/core/native/crypto.go @@ -5,7 +5,10 @@ import ( "encoding/binary" "errors" "fmt" + "math/big" + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" @@ -61,6 +64,42 @@ func newCrypto() *Crypto { manifest.NewParameter("curve", smartcontract.IntegerType)) md = newMethodAndPrice(c.verifyWithECDsa, 1<<15, callflag.NoneFlag) c.AddMethod(md, desc) + + desc = newDescriptor("bls12381Serialize", smartcontract.ByteArrayType, + manifest.NewParameter("g", smartcontract.InteropInterfaceType)) + md = newMethodAndPrice(c.bls12381Serialize, 1<<19, callflag.NoneFlag) + c.AddMethod(md, desc) + + desc = newDescriptor("bls12381Deserialize", smartcontract.InteropInterfaceType, + manifest.NewParameter("data", smartcontract.ByteArrayType)) + md = newMethodAndPrice(c.bls12381Deserialize, 1<<19, callflag.NoneFlag) + c.AddMethod(md, desc) + + desc = newDescriptor("bls12381Equal", smartcontract.BoolType, + manifest.NewParameter("x", smartcontract.InteropInterfaceType), + manifest.NewParameter("y", smartcontract.InteropInterfaceType)) + md = newMethodAndPrice(c.bls12381Equal, 1<<5, callflag.NoneFlag) + c.AddMethod(md, desc) + + desc = newDescriptor("bls12381Add", smartcontract.InteropInterfaceType, + manifest.NewParameter("x", smartcontract.InteropInterfaceType), + manifest.NewParameter("y", smartcontract.InteropInterfaceType)) + md = newMethodAndPrice(c.bls12381Add, 1<<19, callflag.NoneFlag) + c.AddMethod(md, desc) + + desc = newDescriptor("bls12381Mul", smartcontract.InteropInterfaceType, + manifest.NewParameter("x", smartcontract.InteropInterfaceType), + manifest.NewParameter("mul", smartcontract.ByteArrayType), + manifest.NewParameter("neg", smartcontract.BoolType)) + md = newMethodAndPrice(c.bls12381Mul, 1<<21, callflag.NoneFlag) + c.AddMethod(md, desc) + + desc = newDescriptor("bls12381Pairing", smartcontract.InteropInterfaceType, + manifest.NewParameter("g1", smartcontract.InteropInterfaceType), + manifest.NewParameter("g2", smartcontract.InteropInterfaceType)) + md = newMethodAndPrice(c.bls12381Pairing, 1<<23, callflag.NoneFlag) + c.AddMethod(md, desc) + return c } @@ -137,6 +176,287 @@ func curveFromStackitem(si stackitem.Item) (elliptic.Curve, error) { } } +func (c *Crypto) bls12381Serialize(_ *interop.Context, args []stackitem.Item) stackitem.Item { + val := args[0].(*stackitem.Interop).Value() + var res []byte + switch p := val.(type) { + case *bls12381.G1Affine: + compressed := p.Bytes() + res = compressed[:] + case *bls12381.G1Jac: + g1Affine := new(bls12381.G1Affine) + g1Affine.FromJacobian(p) + compressed := g1Affine.Bytes() + res = compressed[:] + case *bls12381.G2Affine: + compressed := p.Bytes() + res = compressed[:] + case *bls12381.G2Jac: + g2Affine := new(bls12381.G2Affine) + g2Affine.FromJacobian(p) + compressed := g2Affine.Bytes() + res = compressed[:] + case *bls12381.GT: + compressed := p.Bytes() + res = compressed[:] + default: + panic(errors.New("unknown bls12381 point type")) + } + return stackitem.NewByteArray(res) +} + +func (c *Crypto) bls12381Deserialize(_ *interop.Context, args []stackitem.Item) stackitem.Item { + buf, err := args[0].TryBytes() + if err != nil { + panic(fmt.Errorf("invalid serialized bls12381 point: %w", err)) + } + var res interface{} + switch l := len(buf); l { + case bls12381.SizeOfG1AffineCompressed: + g1Affine := new(bls12381.G1Affine) + _, err = g1Affine.SetBytes(buf) + if err != nil { + panic(fmt.Errorf("failed to decode bls12381 G1Affine point: %w", err)) + } + res = g1Affine + case bls12381.SizeOfG2AffineCompressed: + g2Affine := new(bls12381.G2Affine) + _, err = g2Affine.SetBytes(buf) + if err != nil { + panic(fmt.Errorf("failed to decode bls12381 G2Affine point: %w", err)) + } + res = g2Affine + case bls12381.SizeOfGT: + gt := new(bls12381.GT) + err := gt.SetBytes(buf) + if err != nil { + panic(fmt.Errorf("failed to decode GT point: %w", err)) + } + res = gt + } + return stackitem.NewInterop(res) +} + +func (c *Crypto) bls12381Equal(_ *interop.Context, args []stackitem.Item) stackitem.Item { + a := args[0].(*stackitem.Interop).Value() + b := args[1].(*stackitem.Interop).Value() + var res bool + switch x := a.(type) { + case *bls12381.G1Affine: + y, ok := b.(*bls12381.G1Affine) + if !ok { + panic(errors.New("y is not bls12381 G1Affine point")) + } + res = x.Equal(y) + case *bls12381.G1Jac: + y, ok := b.(*bls12381.G1Jac) + if !ok { + panic(errors.New("y is not bls12381 G1Jac point")) + } + res = x.Equal(y) + case *bls12381.G2Affine: + y, ok := b.(*bls12381.G2Affine) + if !ok { + panic(errors.New("y is not bls12381 G2Affine point")) + } + res = x.Equal(y) + case *bls12381.G2Jac: + y, ok := b.(*bls12381.G2Jac) + if !ok { + panic(errors.New("y is not bls12381 G2Jac point")) + } + res = x.Equal(y) + default: + panic(fmt.Errorf("unexpected x bls12381 point type: %T", x)) + } + return stackitem.NewBool(res) +} + +func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackitem.Item { + a := args[0].(*stackitem.Interop).Value() + b := args[1].(*stackitem.Interop).Value() + var res interface{} + switch x := a.(type) { + case *bls12381.G1Affine: + switch y := b.(type) { + case *bls12381.G1Affine: + xJac := new(bls12381.G1Jac) + xJac.FromAffine(x) + xJac.AddMixed(y) + res = xJac + case *bls12381.G1Jac: + yJac := new(bls12381.G1Jac) + yJac.Set(y) + yJac.AddMixed(x) + res = yJac + default: + panic("inconsistent point types") + } + case *bls12381.G1Jac: + resJac := new(bls12381.G1Jac) + resJac.Set(x) + switch y := b.(type) { + case *bls12381.G1Affine: + resJac.AddMixed(y) + case *bls12381.G1Jac: + resJac.AddAssign(y) + default: + panic("inconsistent") + } + res = resJac + case *bls12381.G2Affine: + switch y := b.(type) { + case *bls12381.G2Affine: + xJac := new(bls12381.G2Jac) + xJac.FromAffine(x) + xJac.AddMixed(y) + res = xJac + case *bls12381.G2Jac: + yJac := new(bls12381.G2Jac) + yJac.Set(y) + yJac.AddMixed(x) + res = yJac + default: + panic("inconsistent") + } + case *bls12381.G2Jac: + resJac := new(bls12381.G2Jac) + resJac.Set(x) + switch y := b.(type) { + case *bls12381.G2Affine: + resJac.AddMixed(y) + case *bls12381.G2Jac: + resJac.AddAssign(y) + default: + panic("invalid") + } + res = resJac + case *bls12381.GT: + resGT := new(bls12381.GT) + resGT.Set(x) + switch y := b.(type) { + case *bls12381.GT: + // It's multiplication, see https://github.com/neo-project/Neo.Cryptography.BLS12_381/issues/4. + resGT.Mul(x, y) + default: + panic("invalid") + } + res = resGT + default: + panic(fmt.Errorf("unexpected bls12381 point type: %T", x)) + } + return stackitem.NewInterop(res) +} + +func scalarFromBytes(bytes []byte, neg bool) (*fr.Element, error) { + alpha := new(fr.Element) + if len(bytes) != fr.Bytes { + return nil, fmt.Errorf("invalid multiplier: 32-bytes scalar is expected, got %d", len(bytes)) + } + // The input bytes are in the LE form, so we can't use fr.Element.SetBytesCanonical as far + // as it accepts BE. + v, err := fr.LittleEndian.Element((*[fr.Bytes]byte)(bytes)) + if err != nil { + return nil, fmt.Errorf("invalid multiplier: failed to decode scalar: %w", err) + } + *alpha = v + if neg { + alpha.Neg(alpha) + } + return alpha, nil +} + +func (c *Crypto) bls12381Mul(_ *interop.Context, args []stackitem.Item) stackitem.Item { + a := args[0].(*stackitem.Interop).Value() + mulBytes, err := args[1].TryBytes() + if err != nil { + panic(fmt.Errorf("invalid multiplier: %w", err)) + } + neg, err := args[2].TryBool() + if err != nil { + panic(fmt.Errorf("invalid negative argument: %w", err)) + } + alpha, err := scalarFromBytes(mulBytes, neg) + if err != nil { + panic(err) + } + alphaBi := new(big.Int) + alpha.BigInt(alphaBi) + + var res interface{} + switch x := a.(type) { + case *bls12381.G1Affine: + // The result is in Jacobian form in the reference implementation. + g1Jac := new(bls12381.G1Jac) + g1Jac.FromAffine(x) + g1Jac.ScalarMultiplication(g1Jac, alphaBi) + res = g1Jac + case *bls12381.G1Jac: + g1Jac := new(bls12381.G1Jac) + g1Jac.ScalarMultiplication(x, alphaBi) + res = g1Jac + case *bls12381.G2Affine: + // The result is in Jacobian form in the reference implementation. + g2Jac := new(bls12381.G2Jac) + g2Jac.FromAffine(x) + g2Jac.ScalarMultiplication(g2Jac, alphaBi) + res = g2Jac + case *bls12381.G2Jac: + g2Jac := new(bls12381.G2Jac) + g2Jac.ScalarMultiplication(x, alphaBi) + res = g2Jac + case *bls12381.GT: + gt := new(bls12381.GT) + + // C# implementation differs a bit from go's. They use double-and-add algorithm, see + // https://github.com/neo-project/Neo.Cryptography.BLS12_381/blob/844bc3a4f7d8ba2c545ace90ca124f8ada4c8d29/src/Neo.Cryptography.BLS12_381/Gt.cs#L102 + // and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Double-and-add, + // Pay attention that C#'s Gt.Double() squares (not doubles!) the initial GT point. + // Thus.C#'s scalar multiplication operation over Gt and Scalar is effectively an exponent. + // Go's exponent algorithm differs a bit from the C#'s double-and-add in that go's one + // uses 2-bits windowed method for multiplication. However, the resulting GT point is + // absolutely the same between two implementations. + gt.Exp(*x, alphaBi) + + res = gt + default: + panic(fmt.Errorf("unexpected bls12381 point type: %T", x)) + } + return stackitem.NewInterop(res) +} + +func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stackitem.Item { + a := args[0].(*stackitem.Interop).Value() + b := args[1].(*stackitem.Interop).Value() + var ( + x *bls12381.G1Affine + y *bls12381.G2Affine + ) + switch p := a.(type) { + case *bls12381.G1Affine: + x = p + case *bls12381.G1Jac: + x = new(bls12381.G1Affine) + x.FromJacobian(p) + default: + panic(fmt.Errorf("unexpected bls12381 point type (g1): %T", x)) + } + switch p := b.(type) { + case *bls12381.G2Affine: + y = p + case *bls12381.G2Jac: + y = new(bls12381.G2Affine) + y.FromJacobian(p) + default: + panic(fmt.Errorf("unexpected bls12381 point type (g2): %T", x)) + } + gt, err := bls12381.Pair([]bls12381.G1Affine{*x}, []bls12381.G2Affine{*y}) + if err != nil { + panic(fmt.Errorf("failed to perform pairing operation")) + } + return stackitem.NewInterop(interface{}(>)) +} + // Metadata implements the Contract interface. func (c *Crypto) Metadata() *interop.ContractMD { return &c.ContractMD diff --git a/pkg/core/native/crypto_test.go b/pkg/core/native/crypto_test.go index 11cc87db7..47688e2c2 100644 --- a/pkg/core/native/crypto_test.go +++ b/pkg/core/native/crypto_test.go @@ -7,6 +7,7 @@ import ( "math/big" "testing" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/vm" @@ -141,3 +142,63 @@ func testECDSAVerify(t *testing.T, curve NamedCurve) { runCase(t, false, true, msg, priv.PublicKey().Bytes(), sign, int64(curve)) }) } + +func TestCryptolib_ScalarFromBytes_Compat(t *testing.T) { + r2Ref := &fr.Element{ + 0xc999_e990_f3f2_9c6d, + 0x2b6c_edcb_8792_5c23, + 0x05d3_1496_7254_398f, + 0x0748_d9d9_9f59_ff11, + } // R2 Scalar representation taken from the https://github.com/neo-project/Neo.Cryptography.BLS12_381/blob/844bc3a4f7d8ba2c545ace90ca124f8ada4c8d29/src/Neo.Cryptography.BLS12_381/ScalarConstants.cs#L55 + + tcs := map[string]struct { + bytes []byte + expected *fr.Element + shouldFail bool + }{ + "zero": { + bytes: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + expected: new(fr.Element).SetZero(), + }, + "one": { + bytes: []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + expected: new(fr.Element).SetOne(), + }, + "R2": { + bytes: []byte{254, 255, 255, 255, 1, 0, 0, 0, 2, 72, 3, 0, 250, 183, 132, 88, 245, 79, 188, 236, 239, 79, 140, 153, 111, 5, 197, 172, 89, 177, 36, 24}, + expected: r2Ref, + }, + "negative": { + bytes: []byte{0, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115}, + }, + "modulus": { + bytes: []byte{1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115}, + shouldFail: true, + }, + "larger than modulus": { + bytes: []byte{2, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115}, + shouldFail: true, + }, + "larger than modulus 2": { + bytes: []byte{1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216, 58, 51, 72, 125, 157, 41, 83, 167, 237, 115}, + shouldFail: true, + }, + "larger than modulus 3": { + bytes: []byte{1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 116}, + shouldFail: true, + }, + } + for name, tc := range tcs { + t.Run(name, func(t *testing.T) { + actual, err := scalarFromBytes(tc.bytes, false) + if tc.shouldFail { + require.Error(t, err) + } else { + require.NoError(t, err) + if tc.expected != nil { + require.Equal(t, tc.expected, actual) + } + } + }) + } +} diff --git a/pkg/core/native/native_test/cryptolib_test.go b/pkg/core/native/native_test/cryptolib_test.go new file mode 100644 index 000000000..bccda21a2 --- /dev/null +++ b/pkg/core/native/native_test/cryptolib_test.go @@ -0,0 +1,352 @@ +package native_test + +import ( + "encoding/hex" + "strconv" + "strings" + "testing" + + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/neotest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/stretchr/testify/require" +) + +// A set of points taken from the reference implementation for compatibility tests. +var ( + g1 []byte + g2 []byte + gt []byte + notG1, notG2 []byte +) + +func init() { + g1, _ = hex.DecodeString("97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb") + g2, _ = hex.DecodeString("93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8") + gt, _ = hex.DecodeString("0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b67663104c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef03350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a211b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba5706fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a19f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d018107154f25a764bd3c79937a45b84546da634b8f6be14a8061e55cceba478b23f7dacaa35c8ca78beae9624045b4b601b2f522473d171391125ba84dc4007cfbf2f8da752f7c74185203fcca589ac719c34dffbbaad8431dad1c1fb597aaa5193502b86edb8857c273fa075a50512937e0794e1e65a7617c90d8bd66065b1fffe51d7a579973b1315021ec3c19934f1368bb445c7c2d209703f239689ce34c0378a68e72a6b3b216da0e22a5031b54ddff57309396b38c881c4c849ec23e87089a1c5b46e5110b86750ec6a532348868a84045483c92b7af5af689452eafabf1a8943e50439f1d59882a98eaa0170f1250ebd871fc0a92a7b2d83168d0d727272d441befa15c503dd8e90ce98db3e7b6d194f60839c508a84305aaca1789b6") + notG1, _ = hex.DecodeString("8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") + notG2, _ = hex.DecodeString("8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") +} + +func newCryptolibClient(t *testing.T) *neotest.ContractInvoker { + return newNativeClient(t, nativenames.CryptoLib) +} + +func TestCryptolib_TestG1_Compat(t *testing.T) { + c := newCryptolibClient(t) + cryptoInvoker := c.WithSigners(c.Committee) + + // Use testinvoke because the return value of this method is InteropInterface. + stack, err := cryptoInvoker.TestInvoke(t, "bls12381Deserialize", g1) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.InteropT, itm.Type()) + actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.G1Affine) + require.True(t, ok) + arr := actual.Bytes() // the result in compressed form. + // Expected value is taken from the reference test. + require.Equal(t, "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", + hex.EncodeToString(arr[:])) +} + +func TestCryptolib_TestG2_Compat(t *testing.T) { + c := newCryptolibClient(t) + cryptoInvoker := c.WithSigners(c.Committee) + + // Use testinvoke because the return value of this method is InteropInterface. + stack, err := cryptoInvoker.TestInvoke(t, "bls12381Deserialize", g2) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.InteropT, itm.Type()) + actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.G2Affine) + require.True(t, ok) + arr := actual.Bytes() // the result in compressed form. + // Expected value is taken from the reference test. + require.Equal(t, "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8", + hex.EncodeToString(arr[:])) +} + +func TestCryptolib_TestNotG1_Compat(t *testing.T) { + c := newCryptolibClient(t) + cryptoInvoker := c.WithSigners(c.Committee) + + cryptoInvoker.InvokeFail(t, "failed to decode bls12381 G1Affine point: invalid point: subgroup check failed", "bls12381Deserialize", notG1) +} + +func TestCryptolib_TestNotG2_Compat(t *testing.T) { + c := newCryptolibClient(t) + cryptoInvoker := c.WithSigners(c.Committee) + + cryptoInvoker.InvokeFail(t, "failed to decode bls12381 G2Affine point: invalid point: subgroup check failed", "bls12381Deserialize", notG2) +} + +func TestCryptolib_TestBls12381Add_Compat(t *testing.T) { + c := newCryptolibClient(t) + + script := io.NewBufBinWriter() + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, gt) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, gt) + emit.Opcodes(script.BinWriter, opcode.PUSH2, opcode.PACK) + emit.AppCallNoArgs(script.BinWriter, c.Hash, "bls12381Add", callflag.All) + + stack, err := c.TestInvokeScript(t, script.Bytes(), c.Signers) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.InteropT, itm.Type()) + actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + require.True(t, ok) + arr := actual.Bytes() + // Expected value is taken from the reference test. + require.Equal(t, strings.ToLower("079AB7B345EB23C944C957A36A6B74C37537163D4CBF73BAD9751DE1DD9C68EF72CB21447E259880F72A871C3EDA1B0C017F1C95CF79B22B459599EA57E613E00CB75E35DE1F837814A93B443C54241015AC9761F8FB20A44512FF5CFC04AC7F0F6B8B52B2B5D0661CBF232820A257B8C5594309C01C2A45E64C6A7142301E4FB36E6E16B5A85BD2E437599D103C3ACE06D8046C6B3424C4CD2D72CE98D279F2290A28A87E8664CB0040580D0C485F34DF45267F8C215DCBCD862787AB555C7E113286DEE21C9C63A458898BEB35914DC8DAAAC453441E7114B21AF7B5F47D559879D477CF2A9CBD5B40C86BECD071280900410BB2751D0A6AF0FE175DCF9D864ECAAC463C6218745B543F9E06289922434EE446030923A3E4C4473B4E3B1914081ABD33A78D31EB8D4C1BB3BAAB0529BB7BAF1103D848B4CEAD1A8E0AA7A7B260FBE79C67DBE41CA4D65BA8A54A72B61692A61CE5F4D7A093B2C46AA4BCA6C4A66CF873D405EBC9C35D8AA639763720177B23BEFFAF522D5E41D3C5310EA3331409CEBEF9EF393AA00F2AC64673675521E8FC8FDDAF90976E607E62A740AC59C3DDDF95A6DE4FBA15BEB30C43D4E3F803A3734DBEB064BF4BC4A03F945A4921E49D04AB8D45FD753A28B8FA082616B4B17BBCB685E455FF3BF8F60C3BD32A0C185EF728CF41A1B7B700B7E445F0B372BC29E370BC227D443C70AE9DBCF73FEE8ACEDBD317A286A53266562D817269C004FB0F149DD925D2C590A960936763E519C2B62E14C7759F96672CD852194325904197B0B19C6B528AB33566946AF39B"), + hex.EncodeToString(arr[:])) +} + +func TestCryptolib_TestBls12381Mul_Compat(t *testing.T) { + c := newCryptolibClient(t) + + check := func(t *testing.T, neg bool, expected string) { + data := make([]byte, fr.Bytes) + data[0] = 0x03 + script := io.NewBufBinWriter() + if neg { + emit.Opcodes(script.BinWriter, opcode.PUSHT) + } else { + emit.Opcodes(script.BinWriter, opcode.PUSHF) + } + emit.Bytes(script.BinWriter, data) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, gt) + emit.Opcodes(script.BinWriter, opcode.PUSH3, opcode.PACK) + emit.AppCallNoArgs(script.BinWriter, c.Hash, "bls12381Mul", callflag.All) + + stack, err := c.TestInvokeScript(t, script.Bytes(), c.Signers) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.InteropT, itm.Type()) + actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + require.True(t, ok) + arr := actual.Bytes() + // Expected value is taken from the reference test. + require.Equal(t, strings.ToLower(expected), hex.EncodeToString(arr[:])) + } + check(t, false, "18B2DB6B3286BAEA116CCAD8F5554D170A69B329A6DE5B24C50B8834965242001A1C58089FD872B211ACD3263897FA660B117248D69D8AC745283A3E6A4CCEC607F6CF7CEDEE919575D4B7C8AE14C36001F76BE5FCA50ADC296EF8DF4926FA7F0B55A75F255FE61FC2DA7CFFE56ADC8775AAAB54C50D0C4952AD919D90FB0EB221C41ABB9F2352A11BE2D7F176ABE41E0E30AFB34FC2CE16136DE66900D92068F30011E9882C0A56E7E7B30F08442BE9E58D093E1888151136259D059FB539210D635BC491D5244A16CA28FDCF10546EC0F7104D3A419DDC081BA30ECB0CD2289010C2D385946229B7A9735ADC82736914FE61AD26C6C38B787775DE3B939105DE055F8D7004358272A0823F6F1787A7ABB6C3C59C8C9CBD1674AC900512632818CDD273F0D38833C07467EAF77743B70C924D43975D3821D47110A358757F926FCF970660FBDD74EF15D93B81E3AA290C78F59CBC6ED0C1E0DCBADFD11A73EB7137850D29EFEB6FA321330D0CF70F5C7F6B004BCF86AC99125F8FECF83157930BEC2AF89F8B378C6D7F63B0A07B3651F5207A84F62CEE929D574DA154EBE795D519B661086F069C9F061BA3B53DC4910EA1614C87B114E2F9EF328AC94E93D00440B412D5AE5A3C396D52D26C0CDF2156EBD3D3F60EA500C42120A7CE1F7EF80F15323118956B17C09E80E96ED4E1572461D604CDE2533330C684F86680406B1D3EE830CBAFE6D29C9A0A2F41E03E26095B713EB7E782144DB1EC6B53047FCB606B7B665B3DD1F52E95FCF2AE59C4AB159C3F98468C0A43C36C022B548189B6") + check(t, true, "014E367F06F92BB039AEDCDD4DF65FC05A0D985B4CA6B79AA2254A6C605EB424048FA7F6117B8D4DA8522CD9C767B0450EEF9FA162E25BD305F36D77D8FEDE115C807C0805968129F15C1AD8489C32C41CB49418B4AEF52390900720B6D8B02C0EAB6A8B1420007A88412AB65DE0D04FEECCA0302E7806761483410365B5E771FCE7E5431230AD5E9E1C280E8953C68D0BD06236E9BD188437ADC14D42728C6E7177399B6B5908687F491F91EE6CCA3A391EF6C098CBEAEE83D962FA604A718A0C9DB625A7AAC25034517EB8743B5868A3803B37B94374E35F152F922BA423FB8E9B3D2B2BBF9DD602558CA5237D37420502B03D12B9230ED2A431D807B81BD18671EBF78380DD3CF490506187996E7C72F53C3914C76342A38A536FFAED478318CDD273F0D38833C07467EAF77743B70C924D43975D3821D47110A358757F926FCF970660FBDD74EF15D93B81E3AA290C78F59CBC6ED0C1E0DCBADFD11A73EB7137850D29EFEB6FA321330D0CF70F5C7F6B004BCF86AC99125F8FECF83157930BEC2AF89F8B378C6D7F63B0A07B3651F5207A84F62CEE929D574DA154EBE795D519B661086F069C9F061BA3B53DC4910EA1614C87B114E2F9EF328AC94E93D00440B412D5AE5A3C396D52D26C0CDF2156EBD3D3F60EA500C42120A7CE1F7EF80F15323118956B17C09E80E96ED4E1572461D604CDE2533330C684F86680406B1D3EE830CBAFE6D29C9A0A2F41E03E26095B713EB7E782144DB1EC6B53047FCB606B7B665B3DD1F52E95FCF2AE59C4AB159C3F98468C0A43C36C022B548189B6") +} + +func TestCryptolib_TestBls12381Pairing_Compat(t *testing.T) { + c := newCryptolibClient(t) + + script := io.NewBufBinWriter() + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, g2) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, g1) + emit.Opcodes(script.BinWriter, opcode.PUSH2, opcode.PACK) + emit.AppCallNoArgs(script.BinWriter, c.Hash, "bls12381Pairing", callflag.All) + + stack, err := c.TestInvokeScript(t, script.Bytes(), c.Signers) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.InteropT, itm.Type()) + actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + require.True(t, ok) + arr := actual.Bytes() + // Expected value is taken from the reference test. + require.Equal(t, strings.ToLower("0F41E58663BF08CF068672CBD01A7EC73BACA4D72CA93544DEFF686BFD6DF543D48EAA24AFE47E1EFDE449383B67663104C581234D086A9902249B64728FFD21A189E87935A954051C7CDBA7B3872629A4FAFC05066245CB9108F0242D0FE3EF03350F55A7AEFCD3C31B4FCB6CE5771CC6A0E9786AB5973320C806AD360829107BA810C5A09FFDD9BE2291A0C25A99A211B8B424CD48BF38FCEF68083B0B0EC5C81A93B330EE1A677D0D15FF7B984E8978EF48881E32FAC91B93B47333E2BA5706FBA23EB7C5AF0D9F80940CA771B6FFD5857BAAF222EB95A7D2809D61BFE02E1BFD1B68FF02F0B8102AE1C2D5D5AB1A19F26337D205FB469CD6BD15C3D5A04DC88784FBB3D0B2DBDEA54D43B2B73F2CBB12D58386A8703E0F948226E47EE89D018107154F25A764BD3C79937A45B84546DA634B8F6BE14A8061E55CCEBA478B23F7DACAA35C8CA78BEAE9624045B4B601B2F522473D171391125BA84DC4007CFBF2F8DA752F7C74185203FCCA589AC719C34DFFBBAAD8431DAD1C1FB597AAA5193502B86EDB8857C273FA075A50512937E0794E1E65A7617C90D8BD66065B1FFFE51D7A579973B1315021EC3C19934F1368BB445C7C2D209703F239689CE34C0378A68E72A6B3B216DA0E22A5031B54DDFF57309396B38C881C4C849EC23E87089A1C5B46E5110B86750EC6A532348868A84045483C92B7AF5AF689452EAFABF1A8943E50439F1D59882A98EAA0170F1250EBD871FC0A92A7B2D83168D0D727272D441BEFA15C503DD8E90CE98DB3E7B6D194F60839C508A84305AACA1789B6"), + hex.EncodeToString(arr[:])) +} + +func TestCryptolib_TestBls12381Equal_Compat(t *testing.T) { + c := newCryptolibClient(t) + + script := io.NewBufBinWriter() + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, g1) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, g1) + emit.Opcodes(script.BinWriter, opcode.PUSH2, opcode.PACK) + emit.AppCallNoArgs(script.BinWriter, c.Hash, "bls12381Equal", callflag.All) + + stack, err := c.TestInvokeScript(t, script.Bytes(), c.Signers) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.BooleanT, itm.Type()) + require.True(t, itm.Value().(bool)) +} + +// pointType represents one of the BLS12-381 point types and is used for tests only. +type pointType byte + +const ( + g1JacP pointType = iota + g2JacP + gtP +) + +// Data used for this test are generated by C# library and taken from the reference +// tests. +func TestCryptolib_TestBls12381Mul_CompatCustom(t *testing.T) { + tcs := []struct { + name string + point string // serialized hex-encoded point representation. + mul string // serialized hex-encoded Scalar multiplier representation. + neg bool // whether Scalar must be negative. + expectedTyp pointType // point type of the expected result. + expected string // serialized hex-encoded result of (point * mul) multiplication taken from the reference implementation. + }{ + { + name: "GT mul by positive scalar", + point: "14fd52fe9bfd08bbe23fcdf1d3bc5390c62e75a8786a72f8a343123a30a7c5f8d18508a21a2bf902f4db2c068913bc1c130e7ce13260d601c89ee717acfd3d4e1d80f409dd2a5c38b176f0b64d3d0a224c502717270dfecf2b825ac24608215c0d7fcfdf3c1552ada42b7e0521bc2e7389436660c352ecbf2eedf30b77b6b501df302399e6240473af47abe56fc974780c214542fcc0cf10e3001fa5e82d398f6ba1ddd1ccdf133bfd75e033eae50aec66bd5e884b8c74d4c1c6ac7c01278ac5164a54600cb2e24fec168f82542fbf98234dbb9ddf06503dc3c497da88b73db584ba19e685b1b398b51f40160e6c8f0917b4a68dedcc04674e5f5739cf0d845ba801263f712ed4ddda59c1d9909148e3f28124ae770682c9b19233bf0bcfa00d05bfe708d381b066b83a883ba8251ce2ea6772cbde51e1322d82b2c8a026a2153f4822e20cb69b8b05003ee74e09cb481728d688caa8a671f90b55488e272f48c7c5ae32526d3635a5343eb02640358d9ac445c76a5d8f52f653bbaee04ba5ce03c68b88c25be6fd3611cc21c9968e4f87e541beeccc5170b8696a439bb666ad8a6608ab30ebc7dfe56eaf0dd9ab8439171a6e4e0d608e6e6c8ac5ddcf8d6d2a950d06051e6b6c4d3feb6dc8dac2acadd345cadfb890454a2101a112f7471f0e001701f60f3d4352c4d388c0f198854908c0e939719709c1b3f82d2a25cc7156a3838bc141e041c259849326fbd0839f15cea6a78b89349dcd1c03695a74e72d3657af4ee2cf267337bc96363ef4a1c5d5d7a673cc3a3c1a1350043f99537d62", + mul: "8463159bd9a1d1e1fd815172177ec24c0c291353ed88b3d1838fd9d63b1efd0b", + neg: false, + expectedTyp: gtP, + expected: "03dc980ce0c037634816f9fc1edb2e1807e38a51f838e3a684f195d6c52c41d6a8a5b64d57d3fda507bebe3bd4b661af0e4f7c46754b373c955982b4d64a24838cbc010d04b6ceb499bf411d114dab77eaf70f96ab66c2868dcd63706b602b07010c487fc16c90b61e1c2ad33c31c8f3fc86d114a59b127ac584640f149f3597102c55dd1ed8a305a10c052c0a724e570fc079e410123735a6144ccd88d9e4e91d7b889f80b18a1741eacd6f244fce3cf57795e619b6648b9238053b4b8e4ed6115c905fbcb61525370667ff43144e12b700662a7344ac1af97f11d09779ca6865973f95ff318b42ff00df7c6eb958160947a0ab6cb25534af51ce1f0b076907c6eb5ce0760bd7670cab8814cc3308766eb6e52b5427dbf85d6424990fd3354515ab880358bc55075a08f36b855694c02ee0bd63adefe235ba4ee41dc600a1cae950c1dc760bf7b1edd8712e9e90eebb19de705e29f4feb870129441bd4b9e91c3d37e60c12fa79a5b1e4132ba9498044e6fbf2de37e4dd88b4e9095b46f122019e73a561ba3967b32813c3ec74b8e1b6ab619eeab698e6638114cb29ca9c3d353192db3d392fee2b4dfdfd36b13db440534dd754417cffcd470f4d4cfdcb6d7896181c27b8b30622d7a4ca0a05a7ea67ca011cab07738235b115bbd330239691487d2de5d679a8cad2fe5c7fff16b0b0f3f929619c8005289c3d7ffe5bcd5ea19651bfc9366682a2790cab45ee9a98815bb7e58dc666e2209cd9d700546cf181ceb43fe719243930984b696b0d18d4cd1f5d960e149a2b753b1396e4f8f3b16", + }, + { + name: "GT mul by positive scalar", + point: "0e0c651ff4a57adebab1fa41aa8d1e53d1cf6a6cc554282a24bb460ea0dc169d3ede8b5a93a331698f3926d273a729aa18788543413f43ada55a6a7505e3514f0db7e14d58311c3211962a350bcf908b3af90fbae31ff536fe542328ad25cd3e044a796200c8a8ead7edbc3a8a37209c5d37433ca7d8b0e644d7aac9726b524c41fef1cf0d546c252d795dffc445ddee07041f57c4c9a673bd314294e280ab61390731c09ad904bdd7b8c087d0ce857ea86e78f2d98e75d9b5e377e5751d67cf1717cbce31bc7ea6df95132549bf6d284a68005c53228127671afa54ecfd4c5c4debc437c4c6d9b9aeeee8b4159a5691128c6dc68b309fd822b14f3ce8ff390bd6834d30147e8ab2edc59d0d7b14cc13c79e6eed5fd6cae1795ba3760345d59c0c585f79c900902515e3e95938d9929ad8310e71fc7fd54be9c7529f244af40dadaca0b3bd8afd911f24b261079de48b161dd8f340d42bd84e717275193a0375d9e10fbe048bbea30abd64d3fe085c15b9be192f7baaa0b3a9658bcbb4292a0c0149beb30e54b065a75df45e5da77583f4471e3454cea90a00b5a9a224c15e2ebe01f0ab8aa86591c1012c618d41fdce07ecfcaddc8dc408b7176b79d8711a4161a56f41a5be6714cbcaa70e53387ab049826ac9e636640bc6da919e52f86f3209572b62d9bfd48bd2b5ef217932237b90a70d40167623d0f25a73b753e3214310bc5b6e017aebc1a9ca0c8067a97da6162c70cc754f1b2ac3b05ba834712758c8de4641ef09237edf588989182ab3047ee42da2b840fd3633fa0f34d46ad961", + mul: "06c93a0ebbc8b5cd3af798b8f72442a67aa885b395452a08e48ec80b4e9f1b3f", + neg: false, + expectedTyp: gtP, + expected: "0d6d91f120ab61e14a3163601ce584f053f1de9dc0a548b6fbf37a776ec7b6ce6b866e8c8b0fc0ac8d32a9a9747c98bf0e6aee5bddd058313958bfc3ac1ed75284628f92bb9b99fee101e1bee9d74bad7812287ea76bdbe07f20ff9998d6e9f016689be1cfc4337433644a679945d5c34a6d4dd984c56d6c28428438268b385cb1d86f69b0377b18f9b084e1d0b6596213233d559a1b5caaba38be853f667fc3b1f9f2c4c9020584502ff5f370b0aba7768a1a4ca4328bc3c7be2bc9c3949f5e16fd3bfc16b11da41b7393e56e777640b000db15b6e6192e5c59dfece90c6fc0b6071fdeef7061974b5e967c5b88b1db09f7c92077c16f56aff9e9627f5e09928e965daee17d05ef3fdc0c502b649db473b5b2bba867d829b04d32cfeab7387614190b265382378f75e4e085a5537d4f200fe56b74b7c52c5546b30d51862e1ac1f60eba157880090a42ea9b0295529f134c1fc90f19a4c20dc0be105b07e0c67218b2f5619a66d8d770d539658eb74c255743e5847bc437fef3077d0a6c4f17198d63cf17e6957f2ad9449269af009635697e92254a3f67be9b8760fd9f974826a1829fedb4cf66968b7c63b0c88c510da12e6d52255256757afa03ad29b5c1624292ef7eb463eb4bc81ac7426f36db3fe1513bdd31bc138bfe903bbb0c5207001335f708c16cea15ef6b77c3215326a779e927b8c2081b15adffe71ba75164e376665533c5bb59373b27dbe93a0a0e1796d821a1b9ff01846446c5ad53064cb9b941f97aa870285395e1a44c9f6e5144ea5a0cf57b9fdd962a5ec3ff1f72fe", + }, + { + name: "GT mul by positive scalar", + point: "0e0c651ff4a57adebab1fa41aa8d1e53d1cf6a6cc554282a24bb460ea0dc169d3ede8b5a93a331698f3926d273a729aa18788543413f43ada55a6a7505e3514f0db7e14d58311c3211962a350bcf908b3af90fbae31ff536fe542328ad25cd3e044a796200c8a8ead7edbc3a8a37209c5d37433ca7d8b0e644d7aac9726b524c41fef1cf0d546c252d795dffc445ddee07041f57c4c9a673bd314294e280ab61390731c09ad904bdd7b8c087d0ce857ea86e78f2d98e75d9b5e377e5751d67cf1717cbce31bc7ea6df95132549bf6d284a68005c53228127671afa54ecfd4c5c4debc437c4c6d9b9aeeee8b4159a5691128c6dc68b309fd822b14f3ce8ff390bd6834d30147e8ab2edc59d0d7b14cc13c79e6eed5fd6cae1795ba3760345d59c0c585f79c900902515e3e95938d9929ad8310e71fc7fd54be9c7529f244af40dadaca0b3bd8afd911f24b261079de48b161dd8f340d42bd84e717275193a0375d9e10fbe048bbea30abd64d3fe085c15b9be192f7baaa0b3a9658bcbb4292a0c0149beb30e54b065a75df45e5da77583f4471e3454cea90a00b5a9a224c15e2ebe01f0ab8aa86591c1012c618d41fdce07ecfcaddc8dc408b7176b79d8711a4161a56f41a5be6714cbcaa70e53387ab049826ac9e636640bc6da919e52f86f3209572b62d9bfd48bd2b5ef217932237b90a70d40167623d0f25a73b753e3214310bc5b6e017aebc1a9ca0c8067a97da6162c70cc754f1b2ac3b05ba834712758c8de4641ef09237edf588989182ab3047ee42da2b840fd3633fa0f34d46ad961", + mul: "b0010000000000005e0000000000000071f30400000000006d9189c813000000", + neg: false, + expectedTyp: gtP, + expected: "0919ad29cdbe0b6bbd636fbe3c8930a1b959e5aa37294a6cc7d018e2776580768bb98bf91ce1bc97f2e6fa647e7dad7b15db564645d2e4868129ed414b7e369e831b8ff93997a22b6ca0e2ba288783f535aed4b44cf3e952897db1536da18a120a70da2b9dd901bd12a5a7047d3b6346ba1aea53b642b7355a91f957687fccd840ef24af100d0ada6b49e35183456ec30b505098526b975477b6ca0273d3a841c85e4a8319b950e76ec217a4f939844baa6b875a4046a30c618636fe9b25c620030f31044f883789945c2bcb75d7d4099b2bc97665e75c1bee27bc3864e7e5e2ccb57a9da0b57be1a6aca217a6cfda090c4fd222f7b8cfdc32969da4fe8828a59ee1314546efdf99ef7ede1a42df6e7a126fe83b4c41b5e70a56bd9ab499f7e80e27a08884be05f1d2a527417fc6e30448333c0724463bf92d722ef5fd6f06949e294e6f941976d24c856038b55a2ec200d14d958a688f23b572993bd0f18cbbc20defe88e423b262c552dcc4d9f63ad78e85efbcea9449f81f39e1a887eb79b07056bb5a672444e240660617ba7a40985a622c687c1d05c12cee7b086abfc5f39a83a5ad7638ee559f710013b772d4207924687cb30100bcd4e8c83c9fa19dce7785bf3ae7681a0968fd9661c990e2dace05902dceeed65aacf51a04e72f0fd04858ea70fb72f2a3807dc1839a385d85b536abfd3ec76d4931b3bc5ec4d90e2ebc0342567c9507abdfafa602fc6983f13f20eb26b4169dc3908109fe3c1887db4be8f30edad989dc8caa234f9818ac488b110ad30a30f769277168650b6910e", + }, + { + name: "GT mul by negative scalar", + point: "0bdbfc3b68e7067630a1908de2ce15e1890d57b855ffc2ee0fe765293581c304d0507254fd9921d8ff4bff3185b1e8ae017091a6b9e243c3108b4302f30e2f4cb452c4574d23d06942cf915fb0b64c3546aa0bfbba5182dc42b63ebd09cd950f06ebf85ff360032e63d5422fed5969b80ed4abaf58d29317d9cf8e5a55744993ffc0ccc586a187c63f9c47d4b41870aa0fd73e13a4f7d3b072407a3bfa6539f8d56856542b17326ab77833df274e61a41c237a6dbf20a333698a675fded6ab1a114891795eabbedcb81590ff9bfb4b23b66c8b8376a69cf58511c80f3ac83d52c0c950be8c30d01108479f232d8e4e8919d869dc85db0b9d6ccf40eb8f8ab08e43a910c341737a55e751fa4a097ee82c5ac83d38c543d957bd9850af16039d1a00c96575d2ee24e9990b3401153446aa6593d3afb6ce7ca57d6432b8dda31aaa1a08834ad38deae5a807d11663adc5c20ae7227a2cbb7917d1489175b89ed1ba415e4fc55b7d0a286caf2f5f40b0dd39cdd8fc8c271d8a7ae952fe6ece5f7c1019bfab0167af86314a73bfa37fd16bc6edff6d9ee75610a4eec1818c668ef9f509b1cdd54542e73dc0e343a4fd6e3bb618540c1d060b60b63b645a895105425eb813b08b6ac91be3145da04040f2a45ffcf06e96b685519fca93b0f15238dc0e030c2199127ba82fa8a193f5f01ae24270e9669923653db38cae711d68169aa25df51a8915f3f8219892f4f5e67d550b00910011685017dcc1777a9d48689ce590d57c1fc942d49cfad0ed7efc0169a95d7e7378af26bafb90d1619bcdab64cd", + mul: "688e58217305c1fd2fe0637cbd8e7414d4d0a2113314eb05592f97930d23b34d", + neg: true, + expectedTyp: gtP, + expected: "056fdc84f044148950c0b7c4c0613f5710fcaeb1b023b9d8f814dc39d48702db70ce41aa276566960e37237f22b086b017b9ed0e264e2b7872c8a7affb8b9f847a528d092a038dab4ac58d3a33d30e2e5078b5e39ebb7441c56ae7556b63ecd6139ed9be1c5eb9f987cc704c913c1e23d44d2e04377347f6c471edc40cdb2cd4e32c396194363cd21ceff9bedbd164a41050e701012f0456383210f8054e76c0906e3f37e10d4a3d6342e79e39d566ea785b385bb692cddbd6c16456dfabf19f0f84c27ec4bce096af0369ac070747cd89d97bc287afe5ed5e495ed2d743adbd8eec47df6c3a69628e803e23d824845800e44a8d874756a7541128892e55e9df1d1fe0583ef967db6740617a9ff50766866c0fa631aed8639cd0c13d3d6f6f210b340ee315caec4cc31c916d651db5e002e259fca081fb605258ccf692d786bd5bb45a054c4d8498ac2a7fa241870df60ba0fd8a2b063740af11e7530db1e758a8e2858a443104b8337e18c083035768a0e93126f116bb9c50c8cebe30e0ceaa0c0b53eb2b6a1f96b34b6cc36f3417edda184e19ae1790d255337f14315323e1d2d7382b344bdc0b6b2cfab5837c24c916640ca351539d5459389a9c7f9b0d79e04e4a8392e0c2495dcecf7d48b10c7043825b7c6709108d81856ebf98385f0d099e6521714c48b8eb5d2e97665375175f47c57d427d35a9dc44064a99d1c079028e36d34540baba947333ab3c8976b801ea48578159f041e740ea5bf73c1de3c1043a6e03311d0f2463b72694249ccc5d603e4a93cfd8a6713fb0470383c23f", + }, + { + name: "GT mul by zero scalar", + point: "176ec726aa447f1791e69fc70a71103c84b17385094ef06a9a0235ac7241f6635377f55ad486c216c8701d61ea2ace3e05ca1605f238dc8f29f868b795e45645c6f7ff8d9d8ffd77b5e149b0325c2a8f24dde40e80a3381ae72a9a1104ef02d70af7cf8f2fe6ff38961b352b0fde6f8536424fc9aa5805b8e12313bdfc01d5c1db1c0a37654c307fbd252c265dcbfc040ee5605ffd6ac20aab15b0343e47831f4157a20ecedd7350d2cf070c0c7d423786fd97aa7236b99f4462fb23e173528815bf2cf3ccbfc38303fa8154d70ee5e1e3158cbb14d5c87a773cbe948a5cfec2763c5e7129940906920aed344453b0f801760fd3eac8e254ce8e0ae4edd30c914bea9e2935acd4a6a9d42d185a9a6e786c8e462b769b2112423f6591b093347718897438ba918b9e4525888194b20ee17709f7dea319cfd053bb1c222783340326953fd3763eb6feaaa4d1458ee6ca001818ad88222a97e43a71dca8d2abaef70657b9ff7b94ca422d0c50ddb4265fa35514ed534217ce2f0219c6985ec2827a0ee1dc17940926551072d693d89e36e6d14162f414b52587e5612ed4a562c9ac15df9d5fa68ccf61d52fea64b2f5d7a600e0a8fa735105bc9a2ecb69b6d9161e55a4ccdc2285164c6846fa5bdc106d1e0693ebd5fe86432e5e88c55f0159ec3217332c8492332dfbd93970f002a6a05f23484e081f38815785e766779c843765d58b2444295a87939ad7f8fa4c11e8530a62426063c9a57cf3481a00372e443dc014fd6ef4723dd4636105d7ce7b96c4b2b3b641c3a2b6e0fa9be6187e5bfaf9", + mul: "0000000000000000000000000000000000000000000000000000000000000000", + neg: false, + expectedTyp: gtP, + expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + }, + { + name: "G1Affine mul by positive scalar", + point: "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8", + mul: "8463159bd9a1d1e1fd815172177ec24c0c291353ed88b3d1838fd9d63b1efd0b", + neg: false, + expectedTyp: g1JacP, + expected: "ae85e3e2d677c9e3424ed79b5a7554262c3d6849202b84d2e7024e4b1f2e9dd3f7cf20b807a9f2a67d87e47e9e94d361", + }, + { + name: "G1Affine mul by negative scalar", + point: "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8", + mul: "8463159bd9a1d1e1fd815172177ec24c0c291353ed88b3d1838fd9d63b1efd0b", + neg: true, + expectedTyp: g1JacP, + expected: "8e85e3e2d677c9e3424ed79b5a7554262c3d6849202b84d2e7024e4b1f2e9dd3f7cf20b807a9f2a67d87e47e9e94d361", + }, + { + name: "G1Affine mul by zero scalar", + point: "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8", + mul: "0000000000000000000000000000000000000000000000000000000000000000", + neg: false, + expectedTyp: g1JacP, + expected: "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + { + name: "G2Affine mul by positive scalar", + point: "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365", + mul: "cbfffe3e37e53e31306addde1a1725641fbe88cd047ee7477966c44a3f764b47", + neg: false, + expectedTyp: g2JacP, + expected: "88ae9bba988e854877c66dfb7ff84aa5e107861aa51d1a2a8dac2414d716a7e219bc4b0239e4b12d2182f57b5eea82830639f2e6713098ae8d4b4c3942f366614bac35c91c83ecb57fa90fe03094aca1ecd3555a7a6fdfa2417b5bb06917732e", + }, + { + name: "G2Affine mul by negative scalar", + point: "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365", + mul: "cbfffe3e37e53e31306addde1a1725641fbe88cd047ee7477966c44a3f764b47", + neg: true, + expectedTyp: g2JacP, + expected: "a8ae9bba988e854877c66dfb7ff84aa5e107861aa51d1a2a8dac2414d716a7e219bc4b0239e4b12d2182f57b5eea82830639f2e6713098ae8d4b4c3942f366614bac35c91c83ecb57fa90fe03094aca1ecd3555a7a6fdfa2417b5bb06917732e", + }, + { + name: "G2Affine mul by zero scalar", + point: "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365", + mul: "0000000000000000000000000000000000000000000000000000000000000000", + neg: false, + expectedTyp: g2JacP, + expected: "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + } + c := newCryptolibClient(t) + + check := func(t *testing.T, resTyp pointType, gt string, mul string, neg bool, expected string) { + gtBytes, err := hex.DecodeString(gt) + require.NoError(t, err) + mulBytes, err := hex.DecodeString(mul) + require.NoError(t, err) + script := io.NewBufBinWriter() + if neg { + emit.Opcodes(script.BinWriter, opcode.PUSHT) + } else { + emit.Opcodes(script.BinWriter, opcode.PUSHF) + } + emit.Bytes(script.BinWriter, mulBytes) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, gtBytes) + emit.Opcodes(script.BinWriter, opcode.PUSH3, opcode.PACK) + emit.AppCallNoArgs(script.BinWriter, c.Hash, "bls12381Mul", callflag.All) + + stack, err := c.TestInvokeScript(t, script.Bytes(), c.Signers) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.InteropT, itm.Type()) + var actual []byte + switch resTyp { + case gtP: + gt, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + require.True(t, ok) + arr := gt.Bytes() + actual = arr[:] + case g1JacP: + g1Jac, ok := itm.(*stackitem.Interop).Value().(*bls12381.G1Jac) + require.True(t, ok) + g1Affine := new(bls12381.G1Affine) + g1Affine.FromJacobian(g1Jac) + arr := g1Affine.Bytes() + actual = arr[:] + case g2JacP: + g2Jac, ok := itm.(*stackitem.Interop).Value().(*bls12381.G2Jac) + require.True(t, ok) + g2Affine := new(bls12381.G2Affine) + g2Affine.FromJacobian(g2Jac) + arr := g2Affine.Bytes() + actual = arr[:] + default: + t.Fatal("unexpected result type", resTyp) + } + require.Equal(t, strings.ToLower(expected), hex.EncodeToString(actual)) + } + + for i, tc := range tcs { + t.Run(strconv.Itoa(i), func(t *testing.T) { + check(t, tc.expectedTyp, + tc.point, + tc.mul, + tc.neg, + tc.expected) + }) + } +} diff --git a/pkg/neotest/basic.go b/pkg/neotest/basic.go index ce6ed44b1..d904f39ab 100644 --- a/pkg/neotest/basic.go +++ b/pkg/neotest/basic.go @@ -181,13 +181,18 @@ func (e *Executor) InvokeScript(t testing.TB, script []byte, signers []Signer) u // PrepareInvocation creates a transaction with the specified script and signs it // by the provided signer. func (e *Executor) PrepareInvocation(t testing.TB, script []byte, signers []Signer, validUntilBlock ...uint32) *transaction.Transaction { + tx := e.PrepareInvocationNoSign(t, script, validUntilBlock...) + e.SignTx(t, tx, -1, signers...) + return tx +} + +func (e *Executor) PrepareInvocationNoSign(t testing.TB, script []byte, validUntilBlock ...uint32) *transaction.Transaction { tx := transaction.New(script, 0) tx.Nonce = Nonce() tx.ValidUntilBlock = e.Chain.BlockHeight() + 1 if len(validUntilBlock) != 0 { tx.ValidUntilBlock = validUntilBlock[0] } - e.SignTx(t, tx, -1, signers...) return tx } diff --git a/pkg/neotest/client.go b/pkg/neotest/client.go index 9596c12cb..bd96bab47 100644 --- a/pkg/neotest/client.go +++ b/pkg/neotest/client.go @@ -47,7 +47,28 @@ func (e *Executor) ValidatorInvoker(h util.Uint160) *ContractInvoker { } } -// TestInvoke creates test the VM and invokes the method with the args. +// TestInvokeScript creates test VM and invokes the script with the args and signers. +func (c *ContractInvoker) TestInvokeScript(t testing.TB, script []byte, signers []Signer, validUntilBlock ...uint32) (*vm.Stack, error) { + tx := c.PrepareInvocationNoSign(t, script, validUntilBlock...) + for _, acc := range signers { + tx.Signers = append(tx.Signers, transaction.Signer{ + Account: acc.ScriptHash(), + Scopes: transaction.Global, + }) + } + b := c.NewUnsignedBlock(t, tx) + ic, err := c.Chain.GetTestVM(trigger.Application, tx, b) + if err != nil { + return nil, err + } + t.Cleanup(ic.Finalize) + + ic.VM.LoadWithFlags(tx.Script, callflag.All) + err = ic.VM.Run() + return ic.VM.Estack(), err +} + +// TestInvoke creates test VM and invokes the method with the args. func (c *ContractInvoker) TestInvoke(t testing.TB, method string, args ...any) (*vm.Stack, error) { tx := c.PrepareInvokeNoSign(t, method, args...) b := c.NewUnsignedBlock(t, tx) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index c5be0f3e0..2b0b9fb50 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -82,7 +82,7 @@ const ( faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60" faultedTxBlock uint32 = 23 invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA" - block20StateRootLE = "811a287a0235cfb3c7def100ae7029335a10e8b90d0ca59c460955c0546a0414" + block20StateRootLE = "33b4cee6a59b9dc9d186fc235dc81e2ffe74418d7d777d538422a62b8e635ef2" ) var ( From 69102a6aa3f05c28bc078aa73dde54cddbca1a31 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 23 Mar 2023 20:06:47 +0300 Subject: [PATCH 016/125] interop: add groth16 interop API --- pkg/compiler/native_test.go | 6 ++++ pkg/interop/native/crypto/crypto.go | 49 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/pkg/compiler/native_test.go b/pkg/compiler/native_test.go index 088d714b8..8f3b8487b 100644 --- a/pkg/compiler/native_test.go +++ b/pkg/compiler/native_test.go @@ -218,6 +218,12 @@ func TestNativeHelpersCompile(t *testing.T) { {"ripemd160", []string{"[]byte{1, 2, 3}"}}, {"murmur32", []string{"[]byte{1, 2, 3}", "123"}}, {"verifyWithECDsa", []string{"[]byte{1, 2, 3}", pub, sig, "crypto.Secp256k1"}}, + {"bls12381Serialize", []string{"crypto.Bls12381Point{}"}}, + {"bls12381Deserialize", []string{"[]byte{1, 2, 3}"}}, + {"bls12381Equal", []string{"crypto.Bls12381Point{}", "crypto.Bls12381Point{}"}}, + {"bls12381Add", []string{"crypto.Bls12381Point{}", "crypto.Bls12381Point{}"}}, + {"bls12381Mul", []string{"crypto.Bls12381Point{}", "[]byte{1, 2, 3}", "true"}}, + {"bls12381Pairing", []string{"crypto.Bls12381Point{}", "crypto.Bls12381Point{}"}}, }) runNativeTestCases(t, cs.Std.ContractMD, "std", []nativeTestCase{ {"serialize", []string{"[]byte{1, 2, 3}"}}, diff --git a/pkg/interop/native/crypto/crypto.go b/pkg/interop/native/crypto/crypto.go index 8055a6b07..2d82357c0 100644 --- a/pkg/interop/native/crypto/crypto.go +++ b/pkg/interop/native/crypto/crypto.go @@ -43,3 +43,52 @@ func Murmur32(b []byte, seed int) []byte { func VerifyWithECDsa(msg []byte, pub interop.PublicKey, sig interop.Signature, curve NamedCurve) bool { return neogointernal.CallWithToken(Hash, "verifyWithECDsa", int(contract.NoneFlag), msg, pub, sig, curve).(bool) } + +// Bls12381Point represents BLS12-381 curve point (G1 or G2 in the Affine or +// Jacobian form or GT). Bls12381Point structure is needed for the operations +// with the curve's points (serialization, addition, multiplication, pairing and +// equality checks). It's an opaque type that can only be created properly by +// Bls12381Deserialize, Bls12381Add, Bls12381Mul or Bls12381Pairing. The only +// way to expose the Bls12381Point out of the runtime to the outside world is by +// serializing it with Bls12381Serialize method call. +type Bls12381Point struct{} + +// Bls12381Serialize calls `bls12381Serialize` method of native CryptoLib contract +// and serializes given BLS12-381 point into byte array. +func Bls12381Serialize(g Bls12381Point) []byte { + return neogointernal.CallWithToken(Hash, "bls12381Serialize", int(contract.NoneFlag), g).([]byte) +} + +// Bls12381Deserialize calls `bls12381Deserialize` method of native CryptoLib +// contract and deserializes given BLS12-381 point from byte array. +func Bls12381Deserialize(data []byte) Bls12381Point { + return neogointernal.CallWithToken(Hash, "bls12381Deserialize", int(contract.NoneFlag), data).(Bls12381Point) +} + +// Bls12381Equal calls `bls12381Equal` method of native CryptoLib contract and +// checks whether two BLS12-381 points are equal. +func Bls12381Equal(x, y Bls12381Point) bool { + return neogointernal.CallWithToken(Hash, "bls12381Equal", int(contract.NoneFlag), x, y).(bool) +} + +// Bls12381Add calls `bls12381Add` method of native CryptoLib contract and +// performs addition operation over two BLS12-381 points. +func Bls12381Add(x, y Bls12381Point) Bls12381Point { + return neogointernal.CallWithToken(Hash, "bls12381Add", int(contract.NoneFlag), x, y).(Bls12381Point) +} + +// Bls12381Mul calls `bls12381Mul` method of native CryptoLib contract and +// performs multiplication operation over BLS12-381 point and the given scalar +// multiplicator. The multiplicator is the serialized LE representation of the +// field element stored on 4 words (uint64) with 32-bytes length. The last +// argument denotes whether the multiplicator should be negative. +func Bls12381Mul(x Bls12381Point, mul []byte, neg bool) Bls12381Point { + return neogointernal.CallWithToken(Hash, "bls12381Mul", int(contract.NoneFlag), x, mul, neg).(Bls12381Point) +} + +// Bls12381Pairing calls `bls12381Pairing` method of native CryptoLib contract and +// performs pairing operation over two BLS12-381 points which must be G1 and G2 either +// in Affine or Jacobian forms. The result of this operation is GT point. +func Bls12381Pairing(g1, g2 Bls12381Point) Bls12381Point { + return neogointernal.CallWithToken(Hash, "bls12381Pairing", int(contract.NoneFlag), g1, g2).(Bls12381Point) +} From 68cb07999b91f7a8ab8705ebd992dc26c28dacf1 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 28 Mar 2023 19:50:27 +0300 Subject: [PATCH 017/125] scripts: adjust dependency updator We don't need these `--compat` flags anymore since 1.16 support is dropped. --- scripts/update_deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_deps.sh b/scripts/update_deps.sh index 603ee2b7a..5a1d71028 100755 --- a/scripts/update_deps.sh +++ b/scripts/update_deps.sh @@ -15,7 +15,7 @@ go mod tidy for dir in "$root"/examples/*/; do cd "$dir" || exit 1 go get github.com/nspcc-dev/neo-go/pkg/interop@"$REV" - go mod tidy --compat=1.17 + go mod tidy done cd "$root"/internal/contracts/oracle_contract || exit 1 From 66b82d0a7d4c5b53bb3c95dc38c58df474d35363 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 5 Apr 2023 15:54:36 +0300 Subject: [PATCH 018/125] *: update interop dependency --- examples/engine/go.mod | 2 +- examples/engine/go.sum | 4 ++-- examples/events/go.mod | 2 +- examples/events/go.sum | 4 ++-- examples/iterator/go.mod | 2 +- examples/iterator/go.sum | 4 ++-- examples/nft-d/go.mod | 2 +- examples/nft-d/go.sum | 4 ++-- examples/nft-nd-nns/go.mod | 2 +- examples/nft-nd-nns/go.sum | 4 ++-- examples/nft-nd/go.mod | 2 +- examples/nft-nd/go.sum | 4 ++-- examples/oracle/go.mod | 2 +- examples/oracle/go.sum | 4 ++-- examples/runtime/go.mod | 2 +- examples/runtime/go.sum | 4 ++-- examples/storage/go.mod | 2 +- examples/storage/go.sum | 4 ++-- examples/timer/go.mod | 2 +- examples/timer/go.sum | 4 ++-- examples/token/go.mod | 2 +- examples/token/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- internal/contracts/oracle_contract/go.mod | 2 +- internal/contracts/oracle_contract/go.sum | 4 ++-- 26 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/engine/go.mod b/examples/engine/go.mod index 293079d43..cac509115 100644 --- a/examples/engine/go.mod +++ b/examples/engine/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/engine/go.sum b/examples/engine/go.sum index a6410fb0d..029592186 100644 --- a/examples/engine/go.sum +++ b/examples/engine/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/events/go.mod b/examples/events/go.mod index 9f5a5d8ea..feae20fd6 100644 --- a/examples/events/go.mod +++ b/examples/events/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/events/go.sum b/examples/events/go.sum index a6410fb0d..029592186 100644 --- a/examples/events/go.sum +++ b/examples/events/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/iterator/go.mod b/examples/iterator/go.mod index 17cb817ac..c4d661733 100644 --- a/examples/iterator/go.mod +++ b/examples/iterator/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/iterator/go.sum b/examples/iterator/go.sum index a6410fb0d..029592186 100644 --- a/examples/iterator/go.sum +++ b/examples/iterator/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/nft-d/go.mod b/examples/nft-d/go.mod index c6869184a..c19095fc3 100644 --- a/examples/nft-d/go.mod +++ b/examples/nft-d/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/nft-d/go.sum b/examples/nft-d/go.sum index a6410fb0d..029592186 100644 --- a/examples/nft-d/go.sum +++ b/examples/nft-d/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/nft-nd-nns/go.mod b/examples/nft-nd-nns/go.mod index 7388cbdd3..e7d7fcf37 100644 --- a/examples/nft-nd-nns/go.mod +++ b/examples/nft-nd-nns/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 github.com/stretchr/testify v1.8.0 ) diff --git a/examples/nft-nd-nns/go.sum b/examples/nft-nd-nns/go.sum index 1244eceba..59194b659 100644 --- a/examples/nft-nd-nns/go.sum +++ b/examples/nft-nd-nns/go.sum @@ -187,8 +187,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 h1:NCIUxkLRB3ovLzM1lvQA6wBNn8fuY7dQx4cMJKLuaAs= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5/go.mod h1:aWrWJZBYO+9kYC4+qJXvEjySW1WIyPnrHpmdrzd5mJY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 h1:rpMCoRa7expLc9gMiOP724gz6YSykZzmMALR/CmiwnU= diff --git a/examples/nft-nd/go.mod b/examples/nft-nd/go.mod index 0d6c758ad..6f1662b0b 100644 --- a/examples/nft-nd/go.mod +++ b/examples/nft-nd/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/nft-nd/go.sum b/examples/nft-nd/go.sum index a6410fb0d..029592186 100644 --- a/examples/nft-nd/go.sum +++ b/examples/nft-nd/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/oracle/go.mod b/examples/oracle/go.mod index 71a02b91a..668c822bc 100644 --- a/examples/oracle/go.mod +++ b/examples/oracle/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/oracle/go.sum b/examples/oracle/go.sum index a6410fb0d..029592186 100644 --- a/examples/oracle/go.sum +++ b/examples/oracle/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/runtime/go.mod b/examples/runtime/go.mod index 9edc86543..0d7b6cac7 100644 --- a/examples/runtime/go.mod +++ b/examples/runtime/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/runtime/go.sum b/examples/runtime/go.sum index a6410fb0d..029592186 100644 --- a/examples/runtime/go.sum +++ b/examples/runtime/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/storage/go.mod b/examples/storage/go.mod index 66494077d..863173296 100644 --- a/examples/storage/go.mod +++ b/examples/storage/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/storage/go.sum b/examples/storage/go.sum index a6410fb0d..029592186 100644 --- a/examples/storage/go.sum +++ b/examples/storage/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/timer/go.mod b/examples/timer/go.mod index 17b43d5b1..d6f575941 100644 --- a/examples/timer/go.mod +++ b/examples/timer/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/timer/go.sum b/examples/timer/go.sum index a6410fb0d..029592186 100644 --- a/examples/timer/go.sum +++ b/examples/timer/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/token/go.mod b/examples/token/go.mod index f26033259..8591a3b3b 100644 --- a/examples/token/go.mod +++ b/examples/token/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/examples/token/go.sum b/examples/token/go.sum index a6410fb0d..029592186 100644 --- a/examples/token/go.sum +++ b/examples/token/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/go.mod b/go.mod index 1f5255334..ed129974e 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 github.com/nspcc-dev/rfc6979 v0.2.0 github.com/pierrec/lz4 v2.6.1+incompatible diff --git a/go.sum b/go.sum index 0b24180df..f725f3296 100644 --- a/go.sum +++ b/go.sum @@ -268,8 +268,8 @@ github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= diff --git a/internal/contracts/oracle_contract/go.mod b/internal/contracts/oracle_contract/go.mod index 7f4d13c99..687c92312 100644 --- a/internal/contracts/oracle_contract/go.mod +++ b/internal/contracts/oracle_contract/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/internal/examples/oracle go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 diff --git a/internal/contracts/oracle_contract/go.sum b/internal/contracts/oracle_contract/go.sum index a6410fb0d..029592186 100644 --- a/internal/contracts/oracle_contract/go.sum +++ b/internal/contracts/oracle_contract/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb h1:GFxfkpXEYAbMIr69JpKOsQWeLOaGrd49HNAor8uDW+A= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= From 01ac2d9f318ce6c8efcf58b1300e8690f58bde5d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 3 Apr 2023 15:53:37 +0300 Subject: [PATCH 019/125] rpc: emit Null in case of `Any` parameter with zero-len value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise it leads to the following error in the TestActor_CallWithNilParam: ``` === RUN TestActor_CallWithNilParam logger.go:130: 2023-04-03T15:58:27.672+0300 INFO initial gas supply is not set or wrong, setting default value {"InitialGASSupply": "52000000"} logger.go:130: 2023-04-03T15:58:27.672+0300 INFO P2PNotaryRequestPayloadPool size is not set or wrong, setting default value {"P2PNotaryRequestPayloadPoolSize": 1000} logger.go:130: 2023-04-03T15:58:27.672+0300 INFO MaxBlockSize is not set or wrong, setting default value {"MaxBlockSize": 262144} logger.go:130: 2023-04-03T15:58:27.672+0300 INFO MaxBlockSystemFee is not set or wrong, setting default value {"MaxBlockSystemFee": 900000000000} logger.go:130: 2023-04-03T15:58:27.672+0300 INFO MaxTransactionsPerBlock is not set or wrong, using default value {"MaxTransactionsPerBlock": 512} logger.go:130: 2023-04-03T15:58:27.672+0300 INFO MaxValidUntilBlockIncrement is not set or wrong, using default value {"MaxValidUntilBlockIncrement": 5760} logger.go:130: 2023-04-03T15:58:27.675+0300 INFO no storage version found! creating genesis block logger.go:130: 2023-04-03T15:58:27.675+0300 INFO ExtensiblePoolSize is not set or wrong, using default value {"ExtensiblePoolSize": 20} logger.go:130: 2023-04-03T15:58:27.675+0300 INFO SessionPoolSize is not set or wrong, setting default value {"SessionPoolSize": 20} logger.go:130: 2023-04-03T15:58:27.675+0300 INFO MaxWebSocketClients is not set or wrong, setting default value {"MaxWebSocketClients": 64} logger.go:130: 2023-04-03T15:58:27.675+0300 INFO starting rpc-server {"endpoint": "localhost:0"} logger.go:130: 2023-04-03T15:58:27.677+0300 DEBUG done processing headers {"headerIndex": 1, "blockHeight": 0, "took": "436.313µs"} logger.go:130: 2023-04-03T15:58:27.679+0300 DEBUG done processing headers {"headerIndex": 2, "blockHeight": 1, "took": "272.891µs"} logger.go:130: 2023-04-03T15:58:27.680+0300 DEBUG done processing headers {"headerIndex": 3, "blockHeight": 2, "took": "276.949µs"} logger.go:130: 2023-04-03T15:58:27.681+0300 DEBUG done processing headers {"headerIndex": 4, "blockHeight": 3, "took": "286.028µs"} logger.go:130: 2023-04-03T15:58:27.681+0300 DEBUG done processing headers {"headerIndex": 5, "blockHeight": 4, "took": "268.673µs"} logger.go:130: 2023-04-03T15:58:27.681+0300 INFO bad notification {"contract": "565cff9508ebc75aadd7fe59f38dac610ab6093c", "event": "Transfer", "error": "parameter 0 type mismatch: Hash160 vs ByteString"} logger.go:130: 2023-04-03T15:58:27.682+0300 DEBUG done processing headers {"headerIndex": 6, "blockHeight": 5, "took": "380.988µs"} logger.go:130: 2023-04-03T15:58:27.683+0300 DEBUG done processing headers {"headerIndex": 7, "blockHeight": 6, "took": "273.543µs"} logger.go:130: 2023-04-03T15:58:27.683+0300 DEBUG done processing headers {"headerIndex": 8, "blockHeight": 7, "took": "275.163µs"} logger.go:130: 2023-04-03T15:58:27.684+0300 DEBUG done processing headers {"headerIndex": 9, "blockHeight": 8, "took": "259.578µs"} logger.go:130: 2023-04-03T15:58:27.685+0300 DEBUG done processing headers {"headerIndex": 10, "blockHeight": 9, "took": "266.882µs"} logger.go:130: 2023-04-03T15:58:27.686+0300 DEBUG done processing headers {"headerIndex": 11, "blockHeight": 10, "took": "295.3µs"} logger.go:130: 2023-04-03T15:58:27.687+0300 DEBUG done processing headers {"headerIndex": 12, "blockHeight": 11, "took": "295.568µs"} logger.go:130: 2023-04-03T15:58:27.688+0300 DEBUG done processing headers {"headerIndex": 13, "blockHeight": 12, "took": "258.197µs"} logger.go:130: 2023-04-03T15:58:27.689+0300 DEBUG done processing headers {"headerIndex": 14, "blockHeight": 13, "took": "261.602µs"} logger.go:130: 2023-04-03T15:58:27.689+0300 DEBUG done processing headers {"headerIndex": 15, "blockHeight": 14, "took": "268.922µs"} logger.go:130: 2023-04-03T15:58:27.690+0300 DEBUG done processing headers {"headerIndex": 16, "blockHeight": 15, "took": "276.176µs"} logger.go:130: 2023-04-03T15:58:27.691+0300 DEBUG done processing headers {"headerIndex": 17, "blockHeight": 16, "took": "256.068µs"} logger.go:130: 2023-04-03T15:58:27.692+0300 DEBUG done processing headers {"headerIndex": 18, "blockHeight": 17, "took": "262.303µs"} logger.go:130: 2023-04-03T15:58:27.692+0300 DEBUG done processing headers {"headerIndex": 19, "blockHeight": 18, "took": "265.087µs"} logger.go:130: 2023-04-03T15:58:27.693+0300 DEBUG done processing headers {"headerIndex": 20, "blockHeight": 19, "took": "260.758µs"} logger.go:130: 2023-04-03T15:58:27.694+0300 DEBUG done processing headers {"headerIndex": 21, "blockHeight": 20, "took": "263.482µs"} logger.go:130: 2023-04-03T15:58:27.694+0300 DEBUG done processing headers {"headerIndex": 22, "blockHeight": 21, "took": "327.812µs"} logger.go:130: 2023-04-03T15:58:27.696+0300 DEBUG done processing headers {"headerIndex": 23, "blockHeight": 22, "took": "284.104µs"} logger.go:130: 2023-04-03T15:58:27.697+0300 WARN contract invocation failed {"tx": "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60", "block": 23, "error": "at instruction 0 (ABORT): ABORT"} logger.go:130: 2023-04-03T15:58:27.697+0300 DEBUG processing rpc request {"method": "getversion", "params": "[]"} logger.go:130: 2023-04-03T15:58:27.698+0300 DEBUG processing rpc request {"method": "invokefunction", "params": "[565cff9508ebc75aadd7fe59f38dac610ab6093c putValue ]"} client_test.go:2562: Error Trace: /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/services/rpcsrv/client_test.go:2562 Error: Should be true Test: TestActor_CallWithNilParam Messages: at instruction 6 (PACK): OPACK: invalid length logger.go:130: 2023-04-03T15:58:27.699+0300 INFO shutting down RPC server {"endpoint": "127.0.0.1:46005"} logger.go:130: 2023-04-03T15:58:27.700+0300 INFO persisted to disk {"blocks": 23, "keys": 1236, "headerHeight": 23, "blockHeight": 23, "took": "908.825µs"} --- FAIL: TestActor_CallWithNilParam (0.03s) FAIL ``` See also the ref. https://github.com/neo-project/neo/blob/df534f6b0c700e1c7b3eb1315c4560fedce793b8/src/Neo/SmartContract/ContractParameter.cs#L141 and the way how parameters are handled by ref. RPC server: https://github.com/neo-project/neo-modules/blob/4b3a76e1b760798b2e9bc8706bc5f4cf22c1f5ae/src/RpcServer/RpcServer.SmartContract.cs#L202 and FromJSON implementation: https://github.com/neo-project/neo/blob/df534f6b0c700e1c7b3eb1315c4560fedce793b8/src/Neo/SmartContract/ContractParameter.cs#L70 --- pkg/services/rpcsrv/client_test.go | 32 +++++++++++++++++++++++++ pkg/services/rpcsrv/params/txBuilder.go | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index de0606f8d..da23e6e87 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -18,6 +18,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/websocket" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/internal/testchain" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core" @@ -2529,3 +2530,34 @@ func TestWSClient_SubscriptionsCompat(t *testing.T) { checkRelevant(t, false) }) } + +func TestActor_CallWithNilParam(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) + acc, err := wallet.NewAccount() + require.NoError(t, err) + act, err := actor.New(c, []actor.SignerAccount{ + { + Signer: transaction.Signer{ + Account: acc.ScriptHash(), + }, + Account: acc, + }, + }) + require.NoError(t, err) + + rubles, err := chain.GetContractScriptHash(basicchain.RublesContractID) + require.NoError(t, err) + + // We don't have a suitable contract, thus use Rubles with simple put method, + // it should fail at the moment of conversion Null value to ByteString (not earlier, + // and that's the point of the test!). + res, err := act.Call(rubles, "putValue", "123", (*util.Uint160)(nil)) + require.NoError(t, err) + + require.True(t, strings.Contains(res.FaultException, "invalid conversion: Null/ByteString"), res.FaultException) +} diff --git a/pkg/services/rpcsrv/params/txBuilder.go b/pkg/services/rpcsrv/params/txBuilder.go index 9872c7cc6..9d2c9ea2d 100644 --- a/pkg/services/rpcsrv/params/txBuilder.go +++ b/pkg/services/rpcsrv/params/txBuilder.go @@ -84,7 +84,7 @@ func ExpandArrayIntoScript(script *io.BinWriter, slice []Param) error { return err } case smartcontract.AnyType: - if fp.Value.IsNull() { + if fp.Value.IsNull() || len(fp.Value.RawMessage) == 0 { emit.Opcodes(script, opcode.PUSHNULL) } default: From f479b2bc576a18ac5a635b7cfebd920f5adca559 Mon Sep 17 00:00:00 2001 From: Erik van den Brink Date: Thu, 6 Apr 2023 18:33:09 +0200 Subject: [PATCH 020/125] neorpc: change peer port to int type (fixes nspcc-dev#2910) --- ROADMAP.md | 9 ++++++ pkg/neorpc/result/peers.go | 50 +++++++++++++++++++++++++++++---- pkg/neorpc/result/peers_test.go | 30 ++++++++++++++++---- pkg/rpcclient/rpc_test.go | 9 +++--- 4 files changed, 83 insertions(+), 15 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index dbeabf41d..5804dda3e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -114,3 +114,12 @@ for security reasons. Removal of these options from ProtocolConfiguration is scheduled for May-June 2023 (~0.103.0 release). + +## GetPeers RPC server response type changes and RPC client support + +GetPeers RPC command returns a list of Peers where the port type has changed from +string to uint16 to match C#. The RPC client currently supports unmarshalling both +formats. + +Removal of Peer unmarshalling with string based ports is scheduled for ~September 2023 +(~0.105.0 release). diff --git a/pkg/neorpc/result/peers.go b/pkg/neorpc/result/peers.go index 4a4c4f923..33051f71d 100644 --- a/pkg/neorpc/result/peers.go +++ b/pkg/neorpc/result/peers.go @@ -1,7 +1,9 @@ package result import ( - "strings" + "encoding/json" + "net" + "strconv" ) type ( @@ -18,7 +20,7 @@ type ( // Peer represents a peer. Peer struct { Address string `json:"address"` - Port string `json:"port"` + Port uint16 `json:"port"` } ) @@ -49,12 +51,50 @@ func (g *GetPeers) AddBad(addrs []string) { // addPeers adds a set of peers to the given peer slice. func (p *Peers) addPeers(addrs []string) { for i := range addrs { - addressParts := strings.Split(addrs[i], ":") + host, portStr, err := net.SplitHostPort(addrs[i]) + if err != nil { + continue + } + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + port = 0 + } peer := Peer{ - Address: addressParts[0], - Port: addressParts[1], + Address: host, + Port: uint16(port), } *p = append(*p, peer) } } + +func (p *Peer) UnmarshalJSON(data []byte) error { + type NewPeer Peer + var np NewPeer + + err := json.Unmarshal(data, &np) + if err == nil { + *p = Peer(np) + return nil + } + + type OldPeer struct { + Address string `json:"address"` + Port string `json:"port"` + } + var op OldPeer + + err = json.Unmarshal(data, &op) + if err == nil { + port, err := strconv.ParseUint(op.Port, 10, 16) + if err != nil { + return err + } + + *p = Peer{ + Address: op.Address, + Port: uint16(port), + } + } + return err +} diff --git a/pkg/neorpc/result/peers_test.go b/pkg/neorpc/result/peers_test.go index 6e5a9339e..8680ac207 100644 --- a/pkg/neorpc/result/peers_test.go +++ b/pkg/neorpc/result/peers_test.go @@ -1,6 +1,7 @@ package result import ( + "encoding/json" "testing" "github.com/stretchr/testify/require" @@ -13,14 +14,31 @@ func TestGetPeers(t *testing.T) { require.Equal(t, 0, len(gp.Bad)) gp.AddUnconnected([]string{"1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"}) - gp.AddConnected([]string{"192.168.0.1:10333"}) - gp.AddBad([]string{"127.0.0.1:20333"}) + unsupportedFormat := "2001:DB0:0:123A:::30" + gp.AddConnected([]string{"192.168.0.1:10333", unsupportedFormat, "[2001:DB0:0:123A::]:30"}) + gp.AddBad([]string{"127.0.0.1:20333", "127.0.0.1:65536"}) require.Equal(t, 3, len(gp.Unconnected)) - require.Equal(t, 1, len(gp.Connected)) - require.Equal(t, 1, len(gp.Bad)) + require.Equal(t, 2, len(gp.Connected)) + require.Equal(t, 2, len(gp.Bad)) require.Equal(t, "192.168.0.1", gp.Connected[0].Address) - require.Equal(t, "10333", gp.Connected[0].Port) + require.Equal(t, uint16(10333), gp.Connected[0].Port) + require.Equal(t, uint16(30), gp.Connected[1].Port) require.Equal(t, "127.0.0.1", gp.Bad[0].Address) - require.Equal(t, "20333", gp.Bad[0].Port) + require.Equal(t, uint16(20333), gp.Bad[0].Port) + require.Equal(t, uint16(0), gp.Bad[1].Port) + + gps := GetPeers{} + oldPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": "10333"},{"address": "27.188.182.47","port": "10333"}],"connected": [{"address": "54.227.43.72","port": "10333"},{"address": "157.90.177.38","port": "10333"}],"bad": [{"address": "5.226.142.226","port": "10333"}]}` + err := json.Unmarshal([]byte(oldPeerFormat), &gps) + require.NoError(t, err) + newPeerFormat := `{"unconnected": [{"address": "20.109.188.128","port": 10333},{"address": "27.188.182.47","port": 10333}],"connected": [{"address": "54.227.43.72","port": 10333},{"address": "157.90.177.38","port": 10333}],"bad": [{"address": "5.226.142.226","port": 10333},{"address": "54.208.117.178","port": 10333}]}` + err = json.Unmarshal([]byte(newPeerFormat), &gps) + require.NoError(t, err) + badIntFormat := `{"unconnected": [{"address": "20.109.188.128","port": 65536}],"connected": [],"bad": []}` + err = json.Unmarshal([]byte(badIntFormat), &gps) + require.Error(t, err) + badStringFormat := `{"unconnected": [{"address": "20.109.188.128","port": "badport"}],"connected": [],"bad": []}` + err = json.Unmarshal([]byte(badStringFormat), &gps) + require.Error(t, err) } diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index 87092343d..3cf3b9f9b 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -700,25 +700,26 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (any, error) { return c.GetPeers() }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"unconnected":[{"address":"172.200.0.1","port":"20333"}],"connected":[{"address":"127.0.0.1","port":"20335"}],"bad":[{"address":"172.200.0.254","port":"20332"}]}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"unconnected":[{"address":"172.200.0.1","port":20333}],"connected":[{"address":"127.0.0.1","port":20335}],"bad":[{"address":"172.200.0.254","port":20332}]}}`, result: func(c *Client) any { + return &result.GetPeers{ Unconnected: result.Peers{ { Address: "172.200.0.1", - Port: "20333", + Port: 20333, }, }, Connected: result.Peers{ { Address: "127.0.0.1", - Port: "20335", + Port: 20335, }, }, Bad: result.Peers{ { Address: "172.200.0.254", - Port: "20332", + Port: 20332, }, }, } From 41caeed5c075f976fb2d04bb79644ddb8cd77c51 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 11 Apr 2023 16:47:37 +0300 Subject: [PATCH 021/125] core: fix state reset log message Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index bde36a856..813d46b34 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -682,7 +682,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) v := bc.dao.Version cache := bc.dao // dao is MemCachedStore over DB, so use dao directly to persist cached changes right to the underlying DB - bc.log.Info("initialize state reset", zap.Uint32("target height", height)) + bc.log.Info("initializing state reset", zap.Uint32("target height", height)) start := time.Now() p := start keys := 0 From e3747b1d57a15ed828a0282c4cc5feda223a8115 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 11 Apr 2023 16:53:24 +0300 Subject: [PATCH 022/125] core: change log level of reset stages notifications Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 813d46b34..e35b6846b 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -697,7 +697,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) } fallthrough case stateJumpStarted: - bc.log.Info("trying to reset blocks, transactions and AERs") + bc.log.Debug("trying to reset blocks, transactions and AERs") // Remove blocks/transactions/aers from currHeight down to height (not including height itself). // Keep headers for now, they'll be removed later. It's hard to handle the whole set of changes in // one stage, so persist periodically. @@ -738,7 +738,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) p = time.Now() fallthrough case staleBlocksRemoved: - bc.log.Info("trying to reset contract storage items") + bc.log.Debug("trying to reset contract storage items") pStorageStart := p var mode = mpt.ModeAll @@ -797,7 +797,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) fallthrough case newStorageItemsAdded: // Reset SYS-prefixed and IX-prefixed information. - bc.log.Info("trying to reset headers information") + bc.log.Debug("trying to reset headers information") for i := height + 1; i <= hHeight; i++ { cache.PurgeHeader(bc.GetHeaderHash(i)) } @@ -819,7 +819,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) fallthrough case headersReset: // Reset MPT. - bc.log.Info("trying to reset state root information and NEP transfers") + bc.log.Debug("trying to reset state root information and NEP transfers") err = bc.stateRoot.ResetState(height, cache.Store) if err != nil { return fmt.Errorf("failed to rollback MPT state: %w", err) @@ -848,7 +848,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) } // Direct (cache-less) DB operation: remove stale storage items. - bc.log.Info("trying to remove stale storage items") + bc.log.Debug("trying to remove stale storage items") keys = 0 err = bc.store.SeekGC(storage.SeekRange{ Prefix: []byte{byte(statesync.TemporaryPrefix(v.StoragePrefix))}, @@ -862,7 +862,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) bc.log.Info("stale storage items are reset", zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) p = time.Now() - bc.log.Info("trying to remove state reset point") + bc.log.Debug("trying to remove state reset point") cache.Store.Delete(resetStageKey) // Unlike the state jump, state sync point must be removed as we have complete state for this height. cache.Store.Delete([]byte{byte(storage.SYSStateSyncPoint)}) From cb0f786b28835229f066a31ac62d6e964c9d22f7 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 21 Nov 2022 12:04:52 +0300 Subject: [PATCH 023/125] core: move batch persist to a separate routine Resetting mainnet from 2512046 blocks (full logs are attached to https://github.com/nspcc-dev/neo-go/pull/2813#issuecomment-1324115555). -------- LevelDB | ------------------------ to | old | new | ------|--------|--------| 1 | 5m11s | 4m50s | ------|--------|--------| 1M | 10m40s | 9m40s | ------|--------|--------| 2.5M | 17m38s | 17m36s | ------------------------ -------- BoltDB | ------------------------ to | old | new | ------|--------|--------| 1 | 8m3s | 5m51s | ------|--------|--------| 1M | 20m30s | 13m2s | ------|--------|--------| 2.5M | 31m26s | 18m47s | ------------------------ Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 190 ++++++++++++++++++++++++++++------------- 1 file changed, 129 insertions(+), 61 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index e35b6846b..707775189 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -685,15 +685,42 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) bc.log.Info("initializing state reset", zap.Uint32("target height", height)) start := time.Now() p := start - keys := 0 + + // Start batch persisting routine, it will be used for blocks/txs/AERs/storage items batches persist. + type postPersist func(persistedKeys int, err error) error + var ( + persistCh = make(chan postPersist) + persistToExitCh = make(chan struct{}) + ) + go func() { + for { + f, ok := <-persistCh + if !ok { + break + } + persistErr := f(cache.Persist()) + if persistErr != nil { + bc.log.Fatal("persist failed", zap.Error(persistErr)) + panic(persistErr) + } + } + close(persistToExitCh) + }() + defer func() { + close(persistCh) + <-persistToExitCh + bc.log.Info("reset finished successfully", zap.Duration("took", time.Since(start))) + }() resetStageKey := []byte{byte(storage.SYSStateChangeStage)} switch stage { case none: cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(stateJumpStarted)}) - _, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed to persist state reset start marker to the DB: %w", err) + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist state reset start marker to the DB: %w", err) + } + return nil } fallthrough case stateJumpStarted: @@ -703,8 +730,9 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) // one stage, so persist periodically. const persistBatchSize = 100 * headerBatchCount // count blocks only, should be enough to avoid OOM killer even for large blocks var ( - pBlocksStart = p - blocksCnt, batchCnt, keysCnt int + pBlocksStart = p + blocksCnt, batchCnt int + keysCnt = new(int) ) for i := height + 1; i <= currHeight; i++ { err := cache.DeleteBlock(bc.GetHeaderHash(i)) @@ -713,34 +741,56 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) } blocksCnt++ if blocksCnt == persistBatchSize { - keys, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed to persist intermediate batch removed blocks, transactions and AERs: %w", err) - } blocksCnt = 0 batchCnt++ - keysCnt += keys - bc.log.Info("intermediate batch of removed blocks, transactions and AERs is persisted", zap.Int("batches persisted", batchCnt), zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) + bc.log.Info("intermediate batch of removed blocks, transactions and AERs is collected", + zap.Int("batch", batchCnt), + zap.Duration("took", time.Since(p))) + + persistStart := time.Now() + persistBatch := batchCnt + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist intermediate batch of removed blocks, transactions and AERs: %w", err) + } + *keysCnt += persistedKeys + bc.log.Debug("intermediate batch of removed blocks, transactions and AERs is persisted", + zap.Int("batch", persistBatch), + zap.Duration("took", time.Since(persistStart)), + zap.Int("keys", persistedKeys)) + return nil + } p = time.Now() } } cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(staleBlocksRemoved)}) - keys, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed to persist last batch of removed blocks, transactions ans AERs: %w", err) - } batchCnt++ - keysCnt += keys - bc.log.Info("last batch of removed blocks, transactions and AERs is persisted", zap.Int("batches persisted", batchCnt), zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) + bc.log.Info("last batch of removed blocks, transactions and AERs is collected", + zap.Int("batch", batchCnt), + zap.Duration("took", time.Since(p))) + bc.log.Info("blocks, transactions ans AERs are reset", zap.Duration("took", time.Since(pBlocksStart))) - bc.log.Info("blocks, transactions ans AERs are reset", zap.Duration("took", time.Since(pBlocksStart)), - zap.Int("overall persisted keys", keysCnt)) + persistStart := time.Now() + persistBatch := batchCnt + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist last batch of removed blocks, transactions ans AERs: %w", err) + } + *keysCnt += persistedKeys + bc.log.Debug("last batch of removed blocks, transactions and AERs is persisted", + zap.Int("batch", persistBatch), + zap.Duration("took", time.Since(persistStart)), + zap.Int("keys", persistedKeys)) + return nil + } p = time.Now() fallthrough case staleBlocksRemoved: + // Completely remove contract IDs to update them later. bc.log.Debug("trying to reset contract storage items") pStorageStart := p + p = time.Now() var mode = mpt.ModeAll if bc.config.Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeGCFlag @@ -750,25 +800,27 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) newStoragePrefix := statesync.TemporaryPrefix(oldStoragePrefix) const persistBatchSize = 200000 - var ( - seekErr error - cnt int - storageItmsCnt int - batchCnt int - ) + var cnt, storageItmsCnt, batchCnt int trieStore.Seek(storage.SeekRange{Prefix: []byte{byte(oldStoragePrefix)}}, func(k, v []byte) bool { - if seekErr != nil { - return false - } if cnt >= persistBatchSize { cnt = 0 - keys, seekErr = cache.Persist() - if seekErr != nil { - seekErr = fmt.Errorf("failed to persist intermediate batch of contract storage items and IDs: %w", seekErr) - return false - } batchCnt++ - bc.log.Info("intermediate batch of contract storage items and IDs is persisted", zap.Int("batch", batchCnt), zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) + bc.log.Info("intermediate batch of contract storage items and IDs is collected", + zap.Int("batch", batchCnt), + zap.Duration("took", time.Since(p))) + + persistStart := time.Now() + persistBatch := batchCnt + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist intermediate batch of contract storage items: %w", err) + } + bc.log.Debug("intermediate batch of contract storage items is persisted", + zap.Int("batch", persistBatch), + zap.Duration("took", time.Since(persistStart)), + zap.Int("keys", persistedKeys)) + return nil + } p = time.Now() } // May safely omit KV copying. @@ -779,20 +831,23 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) return true }) - if seekErr != nil { - return fmt.Errorf("failed to reset contract contract storage items and IDs: %w", seekErr) - } trieStore.Close() cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(newStorageItemsAdded)}) - keys, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed to persist contract storage items and IDs changes to the DB: %w", err) - } batchCnt++ - bc.log.Info("last batch of contract storage items and IDs is persisted", zap.Int("batch", batchCnt), zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) - bc.log.Info("contract storage items and IDs are reset", zap.Duration("took", time.Since(pStorageStart)), + persistBatch := batchCnt + bc.log.Info("last batch of contract storage items is collected", zap.Int("batch", batchCnt), zap.Duration("took", time.Since(p))) + bc.log.Info("contract storage items are reset", zap.Duration("took", time.Since(pStorageStart)), zap.Int("keys", storageItmsCnt)) + + lastStart := time.Now() + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist contract storage items and IDs changes to the DB: %w", err) + } + bc.log.Debug("last batch of contract storage items and IDs is persisted", zap.Int("batch", persistBatch), zap.Duration("took", time.Since(lastStart)), zap.Int("keys", persistedKeys)) + return nil + } p = time.Now() fallthrough case newStorageItemsAdded: @@ -809,12 +864,16 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) bc.persistent.Version = v cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(headersReset)}) - keys, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed to persist headers changes to the DB: %w", err) - } + bc.log.Info("headers information is reset", zap.Duration("took", time.Since(p))) - bc.log.Info("headers information is reset", zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) + persistStart := time.Now() + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist headers changes to the DB: %w", err) + } + bc.log.Debug("headers information is persisted", zap.Duration("took", time.Since(persistStart)), zap.Int("keys", persistedKeys)) + return nil + } p = time.Now() fallthrough case headersReset: @@ -832,12 +891,17 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) } cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(transfersReset)}) - keys, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed tpo persist contract storage items changes to the DB: %w", err) - } + bc.log.Info("state root information and NEP transfers are reset", zap.Duration("took", time.Since(p))) - bc.log.Info("state root information and NEP transfers are reset", zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) + persistStart := time.Now() + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist contract storage items changes to the DB: %w", err) + } + + bc.log.Debug("state root information and NEP transfers are persisted", zap.Duration("took", time.Since(persistStart)), zap.Int("keys", persistedKeys)) + return nil + } p = time.Now() fallthrough case transfersReset: @@ -849,7 +913,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) // Direct (cache-less) DB operation: remove stale storage items. bc.log.Debug("trying to remove stale storage items") - keys = 0 + keys := 0 err = bc.store.SeekGC(storage.SeekRange{ Prefix: []byte{byte(statesync.TemporaryPrefix(v.StoragePrefix))}, }, func(_, _ []byte) bool { @@ -866,18 +930,22 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) cache.Store.Delete(resetStageKey) // Unlike the state jump, state sync point must be removed as we have complete state for this height. cache.Store.Delete([]byte{byte(storage.SYSStateSyncPoint)}) - keys, err = cache.Persist() - if err != nil { - return fmt.Errorf("failed to persist state reset stage to DAO: %w", err) + bc.log.Info("state reset point is removed", zap.Duration("took", time.Since(p))) + + persistStart := time.Now() + persistCh <- func(persistedKeys int, err error) error { + if err != nil { + return fmt.Errorf("failed to persist state reset stage to DAO: %w", err) + } + bc.log.Info("state reset point information is persisted", zap.Duration("took", time.Since(persistStart)), zap.Int("keys", persistedKeys)) + return nil } - bc.log.Info("stale reset point is removed", zap.Duration("took", time.Since(p)), zap.Int("keys", keys)) + p = time.Now() err = bc.resetRAMState(height, true) if err != nil { return fmt.Errorf("failed to update in-memory blockchain data: %w", err) } - - bc.log.Info("reset finished successfully", zap.Duration("took", time.Since(start))) return nil } From 400620a9fb60c8b946e067482903417e4a14e8d9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 11 Apr 2023 14:18:48 +0300 Subject: [PATCH 024/125] core: avoid squashing of data from different state reset stages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cache` persisting operation is concurrent with the storage modifications made by further state reset stages. We can't allow situation when data from the next stage are leaking into the previous stage. State reset stages must be atomic in turms of DB persisting, thus, use another `upperCache` MemCached store to keep them apart. Here are the results of mainnet's BoltDB reset from 1.1M to 6K: This patch: ``` anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ ./bin/neo-go db reset -m --debug --height 600000 2023-04-11T16:15:25.783+0300 INFO MaxBlockSize is not set or wrong, setting default value {"MaxBlockSize": 262144} 2023-04-11T16:15:25.783+0300 INFO MaxBlockSystemFee is not set or wrong, setting default value {"MaxBlockSystemFee": 900000000000} 2023-04-11T16:15:25.783+0300 INFO MaxTransactionsPerBlock is not set or wrong, using default value {"MaxTransactionsPerBlock": 512} 2023-04-11T16:15:25.783+0300 INFO MaxValidUntilBlockIncrement is not set or wrong, using default value {"MaxValidUntilBlockIncrement": 5760} 2023-04-11T16:15:25.787+0300 INFO restoring blockchain {"version": "0.2.8"} 2023-04-11T16:15:25.906+0300 INFO initializing state reset {"target height": 600000} 2023-04-11T16:15:25.906+0300 DEBUG trying to reset blocks, transactions and AERs 2023-04-11T16:15:57.031+0300 INFO intermediate batch of removed blocks, transactions and AERs is collected {"batch": 1, "took": "31.125057214s"} 2023-04-11T16:16:12.644+0300 DEBUG intermediate batch of removed blocks, transactions and AERs is persisted {"batch": 1, "took": "15.613156971s", "keys": 321895} 2023-04-11T16:16:13.895+0300 INFO intermediate batch of removed blocks, transactions and AERs is collected {"batch": 2, "took": "16.663444208s"} 2023-04-11T16:16:19.784+0300 INFO last batch of removed blocks, transactions and AERs is collected {"batch": 3, "took": "5.760308543s"} 2023-04-11T16:16:19.784+0300 INFO blocks, transactions ans AERs are reset {"took": "53.878632911s"} 2023-04-11T16:16:22.870+0300 DEBUG intermediate batch of removed blocks, transactions and AERs is persisted {"batch": 2, "took": "8.974838893s", "keys": 334823} 2023-04-11T16:16:22.870+0300 DEBUG trying to reset contract storage items 2023-04-11T16:16:27.272+0300 DEBUG last batch of removed blocks, transactions and AERs is persisted {"batch": 3, "took": "7.487357441s", "keys": 208913} 2023-04-11T16:17:23.678+0300 INFO intermediate batch of contract storage items and IDs is collected {"batch": 1, "took": "1m0.80711106s"} 2023-04-11T16:18:00.769+0300 INFO intermediate batch of contract storage items and IDs is collected {"batch": 2, "took": "36.967660061s"} 2023-04-11T16:18:20.478+0300 DEBUG intermediate batch of contract storage items is persisted {"batch": 1, "took": "56.796257788s", "keys": 200000} 2023-04-11T16:18:54.115+0300 INFO intermediate batch of contract storage items and IDs is collected {"batch": 3, "took": "33.637412437s"} 2023-04-11T16:19:18.844+0300 DEBUG intermediate batch of contract storage items is persisted {"batch": 2, "took": "1m18.0737668s", "keys": 200000} 2023-04-11T16:19:27.650+0300 INFO last batch of contract storage items is collected {"batch": 4, "took": "8.806264019s"} 2023-04-11T16:19:27.650+0300 INFO contract storage items are reset {"took": "3m4.780232077s", "keys": 656944} 2023-04-11T16:20:15.660+0300 DEBUG intermediate batch of contract storage items is persisted {"batch": 3, "took": "1m21.544386403s", "keys": 200000} 2023-04-11T16:20:15.660+0300 DEBUG trying to reset headers information 2023-04-11T16:20:16.385+0300 INFO headers information is reset {"took": "725.174932ms"} 2023-04-11T16:20:19.586+0300 DEBUG last batch of contract storage items and IDs is persisted {"batch": 4, "took": "51.936278608s", "keys": 56945} 2023-04-11T16:20:19.587+0300 DEBUG trying to reset state root information and NEP transfers 2023-04-11T16:20:35.845+0300 INFO state root information and NEP transfers are reset {"took": "16.25852114s"} 2023-04-11T16:21:10.000+0300 DEBUG headers information is persisted {"took": "53.613638429s", "keys": 528438} 2023-04-11T16:21:10.003+0300 DEBUG trying to remove stale storage items 2023-04-11T16:21:18.108+0300 INFO stale storage items are reset {"took": "8.105140658s", "keys": 1350176} 2023-04-11T16:21:18.108+0300 DEBUG trying to remove state reset point 2023-04-11T16:21:18.108+0300 INFO state reset point is removed {"took": "8.554µs"} 2023-04-11T16:21:20.151+0300 DEBUG state root information and NEP transfers are persisted {"took": "44.305707049s", "keys": 602578} 2023-04-11T16:21:20.212+0300 INFO state reset point information is persisted {"took": "2.103764633s", "keys": 2} 2023-04-11T16:21:20.213+0300 INFO reset finished successfully {"took": "5m54.306861367s"} ``` The previous commit: ``` anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ ./bin/neo-go db reset -m --debug --height 600000 2023-04-11T16:24:04.256+0300 INFO MaxBlockSize is not set or wrong, setting default value {"MaxBlockSize": 262144} 2023-04-11T16:24:04.256+0300 INFO MaxBlockSystemFee is not set or wrong, setting default value {"MaxBlockSystemFee": 900000000000} 2023-04-11T16:24:04.256+0300 INFO MaxTransactionsPerBlock is not set or wrong, using default value {"MaxTransactionsPerBlock": 512} 2023-04-11T16:24:04.256+0300 INFO MaxValidUntilBlockIncrement is not set or wrong, using default value {"MaxValidUntilBlockIncrement": 5760} 2023-04-11T16:24:04.261+0300 INFO restoring blockchain {"version": "0.2.8"} 2023-04-11T16:24:04.368+0300 INFO initializing state reset {"target height": 600000} 2023-04-11T16:24:04.368+0300 DEBUG trying to reset blocks, transactions and AERs 2023-04-11T16:24:30.363+0300 INFO intermediate batch of removed blocks, transactions and AERs is collected {"batch": 1, "took": "25.995261037s"} 2023-04-11T16:24:44.947+0300 DEBUG intermediate batch of removed blocks, transactions and AERs is persisted {"batch": 1, "took": "14.584447338s", "keys": 321897} 2023-04-11T16:24:45.791+0300 INFO intermediate batch of removed blocks, transactions and AERs is collected {"batch": 2, "took": "15.428492824s"} 2023-04-11T16:24:51.252+0300 INFO last batch of removed blocks, transactions and AERs is collected {"batch": 3, "took": "5.460662766s"} 2023-04-11T16:24:51.252+0300 INFO blocks, transactions ans AERs are reset {"took": "46.884558096s"} 2023-04-11T16:24:55.399+0300 DEBUG intermediate batch of removed blocks, transactions and AERs is persisted {"batch": 2, "took": "9.607820004s", "keys": 334821} 2023-04-11T16:24:55.399+0300 DEBUG trying to reset contract storage items 2023-04-11T16:24:59.981+0300 DEBUG last batch of removed blocks, transactions and AERs is persisted {"batch": 3, "took": "8.728713255s", "keys": 208913} 2023-04-11T16:25:50.827+0300 INFO intermediate batch of contract storage items and IDs is collected {"batch": 1, "took": "55.426411416s"} 2023-04-11T16:26:28.734+0300 INFO intermediate batch of contract storage items and IDs is collected {"batch": 2, "took": "37.902647706s"} 2023-04-11T16:26:53.960+0300 DEBUG intermediate batch of contract storage items is persisted {"batch": 1, "took": "1m3.129453265s", "keys": 200001} 2023-04-11T16:27:27.645+0300 INFO intermediate batch of contract storage items and IDs is collected {"batch": 3, "took": "33.685283662s"} 2023-04-11T16:27:52.173+0300 DEBUG intermediate batch of contract storage items is persisted {"batch": 2, "took": "1m23.438465575s", "keys": 199999} 2023-04-11T16:28:00.995+0300 INFO last batch of contract storage items is collected {"batch": 4, "took": "8.821990443s"} 2023-04-11T16:28:00.995+0300 INFO contract storage items are reset {"took": "3m5.595950958s", "keys": 656944} 2023-04-11T16:28:49.164+0300 DEBUG intermediate batch of contract storage items is persisted {"batch": 3, "took": "1m21.518344712s", "keys": 200000} 2023-04-11T16:28:49.164+0300 DEBUG trying to reset headers information 2023-04-11T16:28:49.936+0300 INFO headers information is reset {"took": "772.36435ms"} 2023-04-11T16:28:53.122+0300 DEBUG last batch of contract storage items and IDs is persisted {"batch": 4, "took": "52.126928092s", "keys": 56945} 2023-04-11T16:28:53.122+0300 DEBUG trying to reset state root information and NEP transfers 2023-04-11T16:29:09.332+0300 INFO state root information and NEP transfers are reset {"took": "16.20921699s"} 2023-04-11T16:29:46.264+0300 DEBUG headers information is persisted {"took": "56.326715249s", "keys": 528438} 2023-04-11T16:29:46.267+0300 DEBUG trying to remove stale storage items 2023-04-11T16:29:53.986+0300 INFO stale storage items are reset {"took": "7.718950145s", "keys": 1350176} 2023-04-11T16:29:53.986+0300 DEBUG trying to remove state reset point 2023-04-11T16:29:53.986+0300 INFO state reset point is removed {"took": "6.013µs"} 2023-04-11T16:29:55.899+0300 DEBUG state root information and NEP transfers are persisted {"took": "46.567302762s", "keys": 602578} 2023-04-11T16:29:55.929+0300 INFO state reset point information is persisted {"took": "1.942392208s", "keys": 2} 2023-04-11T16:29:55.929+0300 INFO reset finished successfully {"took": "5m51.561573137s"} ``` Master: ``` anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ ./bin/neo-go db reset -m --debug --height 600000 2023-04-11T16:34:12.410+0300 INFO MaxBlockSize is not set or wrong, setting default value {"MaxBlockSize": 262144} 2023-04-11T16:34:12.410+0300 INFO MaxBlockSystemFee is not set or wrong, setting default value {"MaxBlockSystemFee": 900000000000} 2023-04-11T16:34:12.410+0300 INFO MaxTransactionsPerBlock is not set or wrong, using default value {"MaxTransactionsPerBlock": 512} 2023-04-11T16:34:12.410+0300 INFO MaxValidUntilBlockIncrement is not set or wrong, using default value {"MaxValidUntilBlockIncrement": 5760} 2023-04-11T16:34:12.413+0300 INFO restoring blockchain {"version": "0.2.8"} 2023-04-11T16:34:12.495+0300 INFO initialize state reset {"target height": 600000} 2023-04-11T16:34:12.513+0300 INFO trying to reset blocks, transactions and AERs 2023-04-11T16:35:03.582+0300 INFO intermediate batch of removed blocks, transactions and AERs is persisted {"batches persisted": 1, "took": "51.087226195s", "keys": 321895} 2023-04-11T16:35:31.302+0300 INFO intermediate batch of removed blocks, transactions and AERs is persisted {"batches persisted": 2, "took": "27.719871393s", "keys": 334823} 2023-04-11T16:35:41.309+0300 INFO last batch of removed blocks, transactions and AERs is persisted {"batches persisted": 3, "took": "10.007017388s", "keys": 208913} 2023-04-11T16:35:41.309+0300 INFO blocks, transactions ans AERs are reset {"took": "1m28.814245057s", "overall persisted keys": 865631} 2023-04-11T16:35:41.309+0300 INFO trying to reset contract storage items 2023-04-11T16:37:38.315+0300 INFO intermediate batch of contract storage items and IDs is persisted {"batch": 1, "took": "1m57.00650253s", "keys": 200000} 2023-04-11T16:39:29.704+0300 INFO intermediate batch of contract storage items and IDs is persisted {"batch": 2, "took": "1m51.385224725s", "keys": 200000} 2023-04-11T16:41:14.991+0300 INFO intermediate batch of contract storage items and IDs is persisted {"batch": 3, "took": "1m45.287483794s", "keys": 200000} 2023-04-11T16:41:31.667+0300 INFO last batch of contract storage items and IDs is persisted {"batch": 4, "took": "16.675347478s", "keys": 56945} 2023-04-11T16:41:31.667+0300 INFO contract storage items and IDs are reset {"took": "5m50.357775401s", "keys": 656944} 2023-04-11T16:41:31.667+0300 INFO trying to reset headers information 2023-04-11T16:42:16.779+0300 INFO headers information is reset {"took": "45.111354262s", "keys": 528438} 2023-04-11T16:42:16.784+0300 INFO trying to reset state root information and NEP transfers 2023-04-11T16:42:35.778+0300 INFO state root information and NEP transfers are reset {"took": "18.99373117s", "keys": 602578} 2023-04-11T16:42:35.781+0300 INFO trying to remove stale storage items 2023-04-11T16:42:43.884+0300 INFO stale storage items are reset {"took": "8.103929306s", "keys": 1350176} 2023-04-11T16:42:43.885+0300 INFO trying to remove state reset point 2023-04-11T16:42:43.926+0300 INFO stale reset point is removed {"took": "41.858883ms", "keys": 2} 2023-04-11T16:42:43.932+0300 INFO reset finished successfully {"took": "8m31.437493325s"} ``` Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 91 +++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 707775189..f9996d3b4 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -680,7 +680,16 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) return fmt.Errorf("failed to retrieve stateroot for height %d: %w", height, err) } v := bc.dao.Version - cache := bc.dao // dao is MemCachedStore over DB, so use dao directly to persist cached changes right to the underlying DB + // dao is MemCachedStore over DB, we use dao directly to persist cached changes + // right to the underlying DB. + cache := bc.dao + // upperCache is a private MemCachedStore over cache. During each of the state + // sync stages we put the data inside the upperCache; in the end of each stage + // we persist changes from upperCache to cache. Changes from cache are persisted + // directly to the underlying persistent storage (boltDB, levelDB, etc.). + // upperCache/cache segregation is needed to keep the DB state clean and to + // persist data from different stages separately. + upperCache := cache.GetPrivate() bc.log.Info("initializing state reset", zap.Uint32("target height", height)) start := time.Now() @@ -715,7 +724,14 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) resetStageKey := []byte{byte(storage.SYSStateChangeStage)} switch stage { case none: - cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(stateJumpStarted)}) + upperCache.Store.Put(resetStageKey, []byte{stateResetBit | byte(stateJumpStarted)}) + // Technically, there's no difference between Persist() and PersistSync() for the private + // MemCached storage, but we'd better use the sync version in case of some further code changes. + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist state reset start marker to the DB: %w", err) @@ -735,7 +751,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) keysCnt = new(int) ) for i := height + 1; i <= currHeight; i++ { - err := cache.DeleteBlock(bc.GetHeaderHash(i)) + err := upperCache.DeleteBlock(bc.GetHeaderHash(i)) if err != nil { return fmt.Errorf("error while removing block %d: %w", i, err) } @@ -749,6 +765,11 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) persistStart := time.Now() persistBatch := batchCnt + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist intermediate batch of removed blocks, transactions and AERs: %w", err) @@ -763,7 +784,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) p = time.Now() } } - cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(staleBlocksRemoved)}) + upperCache.Store.Put(resetStageKey, []byte{stateResetBit | byte(staleBlocksRemoved)}) batchCnt++ bc.log.Info("last batch of removed blocks, transactions and AERs is collected", zap.Int("batch", batchCnt), @@ -772,6 +793,11 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) persistStart := time.Now() persistBatch := batchCnt + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist last batch of removed blocks, transactions ans AERs: %w", err) @@ -795,7 +821,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) if bc.config.Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeGCFlag } - trieStore := mpt.NewTrieStore(sr.Root, mode, cache.Store) + trieStore := mpt.NewTrieStore(sr.Root, mode, upperCache.Store) oldStoragePrefix := v.StoragePrefix newStoragePrefix := statesync.TemporaryPrefix(oldStoragePrefix) @@ -811,6 +837,11 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) persistStart := time.Now() persistBatch := batchCnt + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist intermediate batch of contract storage items: %w", err) @@ -825,7 +856,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) } // May safely omit KV copying. k[0] = byte(newStoragePrefix) - cache.Store.Put(k, v) + upperCache.Store.Put(k, v) cnt++ storageItmsCnt++ @@ -833,7 +864,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) }) trieStore.Close() - cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(newStorageItemsAdded)}) + upperCache.Store.Put(resetStageKey, []byte{stateResetBit | byte(newStorageItemsAdded)}) batchCnt++ persistBatch := batchCnt bc.log.Info("last batch of contract storage items is collected", zap.Int("batch", batchCnt), zap.Duration("took", time.Since(p))) @@ -841,6 +872,11 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) zap.Int("keys", storageItmsCnt)) lastStart := time.Now() + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist contract storage items and IDs changes to the DB: %w", err) @@ -854,19 +890,29 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) // Reset SYS-prefixed and IX-prefixed information. bc.log.Debug("trying to reset headers information") for i := height + 1; i <= hHeight; i++ { - cache.PurgeHeader(bc.GetHeaderHash(i)) + upperCache.PurgeHeader(bc.GetHeaderHash(i)) } - cache.DeleteHeaderHashes(height+1, headerBatchCount) - cache.StoreAsCurrentBlock(b) - cache.PutCurrentHeader(b.Hash(), height) + upperCache.DeleteHeaderHashes(height+1, headerBatchCount) + upperCache.StoreAsCurrentBlock(b) + upperCache.PutCurrentHeader(b.Hash(), height) v.StoragePrefix = statesync.TemporaryPrefix(v.StoragePrefix) - cache.PutVersion(v) + upperCache.PutVersion(v) + // It's important to manually change the cache's Version at this stage, so that native cache + // can be properly initialized (with the correct contract storage data prefix) at the final + // stage of the state reset. At the same time, DB's SYSVersion-prefixed data will be persisted + // from upperCache to cache in a standard way (several lines below). + cache.Version = v bc.persistent.Version = v - cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(headersReset)}) + upperCache.Store.Put(resetStageKey, []byte{stateResetBit | byte(headersReset)}) bc.log.Info("headers information is reset", zap.Duration("took", time.Since(p))) persistStart := time.Now() + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist headers changes to the DB: %w", err) @@ -879,21 +925,26 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) case headersReset: // Reset MPT. bc.log.Debug("trying to reset state root information and NEP transfers") - err = bc.stateRoot.ResetState(height, cache.Store) + err = bc.stateRoot.ResetState(height, upperCache.Store) if err != nil { return fmt.Errorf("failed to rollback MPT state: %w", err) } // Reset transfers. - err = bc.resetTransfers(cache, height) + err = bc.resetTransfers(upperCache, height) if err != nil { return fmt.Errorf("failed to strip transfer log / transfer info: %w", err) } - cache.Store.Put(resetStageKey, []byte{stateResetBit | byte(transfersReset)}) + upperCache.Store.Put(resetStageKey, []byte{stateResetBit | byte(transfersReset)}) bc.log.Info("state root information and NEP transfers are reset", zap.Duration("took", time.Since(p))) persistStart := time.Now() + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } + upperCache = cache.GetPrivate() persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist contract storage items changes to the DB: %w", err) @@ -927,12 +978,16 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) p = time.Now() bc.log.Debug("trying to remove state reset point") - cache.Store.Delete(resetStageKey) + upperCache.Store.Delete(resetStageKey) // Unlike the state jump, state sync point must be removed as we have complete state for this height. - cache.Store.Delete([]byte{byte(storage.SYSStateSyncPoint)}) + upperCache.Store.Delete([]byte{byte(storage.SYSStateSyncPoint)}) bc.log.Info("state reset point is removed", zap.Duration("took", time.Since(p))) persistStart := time.Now() + _, uerr := upperCache.PersistSync() + if uerr != nil { + panic(uerr) + } persistCh <- func(persistedKeys int, err error) error { if err != nil { return fmt.Errorf("failed to persist state reset stage to DAO: %w", err) From d5bea0ad4c2a221b14981b4bf3e2ae5e9e0dfee5 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 24 Mar 2023 19:32:06 +0300 Subject: [PATCH 025/125] core: add Backwards option for storage iterators Signed-off-by: Anna Shaleva --- pkg/compiler/syscall_test.go | 1 + pkg/core/interop/storage/find.go | 6 ++++-- pkg/core/interop/storage/storage_test.go | 13 ++++++++++++- pkg/interop/storage/storage.go | 2 ++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/pkg/compiler/syscall_test.go b/pkg/compiler/syscall_test.go index fc56d6d0a..466271343 100644 --- a/pkg/compiler/syscall_test.go +++ b/pkg/compiler/syscall_test.go @@ -44,6 +44,7 @@ func TestFindFlags(t *testing.T) { require.EqualValues(t, storage.DeserializeValues, istorage.FindDeserialize) require.EqualValues(t, storage.PickField0, istorage.FindPick0) require.EqualValues(t, storage.PickField1, istorage.FindPick1) + require.EqualValues(t, storage.Backwards, istorage.FindBackwards) } type syscallTestCase struct { diff --git a/pkg/core/interop/storage/find.go b/pkg/core/interop/storage/find.go index 9d2f96668..666950e34 100644 --- a/pkg/core/interop/storage/find.go +++ b/pkg/core/interop/storage/find.go @@ -19,9 +19,10 @@ const ( FindDeserialize = 1 << 3 FindPick0 = 1 << 4 FindPick1 = 1 << 5 + FindBackwards = 1 << 7 FindAll = FindDefault | FindKeysOnly | FindRemovePrefix | FindValuesOnly | - FindDeserialize | FindPick0 | FindPick1 + FindDeserialize | FindPick0 | FindPick1 | FindBackwards ) // Iterator is an iterator state representation. @@ -111,8 +112,9 @@ func Find(ic *interop.Context) error { if opts&FindDeserialize == 0 && (opts&FindPick0 != 0 || opts&FindPick1 != 0) { return fmt.Errorf("%w: PickN is specified without Deserialize", errFindInvalidOptions) } + bkwrds := opts&FindBackwards != 0 ctx, cancel := context.WithCancel(context.Background()) - seekres := ic.DAO.SeekAsync(ctx, stc.ID, storage.SeekRange{Prefix: prefix}) + seekres := ic.DAO.SeekAsync(ctx, stc.ID, storage.SeekRange{Prefix: prefix, Backwards: bkwrds}) item := NewIterator(seekres, prefix, opts) ic.VM.Estack().PushItem(stackitem.NewInterop(item)) ic.RegisterCancelFunc(func() { diff --git a/pkg/core/interop/storage/storage_test.go b/pkg/core/interop/storage/storage_test.go index fec1820b2..a4f3e5449 100644 --- a/pkg/core/interop/storage/storage_test.go +++ b/pkg/core/interop/storage/storage_test.go @@ -197,7 +197,18 @@ func TestFind(t *testing.T) { }), }) }) - + t.Run("normal invocation, backwards", func(t *testing.T) { + testFind(t, []byte{0x01}, istorage.FindBackwards, []stackitem.Item{ + stackitem.NewStruct([]stackitem.Item{ + stackitem.NewByteArray(skeys[0]), + stackitem.NewByteArray(items[0]), + }), + stackitem.NewStruct([]stackitem.Item{ + stackitem.NewByteArray(skeys[2]), + stackitem.NewByteArray(items[2]), + }), + }) + }) t.Run("keys only", func(t *testing.T) { testFind(t, []byte{0x01}, istorage.FindKeysOnly, []stackitem.Item{ stackitem.NewByteArray(skeys[2]), diff --git a/pkg/interop/storage/storage.go b/pkg/interop/storage/storage.go index 146e32104..30b649f7a 100644 --- a/pkg/interop/storage/storage.go +++ b/pkg/interop/storage/storage.go @@ -36,6 +36,8 @@ const ( PickField0 FindFlags = 1 << 4 // PickField1 is used to get second field in a serialized struct or array. PickField1 FindFlags = 1 << 5 + // Backwards is used to iterate over elements in reversed (descending) order. + Backwards FindFlags = 1 << 7 ) // ConvertContextToReadOnly returns new context from the given one, but with From 1962dd956c00c1e366372bf036b4d8c1860f273b Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 12 Apr 2023 16:43:44 +0300 Subject: [PATCH 026/125] *: update interop deps Signed-off-by: Anna Shaleva --- examples/engine/go.mod | 2 +- examples/engine/go.sum | 4 ++-- examples/events/go.mod | 2 +- examples/events/go.sum | 4 ++-- examples/iterator/go.mod | 2 +- examples/iterator/go.sum | 4 ++-- examples/nft-d/go.mod | 2 +- examples/nft-d/go.sum | 4 ++-- examples/nft-nd-nns/go.mod | 2 +- examples/nft-nd-nns/go.sum | 4 ++-- examples/nft-nd/go.mod | 2 +- examples/nft-nd/go.sum | 4 ++-- examples/oracle/go.mod | 2 +- examples/oracle/go.sum | 4 ++-- examples/runtime/go.mod | 2 +- examples/runtime/go.sum | 4 ++-- examples/storage/go.mod | 2 +- examples/storage/go.sum | 4 ++-- examples/timer/go.mod | 2 +- examples/timer/go.sum | 4 ++-- examples/token/go.mod | 2 +- examples/token/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- internal/contracts/oracle_contract/go.mod | 2 +- internal/contracts/oracle_contract/go.sum | 4 ++-- 26 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/engine/go.mod b/examples/engine/go.mod index cac509115..7658c1d5b 100644 --- a/examples/engine/go.mod +++ b/examples/engine/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/engine/go.sum b/examples/engine/go.sum index 029592186..70617580d 100644 --- a/examples/engine/go.sum +++ b/examples/engine/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/events/go.mod b/examples/events/go.mod index feae20fd6..d57741acc 100644 --- a/examples/events/go.mod +++ b/examples/events/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/events/go.sum b/examples/events/go.sum index 029592186..70617580d 100644 --- a/examples/events/go.sum +++ b/examples/events/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/iterator/go.mod b/examples/iterator/go.mod index c4d661733..d77d6574f 100644 --- a/examples/iterator/go.mod +++ b/examples/iterator/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/iterator/go.sum b/examples/iterator/go.sum index 029592186..70617580d 100644 --- a/examples/iterator/go.sum +++ b/examples/iterator/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/nft-d/go.mod b/examples/nft-d/go.mod index c19095fc3..efedc05a9 100644 --- a/examples/nft-d/go.mod +++ b/examples/nft-d/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/nft-d/go.sum b/examples/nft-d/go.sum index 029592186..70617580d 100644 --- a/examples/nft-d/go.sum +++ b/examples/nft-d/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/nft-nd-nns/go.mod b/examples/nft-nd-nns/go.mod index e7d7fcf37..ebe69fd8c 100644 --- a/examples/nft-nd-nns/go.mod +++ b/examples/nft-nd-nns/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a github.com/stretchr/testify v1.8.0 ) diff --git a/examples/nft-nd-nns/go.sum b/examples/nft-nd-nns/go.sum index 59194b659..bfaf070bd 100644 --- a/examples/nft-nd-nns/go.sum +++ b/examples/nft-nd-nns/go.sum @@ -187,8 +187,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 h1:NCIUxkLRB3ovLzM1lvQA6wBNn8fuY7dQx4cMJKLuaAs= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5/go.mod h1:aWrWJZBYO+9kYC4+qJXvEjySW1WIyPnrHpmdrzd5mJY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 h1:rpMCoRa7expLc9gMiOP724gz6YSykZzmMALR/CmiwnU= diff --git a/examples/nft-nd/go.mod b/examples/nft-nd/go.mod index 6f1662b0b..b5fe7fedc 100644 --- a/examples/nft-nd/go.mod +++ b/examples/nft-nd/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/nft-nd/go.sum b/examples/nft-nd/go.sum index 029592186..70617580d 100644 --- a/examples/nft-nd/go.sum +++ b/examples/nft-nd/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/oracle/go.mod b/examples/oracle/go.mod index 668c822bc..eaa29ecb1 100644 --- a/examples/oracle/go.mod +++ b/examples/oracle/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/oracle/go.sum b/examples/oracle/go.sum index 029592186..70617580d 100644 --- a/examples/oracle/go.sum +++ b/examples/oracle/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/runtime/go.mod b/examples/runtime/go.mod index 0d7b6cac7..6c9134d1e 100644 --- a/examples/runtime/go.mod +++ b/examples/runtime/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/runtime/go.sum b/examples/runtime/go.sum index 029592186..70617580d 100644 --- a/examples/runtime/go.sum +++ b/examples/runtime/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/storage/go.mod b/examples/storage/go.mod index 863173296..d8329e0c3 100644 --- a/examples/storage/go.mod +++ b/examples/storage/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/storage/go.sum b/examples/storage/go.sum index 029592186..70617580d 100644 --- a/examples/storage/go.sum +++ b/examples/storage/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/timer/go.mod b/examples/timer/go.mod index d6f575941..75979d7c8 100644 --- a/examples/timer/go.mod +++ b/examples/timer/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/timer/go.sum b/examples/timer/go.sum index 029592186..70617580d 100644 --- a/examples/timer/go.sum +++ b/examples/timer/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/token/go.mod b/examples/token/go.mod index 8591a3b3b..c4b8ca56a 100644 --- a/examples/token/go.mod +++ b/examples/token/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/examples/token/go.sum b/examples/token/go.sum index 029592186..70617580d 100644 --- a/examples/token/go.sum +++ b/examples/token/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/go.mod b/go.mod index ed129974e..17c27414d 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 github.com/nspcc-dev/rfc6979 v0.2.0 github.com/pierrec/lz4 v2.6.1+incompatible diff --git a/go.sum b/go.sum index f725f3296..a115b1f27 100644 --- a/go.sum +++ b/go.sum @@ -268,8 +268,8 @@ github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= diff --git a/internal/contracts/oracle_contract/go.mod b/internal/contracts/oracle_contract/go.mod index 687c92312..98a1977c7 100644 --- a/internal/contracts/oracle_contract/go.mod +++ b/internal/contracts/oracle_contract/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/internal/examples/oracle go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a diff --git a/internal/contracts/oracle_contract/go.sum b/internal/contracts/oracle_contract/go.sum index 029592186..70617580d 100644 --- a/internal/contracts/oracle_contract/go.sum +++ b/internal/contracts/oracle_contract/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91 h1:hU7UwIQp+r13s62B0ofBLYcP7R5zU6wl8haLEdkGWBY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230405124917-68cb07999b91/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= From 541da7e83b77a5512656c188f913892b80f6b0d3 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 11 Apr 2023 18:45:50 +0300 Subject: [PATCH 027/125] cli: add `util ops` command Signed-off-by: Anna Shaleva --- cli/util/convert.go | 52 +++++++++++++++++++++++++++++++++++++++++++ cli/util/util_test.go | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/cli/util/convert.go b/cli/util/convert.go index 1fb910216..71a1c9547 100644 --- a/cli/util/convert.go +++ b/cli/util/convert.go @@ -1,10 +1,14 @@ package util import ( + "encoding/base64" + "encoding/hex" "fmt" + "os" "github.com/nspcc-dev/neo-go/cli/options" vmcli "github.com/nspcc-dev/neo-go/cli/vm" + "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/urfave/cli" ) @@ -44,6 +48,22 @@ func NewCommands() []cli.Command { Action: txDump, Flags: txDumpFlags, }, + { + Name: "ops", + Usage: "Pretty-print VM opcodes of the given base64- or hex- encoded script (base64 is checked first). If the input file is specified, then the script is taken from the file.", + UsageText: "ops [-i path-to-file] [--hex]", + Action: handleOps, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "in, i", + Usage: "input file containing base64- or hex- encoded script representation", + }, + cli.BoolFlag{ + Name: "hex", + Usage: "use hex encoding and do not check base64", + }, + }, + }, }, }, } @@ -57,3 +77,35 @@ func handleParse(ctx *cli.Context) error { fmt.Fprint(ctx.App.Writer, res) return nil } + +func handleOps(ctx *cli.Context) error { + var ( + s string + err error + b []byte + ) + in := ctx.String("in") + if len(in) != 0 { + b, err := os.ReadFile(in) + if err != nil { + return cli.NewExitError(fmt.Errorf("failed to read file: %w", err), 1) + } + s = string(b) + } else { + if !ctx.Args().Present() { + return cli.NewExitError("missing script", 1) + } + s = ctx.Args()[0] + } + b, err = base64.StdEncoding.DecodeString(s) + if err != nil || ctx.Bool("hex") { + b, err = hex.DecodeString(s) + } + if err != nil { + return cli.NewExitError("unknown encoding: base64 or hex are supported", 1) + } + v := vm.New() + v.LoadScript(b) + v.PrintOps(ctx.App.Writer) + return nil +} diff --git a/cli/util/util_test.go b/cli/util/util_test.go index e2f073465..609937fc9 100644 --- a/cli/util/util_test.go +++ b/cli/util/util_test.go @@ -1,10 +1,13 @@ package util_test import ( + "os" + "path/filepath" "testing" "github.com/nspcc-dev/neo-go/internal/testcli" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" ) func TestUtilConvert(t *testing.T) { @@ -24,3 +27,39 @@ func TestUtilConvert(t *testing.T) { e.CheckNextLine(t, "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzMDIwMQ==") // string to base64 e.CheckEOF(t) } + +func TestUtilOps(t *testing.T) { + e := testcli.NewExecutor(t, false) + base64Str := "EUA=" + hexStr := "1140" + + check := func(t *testing.T) { + e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER") + e.CheckNextLine(t, "PUSH1") + e.CheckNextLine(t, "RET") + e.CheckEOF(t) + } + + e.Run(t, "neo-go", "util", "ops", base64Str) // base64 + check(t) + + e.Run(t, "neo-go", "util", "ops", hexStr) // base64 is checked firstly by default, but it's invalid script if decoded from base64 + e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER") + e.CheckNextLine(t, ".*ERROR: incorrect opcode") + e.CheckEOF(t) + + e.Run(t, "neo-go", "util", "ops", "--hex", hexStr) // explicitly specify hex encoding + check(t) + + e.RunWithError(t, "neo-go", "util", "ops", "%&~*") // unknown encoding + + tmp := filepath.Join(t.TempDir(), "script_base64.txt") + require.NoError(t, os.WriteFile(tmp, []byte(base64Str), os.ModePerm)) + e.Run(t, "neo-go", "util", "ops", "--in", tmp) // base64 from file + check(t) + + tmp = filepath.Join(t.TempDir(), "script_hex.txt") + require.NoError(t, os.WriteFile(tmp, []byte(hexStr), os.ModePerm)) + e.Run(t, "neo-go", "util", "ops", "--hex", "--in", tmp) // hex from file + check(t) +} From 55ab38ed8120483b3a3b743e790315b5757da078 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 12:00:52 +0300 Subject: [PATCH 028/125] network: do not use error channel to start network srv It's obsolete thing, we have looger and it perfectly suits our needs. Signed-off-by: Anna Shaleva --- cli/server/server.go | 2 +- internal/testcli/executor.go | 2 +- pkg/network/server.go | 2 +- pkg/network/server_test.go | 18 +++--------------- pkg/services/rpcsrv/subscription_test.go | 4 ++-- 5 files changed, 8 insertions(+), 20 deletions(-) diff --git a/cli/server/server.go b/cli/server/server.go index bcea6b115..e1b9c5edf 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -489,7 +489,7 @@ func startServer(ctx *cli.Context) error { rpcServer := rpcsrv.New(chain, cfg.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan) serv.AddService(&rpcServer) - go serv.Start(errChan) + go serv.Start() if !cfg.ApplicationConfiguration.RPC.StartWhenSynchronized { rpcServer.Start() } diff --git a/internal/testcli/executor.go b/internal/testcli/executor.go index d65823334..20fa01a64 100644 --- a/internal/testcli/executor.go +++ b/internal/testcli/executor.go @@ -164,7 +164,7 @@ func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch }) require.NoError(t, err) netSrv.AddConsensusService(cons, cons.OnPayload, cons.OnTransaction) - go netSrv.Start(make(chan error, 1)) + go netSrv.Start() errCh := make(chan error, 2) rpcServer := rpcsrv.New(chain, cfg.ApplicationConfiguration.RPC, netSrv, nil, logger, errCh) rpcServer.Start() diff --git a/pkg/network/server.go b/pkg/network/server.go index 0ce3697d5..b6661b2a4 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -265,7 +265,7 @@ func (s *Server) ID() uint32 { // Start will start the server and its underlying transport. Calling it twice // is an error. -func (s *Server) Start(errChan chan error) { +func (s *Server) Start() { s.log.Info("node started", zap.Uint32("blockHeight", s.chain.BlockHeight()), zap.Uint32("headerHeight", s.chain.HeaderHeight())) diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index edd1968b1..4b95eee4a 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -87,20 +87,11 @@ func TestNewServer(t *testing.T) { }) } -func startWithChannel(s *Server) chan error { - ch := make(chan error) - go func() { - s.Start(ch) - close(ch) - }() - return ch -} - func TestServerStartAndShutdown(t *testing.T) { t.Run("no consensus", func(t *testing.T) { s := newTestServer(t, ServerConfig{}) - ch := startWithChannel(s) + go s.Start() p := newLocalPeer(t, s) s.register <- p require.Eventually(t, func() bool { return 1 == s.PeerCount() }, time.Second, time.Millisecond*10) @@ -109,7 +100,6 @@ func TestServerStartAndShutdown(t *testing.T) { assert.Nil(t, s.txCallback) s.Shutdown() - <-ch require.True(t, s.transports[0].(*fakeTransp).closed.Load()) err, ok := p.droppedWith.Load().(error) @@ -121,14 +111,13 @@ func TestServerStartAndShutdown(t *testing.T) { cons := new(fakeConsensus) s.AddConsensusService(cons, cons.OnPayload, cons.OnTransaction) - ch := startWithChannel(s) + go s.Start() p := newLocalPeer(t, s) s.register <- p assert.True(t, s.services["fake"].(*fakeConsensus).started.Load()) s.Shutdown() - <-ch require.True(t, s.services["fake"].(*fakeConsensus).stopped.Load()) }) @@ -401,10 +390,9 @@ func startTestServer(t *testing.T, protocolCfg ...func(*config.Blockchain)) *Ser } func startWithCleanup(t *testing.T, s *Server) { - ch := startWithChannel(s) + go s.Start() t.Cleanup(func() { s.Shutdown() - <-ch }) } diff --git a/pkg/services/rpcsrv/subscription_test.go b/pkg/services/rpcsrv/subscription_test.go index 2aece5b6e..ba654a5b3 100644 --- a/pkg/services/rpcsrv/subscription_test.go +++ b/pkg/services/rpcsrv/subscription_test.go @@ -99,7 +99,7 @@ func TestSubscriptions(t *testing.T) { defer chain.Close() defer rpcSrv.Shutdown() - go rpcSrv.coreServer.Start(make(chan error)) + go rpcSrv.coreServer.Start() defer rpcSrv.coreServer.Shutdown() for _, feed := range subFeeds { @@ -374,7 +374,7 @@ func TestFilteredNotaryRequestSubscriptions(t *testing.T) { } chain, rpcSrv, c, respMsgs, finishedFlag := initCleanServerAndWSClient(t) - go rpcSrv.coreServer.Start(make(chan error, 1)) + go rpcSrv.coreServer.Start() defer chain.Close() defer rpcSrv.Shutdown() From 8149d33fef0f0b8b2be1fad9a495264cf7c0e85a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 12:43:21 +0300 Subject: [PATCH 029/125] config: use uint32 for validators/committee members count Signed-off-by: Anna Shaleva --- docs/node-configuration.md | 4 +-- pkg/config/protocol_config.go | 14 +++++------ pkg/config/protocol_config_test.go | 40 +++++++++++++++--------------- pkg/core/blockchain_core_test.go | 4 +-- pkg/neorpc/result/version.go | 12 ++++----- pkg/rpcclient/actor/maker.go | 4 +-- pkg/rpcclient/actor/maker_test.go | 2 +- 7 files changed, 40 insertions(+), 40 deletions(-) diff --git a/docs/node-configuration.md b/docs/node-configuration.md index 0baaabc4c..36a2013f1 100644 --- a/docs/node-configuration.md +++ b/docs/node-configuration.md @@ -341,7 +341,7 @@ protocol-related settings described in the table below. | Section | Type | Default value | Description | Notes | | --- | --- | --- | --- | --- | -| CommitteeHistory | map[uint32]int | none | Number of committee members after the given height, for example `{0: 1, 20: 4}` sets up a chain with one committee member since the genesis and then changes the setting to 4 committee members at the height of 20. `StandbyCommittee` committee setting must have the number of keys equal or exceeding the highest value in this option. Blocks numbers where the change happens must be divisible by the old and by the new values simultaneously. If not set, committee size is derived from the `StandbyCommittee` setting and never changes. | +| CommitteeHistory | map[uint32]uint32 | none | Number of committee members after the given height, for example `{0: 1, 20: 4}` sets up a chain with one committee member since the genesis and then changes the setting to 4 committee members at the height of 20. `StandbyCommittee` committee setting must have the number of keys equal or exceeding the highest value in this option. Blocks numbers where the change happens must be divisible by the old and by the new values simultaneously. If not set, committee size is derived from the `StandbyCommittee` setting and never changes. | | GarbageCollectionPeriod | `uint32` | 10000 | Controls MPT garbage collection interval (in blocks) for configurations with `RemoveUntraceableBlocks` enabled and `KeepOnlyLatestState` disabled. In this mode the node stores a number of MPT trees (corresponding to `MaxTraceableBlocks` and `StateSyncInterval`), but the DB needs to be clean from old entries from time to time. Doing it too often will cause too much processing overhead, doing it too rarely will leave more useless data in the DB. This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, ApplicationConfiguration is prioritized over this one. | | Hardforks | `map[string]uint32` | [] | The set of incompatible changes that affect node behaviour starting from the specified height. The default value is an empty set which should be interpreted as "each known hard-fork is applied from the zero blockchain height". The list of valid hard-fork names:
• `Aspidochelone` represents hard-fork introduced in [#2469](https://github.com/nspcc-dev/neo-go/pull/2469) (ported from the [reference](https://github.com/neo-project/neo/pull/2712)). It adjusts the prices of `System.Contract.CreateStandardAccount` and `System.Contract.CreateMultisigAccount` interops so that the resulting prices are in accordance with `sha256` method of native `CryptoLib` contract. It also includes [#2519](https://github.com/nspcc-dev/neo-go/pull/2519) (ported from the [reference](https://github.com/neo-project/neo/pull/2749)) that adjusts the price of `System.Runtime.GetRandom` interop and fixes its vulnerability. A special NeoGo-specific change is included as well for ContractManagement's update/deploy call flags behaviour to be compatible with pre-0.99.0 behaviour that was changed because of the [3.2.0 protocol change](https://github.com/neo-project/neo/pull/2653). | | KeepOnlyLatestState | `bool` | `false` | Specifies if MPT should only store the latest state (or a set of latest states, see `P2PStateExcangeExtensions` section for details). If true, DB size will be smaller, but older roots won't be accessible. This value should remain the same for the same database. | This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, setting any of them to true enables the function. | @@ -366,6 +366,6 @@ protocol-related settings described in the table below. | StateSyncInterval | `int` | `40000` | The number of blocks between state heights available for MPT state data synchronization. | `P2PStateExchangeExtensions` should be enabled to use this setting. | | TimePerBlock | `Duration` | `15s` | Minimal (and targeted for) time interval between blocks. Must be an integer number of milliseconds. | | ValidatorsCount | `int` | `0` | Number of validators set for the whole network lifetime, can't be set if `ValidatorsHistory` setting is used. | -| ValidatorsHistory | map[uint32]int | none | Number of consensus nodes to use after given height (see `CommitteeHistory` also). Heights where the change occurs must be divisible by the number of committee members at that height. Can't be used with `ValidatorsCount` not equal to zero. | +| ValidatorsHistory | map[uint32]uint32 | none | Number of consensus nodes to use after given height (see `CommitteeHistory` also). Heights where the change occurs must be divisible by the number of committee members at that height. Can't be used with `ValidatorsCount` not equal to zero. | | VerifyBlocks | `bool` | `false` | This setting is deprecated and no longer works, please use `SkipBlockVerification` in the `ApplicationConfiguration`, it will be removed in future node versions. | | VerifyTransactions | `bool` | `false` | Denotes whether to verify transactions in the received blocks. | diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 653f1a6e2..943ad6791 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -15,7 +15,7 @@ import ( type ( ProtocolConfiguration struct { // CommitteeHistory stores committee size change history (height: size). - CommitteeHistory map[uint32]int `yaml:"CommitteeHistory"` + CommitteeHistory map[uint32]uint32 `yaml:"CommitteeHistory"` // GarbageCollectionPeriod sets the number of blocks to wait before // starting the next MPT garbage collection cycle when RemoveUntraceableBlocks // option is used. @@ -84,7 +84,7 @@ type ( TimePerBlock time.Duration `yaml:"TimePerBlock"` ValidatorsCount int `yaml:"ValidatorsCount"` // Validators stores history of changes to consensus node number (height: number). - ValidatorsHistory map[uint32]int `yaml:"ValidatorsHistory"` + ValidatorsHistory map[uint32]uint32 `yaml:"ValidatorsHistory"` // Whether to verify received blocks. // // Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions. @@ -97,7 +97,7 @@ type ( // heightNumber is an auxiliary structure for configuration checks. type heightNumber struct { h uint32 - n int + n uint32 } // Validate checks ProtocolConfiguration for internal consistency and returns @@ -187,11 +187,11 @@ func (p *ProtocolConfiguration) GetCommitteeSize(height uint32) int { if len(p.CommitteeHistory) == 0 { return len(p.StandbyCommittee) } - return getBestFromMap(p.CommitteeHistory, height) + return int(getBestFromMap(p.CommitteeHistory, height)) } -func getBestFromMap(dict map[uint32]int, height uint32) int { - var res int +func getBestFromMap(dict map[uint32]uint32, height uint32) uint32 { + var res uint32 var bestH = uint32(0) for h, n := range dict { if h >= bestH && h <= height { @@ -208,7 +208,7 @@ func (p *ProtocolConfiguration) GetNumOfCNs(height uint32) int { if len(p.ValidatorsHistory) == 0 { return p.ValidatorsCount } - return getBestFromMap(p.ValidatorsHistory, height) + return int(getBestFromMap(p.ValidatorsHistory, height)) } // ShouldUpdateCommitteeAt answers the question of whether the committee diff --git a/pkg/config/protocol_config_test.go b/pkg/config/protocol_config_test.go index aa6e6d68b..05731813b 100644 --- a/pkg/config/protocol_config_test.go +++ b/pkg/config/protocol_config_test.go @@ -52,7 +52,7 @@ func TestProtocolConfigurationValidation(t *testing.T) { "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, ValidatorsCount: 4, - ValidatorsHistory: map[uint32]int{0: 4}, + ValidatorsHistory: map[uint32]uint32{0: 4}, } require.Error(t, p.Validate()) p = &ProtocolConfiguration{ @@ -62,8 +62,8 @@ func TestProtocolConfigurationValidation(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 4}, - ValidatorsHistory: map[uint32]int{0: 4, 1000: 5}, + CommitteeHistory: map[uint32]uint32{0: 4}, + ValidatorsHistory: map[uint32]uint32{0: 4, 1000: 5}, } require.Error(t, p.Validate()) p = &ProtocolConfiguration{ @@ -73,8 +73,8 @@ func TestProtocolConfigurationValidation(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 4, 1000: 5}, - ValidatorsHistory: map[uint32]int{0: 4}, + CommitteeHistory: map[uint32]uint32{0: 4, 1000: 5}, + ValidatorsHistory: map[uint32]uint32{0: 4}, } require.Error(t, p.Validate()) p = &ProtocolConfiguration{ @@ -84,8 +84,8 @@ func TestProtocolConfigurationValidation(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 1, 999: 4}, - ValidatorsHistory: map[uint32]int{0: 1}, + CommitteeHistory: map[uint32]uint32{0: 1, 999: 4}, + ValidatorsHistory: map[uint32]uint32{0: 1}, } require.Error(t, p.Validate()) p = &ProtocolConfiguration{ @@ -95,8 +95,8 @@ func TestProtocolConfigurationValidation(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 1, 1000: 4}, - ValidatorsHistory: map[uint32]int{0: 1, 999: 4}, + CommitteeHistory: map[uint32]uint32{0: 1, 1000: 4}, + ValidatorsHistory: map[uint32]uint32{0: 1, 999: 4}, } require.Error(t, p.Validate()) p = &ProtocolConfiguration{ @@ -106,8 +106,8 @@ func TestProtocolConfigurationValidation(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 1, 100: 4}, - ValidatorsHistory: map[uint32]int{0: 4, 100: 4}, + CommitteeHistory: map[uint32]uint32{0: 1, 100: 4}, + ValidatorsHistory: map[uint32]uint32{0: 4, 100: 4}, } require.Error(t, p.Validate()) p = &ProtocolConfiguration{ @@ -123,8 +123,8 @@ func TestProtocolConfigurationValidation(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 1, 100: 4}, - ValidatorsHistory: map[uint32]int{0: 1, 100: 4}, + CommitteeHistory: map[uint32]uint32{0: 1, 100: 4}, + ValidatorsHistory: map[uint32]uint32{0: 1, 100: 4}, } require.NoError(t, p.Validate()) } @@ -137,8 +137,8 @@ func TestGetCommitteeAndCNs(t *testing.T) { "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", }, - CommitteeHistory: map[uint32]int{0: 1, 100: 4}, - ValidatorsHistory: map[uint32]int{0: 1, 200: 4}, + CommitteeHistory: map[uint32]uint32{0: 1, 100: 4}, + ValidatorsHistory: map[uint32]uint32{0: 1, 200: 4}, } require.Equal(t, 1, p.GetCommitteeSize(0)) require.Equal(t, 1, p.GetCommitteeSize(99)) @@ -173,8 +173,8 @@ func TestProtocolConfigurationEquals(t *testing.T) { o = &cfg2.ProtocolConfiguration require.True(t, p.Equals(o)) - o.CommitteeHistory = map[uint32]int{111: 7} - p.CommitteeHistory = map[uint32]int{111: 7} + o.CommitteeHistory = map[uint32]uint32{111: 7} + p.CommitteeHistory = map[uint32]uint32{111: 7} require.True(t, p.Equals(o)) p.CommitteeHistory[111] = 8 require.False(t, p.Equals(o)) @@ -220,9 +220,9 @@ func TestProtocolConfigurationEquals(t *testing.T) { p.StandbyCommittee = nil o.StandbyCommittee = nil - o.ValidatorsHistory = map[uint32]int{111: 0} - p.ValidatorsHistory = map[uint32]int{111: 0} + o.ValidatorsHistory = map[uint32]uint32{111: 0} + p.ValidatorsHistory = map[uint32]uint32{111: 0} require.True(t, p.Equals(o)) - p.ValidatorsHistory = map[uint32]int{112: 0} + p.ValidatorsHistory = map[uint32]uint32{112: 0} require.False(t, p.Equals(o)) } diff --git a/pkg/core/blockchain_core_test.go b/pkg/core/blockchain_core_test.go index eadb0b183..5b1944c52 100644 --- a/pkg/core/blockchain_core_test.go +++ b/pkg/core/blockchain_core_test.go @@ -247,12 +247,12 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { func TestChainWithVolatileNumOfValidators(t *testing.T) { bc := newTestChainWithCustomCfg(t, func(c *config.Config) { c.ProtocolConfiguration.ValidatorsCount = 0 - c.ProtocolConfiguration.CommitteeHistory = map[uint32]int{ + c.ProtocolConfiguration.CommitteeHistory = map[uint32]uint32{ 0: 1, 4: 4, 24: 6, } - c.ProtocolConfiguration.ValidatorsHistory = map[uint32]int{ + c.ProtocolConfiguration.ValidatorsHistory = map[uint32]uint32{ 0: 1, 4: 4, } diff --git a/pkg/neorpc/result/version.go b/pkg/neorpc/result/version.go index aea901da4..deb4f33d4 100644 --- a/pkg/neorpc/result/version.go +++ b/pkg/neorpc/result/version.go @@ -34,13 +34,13 @@ type ( // returned by the server in case they're enabled. // CommitteeHistory stores height:size map of the committee size. - CommitteeHistory map[uint32]int + CommitteeHistory map[uint32]uint32 // P2PSigExtensions is true when Notary subsystem is enabled on the network. P2PSigExtensions bool // StateRootInHeader is true if state root is contained in block header. StateRootInHeader bool // ValidatorsHistory stores height:size map of the validators count. - ValidatorsHistory map[uint32]int + ValidatorsHistory map[uint32]uint32 } // protocolMarshallerAux is an auxiliary struct used for Protocol JSON marshalling. @@ -55,10 +55,10 @@ type ( ValidatorsCount byte `json:"validatorscount"` InitialGasDistribution int64 `json:"initialgasdistribution"` - CommitteeHistory map[uint32]int `json:"committeehistory,omitempty"` - P2PSigExtensions bool `json:"p2psigextensions,omitempty"` - StateRootInHeader bool `json:"staterootinheader,omitempty"` - ValidatorsHistory map[uint32]int `json:"validatorshistory,omitempty"` + CommitteeHistory map[uint32]uint32 `json:"committeehistory,omitempty"` + P2PSigExtensions bool `json:"p2psigextensions,omitempty"` + StateRootInHeader bool `json:"staterootinheader,omitempty"` + ValidatorsHistory map[uint32]uint32 `json:"validatorshistory,omitempty"` } ) diff --git a/pkg/rpcclient/actor/maker.go b/pkg/rpcclient/actor/maker.go index 38b9d92fe..0aa346ab7 100644 --- a/pkg/rpcclient/actor/maker.go +++ b/pkg/rpcclient/actor/maker.go @@ -214,7 +214,7 @@ func (a *Actor) CalculateValidUntilBlock() (uint32, error) { if err != nil { return 0, fmt.Errorf("can't get block count: %w", err) } - var vc = int(a.version.Protocol.ValidatorsCount) + var vc = uint32(a.version.Protocol.ValidatorsCount) var bestH = uint32(0) for h, n := range a.version.Protocol.ValidatorsHistory { // In case it's enabled. if h >= bestH && h <= blockCount { @@ -223,5 +223,5 @@ func (a *Actor) CalculateValidUntilBlock() (uint32, error) { } } - return blockCount + uint32(vc+1), nil + return blockCount + vc + 1, nil } diff --git a/pkg/rpcclient/actor/maker_test.go b/pkg/rpcclient/actor/maker_test.go index 1b17510e8..83fa42a5b 100644 --- a/pkg/rpcclient/actor/maker_test.go +++ b/pkg/rpcclient/actor/maker_test.go @@ -25,7 +25,7 @@ func TestCalculateValidUntilBlock(t *testing.T) { require.NoError(t, err) require.Equal(t, uint32(42+7+1), vub) - client.version.Protocol.ValidatorsHistory = map[uint32]int{ + client.version.Protocol.ValidatorsHistory = map[uint32]uint32{ 0: 7, 40: 4, 80: 10, From 0c049f620fc5ec8f9b0757b44a4105bc73dc5df7 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 13:02:36 +0300 Subject: [PATCH 030/125] config: do not allow zero numbers for validators/committee history Signed-off-by: Anna Shaleva --- pkg/config/protocol_config.go | 6 ++++++ pkg/config/protocol_config_test.go | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 943ad6791..6dc745504 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -130,6 +130,9 @@ func (p *ProtocolConfiguration) Validate() error { } var arr = make([]heightNumber, 0, len(p.CommitteeHistory)) for h, n := range p.CommitteeHistory { + if n == 0 { + return fmt.Errorf("invalid CommitteeHistory: bad members count (%d) for height %d", n, h) + } if int(n) > len(p.StandbyCommittee) { return fmt.Errorf("too small StandbyCommittee for required number of committee members at %d", h) } @@ -148,6 +151,9 @@ func (p *ProtocolConfiguration) Validate() error { } arr = arr[:0] for h, n := range p.ValidatorsHistory { + if n == 0 { + return fmt.Errorf("invalid ValidatorsHistory: bad members count (%d) for height %d", n, h) + } if int(n) > len(p.StandbyCommittee) { return fmt.Errorf("too small StandbyCommittee for required number of validators at %d", h) } diff --git a/pkg/config/protocol_config_test.go b/pkg/config/protocol_config_test.go index 05731813b..c95a2fc1a 100644 --- a/pkg/config/protocol_config_test.go +++ b/pkg/config/protocol_config_test.go @@ -110,6 +110,28 @@ func TestProtocolConfigurationValidation(t *testing.T) { ValidatorsHistory: map[uint32]uint32{0: 4, 100: 4}, } require.Error(t, p.Validate()) + p = &ProtocolConfiguration{ + StandbyCommittee: []string{ + "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", + "02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e", + "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", + "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", + }, + CommitteeHistory: map[uint32]uint32{0: 0, 100: 4}, + ValidatorsHistory: map[uint32]uint32{0: 1, 100: 4}, + } + require.Error(t, p.Validate()) + p = &ProtocolConfiguration{ + StandbyCommittee: []string{ + "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", + "02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e", + "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", + "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62", + }, + CommitteeHistory: map[uint32]uint32{0: 1, 100: 4}, + ValidatorsHistory: map[uint32]uint32{0: 0, 100: 4}, + } + require.Error(t, p.Validate()) p = &ProtocolConfiguration{ Hardforks: map[string]uint32{ "Unknown": 123, // Unknown hard-fork. From a74454aaca45bf9d9fb4c3b0606d8248def345be Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 13:10:01 +0300 Subject: [PATCH 031/125] config: do not allow negative validators count Signed-off-by: Anna Shaleva --- docs/node-configuration.md | 2 +- pkg/config/protocol_config.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/node-configuration.md b/docs/node-configuration.md index 36a2013f1..86e938d86 100644 --- a/docs/node-configuration.md +++ b/docs/node-configuration.md @@ -365,7 +365,7 @@ protocol-related settings described in the table below. | StateRootInHeader | `bool` | `false` | Enables storing state root in block header. | Experimental protocol extension! | | StateSyncInterval | `int` | `40000` | The number of blocks between state heights available for MPT state data synchronization. | `P2PStateExchangeExtensions` should be enabled to use this setting. | | TimePerBlock | `Duration` | `15s` | Minimal (and targeted for) time interval between blocks. Must be an integer number of milliseconds. | -| ValidatorsCount | `int` | `0` | Number of validators set for the whole network lifetime, can't be set if `ValidatorsHistory` setting is used. | +| ValidatorsCount | `uint32` | `0` | Number of validators set for the whole network lifetime, can't be set if `ValidatorsHistory` setting is used. | | ValidatorsHistory | map[uint32]uint32 | none | Number of consensus nodes to use after given height (see `CommitteeHistory` also). Heights where the change occurs must be divisible by the number of committee members at that height. Can't be used with `ValidatorsCount` not equal to zero. | | VerifyBlocks | `bool` | `false` | This setting is deprecated and no longer works, please use `SkipBlockVerification` in the `ApplicationConfiguration`, it will be removed in future node versions. | | VerifyTransactions | `bool` | `false` | Denotes whether to verify transactions in the received blocks. | diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 6dc745504..240d82288 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -82,7 +82,7 @@ type ( // TimePerBlock is the time interval between blocks that consensus nodes work with. // It must be an integer number of milliseconds. TimePerBlock time.Duration `yaml:"TimePerBlock"` - ValidatorsCount int `yaml:"ValidatorsCount"` + ValidatorsCount uint32 `yaml:"ValidatorsCount"` // Validators stores history of changes to consensus node number (height: number). ValidatorsHistory map[uint32]uint32 `yaml:"ValidatorsHistory"` // Whether to verify received blocks. @@ -125,7 +125,7 @@ func (p *ProtocolConfiguration) Validate() error { if p.ValidatorsCount != 0 && len(p.ValidatorsHistory) != 0 { return errors.New("configuration should either have ValidatorsCount or ValidatorsHistory, not both") } - if len(p.StandbyCommittee) < p.ValidatorsCount { + if len(p.StandbyCommittee) < int(p.ValidatorsCount) { return errors.New("validators count can't exceed the size of StandbyCommittee") } var arr = make([]heightNumber, 0, len(p.CommitteeHistory)) @@ -212,7 +212,7 @@ func getBestFromMap(dict map[uint32]uint32, height uint32) uint32 { // It implies valid configuration file. func (p *ProtocolConfiguration) GetNumOfCNs(height uint32) int { if len(p.ValidatorsHistory) == 0 { - return p.ValidatorsCount + return int(p.ValidatorsCount) } return int(getBestFromMap(p.ValidatorsHistory, height)) } From 49cea72e417385f8dd2b191c28bafebb7ddc1b16 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 18:20:52 +0300 Subject: [PATCH 032/125] core: improve documentation to SetOracle/SetNotary I've carefully checked the way how new service can be added to the Blockchain instance or to be removed from it. Current implemention of SetNotary and SetOracle methods doesn't contain dangerous code, and native contracts have atomic values everywhere where service is stored. Current implementation of Notary, Oracle and StateRoot services' reload/disabling/enabling on SIGUSR1 is safe and doesn't require any adjustment. This commit closes #2944, it's not a bug in the code, it's just stale documentation. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index f9996d3b4..29dca5738 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -328,8 +328,8 @@ func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger) (*Bl return bc, nil } -// SetOracle sets oracle module. It doesn't protected by mutex and -// must be called before `bc.Run()` to avoid data race. +// SetOracle sets oracle module. It can safely be called on the running blockchain. +// To unregister Oracle service use SetOracle(nil). func (bc *Blockchain) SetOracle(mod native.OracleService) { orc := bc.contracts.Oracle if mod != nil { @@ -356,8 +356,8 @@ func (bc *Blockchain) SetOracle(mod native.OracleService) { bc.contracts.Designate.OracleService.Store(&mod) } -// SetNotary sets notary module. It doesn't protected by mutex and -// must be called before `bc.Run()` to avoid data race. +// SetNotary sets notary module. It may safely be called on the running blockchain. +// To unregister Notary service use SetNotary(nil). func (bc *Blockchain) SetNotary(mod native.NotaryService) { if mod != nil { keys, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.P2PNotary, bc.BlockHeight()) From 7bcc62d99cdc4b6c0ac42a6f4b3120554fbf652c Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 13:49:07 +0300 Subject: [PATCH 033/125] *: fix Prometheus metrics comment formatting Signed-off-by: Anna Shaleva --- pkg/core/mempool/prometheus.go | 2 +- pkg/core/prometheus.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/core/mempool/prometheus.go b/pkg/core/mempool/prometheus.go index dbe073a0d..ca19c2c83 100644 --- a/pkg/core/mempool/prometheus.go +++ b/pkg/core/mempool/prometheus.go @@ -3,7 +3,7 @@ package mempool import "github.com/prometheus/client_golang/prometheus" var ( - //mempoolUnsortedTx prometheus metric. + // mempoolUnsortedTx prometheus metric. mempoolUnsortedTx = prometheus.NewGauge( prometheus.GaugeOpts{ Help: "Mempool Unsorted TXs", diff --git a/pkg/core/prometheus.go b/pkg/core/prometheus.go index f47b60e20..ab1b2f405 100644 --- a/pkg/core/prometheus.go +++ b/pkg/core/prometheus.go @@ -6,7 +6,7 @@ import ( // Metrics for monitoring service. var ( - //blockHeight prometheus metric. + // blockHeight prometheus metric. blockHeight = prometheus.NewGauge( prometheus.GaugeOpts{ Help: "Current index of processed block", @@ -14,7 +14,7 @@ var ( Namespace: "neogo", }, ) - //persistedHeight prometheus metric. + // persistedHeight prometheus metric. persistedHeight = prometheus.NewGauge( prometheus.GaugeOpts{ Help: "Current persisted block count", @@ -22,7 +22,7 @@ var ( Namespace: "neogo", }, ) - //headerHeight prometheus metric. + // headerHeight prometheus metric. headerHeight = prometheus.NewGauge( prometheus.GaugeOpts{ Help: "Current header height", From 3a71aafc4315d669ebe0efd3b2e1397a26d6eeed Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 13 Apr 2023 14:03:02 +0300 Subject: [PATCH 034/125] core: distinguish notarypool/mempool metrics Move them to the core/network packages, close #2950. The name of mempool's unsorted transactions metrics has been changed along the way to match the core's metrics naming convention. Signed-off-by: Anna Shaleva --- internal/fakechain/fakechain.go | 2 +- pkg/consensus/consensus.go | 2 +- pkg/core/blockchain.go | 6 +++--- pkg/core/blockchain_neotest_test.go | 4 ++-- pkg/core/mempool/mem_pool.go | 18 ++++++++++++------ pkg/core/mempool/mem_pool_test.go | 18 +++++++++--------- pkg/core/mempool/prometheus.go | 24 ------------------------ pkg/core/mempool/subscriptions_test.go | 4 ++-- pkg/core/prometheus.go | 14 ++++++++++++++ pkg/network/prometheus.go | 16 ++++++++++++++++ pkg/network/server.go | 2 +- pkg/services/notary/core_test.go | 2 +- pkg/services/notary/node_test.go | 2 +- pkg/services/notary/notary_test.go | 6 +++--- 14 files changed, 66 insertions(+), 54 deletions(-) delete mode 100644 pkg/core/mempool/prometheus.go diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 83f889f10..51e3a8a0a 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -62,7 +62,7 @@ func NewFakeChainWithCustomCfg(protocolCfg func(c *config.Blockchain)) *FakeChai protocolCfg(&cfg) } return &FakeChain{ - Pool: mempool.New(10, 0, false), + Pool: mempool.New(10, 0, false, nil), PoolTxF: func(*transaction.Transaction) error { return nil }, poolTxWithData: func(*transaction.Transaction, any, *mempool.Pool) error { return nil }, blocks: make(map[util.Uint256]*block.Block), diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 777f5d341..7cd1e52d0 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -506,7 +506,7 @@ func (s *service) verifyBlock(b block.Block) bool { } var fee int64 - var pool = mempool.New(len(coreb.Transactions), 0, false) + var pool = mempool.New(len(coreb.Transactions), 0, false, nil) var mainPool = s.Chain.GetMemPool() for _, tx := range coreb.Transactions { var err error diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index f9996d3b4..07ada76bd 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -309,7 +309,7 @@ func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger) (*Bl store: s, stopCh: make(chan struct{}), runToExitCh: make(chan struct{}), - memPool: mempool.New(cfg.MemPoolSize, 0, false), + memPool: mempool.New(cfg.MemPoolSize, 0, false, updateMempoolMetrics), log: log, events: make(chan bcEvent), subCh: make(chan any), @@ -1446,7 +1446,7 @@ func (bc *Blockchain) AddBlock(block *block.Block) error { if !block.MerkleRoot.Equals(merkle) { return errors.New("invalid block: MerkleRoot mismatch") } - mp = mempool.New(len(block.Transactions), 0, false) + mp = mempool.New(len(block.Transactions), 0, false, nil) for _, tx := range block.Transactions { var err error // Transactions are verified before adding them @@ -2651,7 +2651,7 @@ func (bc *Blockchain) IsTxStillRelevant(t *transaction.Transaction, txpool *memp // current blockchain state. Note that this verification is completely isolated // from the main node's mempool. func (bc *Blockchain) VerifyTx(t *transaction.Transaction) error { - var mp = mempool.New(1, 0, false) + var mp = mempool.New(1, 0, false, nil) bc.lock.RLock() defer bc.lock.RUnlock() return bc.verifyAndPoolTx(t, mp, bc) diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index da59af3cf..ad8c74b5b 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -1301,7 +1301,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { require.True(t, errors.Is(err, core.ErrAlreadyExists)) }) t.Run("MemPoolOOM", func(t *testing.T) { - mp := mempool.New(1, 0, false) + mp := mempool.New(1, 0, false, nil) tx1 := newTestTx(t, h, testScript) tx1.NetworkFee += 10000 // Give it more priority. require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx1)) @@ -1860,7 +1860,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { return tx } - mp := mempool.New(10, 1, false) + mp := mempool.New(10, 1, false, nil) verificationF := func(tx *transaction.Transaction, data any) error { if data.(int) > 5 { return errors.New("bad data") diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index 0faf79c96..901b528bb 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -65,9 +65,10 @@ type Pool struct { // oracleResp contains the ids of oracle responses for the tx in the pool. oracleResp map[uint64]util.Uint256 - capacity int - feePerByte int64 - payerIndex int + capacity int + feePerByte int64 + payerIndex int + updateMetricsCb func(int) resendThreshold uint32 resendFunc func(*transaction.Transaction, any) @@ -286,7 +287,9 @@ func (mp *Pool) Add(t *transaction.Transaction, fee Feer, data ...any) error { // we already checked balance in checkTxConflicts, so don't need to check again mp.tryAddSendersFee(pItem.txn, fee, false) - updateMempoolMetrics(len(mp.verifiedTxes)) + if mp.updateMetricsCb != nil { + mp.updateMetricsCb(len(mp.verifiedTxes)) + } mp.lock.Unlock() if mp.subscriptionsOn.Load() { @@ -342,7 +345,9 @@ func (mp *Pool) removeInternal(hash util.Uint256, feer Feer) { } } } - updateMempoolMetrics(len(mp.verifiedTxes)) + if mp.updateMetricsCb != nil { + mp.updateMetricsCb(len(mp.verifiedTxes)) + } } // RemoveStale filters verified transactions through the given function keeping @@ -420,7 +425,7 @@ func (mp *Pool) checkPolicy(tx *transaction.Transaction, policyChanged bool) boo } // New returns a new Pool struct. -func New(capacity int, payerIndex int, enableSubscriptions bool) *Pool { +func New(capacity int, payerIndex int, enableSubscriptions bool, updateMetricsCb func(int)) *Pool { mp := &Pool{ verifiedMap: make(map[util.Uint256]*transaction.Transaction, capacity), verifiedTxes: make([]item, 0, capacity), @@ -434,6 +439,7 @@ func New(capacity int, payerIndex int, enableSubscriptions bool) *Pool { events: make(chan mempoolevent.Event), subCh: make(chan chan<- mempoolevent.Event), unsubCh: make(chan chan<- mempoolevent.Event), + updateMetricsCb: updateMetricsCb, } mp.subscriptionsOn.Store(false) return mp diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index 43a1f0cef..66882e4f3 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -45,7 +45,7 @@ func (fs *FeerStub) P2PSigExtensionsEnabled() bool { } func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) { - mp := New(10, 0, false) + mp := New(10, 0, false, nil) tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = 0 tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} @@ -66,7 +66,7 @@ func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) { } func TestMemPoolRemoveStale(t *testing.T) { - mp := New(5, 0, false) + mp := New(5, 0, false, nil) txs := make([]*transaction.Transaction, 5) for i := range txs { txs[i] = transaction.New([]byte{byte(opcode.PUSH1)}, 0) @@ -117,7 +117,7 @@ func TestMemPoolAddRemove(t *testing.T) { func TestOverCapacity(t *testing.T) { var fs = &FeerStub{balance: 10000000} const mempoolSize = 10 - mp := New(mempoolSize, 0, false) + mp := New(mempoolSize, 0, false, nil) for i := 0; i < mempoolSize; i++ { tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) @@ -193,7 +193,7 @@ func TestOverCapacity(t *testing.T) { func TestGetVerified(t *testing.T) { var fs = &FeerStub{} const mempoolSize = 10 - mp := New(mempoolSize, 0, false) + mp := New(mempoolSize, 0, false, nil) txes := make([]*transaction.Transaction, 0, mempoolSize) for i := 0; i < mempoolSize; i++ { @@ -217,7 +217,7 @@ func TestGetVerified(t *testing.T) { func TestRemoveStale(t *testing.T) { var fs = &FeerStub{} const mempoolSize = 10 - mp := New(mempoolSize, 0, false) + mp := New(mempoolSize, 0, false, nil) txes1 := make([]*transaction.Transaction, 0, mempoolSize/2) txes2 := make([]*transaction.Transaction, 0, mempoolSize/2) @@ -250,7 +250,7 @@ func TestRemoveStale(t *testing.T) { } func TestMemPoolFees(t *testing.T) { - mp := New(10, 0, false) + mp := New(10, 0, false, nil) fs := &FeerStub{balance: 10000000} sender0 := util.Uint160{1, 2, 3} tx0 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) @@ -355,7 +355,7 @@ func TestMempoolItemsOrder(t *testing.T) { } func TestMempoolAddRemoveOracleResponse(t *testing.T) { - mp := New(3, 0, false) + mp := New(3, 0, false, nil) nonce := uint32(0) fs := &FeerStub{balance: 10000} newTx := func(netFee int64, id uint64) *transaction.Transaction { @@ -425,7 +425,7 @@ func TestMempoolAddRemoveOracleResponse(t *testing.T) { func TestMempoolAddRemoveConflicts(t *testing.T) { capacity := 6 - mp := New(capacity, 0, false) + mp := New(capacity, 0, false, nil) var ( fs = &FeerStub{p2pSigExt: true, balance: 100000} nonce uint32 = 1 @@ -555,7 +555,7 @@ func TestMempoolAddWithDataGetData(t *testing.T) { blockHeight: 5, balance: 100, } - mp := New(10, 1, false) + mp := New(10, 1, false, nil) newTx := func(t *testing.T, netFee int64) *transaction.Transaction { tx := transaction.New([]byte{byte(opcode.RET)}, 0) tx.Signers = []transaction.Signer{{}, {}} diff --git a/pkg/core/mempool/prometheus.go b/pkg/core/mempool/prometheus.go deleted file mode 100644 index ca19c2c83..000000000 --- a/pkg/core/mempool/prometheus.go +++ /dev/null @@ -1,24 +0,0 @@ -package mempool - -import "github.com/prometheus/client_golang/prometheus" - -var ( - // mempoolUnsortedTx prometheus metric. - mempoolUnsortedTx = prometheus.NewGauge( - prometheus.GaugeOpts{ - Help: "Mempool Unsorted TXs", - Name: "mempool_unsorted_tx", - Namespace: "neogo", - }, - ) -) - -func init() { - prometheus.MustRegister( - mempoolUnsortedTx, - ) -} - -func updateMempoolMetrics(unsortedTxnLen int) { - mempoolUnsortedTx.Set(float64(unsortedTxnLen)) -} diff --git a/pkg/core/mempool/subscriptions_test.go b/pkg/core/mempool/subscriptions_test.go index bbe1bc2a3..d476f20bc 100644 --- a/pkg/core/mempool/subscriptions_test.go +++ b/pkg/core/mempool/subscriptions_test.go @@ -13,7 +13,7 @@ import ( func TestSubscriptions(t *testing.T) { t.Run("disabled subscriptions", func(t *testing.T) { - mp := New(5, 0, false) + mp := New(5, 0, false, nil) require.Panics(t, func() { mp.RunSubscriptions() }) @@ -24,7 +24,7 @@ func TestSubscriptions(t *testing.T) { t.Run("enabled subscriptions", func(t *testing.T) { fs := &FeerStub{balance: 100} - mp := New(2, 0, true) + mp := New(2, 0, true, nil) mp.RunSubscriptions() subChan1 := make(chan mempoolevent.Event, 3) subChan2 := make(chan mempoolevent.Event, 3) diff --git a/pkg/core/prometheus.go b/pkg/core/prometheus.go index ab1b2f405..8e429d044 100644 --- a/pkg/core/prometheus.go +++ b/pkg/core/prometheus.go @@ -30,6 +30,14 @@ var ( Namespace: "neogo", }, ) + // mempoolUnsortedTx prometheus metric. + mempoolUnsortedTx = prometheus.NewGauge( + prometheus.GaugeOpts{ + Help: "Mempool unsorted transactions", + Name: "mempool_unsorted_tx", + Namespace: "neogo", + }, + ) ) func init() { @@ -37,6 +45,7 @@ func init() { blockHeight, persistedHeight, headerHeight, + mempoolUnsortedTx, ) } @@ -51,3 +60,8 @@ func updateHeaderHeightMetric(hHeight uint32) { func updateBlockHeightMetric(bHeight uint32) { blockHeight.Set(float64(bHeight)) } + +// updateMempoolMetrics updates metric of the number of unsorted txs inside the mempool. +func updateMempoolMetrics(unsortedTxnLen int) { + mempoolUnsortedTx.Set(float64(unsortedTxnLen)) +} diff --git a/pkg/network/prometheus.go b/pkg/network/prometheus.go index bc1156afe..483e877f7 100644 --- a/pkg/network/prometheus.go +++ b/pkg/network/prometheus.go @@ -50,6 +50,15 @@ var ( }, ) p2pCmds = make(map[CommandType]prometheus.Histogram) + + // notarypoolUnsortedTx prometheus metric. + notarypoolUnsortedTx = prometheus.NewGauge( + prometheus.GaugeOpts{ + Help: "Notary request pool fallback txs", + Name: "notarypool_unsorted_tx", + Namespace: "neogo", + }, + ) ) func init() { @@ -59,6 +68,7 @@ func init() { servAndNodeVersion, poolCount, blockQueueLength, + notarypoolUnsortedTx, ) for _, cmd := range []CommandType{CMDVersion, CMDVerack, CMDGetAddr, CMDAddr, CMDPing, CMDPong, CMDGetHeaders, CMDHeaders, CMDGetBlocks, @@ -103,3 +113,9 @@ func addCmdTimeMetric(cmd CommandType, t time.Duration) { } p2pCmds[cmd].Observe(t.Seconds()) } + +// updateNotarypoolMetrics updates metric of the number of fallback txs inside +// the notary request pool. +func updateNotarypoolMetrics(unsortedTxnLen int) { + notarypoolUnsortedTx.Set(float64(unsortedTxnLen)) +} diff --git a/pkg/network/server.go b/pkg/network/server.go index b6661b2a4..1cb62d637 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -198,7 +198,7 @@ func newServerFromConstructors(config ServerConfig, chain Ledger, stSync StateSy } if chain.P2PSigExtensionsEnabled() { s.notaryFeer = NewNotaryFeer(chain) - s.notaryRequestPool = mempool.New(s.config.P2PNotaryRequestPayloadPoolSize, 1, true) + s.notaryRequestPool = mempool.New(s.config.P2PNotaryRequestPayloadPoolSize, 1, true, updateNotarypoolMetrics) chain.RegisterPostBlock(func(isRelevant func(*transaction.Transaction, *mempool.Pool, bool) bool, txpool *mempool.Pool, _ *block.Block) { s.notaryRequestPool.RemoveStale(func(t *transaction.Transaction) bool { return isRelevant(t, txpool, true) diff --git a/pkg/services/notary/core_test.go b/pkg/services/notary/core_test.go index 657a2bc90..638da3887 100644 --- a/pkg/services/notary/core_test.go +++ b/pkg/services/notary/core_test.go @@ -47,7 +47,7 @@ func getTestNotary(t *testing.T, bc *core.Blockchain, walletPath, pass string, o Chain: bc, Log: zaptest.NewLogger(t), } - mp := mempool.New(10, 1, true) + mp := mempool.New(10, 1, true, nil) ntr, err := notary.NewNotary(cfg, netmode.UnitTestNet, mp, onTx) require.NoError(t, err) diff --git a/pkg/services/notary/node_test.go b/pkg/services/notary/node_test.go index b1779cd6c..93c666dc6 100644 --- a/pkg/services/notary/node_test.go +++ b/pkg/services/notary/node_test.go @@ -21,7 +21,7 @@ func getTestNotary(t *testing.T, bc Ledger, walletPath, pass string) (*wallet.Ac Password: pass, }, } - mp := mempool.New(10, 1, true) + mp := mempool.New(10, 1, true, nil) cfg := Config{ MainCfg: mainCfg, Chain: bc, diff --git a/pkg/services/notary/notary_test.go b/pkg/services/notary/notary_test.go index d3d173e99..9df86c72f 100644 --- a/pkg/services/notary/notary_test.go +++ b/pkg/services/notary/notary_test.go @@ -27,21 +27,21 @@ func TestWallet(t *testing.T) { } t.Run("unexisting wallet", func(t *testing.T) { cfg.MainCfg.UnlockWallet.Path = "./testdata/does_not_exists.json" - _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true), nil) + _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true, nil), nil) require.Error(t, err) }) t.Run("bad password", func(t *testing.T) { cfg.MainCfg.UnlockWallet.Path = "./testdata/notary1.json" cfg.MainCfg.UnlockWallet.Password = "invalid" - _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true), nil) + _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true, nil), nil) require.Error(t, err) }) t.Run("good", func(t *testing.T) { cfg.MainCfg.UnlockWallet.Path = "./testdata/notary1.json" cfg.MainCfg.UnlockWallet.Password = "one" - _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true), nil) + _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true, nil), nil) require.NoError(t, err) }) } From 649877d8f3058f2e003d8dde82948c211a01ed57 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 13 Apr 2023 11:48:18 +0400 Subject: [PATCH 035/125] services/rpcsrv: Test `Server` shutdown with failed precondition There is an existing problem with RPC server shutdown freeze after start failure due to some init actions (at least HTTP listen) described in #2896. Add dedicated unit test which checks that `Shutdown` returns within 5s after `Start` method encounters internal problems. Signed-off-by: Leonard Lyubich --- pkg/services/rpcsrv/server_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 2b0b9fb50..4bcda2473 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -50,6 +50,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/atomic" "go.uber.org/zap/zapcore" ) @@ -3331,3 +3332,21 @@ func BenchmarkHandleIn(b *testing.B) { {"type": "Integer", "value": "42"}, {"type": "Boolean", "value": false}]]}`)) }) } + +func TestFailedPreconditionShutdown(t *testing.T) { + _, srv, _ := initClearServerWithCustomConfig(t, func(c *config.Config) { + c.ApplicationConfiguration.RPC.Addresses = []string{"not an address"} + }) + + srv.Start() + require.Positive(t, len(srv.errChan)) // this is how Start reports internal failures + + var stopped atomic.Bool + + go func() { + srv.Shutdown() + stopped.Store(true) + }() + + require.Eventually(t, stopped.Load, 5*time.Second, 100*time.Millisecond, "Shutdown should return") +} From a113940f0b05ecac15b15dc68f2410d7b8a6dc4d Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 13 Apr 2023 12:03:18 +0400 Subject: [PATCH 036/125] services/rpcsrv: Fix potential shutdown deadlock of RPC server Previously RPC server could never be shut down completely due to some start precondition failure (in particular, inability to serve HTTP on any configured endpoint). The problem was caused by next facts: * start method ran subscription routine after HTTP init succeeded only * stop method blocked waiting for the subscription routine to return Run `handleSubEvents` routine on fresh `Start` unconditionally. With this change, `Shutdown` method won't produce deadlock since `handleSubEvents` closes wait channel. Refs #2896. Signed-off-by: Leonard Lyubich --- pkg/services/rpcsrv/server.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index 88fb38942..78562bc42 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -344,6 +344,9 @@ func (s *Server) Start() { s.log.Info("RPC server already started") return } + + go s.handleSubEvents() + for _, srv := range s.http { srv.Handler = http.HandlerFunc(s.handleHTTPRequest) s.log.Info("starting rpc-server", zap.String("endpoint", srv.Addr)) @@ -363,7 +366,6 @@ func (s *Server) Start() { }(srv) } - go s.handleSubEvents() if cfg := s.config.TLSConfig; cfg.Enabled { for _, srv := range s.https { srv.Handler = http.HandlerFunc(s.handleHTTPRequest) From e126bcc462fb396c470f81ae70bf98bee7374b82 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 13 Apr 2023 12:36:39 +0400 Subject: [PATCH 037/125] services/rpcsrv: Wait for subscription process to complete when stopped Previously RPC server shutdown procedure listened to the execution channel and stopped at the first element that arrived in the queue. This could lead to the following problems: * stopper could steal the execution result from subscriber * stopper didn't wait for other subscription actions to complete Add dedicated channel to `Server` for subscription routine. Close the channel on `handleSubEvents` return and wait for signal in `Shutdown`. Signed-off-by: Leonard Lyubich --- pkg/services/rpcsrv/server.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index 78562bc42..116f56c29 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -148,11 +148,12 @@ type ( transactionSubs int notaryRequestSubs int - blockCh chan *block.Block - executionCh chan *state.AppExecResult - notificationCh chan *state.ContainedNotificationEvent - transactionCh chan *transaction.Transaction - notaryRequestCh chan mempoolevent.Event + blockCh chan *block.Block + executionCh chan *state.AppExecResult + notificationCh chan *state.ContainedNotificationEvent + transactionCh chan *transaction.Transaction + notaryRequestCh chan mempoolevent.Event + subEventsToExitCh chan struct{} } // session holds a set of iterators got after invoke* call with corresponding @@ -319,11 +320,12 @@ func New(chain Ledger, conf config.RPC, coreServer *network.Server, subscribers: make(map[*subscriber]bool), // These are NOT buffered to preserve original order of events. - blockCh: make(chan *block.Block), - executionCh: make(chan *state.AppExecResult), - notificationCh: make(chan *state.ContainedNotificationEvent), - transactionCh: make(chan *transaction.Transaction), - notaryRequestCh: make(chan mempoolevent.Event), + blockCh: make(chan *block.Block), + executionCh: make(chan *state.AppExecResult), + notificationCh: make(chan *state.ContainedNotificationEvent), + transactionCh: make(chan *transaction.Transaction), + notaryRequestCh: make(chan mempoolevent.Event), + subEventsToExitCh: make(chan struct{}), } } @@ -438,7 +440,7 @@ func (s *Server) Shutdown() { } // Wait for handleSubEvents to finish. - <-s.executionCh + <-s.subEventsToExitCh } // SetOracleHandler allows to update oracle handler used by the Server. @@ -2667,6 +2669,8 @@ func (s *Server) unsubscribeFromChannel(event neorpc.EventID) { } } +// handleSubEvents processes Server subscriptions until Shutdown. Upon +// completion signals to subEventCh channel. func (s *Server) handleSubEvents() { var overflowEvent = neorpc.Notification{ JSONRPC: neorpc.JSONRPCVersion, @@ -2780,12 +2784,14 @@ drainloop: } } // It's not required closing these, but since they're drained already - // this is safe and it also allows to give a signal to Shutdown routine. + // this is safe. close(s.blockCh) close(s.transactionCh) close(s.notificationCh) close(s.executionCh) close(s.notaryRequestCh) + // notify Shutdown routine + close(s.subEventsToExitCh) } func (s *Server) blockHeightFromParam(param *params.Param) (uint32, *neorpc.Error) { From e29c33e449bfca6b9481da4e9c2e5a2d40881dec Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 13 Apr 2023 12:53:58 +0400 Subject: [PATCH 038/125] cli/node: Fix deadlock produced by instant RPC service start If `StartWhenSynchronized` is unset in config, `node` command runs RPC service instantly. Previously there was a ground for deadlock. Command started RPC server synchronously. According to server implementation, it sends all internal failures to the parameterized error channel. Deadlock occured because main routine didn't scan the channel. Run `rpcsrv.Server.Start` in a separate go-routine in `startServer`. This prevents potential deadlock caused by writing into unread channel. Fixes #2896. Signed-off-by: Leonard Lyubich --- cli/server/server.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cli/server/server.go b/cli/server/server.go index bcea6b115..030cacafb 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -491,7 +491,10 @@ func startServer(ctx *cli.Context) error { go serv.Start(errChan) if !cfg.ApplicationConfiguration.RPC.StartWhenSynchronized { - rpcServer.Start() + // Run RPC server in a separate routine. This is necessary to avoid a potential + // deadlock: Start() can write errors to errChan which is not yet read in the + // current execution context (see for-loop below). + go rpcServer.Start() } sigCh := make(chan os.Signal, 1) @@ -546,7 +549,8 @@ Main: rpcServer = rpcsrv.New(chain, cfgnew.ApplicationConfiguration.RPC, serv, oracleSrv, log, errChan) serv.AddService(&rpcServer) if !cfgnew.ApplicationConfiguration.RPC.StartWhenSynchronized || serv.IsInSync() { - rpcServer.Start() + // Here similar to the initial run (see above for-loop), so async. + go rpcServer.Start() } pprof.ShutDown() pprof = metrics.NewPprofService(cfgnew.ApplicationConfiguration.Pprof, log) From ef925b2c0bee3125ae646ec60b7e268c74fecfb2 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 18 Apr 2023 18:52:57 +0300 Subject: [PATCH 039/125] docs: fix typo Remove unnecessary word left after documentation refactoring. Signed-off-by: Anna Shaleva --- docs/notary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notary.md b/docs/notary.md index 7c5e112dd..0b70f5e3c 100644 --- a/docs/notary.md +++ b/docs/notary.md @@ -374,7 +374,7 @@ subpackage with an example written in Go doc. `Invocation` script **should be empty**. - A multisignature witness must have regular `Verification` script filled even if `Invocation` script is to be collected from other notary requests. - `Invocation` script either **should be empty**. + `Invocation` script **should be empty**. 8. Calculate network fee for the transaction (that will be `NetworkFee` transaction field). Use [func (*Client) CalculateNetworkFee](https://pkg.go.dev/github.com/nspcc-dev/neo-go@v0.99.2/pkg/rpcclient#Client.CalculateNetworkFee) method with the main transaction given to it. From 45b353781f417b6798c48ad3b1ffcd44c31f63fb Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 18 Apr 2023 19:34:38 +0300 Subject: [PATCH 040/125] rpcclient: correctly handle request channel closure wsReader() closes c.done first and then goes over the list of c.respChannels. Technically this means that any of the two can be taken in this select. Signed-off-by: Roman Khimov --- pkg/rpcclient/wsclient.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index c3f6172a1..ff1e21bd1 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -638,7 +638,10 @@ func (c *WSClient) makeWsRequest(r *neorpc.Request) (*neorpc.Response, error) { select { case <-c.done: return nil, errors.New("connection lost while waiting for the response") - case resp := <-ch: + case resp, ok := <-ch: + if !ok { + return nil, errors.New("connection lost while waiting for the response") + } c.unregisterRespChannel(r.ID) return resp, nil } From 6eaa76520f08441113768dec8918b9407a347f09 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 18 Apr 2023 19:36:57 +0300 Subject: [PATCH 041/125] rpcclient: close subscriber channels on wsReader exit The reader is about to exit and it will close legacy c.Notifications, but it will leave subscription channels at the same time. This is wrong since these channels will no longer receive any new events, game over. Signed-off-by: Roman Khimov --- pkg/rpcclient/wsclient.go | 13 +++++++++- pkg/rpcclient/wsclient_test.go | 43 ++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index ff1e21bd1..49443f408 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -46,7 +46,8 @@ import ( // subscriptions share the same receiver channel, then matching notification is // only sent once per channel. The receiver channel will be closed by the WSClient // immediately after MissedEvent is received from the server; no unsubscription -// is performed in this case, so it's the user responsibility to unsubscribe. +// is performed in this case, so it's the user responsibility to unsubscribe. It +// will also be closed on disconnection from server. type WSClient struct { Client // Notifications is a channel that is used to send events received from @@ -539,6 +540,16 @@ readloop: } c.respChannels = nil c.respLock.Unlock() + c.subscriptionsLock.Lock() + for rcvrCh, ids := range c.receivers { + rcvr := c.subscriptions[ids[0]] + _, ok := rcvr.(*naiveReceiver) + if !ok { // naiveReceiver uses c.Notifications that is about to be closed below. + c.subscriptions[ids[0]].Close() + } + delete(c.receivers, rcvrCh) + } + c.subscriptionsLock.Unlock() close(c.Notifications) c.Client.ctxCancel() } diff --git a/pkg/rpcclient/wsclient_test.go b/pkg/rpcclient/wsclient_test.go index 1d7f3f774..c3f30c894 100644 --- a/pkg/rpcclient/wsclient_test.go +++ b/pkg/rpcclient/wsclient_test.go @@ -30,10 +30,17 @@ import ( ) func TestWSClientClose(t *testing.T) { - srv := initTestServer(t, "") + srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) require.NoError(t, err) + wsc.getNextRequestID = getTestRequestID + bCh := make(chan *block.Block) + _, err = wsc.ReceiveBlocks(nil, bCh) + require.NoError(t, err) wsc.Close() + // Subscriber channel must be closed by server. + _, ok := <-bCh + require.False(t, ok) } func TestWSClientSubscription(t *testing.T) { @@ -296,10 +303,6 @@ func TestWSExecutionVMStateCheck(t *testing.T) { } func TestWSFilteredSubscriptions(t *testing.T) { - bCh := make(chan *block.Block) - txCh := make(chan *transaction.Transaction) - aerCh := make(chan *state.AppExecResult) - ntfCh := make(chan *state.ContainedNotificationEvent) var cases = []struct { name string clientCode func(*testing.T, *WSClient) @@ -308,7 +311,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"blocks primary", func(t *testing.T, wsc *WSClient) { primary := 3 - _, err := wsc.ReceiveBlocks(&neorpc.BlockFilter{Primary: &primary}, bCh) + _, err := wsc.ReceiveBlocks(&neorpc.BlockFilter{Primary: &primary}, make(chan *block.Block)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -323,7 +326,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"blocks since", func(t *testing.T, wsc *WSClient) { var since uint32 = 3 - _, err := wsc.ReceiveBlocks(&neorpc.BlockFilter{Since: &since}, bCh) + _, err := wsc.ReceiveBlocks(&neorpc.BlockFilter{Since: &since}, make(chan *block.Block)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -338,7 +341,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"blocks till", func(t *testing.T, wsc *WSClient) { var till uint32 = 3 - _, err := wsc.ReceiveBlocks(&neorpc.BlockFilter{Till: &till}, bCh) + _, err := wsc.ReceiveBlocks(&neorpc.BlockFilter{Till: &till}, make(chan *block.Block)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -361,7 +364,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { Primary: &primary, Since: &since, Till: &till, - }, bCh) + }, make(chan *block.Block)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -376,7 +379,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"transactions sender", func(t *testing.T, wsc *WSClient) { sender := util.Uint160{1, 2, 3, 4, 5} - _, err := wsc.ReceiveTransactions(&neorpc.TxFilter{Sender: &sender}, txCh) + _, err := wsc.ReceiveTransactions(&neorpc.TxFilter{Sender: &sender}, make(chan *transaction.Transaction)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -390,7 +393,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"transactions signer", func(t *testing.T, wsc *WSClient) { signer := util.Uint160{0, 42} - _, err := wsc.ReceiveTransactions(&neorpc.TxFilter{Signer: &signer}, txCh) + _, err := wsc.ReceiveTransactions(&neorpc.TxFilter{Signer: &signer}, make(chan *transaction.Transaction)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -405,7 +408,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { func(t *testing.T, wsc *WSClient) { sender := util.Uint160{1, 2, 3, 4, 5} signer := util.Uint160{0, 42} - _, err := wsc.ReceiveTransactions(&neorpc.TxFilter{Sender: &sender, Signer: &signer}, txCh) + _, err := wsc.ReceiveTransactions(&neorpc.TxFilter{Sender: &sender, Signer: &signer}, make(chan *transaction.Transaction)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -419,7 +422,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"notifications contract hash", func(t *testing.T, wsc *WSClient) { contract := util.Uint160{1, 2, 3, 4, 5} - _, err := wsc.ReceiveExecutionNotifications(&neorpc.NotificationFilter{Contract: &contract}, ntfCh) + _, err := wsc.ReceiveExecutionNotifications(&neorpc.NotificationFilter{Contract: &contract}, make(chan *state.ContainedNotificationEvent)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -433,7 +436,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"notifications name", func(t *testing.T, wsc *WSClient) { name := "my_pretty_notification" - _, err := wsc.ReceiveExecutionNotifications(&neorpc.NotificationFilter{Name: &name}, ntfCh) + _, err := wsc.ReceiveExecutionNotifications(&neorpc.NotificationFilter{Name: &name}, make(chan *state.ContainedNotificationEvent)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -448,7 +451,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { func(t *testing.T, wsc *WSClient) { contract := util.Uint160{1, 2, 3, 4, 5} name := "my_pretty_notification" - _, err := wsc.ReceiveExecutionNotifications(&neorpc.NotificationFilter{Contract: &contract, Name: &name}, ntfCh) + _, err := wsc.ReceiveExecutionNotifications(&neorpc.NotificationFilter{Contract: &contract, Name: &name}, make(chan *state.ContainedNotificationEvent)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -461,8 +464,8 @@ func TestWSFilteredSubscriptions(t *testing.T) { }, {"executions state", func(t *testing.T, wsc *WSClient) { - state := "FAULT" - _, err := wsc.ReceiveExecutions(&neorpc.ExecutionFilter{State: &state}, aerCh) + vmstate := "FAULT" + _, err := wsc.ReceiveExecutions(&neorpc.ExecutionFilter{State: &vmstate}, make(chan *state.AppExecResult)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -476,7 +479,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { {"executions container", func(t *testing.T, wsc *WSClient) { container := util.Uint256{1, 2, 3} - _, err := wsc.ReceiveExecutions(&neorpc.ExecutionFilter{Container: &container}, aerCh) + _, err := wsc.ReceiveExecutions(&neorpc.ExecutionFilter{Container: &container}, make(chan *state.AppExecResult)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { @@ -489,9 +492,9 @@ func TestWSFilteredSubscriptions(t *testing.T) { }, {"executions state and container", func(t *testing.T, wsc *WSClient) { - state := "FAULT" + vmstate := "FAULT" container := util.Uint256{1, 2, 3} - _, err := wsc.ReceiveExecutions(&neorpc.ExecutionFilter{State: &state, Container: &container}, aerCh) + _, err := wsc.ReceiveExecutions(&neorpc.ExecutionFilter{State: &vmstate, Container: &container}, make(chan *state.AppExecResult)) require.NoError(t, err) }, func(t *testing.T, p *params.Params) { From 77836ea1d07666478aff08890e88b637c8a55ae6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 19 Apr 2023 17:18:04 +0300 Subject: [PATCH 042/125] rpcclient: make Notary Actor follow the request creation doc All Notary contract witnesses in incomplete transaction (both main and fallback) may either have invocation scripts pushing dummy signature on stack or be empty, both ways are OK. Notary actor keeps main tx's Notary witness empty and keeps fallback tx's Notary witness filled with dummy signature. Signed-off-by: Anna Shaleva --- docs/notary.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/notary.md b/docs/notary.md index 0b70f5e3c..80df1b02a 100644 --- a/docs/notary.md +++ b/docs/notary.md @@ -352,9 +352,9 @@ subpackage with an example written in Go doc. with `Deployed` set to `false` and `Script` set to the signer's verification script. - An account for a notary signer is **just a placeholder** and should have - `Contract` field with `Deployed` set to `false`, i.e. the default value for - `Contract` field. That's needed to skip notary verification during regular - network fee calculation at the next step. + `Contract` field with `Deployed` set to `true`. Its `Invocation` witness script + parameters will be guessed by the `verify` method signature of Notary contract + during the network fee calculation at the next step. 6. Fill in the main transaction `Nonce` field. 7. Construct a list of main transactions witnesses (that will be `Scripts` @@ -363,11 +363,17 @@ subpackage with an example written in Go doc. - A contract-based witness should have `Invocation` script that pushes arguments on stack (it may be empty) and empty `Verification` script. If multiple notary requests provide different `Invocation` scripts, the first one will be used - to construct contract-based witness. + to construct contract-based witness. If non-empty `Invocation` script is + specified then it will be taken into account during network fee calculation. + In case of an empty `Invocation` script, its parameters will be guessed from + the contract's `verify` signature during network fee calculation. - A **Notary contract witness** (which is also a contract-based witness) should - have empty `Verification` script. `Invocation` script should be of the form - [opcode.PUSHDATA1, 64, make([]byte, 64)...], i.e. to be a placeholder for - a notary contract signature. + have empty `Verification` script. `Invocation` script should be either empty + (allowed for main transaction and forbidden for fallback transaction) or of + the form [opcode.PUSHDATA1, 64, make([]byte, 64)...] (allowed for main + transaction and required for fallback transaction by the Notary subsystem to + pass verification), i.e. to be a placeholder for a notary contract signature. + Both ways are OK for network fee calculation. - A standard signature witness must have regular `Verification` script filled even if the `Invocation` script is to be collected from other notary requests. From fb7fce0775ff39dd30f346d73267dcd2b32cb4e8 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Thu, 20 Apr 2023 10:46:19 +0800 Subject: [PATCH 043/125] native: optimize vote reward data (fix #2844) Signed-off-by: ZhangTao1596 --- ROADMAP.md | 7 ++ pkg/core/blockchain.go | 7 +- pkg/core/blockchain_neotest_test.go | 3 - pkg/core/native/native_neo.go | 95 +++++++++------------- pkg/core/native/native_test/neo_test.go | 104 ++++++++++++++++++++++++ pkg/core/state/native_state.go | 13 ++- pkg/interop/native/neo/neo.go | 7 +- pkg/services/rpcsrv/client_test.go | 4 +- pkg/services/rpcsrv/server_test.go | 6 +- 9 files changed, 177 insertions(+), 69 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 5804dda3e..0bbaf59eb 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -123,3 +123,10 @@ formats. Removal of Peer unmarshalling with string based ports is scheduled for ~September 2023 (~0.105.0 release). + +## `NEOBalance` from stack item + +We check struct items count before convert LastGasPerVote to let RPC client be compatible with +old versions. + +Removal of this compatiblility code is scheduled for Sep-Oct 2023. diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index f1e514f63..fd9922c79 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2363,7 +2363,12 @@ unsubloop: // CalculateClaimable calculates the amount of GAS generated by owning specified // amount of NEO between specified blocks. func (bc *Blockchain) CalculateClaimable(acc util.Uint160, endHeight uint32) (*big.Int, error) { - return bc.contracts.NEO.CalculateBonus(bc.dao, acc, endHeight) + nextBlock, err := bc.getFakeNextBlock(bc.BlockHeight() + 1) + if err != nil { + return nil, err + } + ic := bc.newInteropContext(trigger.Application, bc.dao, nextBlock, nil) + return bc.contracts.NEO.CalculateBonus(ic, acc, endHeight) } // FeePerByte returns transaction network fee per byte. diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index ad8c74b5b..8a99ad04d 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -739,9 +739,6 @@ func TestBlockchain_GetTransaction(t *testing.T) { func TestBlockchain_GetClaimable(t *testing.T) { bc, acc := chain.NewSingle(t) - e := neotest.NewExecutor(t, bc, acc, acc) - - e.GenerateNewBlocks(t, 10) t.Run("first generation period", func(t *testing.T) { amount, err := bc.CalculateClaimable(acc.ScriptHash(), 1) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index b0b8b1f1e..844d27361 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -409,7 +409,7 @@ func (n *NEO) PostPersist(ic *interop.Context) error { var ( cs = cache.committee isCacheRW bool - key = make([]byte, 38) + key = make([]byte, 34) ) for i := range cs { if cs[i].Votes.Sign() > 0 { @@ -423,17 +423,9 @@ func (n *NEO) PostPersist(ic *interop.Context) error { tmp.Div(tmp, cs[i].Votes) key = makeVoterKey([]byte(cs[i].Key), key) + r := n.getLatestGASPerVote(ic.DAO, key) + tmp.Add(tmp, &r) - var r *big.Int - if g, ok := cache.gasPerVoteCache[cs[i].Key]; ok { - r = &g - } else { - reward := n.getGASPerVote(ic.DAO, key[:34], []uint32{ic.Block.Index + 1}) - r = &reward[0] - } - tmp.Add(tmp, r) - - binary.BigEndian.PutUint32(key[34:], ic.Block.Index+1) if !isCacheRW { cache = ic.DAO.GetRWCache(n.ID).(*NeoCache) isCacheRW = true @@ -447,33 +439,19 @@ func (n *NEO) PostPersist(ic *interop.Context) error { return nil } -func (n *NEO) getGASPerVote(d *dao.Simple, key []byte, indexes []uint32) []big.Int { - sort.Slice(indexes, func(i, j int) bool { - return indexes[i] < indexes[j] - }) - start := make([]byte, 4) - binary.BigEndian.PutUint32(start, indexes[len(indexes)-1]) - - need := len(indexes) - var reward = make([]big.Int, need) - collected := 0 - d.Seek(n.ID, storage.SeekRange{ - Prefix: key, - Start: start, - Backwards: true, - }, func(k, v []byte) bool { - if len(k) == 4 { - num := binary.BigEndian.Uint32(k) - for i, ind := range indexes { - if reward[i].Sign() == 0 && num <= ind { - reward[i] = *bigint.FromBytes(v) - collected++ - } - } - } - return collected < need - }) - return reward +func (n *NEO) getLatestGASPerVote(d *dao.Simple, key []byte) big.Int { + var g big.Int + cache := d.GetROCache(n.ID).(*NeoCache) + if g, ok := cache.gasPerVoteCache[string(key[1:])]; ok { + return g + } + item := d.GetStorageItem(n.ID, key) + if item == nil { + g = *big.NewInt(0) + } else { + g = *bigint.FromBytes(item) + } + return g } func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.StorageItem, amount *big.Int, checkBal *big.Int) (func(), error) { @@ -527,11 +505,15 @@ func (n *NEO) distributeGas(ic *interop.Context, acc *state.NEOBalance) (*big.In if ic.Block == nil || ic.Block.Index == 0 || ic.Block.Index == acc.BalanceHeight { return nil, nil } - gen, err := n.calculateBonus(ic.DAO, acc.VoteTo, &acc.Balance, acc.BalanceHeight, ic.Block.Index) + gen, err := n.calculateBonus(ic.DAO, acc, ic.Block.Index) if err != nil { return nil, err } acc.BalanceHeight = ic.Block.Index + if acc.VoteTo != nil { + latestGasPerVote := n.getLatestGASPerVote(ic.DAO, makeVoterKey(acc.VoteTo.Bytes())) + acc.LastGasPerVote = latestGasPerVote + } return gen, nil } @@ -539,7 +521,7 @@ func (n *NEO) distributeGas(ic *interop.Context, acc *state.NEOBalance) (*big.In func (n *NEO) unclaimedGas(ic *interop.Context, args []stackitem.Item) stackitem.Item { u := toUint160(args[0]) end := uint32(toBigInt(args[1]).Int64()) - gen, err := n.CalculateBonus(ic.DAO, u, end) + gen, err := n.CalculateBonus(ic, u, end) if err != nil { panic(err) } @@ -647,10 +629,7 @@ func (n *NEO) dropCandidateIfZero(d *dao.Simple, cache *NeoCache, pub *keys.Publ d.DeleteStorageItem(n.ID, makeValidatorKey(pub)) voterKey := makeVoterKey(pub.Bytes()) - d.Seek(n.ID, storage.SeekRange{Prefix: voterKey}, func(k, v []byte) bool { - d.DeleteStorageItem(n.ID, append(voterKey, k...)) // d.Seek cuts prefix, thus need to append it again. - return true - }) + d.DeleteStorageItem(n.ID, voterKey) delete(cache.gasPerVoteCache, string(voterKey)) return true @@ -661,7 +640,7 @@ func makeVoterKey(pub []byte, prealloc ...[]byte) []byte { if len(prealloc) != 0 { key = prealloc[0] } else { - key = make([]byte, 34, 38) + key = make([]byte, 34) } key[0] = prefixVoterRewardPerCommittee copy(key[1:], pub) @@ -670,9 +649,12 @@ func makeVoterKey(pub []byte, prealloc ...[]byte) []byte { // CalculateBonus calculates amount of gas generated for holding value NEO from start to end block // and having voted for active committee member. -func (n *NEO) CalculateBonus(d *dao.Simple, acc util.Uint160, end uint32) (*big.Int, error) { +func (n *NEO) CalculateBonus(ic *interop.Context, acc util.Uint160, end uint32) (*big.Int, error) { + if ic.Block == nil || end != ic.Block.Index { + return nil, errors.New("can't calculate bonus of height unequal (BlockHeight + 1)") + } key := makeAccountKey(acc) - si := d.GetStorageItem(n.ID, key) + si := ic.DAO.GetStorageItem(n.ID, key) if si == nil { return nil, storage.ErrKeyNotFound } @@ -680,19 +662,19 @@ func (n *NEO) CalculateBonus(d *dao.Simple, acc util.Uint160, end uint32) (*big. if err != nil { return nil, err } - return n.calculateBonus(d, st.VoteTo, &st.Balance, st.BalanceHeight, end) + return n.calculateBonus(ic.DAO, st, end) } -func (n *NEO) calculateBonus(d *dao.Simple, vote *keys.PublicKey, value *big.Int, start, end uint32) (*big.Int, error) { - r, err := n.CalculateNEOHolderReward(d, value, start, end) - if err != nil || vote == nil { +func (n *NEO) calculateBonus(d *dao.Simple, acc *state.NEOBalance, end uint32) (*big.Int, error) { + r, err := n.CalculateNEOHolderReward(d, &acc.Balance, acc.BalanceHeight, end) + if err != nil || acc.VoteTo == nil { return r, err } - var key = makeVoterKey(vote.Bytes()) - var reward = n.getGASPerVote(d, key, []uint32{start, end}) - var tmp = (&reward[1]).Sub(&reward[1], &reward[0]) - tmp.Mul(tmp, value) + var key = makeVoterKey(acc.VoteTo.Bytes()) + var reward = n.getLatestGASPerVote(d, key) + var tmp = big.NewInt(0).Sub(&reward, &acc.LastGasPerVote) + tmp.Mul(tmp, &acc.Balance) tmp.Div(tmp, bigVoterRewardFactor) tmp.Add(tmp, r) return tmp, nil @@ -869,6 +851,9 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public if err := n.ModifyAccountVotes(acc, ic.DAO, new(big.Int).Neg(&acc.Balance), false); err != nil { return err } + if pub != nil && pub != acc.VoteTo { + acc.LastGasPerVote = n.getLatestGASPerVote(ic.DAO, makeVoterKey(pub.Bytes())) + } oldVote := acc.VoteTo acc.VoteTo = pub if err := n.ModifyAccountVotes(acc, ic.DAO, &acc.Balance, true); err != nil { diff --git a/pkg/core/native/native_test/neo_test.go b/pkg/core/native/native_test/neo_test.go index 011636ca9..dae6e1eb5 100644 --- a/pkg/core/native/native_test/neo_test.go +++ b/pkg/core/native/native_test/neo_test.go @@ -3,13 +3,16 @@ package native_test import ( "bytes" "encoding/json" + "fmt" "math" "math/big" "sort" + "strings" "testing" "github.com/nspcc-dev/neo-go/internal/contracts" "github.com/nspcc-dev/neo-go/internal/random" + "github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" @@ -305,6 +308,15 @@ func TestNEO_GetAccountState(t *testing.T) { neoValidatorInvoker := newNeoValidatorsClient(t) e := neoValidatorInvoker.Executor + cfg := e.Chain.GetConfig() + committeeSize := cfg.GetCommitteeSize(0) + validatorSize := cfg.GetNumOfCNs(0) + advanceChain := func(t *testing.T) { + for i := 0; i < committeeSize; i++ { + neoValidatorInvoker.AddNewBlock(t) + } + } + t.Run("empty", func(t *testing.T) { neoValidatorInvoker.Invoke(t, stackitem.Null{}, "getAccountState", util.Uint160{}) }) @@ -318,8 +330,100 @@ func TestNEO_GetAccountState(t *testing.T) { stackitem.Make(amount), stackitem.Make(lub), stackitem.Null{}, + stackitem.Make(0), }), "getAccountState", acc.ScriptHash()) }) + + t.Run("lastGasPerVote", func(t *testing.T) { + const ( + GasPerBlock = 5 + VoterRewardRatio = 80 + ) + getAccountState := func(t *testing.T, account util.Uint160) *state.NEOBalance { + stack, err := neoValidatorInvoker.TestInvoke(t, "getAccountState", account) + require.NoError(t, err) + as := new(state.NEOBalance) + err = as.FromStackItem(stack.Pop().Item()) + require.NoError(t, err) + return as + } + + amount := int64(1000) + acc := e.NewAccount(t) + neoValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), acc.ScriptHash(), amount, nil) + as := getAccountState(t, acc.ScriptHash()) + require.Equal(t, uint64(amount), as.Balance.Uint64()) + require.Equal(t, e.Chain.BlockHeight(), as.BalanceHeight) + require.Equal(t, uint64(0), as.LastGasPerVote.Uint64()) + committee, _ := e.Chain.GetCommittee() + neoValidatorInvoker.WithSigners(e.Validator, e.Validator.(neotest.MultiSigner).Single(0)).Invoke(t, true, "registerCandidate", committee[0].Bytes()) + neoValidatorInvoker.WithSigners(acc).Invoke(t, true, "vote", acc.ScriptHash(), committee[0].Bytes()) + as = getAccountState(t, acc.ScriptHash()) + require.Equal(t, uint64(0), as.LastGasPerVote.Uint64()) + advanceChain(t) + neoValidatorInvoker.WithSigners(acc).Invoke(t, true, "transfer", acc.ScriptHash(), acc.ScriptHash(), amount, nil) + as = getAccountState(t, acc.ScriptHash()) + expect := GasPerBlock * native.GASFactor * VoterRewardRatio / 100 * (uint64(e.Chain.BlockHeight()) / uint64(committeeSize)) + expect = expect * uint64(committeeSize) / uint64(validatorSize+committeeSize) * native.NEOTotalSupply / as.Balance.Uint64() + require.Equal(t, e.Chain.BlockHeight(), as.BalanceHeight) + require.Equal(t, expect, as.LastGasPerVote.Uint64()) + }) +} + +func TestNEO_GetAccountStateInteropAPI(t *testing.T) { + neoValidatorInvoker := newNeoValidatorsClient(t) + e := neoValidatorInvoker.Executor + + cfg := e.Chain.GetConfig() + committeeSize := cfg.GetCommitteeSize(0) + validatorSize := cfg.GetNumOfCNs(0) + advanceChain := func(t *testing.T) { + for i := 0; i < committeeSize; i++ { + neoValidatorInvoker.AddNewBlock(t) + } + } + + amount := int64(1000) + acc := e.NewAccount(t) + neoValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), acc.ScriptHash(), amount, nil) + committee, _ := e.Chain.GetCommittee() + neoValidatorInvoker.WithSigners(e.Validator, e.Validator.(neotest.MultiSigner).Single(0)).Invoke(t, true, "registerCandidate", committee[0].Bytes()) + neoValidatorInvoker.WithSigners(acc).Invoke(t, true, "vote", acc.ScriptHash(), committee[0].Bytes()) + advanceChain(t) + neoValidatorInvoker.WithSigners(acc).Invoke(t, true, "transfer", acc.ScriptHash(), acc.ScriptHash(), amount, nil) + + var hashAStr string + for i := 0; i < util.Uint160Size; i++ { + hashAStr += fmt.Sprintf("%#x", acc.ScriptHash()[i]) + if i != util.Uint160Size-1 { + hashAStr += ", " + } + } + src := `package testaccountstate + import ( + "github.com/nspcc-dev/neo-go/pkg/interop/native/neo" + "github.com/nspcc-dev/neo-go/pkg/interop" + ) + func GetLastGasPerVote() int { + accState := neo.GetAccountState(interop.Hash160{` + hashAStr + `}) + if accState == nil { + panic("nil state") + } + return accState.LastGasPerVote + }` + ctr := neotest.CompileSource(t, e.Validator.ScriptHash(), strings.NewReader(src), &compiler.Options{ + Name: "testaccountstate_contract", + }) + e.DeployContract(t, ctr, nil) + + const ( + GasPerBlock = 5 + VoterRewardRatio = 80 + ) + expect := GasPerBlock * native.GASFactor * VoterRewardRatio / 100 * (uint64(e.Chain.BlockHeight()) / uint64(committeeSize)) + expect = expect * uint64(committeeSize) / uint64(validatorSize+committeeSize) * native.NEOTotalSupply / uint64(amount) + ctrInvoker := e.NewInvoker(ctr.Hash, e.Committee) + ctrInvoker.Invoke(t, stackitem.Make(expect), "getLastGasPerVote") } func TestNEO_CommitteeBountyOnPersist(t *testing.T) { diff --git a/pkg/core/state/native_state.go b/pkg/core/state/native_state.go index 48eef1a0f..5e4d7c4c3 100644 --- a/pkg/core/state/native_state.go +++ b/pkg/core/state/native_state.go @@ -19,8 +19,9 @@ type NEP17Balance struct { // NEOBalance represents the balance state of a NEO-token. type NEOBalance struct { NEP17Balance - BalanceHeight uint32 - VoteTo *keys.PublicKey + BalanceHeight uint32 + VoteTo *keys.PublicKey + LastGasPerVote big.Int } // NEP17BalanceFromBytes converts the serialized NEP17Balance to a structure. @@ -125,6 +126,7 @@ func (s *NEOBalance) ToStackItem() (stackitem.Item, error) { stackitem.NewBigInteger(&s.Balance), stackitem.NewBigInteger(big.NewInt(int64(s.BalanceHeight))), voteItem, + stackitem.NewBigInteger(&s.LastGasPerVote), }), nil } @@ -157,5 +159,12 @@ func (s *NEOBalance) FromStackItem(item stackitem.Item) error { return fmt.Errorf("invalid public key bytes: %w", err) } s.VoteTo = pub + if len(structItem) >= 4 { + lastGasPerVote, err := structItem[3].TryInteger() + if err != nil { + return fmt.Errorf("invalid last vote reward per neo stackitem: %w", err) + } + s.LastGasPerVote = *lastGasPerVote + } return nil } diff --git a/pkg/interop/native/neo/neo.go b/pkg/interop/native/neo/neo.go index dac6dae9d..4fde83829 100644 --- a/pkg/interop/native/neo/neo.go +++ b/pkg/interop/native/neo/neo.go @@ -15,9 +15,10 @@ import ( // AccountState contains info about a NEO holder. type AccountState struct { - Balance int - Height int - VoteTo interop.PublicKey + Balance int + Height int + VoteTo interop.PublicKey + LastGasPerVote int } // Hash represents NEO contract hash. diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index da23e6e87..55b756c42 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -372,9 +372,9 @@ func TestClientNEOContract(t *testing.T) { require.Equal(t, int64(1000_0000_0000), regP) acc0 := testchain.PrivateKey(0).PublicKey().GetScriptHash() - uncl, err := neoR.UnclaimedGas(acc0, 100) + uncl, err := neoR.UnclaimedGas(acc0, chain.BlockHeight()+1) require.NoError(t, err) - require.Equal(t, big.NewInt(48000), uncl) + require.Equal(t, big.NewInt(10000), uncl) accState, err := neoR.GetAccountState(acc0) require.NoError(t, err) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 4bcda2473..90fd1955d 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -83,7 +83,7 @@ const ( faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60" faultedTxBlock uint32 = 23 invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA" - block20StateRootLE = "33b4cee6a59b9dc9d186fc235dc81e2ffe74418d7d777d538422a62b8e635ef2" + block20StateRootLE = "a2841baec40c6b752ba959c2b2cfee20b6beeabb85460224929bc9ff358bf8d2" ) var ( @@ -943,11 +943,11 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { State: "Added", Key: []byte{0xfb, 0xff, 0xff, 0xff, 0x14, 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb}, - Value: []byte{0x41, 0x03, 0x21, 0x01, 0x01, 0x21, 0x01, 0x18, 0}, + Value: []byte{0x41, 0x04, 0x21, 0x01, 0x01, 0x21, 0x01, 0x18, 0x00, 0x21, 0x00}, }, { State: "Changed", Key: []byte{0xfb, 0xff, 0xff, 0xff, 0x14, 0xee, 0x9e, 0xa2, 0x2c, 0x27, 0xe3, 0x4b, 0xd0, 0x14, 0x8f, 0xc4, 0x10, 0x8e, 0x8, 0xf7, 0x4e, 0x8f, 0x50, 0x48, 0xb2}, - Value: []byte{0x41, 0x03, 0x21, 0x04, 0x2f, 0xd9, 0xf5, 0x05, 0x21, 0x01, 0x18, 0}, + Value: []byte{0x41, 0x04, 0x21, 0x04, 0x2f, 0xd9, 0xf5, 0x05, 0x21, 0x01, 0x18, 0x00, 0x21, 0x00}, }, { State: "Changed", Key: []byte{0xfa, 0xff, 0xff, 0xff, 0x14, 0xee, 0x9e, 0xa2, 0x2c, 0x27, 0xe3, 0x4b, 0xd0, 0x14, 0x8f, 0xc4, 0x10, 0x8e, 0x8, 0xf7, 0x4e, 0x8f, 0x50, 0x48, 0xb2}, From dd8218f87ac55064621c325d6b0efc548d3e02af Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 20 Apr 2023 16:11:15 +0300 Subject: [PATCH 044/125] *: update interop deps after #2892 Signed-off-by: Anna Shaleva --- examples/engine/go.mod | 2 +- examples/engine/go.sum | 4 ++-- examples/events/go.mod | 2 +- examples/events/go.sum | 4 ++-- examples/iterator/go.mod | 2 +- examples/iterator/go.sum | 4 ++-- examples/nft-d/go.mod | 2 +- examples/nft-d/go.sum | 4 ++-- examples/nft-nd-nns/go.mod | 2 +- examples/nft-nd-nns/go.sum | 4 ++-- examples/nft-nd/go.mod | 2 +- examples/nft-nd/go.sum | 4 ++-- examples/oracle/go.mod | 2 +- examples/oracle/go.sum | 4 ++-- examples/runtime/go.mod | 2 +- examples/runtime/go.sum | 4 ++-- examples/storage/go.mod | 2 +- examples/storage/go.sum | 4 ++-- examples/timer/go.mod | 2 +- examples/timer/go.sum | 4 ++-- examples/token/go.mod | 2 +- examples/token/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- internal/contracts/oracle_contract/go.mod | 2 +- internal/contracts/oracle_contract/go.sum | 4 ++-- 26 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/engine/go.mod b/examples/engine/go.mod index 7658c1d5b..94d41135f 100644 --- a/examples/engine/go.mod +++ b/examples/engine/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/engine/go.sum b/examples/engine/go.sum index 70617580d..f665b036a 100644 --- a/examples/engine/go.sum +++ b/examples/engine/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/events/go.mod b/examples/events/go.mod index d57741acc..b4175ed11 100644 --- a/examples/events/go.mod +++ b/examples/events/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/events/go.sum b/examples/events/go.sum index 70617580d..f665b036a 100644 --- a/examples/events/go.sum +++ b/examples/events/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/iterator/go.mod b/examples/iterator/go.mod index d77d6574f..f9a528ba1 100644 --- a/examples/iterator/go.mod +++ b/examples/iterator/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/iterator/go.sum b/examples/iterator/go.sum index 70617580d..f665b036a 100644 --- a/examples/iterator/go.sum +++ b/examples/iterator/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/nft-d/go.mod b/examples/nft-d/go.mod index efedc05a9..5afeb6f09 100644 --- a/examples/nft-d/go.mod +++ b/examples/nft-d/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/nft-d/go.sum b/examples/nft-d/go.sum index 70617580d..f665b036a 100644 --- a/examples/nft-d/go.sum +++ b/examples/nft-d/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/nft-nd-nns/go.mod b/examples/nft-nd-nns/go.mod index ebe69fd8c..589482cd7 100644 --- a/examples/nft-nd-nns/go.mod +++ b/examples/nft-nd-nns/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a github.com/stretchr/testify v1.8.0 ) diff --git a/examples/nft-nd-nns/go.sum b/examples/nft-nd-nns/go.sum index bfaf070bd..619660152 100644 --- a/examples/nft-nd-nns/go.sum +++ b/examples/nft-nd-nns/go.sum @@ -187,8 +187,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5 h1:NCIUxkLRB3ovLzM1lvQA6wBNn8fuY7dQx4cMJKLuaAs= github.com/nspcc-dev/neo-go v0.99.5-0.20221108145959-8746d9877eb5/go.mod h1:aWrWJZBYO+9kYC4+qJXvEjySW1WIyPnrHpmdrzd5mJY= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 h1:rpMCoRa7expLc9gMiOP724gz6YSykZzmMALR/CmiwnU= diff --git a/examples/nft-nd/go.mod b/examples/nft-nd/go.mod index b5fe7fedc..c6b8048c1 100644 --- a/examples/nft-nd/go.mod +++ b/examples/nft-nd/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/nft-nd/go.sum b/examples/nft-nd/go.sum index 70617580d..f665b036a 100644 --- a/examples/nft-nd/go.sum +++ b/examples/nft-nd/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/oracle/go.mod b/examples/oracle/go.mod index eaa29ecb1..224b6c5b7 100644 --- a/examples/oracle/go.mod +++ b/examples/oracle/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/oracle/go.sum b/examples/oracle/go.sum index 70617580d..f665b036a 100644 --- a/examples/oracle/go.sum +++ b/examples/oracle/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/runtime/go.mod b/examples/runtime/go.mod index 6c9134d1e..8dc6ae388 100644 --- a/examples/runtime/go.mod +++ b/examples/runtime/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/runtime/go.sum b/examples/runtime/go.sum index 70617580d..f665b036a 100644 --- a/examples/runtime/go.sum +++ b/examples/runtime/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/storage/go.mod b/examples/storage/go.mod index d8329e0c3..df0640441 100644 --- a/examples/storage/go.mod +++ b/examples/storage/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/storage/go.sum b/examples/storage/go.sum index 70617580d..f665b036a 100644 --- a/examples/storage/go.sum +++ b/examples/storage/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/timer/go.mod b/examples/timer/go.mod index 75979d7c8..7f8d9efcc 100644 --- a/examples/timer/go.mod +++ b/examples/timer/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/timer/go.sum b/examples/timer/go.sum index 70617580d..f665b036a 100644 --- a/examples/timer/go.sum +++ b/examples/timer/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/examples/token/go.mod b/examples/token/go.mod index c4b8ca56a..936db6f72 100644 --- a/examples/token/go.mod +++ b/examples/token/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/examples/token/go.sum b/examples/token/go.sum index 70617580d..f665b036a 100644 --- a/examples/token/go.sum +++ b/examples/token/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= diff --git a/go.mod b/go.mod index 17c27414d..26f3534d7 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 github.com/nspcc-dev/rfc6979 v0.2.0 github.com/pierrec/lz4 v2.6.1+incompatible diff --git a/go.sum b/go.sum index a115b1f27..35421089b 100644 --- a/go.sum +++ b/go.sum @@ -268,8 +268,8 @@ github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= diff --git a/internal/contracts/oracle_contract/go.mod b/internal/contracts/oracle_contract/go.mod index 98a1977c7..1d36a6782 100644 --- a/internal/contracts/oracle_contract/go.mod +++ b/internal/contracts/oracle_contract/go.mod @@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/internal/examples/oracle go 1.18 -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a +require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a diff --git a/internal/contracts/oracle_contract/go.sum b/internal/contracts/oracle_contract/go.sum index 70617580d..f665b036a 100644 --- a/internal/contracts/oracle_contract/go.sum +++ b/internal/contracts/oracle_contract/go.sum @@ -1,2 +1,2 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a h1:MgU7bK0SJ29jH+OHGGFhEGTTOul+BKXI9SVcQnXt6BA= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230412134538-d5bea0ad4c2a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= From d90626d556c0994ebe01eec3f1750646bdf667e1 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Sat, 22 Apr 2023 16:36:49 +0400 Subject: [PATCH 045/125] interop/util: Drop unused import Remove no longer used import left after corresponding code removal in 4671fbb3be8390f6f3a4e238cd33014d0b0b89ab. Signed-off-by: Leonard Lyubich --- pkg/interop/util/util.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/interop/util/util.go b/pkg/interop/util/util.go index 46a2c0506..9e93ed6c3 100644 --- a/pkg/interop/util/util.go +++ b/pkg/interop/util/util.go @@ -4,7 +4,6 @@ Package util contains some special useful functions that are provided by compile package util import ( - "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal" ) From 4a49bf5de4f94f64c21363024064989f6f29f136 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 25 Apr 2023 11:26:36 +0300 Subject: [PATCH 046/125] rpcclient: introduce WSOptions for WSClient Make a separate structure for WSClient configuration. Signed-off-by: Anna Shaleva --- pkg/rpcclient/rpc_test.go | 2 +- pkg/rpcclient/wsclient.go | 13 +++++++++++-- pkg/rpcclient/wsclient_test.go | 28 ++++++++++++++-------------- pkg/services/rpcsrv/client_test.go | 4 ++-- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index 3cf3b9f9b..1e032c7fc 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -1803,7 +1803,7 @@ func TestRPCClients(t *testing.T) { }) t.Run("WSClient", func(t *testing.T) { testRPCClient(t, func(ctx context.Context, endpoint string, opts Options) (*Client, error) { - wsc, err := NewWS(ctx, httpURLtoWS(endpoint), opts) + wsc, err := NewWS(ctx, httpURLtoWS(endpoint), WSOptions{opts}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID require.NoError(t, wsc.Init()) diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index 49443f408..f6bb034e1 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -66,6 +66,7 @@ type WSClient struct { Notifications chan Notification ws *websocket.Conn + wsOpts WSOptions done chan struct{} requests chan *neorpc.Request shutdown chan struct{} @@ -86,6 +87,13 @@ type WSClient struct { respChannels map[uint64]chan *neorpc.Response } +// WSOptions defines options for the web-socket RPC client. It contains a +// set of options for the underlying standard RPC client as far as +// WSClient-specific options. See Options documentation for more details. +type WSOptions struct { + Options +} + // notificationReceiver is an interface aimed to provide WS subscriber functionality // for different types of subscriptions. type notificationReceiver interface { @@ -382,7 +390,7 @@ var errConnClosedByUser = errors.New("connection closed by user") // connection). You need to use websocket URL for it like `ws://1.2.3.4/ws`. // You should call Init method to initialize the network magic the client is // operating on. -func NewWS(ctx context.Context, endpoint string, opts Options) (*WSClient, error) { +func NewWS(ctx context.Context, endpoint string, opts WSOptions) (*WSClient, error) { dialer := websocket.Dialer{HandshakeTimeout: opts.DialTimeout} ws, resp, err := dialer.DialContext(ctx, endpoint, nil) if resp != nil && resp.Body != nil { // Can be non-nil even with error returned. @@ -405,6 +413,7 @@ func NewWS(ctx context.Context, endpoint string, opts Options) (*WSClient, error Notifications: make(chan Notification), ws: ws, + wsOpts: opts, shutdown: make(chan struct{}), done: make(chan struct{}), closeCalled: *atomic.NewBool(false), @@ -414,7 +423,7 @@ func NewWS(ctx context.Context, endpoint string, opts Options) (*WSClient, error receivers: make(map[any][]string), } - err = initClient(ctx, &wsc.Client, endpoint, opts) + err = initClient(ctx, &wsc.Client, endpoint, opts.Options) if err != nil { return nil, err } diff --git a/pkg/rpcclient/wsclient_test.go b/pkg/rpcclient/wsclient_test.go index c3f30c894..b72d2ec6b 100644 --- a/pkg/rpcclient/wsclient_test.go +++ b/pkg/rpcclient/wsclient_test.go @@ -31,7 +31,7 @@ import ( func TestWSClientClose(t *testing.T) { srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID bCh := make(chan *block.Block) @@ -70,7 +70,7 @@ func TestWSClientSubscription(t *testing.T) { for name, f := range cases { t.Run(name, func(t *testing.T) { srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID require.NoError(t, wsc.Init()) @@ -84,7 +84,7 @@ func TestWSClientSubscription(t *testing.T) { for name, f := range cases { t.Run(name, func(t *testing.T) { srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "error":{"code":-32602,"message":"Invalid Params"}}`) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID require.NoError(t, wsc.Init()) @@ -134,7 +134,7 @@ func TestWSClientUnsubscription(t *testing.T) { for name, rc := range cases { t.Run(name, func(t *testing.T) { srv := initTestServer(t, rc.response) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID require.NoError(t, wsc.Init()) @@ -170,7 +170,7 @@ func TestWSClientEvents(t *testing.T) { return } })) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID wsc.cacheLock.Lock() @@ -292,7 +292,7 @@ func TestWSClientEvents(t *testing.T) { func TestWSExecutionVMStateCheck(t *testing.T) { // Will answer successfully if request slips through. srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID require.NoError(t, wsc.Init()) @@ -527,7 +527,7 @@ func TestWSFilteredSubscriptions(t *testing.T) { ws.Close() } })) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID wsc.cache.network = netmode.UnitTestNet @@ -541,14 +541,14 @@ func TestNewWS(t *testing.T) { srv := initTestServer(t, "") t.Run("good", func(t *testing.T) { - c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) c.getNextRequestID = getTestRequestID c.cache.network = netmode.UnitTestNet require.NoError(t, c.Init()) }) t.Run("bad URL", func(t *testing.T) { - _, err := NewWS(context.TODO(), strings.TrimPrefix(srv.URL, "http://"), Options{}) + _, err := NewWS(context.TODO(), strings.TrimPrefix(srv.URL, "http://"), WSOptions{}) require.Error(t, err) }) } @@ -605,7 +605,7 @@ func TestWSConcurrentAccess(t *testing.T) { })) t.Cleanup(srv.Close) - wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) batchCount := 100 completed := atomic.NewInt32(0) @@ -649,7 +649,7 @@ func TestWSConcurrentAccess(t *testing.T) { func TestWSDoubleClose(t *testing.T) { srv := initTestServer(t, "") - c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) require.NotPanics(t, func() { @@ -661,7 +661,7 @@ func TestWSDoubleClose(t *testing.T) { func TestWS_RequestAfterClose(t *testing.T) { srv := initTestServer(t, "") - c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) c.Close() @@ -676,7 +676,7 @@ func TestWS_RequestAfterClose(t *testing.T) { func TestWSClient_ConnClosedError(t *testing.T) { t.Run("standard closing", func(t *testing.T) { srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": 123}`) - c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) // Check client is working. @@ -692,7 +692,7 @@ func TestWSClient_ConnClosedError(t *testing.T) { t.Run("malformed request", func(t *testing.T) { srv := initTestServer(t, "") - c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{}) + c, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{}) require.NoError(t, err) defaultMaxBlockSize := 262144 diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 55b756c42..cb65ed676 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -2074,7 +2074,7 @@ func mkSubsClient(t *testing.T, rpcSrv *Server, httpSrv *httptest.Server, local icl, err = rpcclient.NewInternal(context.Background(), rpcSrv.RegisterLocal) } else { url := "ws" + strings.TrimPrefix(httpSrv.URL, "http") + "/ws" - c, err = rpcclient.NewWS(context.Background(), url, rpcclient.Options{}) + c, err = rpcclient.NewWS(context.Background(), url, rpcclient.WSOptions{}) } require.NoError(t, err) if local { @@ -2240,7 +2240,7 @@ func TestWSClientHandshakeError(t *testing.T) { defer rpcSrv.Shutdown() url := "ws" + strings.TrimPrefix(httpSrv.URL, "http") + "/ws" - _, err := rpcclient.NewWS(context.Background(), url, rpcclient.Options{}) + _, err := rpcclient.NewWS(context.Background(), url, rpcclient.WSOptions{}) require.ErrorContains(t, err, "websocket users limit reached") } From dab13a4e2d8ae4debf99624aac4c56f987a9f7d5 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 21 Apr 2023 17:14:47 +0300 Subject: [PATCH 047/125] rpcclient: close WSClient subscriber on overflow Close #2894. It should be noted that the subscriber's channel is being removed from the list of receivers and closed, but it is still *in the list of subscribers* and no unsubscription is performed by WSClient. Which means that RPC server keeps sending notifications to WSClient and WSClient keeps dropping them (because there's no receiver for this subscription and it's OK, WSClient can handle this and this behaviour is documented). However, it's still the caller's duty to call Unsubscribe() method for this subscription. Signed-off-by: Anna Shaleva --- pkg/rpcclient/rpc_test.go | 2 +- pkg/rpcclient/wsclient.go | 166 +++++++++++++++++++++++++-------- pkg/rpcclient/wsclient_test.go | 82 ++++++++++++++++ 3 files changed, 211 insertions(+), 39 deletions(-) diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index 1e032c7fc..c60e77ec5 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -1803,7 +1803,7 @@ func TestRPCClients(t *testing.T) { }) t.Run("WSClient", func(t *testing.T) { testRPCClient(t, func(ctx context.Context, endpoint string, opts Options) (*Client, error) { - wsc, err := NewWS(ctx, httpURLtoWS(endpoint), WSOptions{opts}) + wsc, err := NewWS(ctx, httpURLtoWS(endpoint), WSOptions{Options: opts}) require.NoError(t, err) wsc.getNextRequestID = getTestRequestID require.NoError(t, wsc.Init()) diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index f6bb034e1..b77e03f4b 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -38,7 +38,11 @@ import ( // will make WSClient wait for the channel reader to get the event and while // it waits every other messages (subscription-related or request replies) // will be blocked. This also means that subscription channel must be properly -// drained after unsubscription. +// drained after unsubscription. If CloseNotificationChannelIfFull option is on +// then the receiver channel will be closed immediately in case if a subsequent +// notification can't be sent to it, which means WSClient's operations are +// unblocking in this mode. No unsubscription is performed in this case, so it's +// still the user responsibility to unsubscribe. // // Any received subscription items (blocks/transactions/nofitications) are passed // via pointers for efficiency, but the actual structures MUST NOT be changed, as @@ -47,7 +51,9 @@ import ( // only sent once per channel. The receiver channel will be closed by the WSClient // immediately after MissedEvent is received from the server; no unsubscription // is performed in this case, so it's the user responsibility to unsubscribe. It -// will also be closed on disconnection from server. +// will also be closed on disconnection from server or on situation when it's +// impossible to send a subsequent notification to the subscriber's channel and +// CloseNotificationChannelIfFull option is on. type WSClient struct { Client // Notifications is a channel that is used to send events received from @@ -92,6 +98,14 @@ type WSClient struct { // WSClient-specific options. See Options documentation for more details. type WSOptions struct { Options + // CloseNotificationChannelIfFull allows WSClient to close a subscriber's + // receive channel in case if the channel isn't read properly and no more + // events can be pushed to it. This option, if set, allows to avoid WSClient + // blocking on a subsequent notification dispatch. However, if enabled, the + // corresponding subscription is kept even after receiver's channel closing, + // thus it's still the caller's duty to call Unsubscribe() for this + // subscription. + CloseNotificationChannelIfFull bool } // notificationReceiver is an interface aimed to provide WS subscriber functionality @@ -102,8 +116,11 @@ type notificationReceiver interface { // Receiver returns notification receiver channel. Receiver() any // TrySend checks whether notification passes receiver filter and sends it - // to the underlying channel if so. - TrySend(ntf Notification) bool + // to the underlying channel if so. It is performed under subscriptions lock + // taken. nonBlocking denotes whether the receiving operation shouldn't block + // the client's operation. It returns whether notification matches the filter + // and whether the receiver channel is overflown. + TrySend(ntf Notification, nonBlocking bool) (bool, bool) // Close closes underlying receiver channel. Close() } @@ -133,12 +150,21 @@ func (r *blockReceiver) Receiver() any { } // TrySend implements notificationReceiver interface. -func (r *blockReceiver) TrySend(ntf Notification) bool { +func (r *blockReceiver) TrySend(ntf Notification, nonBlocking bool) (bool, bool) { if rpcevent.Matches(r, ntf) { - r.ch <- ntf.Value.(*block.Block) - return true + if nonBlocking { + select { + case r.ch <- ntf.Value.(*block.Block): + default: + return true, true + } + } else { + r.ch <- ntf.Value.(*block.Block) + } + + return true, false } - return false + return false, false } // Close implements notificationReceiver interface. @@ -171,12 +197,21 @@ func (r *txReceiver) Receiver() any { } // TrySend implements notificationReceiver interface. -func (r *txReceiver) TrySend(ntf Notification) bool { +func (r *txReceiver) TrySend(ntf Notification, nonBlocking bool) (bool, bool) { if rpcevent.Matches(r, ntf) { - r.ch <- ntf.Value.(*transaction.Transaction) - return true + if nonBlocking { + select { + case r.ch <- ntf.Value.(*transaction.Transaction): + default: + return true, true + } + } else { + r.ch <- ntf.Value.(*transaction.Transaction) + } + + return true, false } - return false + return false, false } // Close implements notificationReceiver interface. @@ -209,12 +244,21 @@ func (r *executionNotificationReceiver) Receiver() any { } // TrySend implements notificationReceiver interface. -func (r *executionNotificationReceiver) TrySend(ntf Notification) bool { +func (r *executionNotificationReceiver) TrySend(ntf Notification, nonBlocking bool) (bool, bool) { if rpcevent.Matches(r, ntf) { - r.ch <- ntf.Value.(*state.ContainedNotificationEvent) - return true + if nonBlocking { + select { + case r.ch <- ntf.Value.(*state.ContainedNotificationEvent): + default: + return true, true + } + } else { + r.ch <- ntf.Value.(*state.ContainedNotificationEvent) + } + + return true, false } - return false + return false, false } // Close implements notificationReceiver interface. @@ -247,12 +291,21 @@ func (r *executionReceiver) Receiver() any { } // TrySend implements notificationReceiver interface. -func (r *executionReceiver) TrySend(ntf Notification) bool { +func (r *executionReceiver) TrySend(ntf Notification, nonBlocking bool) (bool, bool) { if rpcevent.Matches(r, ntf) { - r.ch <- ntf.Value.(*state.AppExecResult) - return true + if nonBlocking { + select { + case r.ch <- ntf.Value.(*state.AppExecResult): + default: + return true, true + } + } else { + r.ch <- ntf.Value.(*state.AppExecResult) + } + + return true, false } - return false + return false, false } // Close implements notificationReceiver interface. @@ -285,12 +338,21 @@ func (r *notaryRequestReceiver) Receiver() any { } // TrySend implements notificationReceiver interface. -func (r *notaryRequestReceiver) TrySend(ntf Notification) bool { +func (r *notaryRequestReceiver) TrySend(ntf Notification, nonBlocking bool) (bool, bool) { if rpcevent.Matches(r, ntf) { - r.ch <- ntf.Value.(*result.NotaryRequestEvent) - return true + if nonBlocking { + select { + case r.ch <- ntf.Value.(*result.NotaryRequestEvent): + default: + return true, true + } + } else { + r.ch <- ntf.Value.(*result.NotaryRequestEvent) + } + + return true, false } - return false + return false, false } // Close implements notificationReceiver interface. @@ -324,12 +386,21 @@ func (r *naiveReceiver) Receiver() any { } // TrySend implements notificationReceiver interface. -func (r *naiveReceiver) TrySend(ntf Notification) bool { +func (r *naiveReceiver) TrySend(ntf Notification, nonBlocking bool) (bool, bool) { if rpcevent.Matches(r, ntf) { - r.ch <- ntf - return true + if nonBlocking { + select { + case r.ch <- ntf: + default: + return true, true + } + } else { + r.ch <- ntf + } + + return true, false } - return false + return false, false } // Close implements notificationReceiver interface. @@ -551,16 +622,30 @@ readloop: c.respLock.Unlock() c.subscriptionsLock.Lock() for rcvrCh, ids := range c.receivers { - rcvr := c.subscriptions[ids[0]] + c.dropSubCh(rcvrCh, ids[0], true) + } + c.subscriptionsLock.Unlock() + c.Client.ctxCancel() +} + +// dropSubCh closes corresponding subscriber's channel and removes it from the +// receivers map. If the channel belongs to a naive subscriber then it will be +// closed manually without call to Close(). The channel is still being kept in +// the subscribers map as technically the server-side subscription still exists +// and the user is responsible for unsubscription. This method must be called +// under subscriptionsLock taken. It's the caller's duty to ensure dropSubCh +// will be called once per channel, otherwise panic will occur. +func (c *WSClient) dropSubCh(rcvrCh any, id string, ignoreCloseNotificationChannelIfFull bool) { + if ignoreCloseNotificationChannelIfFull || c.wsOpts.CloseNotificationChannelIfFull { + rcvr := c.subscriptions[id] _, ok := rcvr.(*naiveReceiver) - if !ok { // naiveReceiver uses c.Notifications that is about to be closed below. - c.subscriptions[ids[0]].Close() + if ok { // naiveReceiver uses c.Notifications that should be handled separately. + close(c.Notifications) + } else { + c.subscriptions[id].Close() } delete(c.receivers, rcvrCh) } - c.subscriptionsLock.Unlock() - close(c.Notifications) - c.Client.ctxCancel() } func (c *WSClient) wsWriter() { @@ -613,15 +698,20 @@ func (c *WSClient) notifySubscribers(ntf Notification) { c.subscriptionsLock.Unlock() return } - c.subscriptionsLock.RLock() - for _, ids := range c.receivers { + c.subscriptionsLock.Lock() + for rcvrCh, ids := range c.receivers { for _, id := range ids { - if c.subscriptions[id].TrySend(ntf) { + ok, dropCh := c.subscriptions[id].TrySend(ntf, c.wsOpts.CloseNotificationChannelIfFull) + if dropCh { + c.dropSubCh(rcvrCh, id, false) + break // strictly single drop per channel + } + if ok { break // strictly one notification per channel } } } - c.subscriptionsLock.RUnlock() + c.subscriptionsLock.Unlock() } func (c *WSClient) unregisterRespChannel(id uint64) { diff --git a/pkg/rpcclient/wsclient_test.go b/pkg/rpcclient/wsclient_test.go index b72d2ec6b..ccd272e3b 100644 --- a/pkg/rpcclient/wsclient_test.go +++ b/pkg/rpcclient/wsclient_test.go @@ -289,6 +289,88 @@ func TestWSClientEvents(t *testing.T) { require.False(t, ok) } +func TestWSClientNonBlockingEvents(t *testing.T) { + // Use buffered channel as a receiver to check it will be closed by WSClient + // after overflow if CloseNotificationChannelIfFull option is enabled. + const chCap = 3 + bCh := make(chan *block.Block, chCap) + + // Events from RPC server testchain. Require events len to be larger than chCap to reach + // subscriber's chanel overflow. + var events = []string{ + fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose), + fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose), + fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose), + fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose), + fmt.Sprintf(`{"jsonrpc":"2.0","method":"block_added","params":[%s]}`, b1Verbose), + } + require.True(t, chCap < len(events)) + + var blocksSent atomic.Bool + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + if req.URL.Path == "/ws" && req.Method == "GET" { + var upgrader = websocket.Upgrader{} + ws, err := upgrader.Upgrade(w, req, nil) + require.NoError(t, err) + for _, event := range events { + err = ws.SetWriteDeadline(time.Now().Add(2 * time.Second)) + require.NoError(t, err) + err = ws.WriteMessage(1, []byte(event)) + if err != nil { + break + } + } + blocksSent.Store(true) + ws.Close() + return + } + })) + wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), WSOptions{CloseNotificationChannelIfFull: true}) + require.NoError(t, err) + wsc.getNextRequestID = getTestRequestID + wsc.cacheLock.Lock() + wsc.cache.initDone = true // Our server mock is restricted, so perform initialisation manually. + wsc.cache.network = netmode.UnitTestNet + wsc.cacheLock.Unlock() + + // Our server mock is restricted, so perform subscriptions manually. + wsc.subscriptionsLock.Lock() + wsc.subscriptions["0"] = &blockReceiver{ch: bCh} + wsc.subscriptions["1"] = &blockReceiver{ch: bCh} + wsc.receivers[chan<- *block.Block(bCh)] = []string{"0", "1"} + wsc.subscriptionsLock.Unlock() + + // Check that events are sent to WSClient. + require.Eventually(t, func() bool { + return blocksSent.Load() + }, time.Second, 100*time.Millisecond) + + // Check that block receiver channel was removed from the receivers list due to overflow. + require.Eventually(t, func() bool { + wsc.subscriptionsLock.RLock() + defer wsc.subscriptionsLock.RUnlock() + return len(wsc.receivers) == 0 + }, 2*time.Second, 200*time.Millisecond) + + // Check that subscriptions are still there and waiting for the call to Unsubscribe() + // to be excluded from the subscriptions map. + wsc.subscriptionsLock.RLock() + require.True(t, len(wsc.subscriptions) == 2) + wsc.subscriptionsLock.RUnlock() + + // Check that receiver was closed after overflow. + for i := 0; i < chCap; i++ { + _, ok := <-bCh + require.True(t, ok) + } + select { + case _, ok := <-bCh: + require.False(t, ok) + default: + t.Fatal("channel wasn't closed by WSClient") + } +} + func TestWSExecutionVMStateCheck(t *testing.T) { // Will answer successfully if request slips through. srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) From 6e8328415ca0319a17804c7469fb14a8f9055590 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 25 Apr 2023 12:01:55 +0300 Subject: [PATCH 048/125] docs: improve Notary's `till` value documentation Close #2986. Signed-off-by: Anna Shaleva --- docs/notary.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/notary.md b/docs/notary.md index 80df1b02a..7c348940c 100644 --- a/docs/notary.md +++ b/docs/notary.md @@ -261,10 +261,14 @@ with the `data` parameter matching the following requirements: - `to` denotes the receiver of the deposit. It can be nil in case `to` equals the GAS sender. - `till` denotes chain's height before which deposit is locked and can't be - withdrawn. `till` can't be set if you're not the deposit owner. Default `till` - value is the current chain height + 5760. `till` can't be less than the current chain - height. `till` can't be less than the currently set `till` value for that deposit if - the deposit already exists. + withdrawn. `till` can't be less than the current chain height. `till` + can't be less than the current `till` value for the deposit if the deposit + already exists. `till` can be set to the provided value iff the transaction + sender is the owner of the deposit, otherwise the provided `till` value will + be overridden by the system. If the sender is not the deposit owner, the + overridden `till` value is either set to be the current chain height + 5760 + (for the newly added deposit) or set to the old `till` value (for the existing + deposit). Note, that the first deposit call for the `to` address can't transfer less than 2×`FEE` GAS. Deposit is allowed for renewal, i.e. consequent `deposit` calls for the same `to` From 3f2e0e5441f3b8b2c0c75c5eda94eb51442f4844 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 25 Apr 2023 12:22:05 +0300 Subject: [PATCH 049/125] Revert "native: make management compatible with C# node 3.5.0" This reverts commit 236e633ee488889a63f59ac9649cbfc10e4783d3. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 8 -------- pkg/core/native/management.go | 6 ++---- pkg/core/native/native_test/management_test.go | 2 -- pkg/services/rpcsrv/client_test.go | 3 +-- pkg/services/rpcsrv/server_test.go | 2 +- 5 files changed, 4 insertions(+), 17 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index fd9922c79..dd389ab09 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2228,14 +2228,6 @@ func (bc *Blockchain) GetContractState(hash util.Uint160) *state.Contract { // GetContractScriptHash returns contract script hash by its ID. func (bc *Blockchain) GetContractScriptHash(id int32) (util.Uint160, error) { - if id < 0 { - for _, n := range bc.contracts.Contracts { - nc := n.Metadata().NativeContract - if nc.ID == id { - return nc.Hash, nil - } - } - } return native.GetContractScriptHash(bc.dao, id) } diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index a5bc83d6c..e177edefb 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -688,10 +688,8 @@ func putContractState(d *dao.Simple, cs *state.Contract, updateCache bool) error if cs.UpdateCounter != 0 { // Update. return nil } - if cs.ID > 0 { - key = putHashKey(key, cs.ID) - d.PutStorageItem(ManagementContractID, key, cs.Hash.BytesBE()) - } + key = putHashKey(key, cs.ID) + d.PutStorageItem(ManagementContractID, key, cs.Hash.BytesBE()) return nil } diff --git a/pkg/core/native/native_test/management_test.go b/pkg/core/native/native_test/management_test.go index a5525fb0b..e60f806b7 100644 --- a/pkg/core/native/native_test/management_test.go +++ b/pkg/core/native/native_test/management_test.go @@ -566,7 +566,6 @@ func TestManagement_GetContract(t *testing.T) { t.Run("by ID, positive", func(t *testing.T) { managementInvoker.Invoke(t, si, "getContractById", cs1.ID) }) - /* C# compatibility t.Run("by ID, native", func(t *testing.T) { csm := managementInvoker.Executor.Chain.GetContractState(managementInvoker.Hash) require.NotNil(t, csm) @@ -574,7 +573,6 @@ func TestManagement_GetContract(t *testing.T) { require.NoError(t, err) managementInvoker.Invoke(t, sim, "getContractById", -1) }) - */ t.Run("by ID, empty", func(t *testing.T) { managementInvoker.Invoke(t, stackitem.Null{}, "getContractById", -100) }) diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 55b756c42..af5a80cd1 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -261,11 +261,10 @@ func TestClientManagementContract(t *testing.T) { cs2, err := c.GetContractStateByHash(gas.Hash) require.NoError(t, err) require.Equal(t, cs2, cs1) - /* C# compat cs1, err = manReader.GetContractByID(-6) require.NoError(t, err) require.Equal(t, cs2, cs1) - */ + ret, err := manReader.HasMethod(gas.Hash, "transfer", 4) require.NoError(t, err) require.True(t, ret) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 90fd1955d..76e0ea92b 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -83,7 +83,7 @@ const ( faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60" faultedTxBlock uint32 = 23 invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA" - block20StateRootLE = "a2841baec40c6b752ba959c2b2cfee20b6beeabb85460224929bc9ff358bf8d2" + block20StateRootLE = "ae445869283f8d7e0debc3f455014c73cde21b9802db99e80248da9f393bce14" ) var ( From e2782aef05b836237361cfa308858f671a70cd26 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 25 Apr 2023 13:12:18 +0300 Subject: [PATCH 050/125] *: adjust Prometheus metrics initialisation on node start Initialize Prometheus metrics on node start where appropriate and review the usage of the following metrics: ``` anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ find | grep prometheus.go ./pkg/network/prometheus.go ./pkg/core/stateroot/prometheus.go ./pkg/core/prometheus.go ./pkg/services/rpcsrv/prometheus.go ./pkg/services/metrics/prometheus.go ``` Close #2970. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 6 ++++++ pkg/core/stateroot/module.go | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index fd9922c79..a1a47d287 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -503,6 +503,10 @@ func (bc *Blockchain) init() error { } } + updateBlockHeightMetric(bHeight) + updatePersistedHeightMetric(bHeight) + updateHeaderHeightMetric(bc.HeaderHeight()) + return bc.updateExtensibleWhitelist(bHeight) } @@ -632,6 +636,8 @@ func (bc *Blockchain) resetRAMState(height uint32, resetHeaders bool) error { } updateBlockHeightMetric(height) + updatePersistedHeightMetric(height) + updateHeaderHeightMetric(bc.HeaderHeight()) return nil } diff --git a/pkg/core/stateroot/module.go b/pkg/core/stateroot/module.go index 751e75d1b..442164d8b 100644 --- a/pkg/core/stateroot/module.go +++ b/pkg/core/stateroot/module.go @@ -152,7 +152,9 @@ func (s *Module) CurrentValidatedHeight() uint32 { func (s *Module) Init(height uint32) error { data, err := s.Store.Get([]byte{byte(storage.DataMPTAux), prefixValidated}) if err == nil { - s.validatedHeight.Store(binary.LittleEndian.Uint32(data)) + h := binary.LittleEndian.Uint32(data) + s.validatedHeight.Store(h) + updateStateHeightMetric(h) } if height == 0 { From 33c971b0e4244685edb67bb447bda766f0e436fe Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 26 Apr 2023 12:52:59 +0300 Subject: [PATCH 051/125] core: add InitializeCache method to Contract interface Make the contracts cache initialization unified. The order of cache iniitialization is not important and Nottary contract is added to the bc.contracts.Contracts wrt P2PSigExtensions setting, thus no functional changes, just refactoring for future applications. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 23 +++-------------------- pkg/core/interop/context.go | 5 +++++ pkg/core/native/crypto.go | 6 ++++++ pkg/core/native/designate.go | 2 +- pkg/core/native/ledger.go | 5 +++++ pkg/core/native/management.go | 2 +- pkg/core/native/management_test.go | 4 ++-- pkg/core/native/native_gas.go | 5 +++++ pkg/core/native/native_neo.go | 3 ++- pkg/core/native/notary.go | 2 +- pkg/core/native/oracle.go | 3 ++- pkg/core/native/policy.go | 2 +- pkg/core/native/std.go | 6 ++++++ 13 files changed, 40 insertions(+), 28 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 56ca5ed74..a70f7bb3a 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1011,29 +1011,12 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) } func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error { - err := bc.contracts.NEO.InitializeCache(blockHeight, d) - if err != nil { - return fmt.Errorf("can't init cache for NEO native contract: %w", err) - } - err = bc.contracts.Management.InitializeCache(d) - if err != nil { - return fmt.Errorf("can't init cache for Management native contract: %w", err) - } - err = bc.contracts.Designate.InitializeCache(d) - if err != nil { - return fmt.Errorf("can't init cache for Designation native contract: %w", err) - } - bc.contracts.Oracle.InitializeCache(d) - if bc.P2PSigExtensionsEnabled() { - err = bc.contracts.Notary.InitializeCache(d) + for _, c := range bc.contracts.Contracts { + err := c.InitializeCache(blockHeight, d) if err != nil { - return fmt.Errorf("can't init cache for Notary native contract: %w", err) + return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err) } } - err = bc.contracts.Policy.InitializeCache(d) - if err != nil { - return fmt.Errorf("can't init cache for Policy native contract: %w", err) - } return nil } diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index 1d1448014..9a8270aab 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -153,6 +153,11 @@ type MethodAndPrice struct { // Contract is an interface for all native contracts. type Contract interface { Initialize(*Context) error + // InitializeCache aimed to initialize contract's cache when the contract has + // been deployed, but in-memory cached data were lost due to the node reset. + // It should be called each time after node restart iff the contract was + // deployed and no Initialize method was called. + InitializeCache(blockHeight uint32, d *dao.Simple) error Metadata() *ContractMD OnPersist(*Context) error PostPersist(*Context) error diff --git a/pkg/core/native/crypto.go b/pkg/core/native/crypto.go index 323a8ed21..2d8afc524 100644 --- a/pkg/core/native/crypto.go +++ b/pkg/core/native/crypto.go @@ -10,6 +10,7 @@ import ( bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -467,6 +468,11 @@ func (c *Crypto) Initialize(ic *interop.Context) error { return nil } +// InitializeCache implements the Contract interface. +func (c *Crypto) InitializeCache(blockHeight uint32, d *dao.Simple) error { + return nil +} + // OnPersist implements the Contract interface. func (c *Crypto) OnPersist(ic *interop.Context) error { return nil diff --git a/pkg/core/native/designate.go b/pkg/core/native/designate.go index caf587ccf..12d8fd79a 100644 --- a/pkg/core/native/designate.go +++ b/pkg/core/native/designate.go @@ -132,7 +132,7 @@ func (s *Designate) Initialize(ic *interop.Context) error { // InitializeCache fills native Designate cache from DAO. It is called at non-zero height, thus // we can fetch the roles data right from the storage. -func (s *Designate) InitializeCache(d *dao.Simple) error { +func (s *Designate) InitializeCache(blockHeight uint32, d *dao.Simple) error { cache := &DesignationCache{} roles := []noderoles.Role{noderoles.Oracle, noderoles.NeoFSAlphabet, noderoles.StateValidator} if s.p2pSigExtensionsEnabled { diff --git a/pkg/core/native/ledger.go b/pkg/core/native/ledger.go index 51734c226..ba21a3487 100644 --- a/pkg/core/native/ledger.go +++ b/pkg/core/native/ledger.go @@ -85,6 +85,11 @@ func (l *Ledger) Initialize(ic *interop.Context) error { return nil } +// InitializeCache implements the Contract interface. +func (l *Ledger) InitializeCache(blockHeight uint32, d *dao.Simple) error { + return nil +} + // OnPersist implements the Contract interface. func (l *Ledger) OnPersist(ic *interop.Context) error { // Actual block/tx processing is done in Blockchain.storeBlock(). diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index e177edefb..f78d4080e 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -610,7 +610,7 @@ func (m *Management) OnPersist(ic *interop.Context) error { // InitializeCache initializes contract cache with the proper values from storage. // Cache initialization should be done apart from Initialize because Initialize is // called only when deploying native contracts. -func (m *Management) InitializeCache(d *dao.Simple) error { +func (m *Management) InitializeCache(blockHeight uint32, d *dao.Simple) error { cache := &ManagementCache{ contracts: make(map[util.Uint160]*state.Contract), nep11: make(map[util.Uint160]struct{}), diff --git a/pkg/core/native/management_test.go b/pkg/core/native/management_test.go index a4cb7bc87..cc8e1e1f8 100644 --- a/pkg/core/native/management_test.go +++ b/pkg/core/native/management_test.go @@ -82,7 +82,7 @@ func TestManagement_Initialize(t *testing.T) { t.Run("good", func(t *testing.T) { d := dao.NewSimple(storage.NewMemoryStore(), false, false) mgmt := newManagement() - require.NoError(t, mgmt.InitializeCache(d)) + require.NoError(t, mgmt.InitializeCache(0, d)) }) /* See #2801 t.Run("invalid contract state", func(t *testing.T) { @@ -101,7 +101,7 @@ func TestManagement_GetNEP17Contracts(t *testing.T) { err := mgmt.Initialize(&interop.Context{DAO: d}) require.NoError(t, err) require.NoError(t, mgmt.Policy.Initialize(&interop.Context{DAO: d})) - err = mgmt.InitializeCache(d) + err = mgmt.InitializeCache(0, d) require.NoError(t, err) require.Empty(t, mgmt.GetNEP17Contracts(d)) diff --git a/pkg/core/native/native_gas.go b/pkg/core/native/native_gas.go index e60f3f959..7276572b6 100644 --- a/pkg/core/native/native_gas.go +++ b/pkg/core/native/native_gas.go @@ -99,6 +99,11 @@ func (g *GAS) Initialize(ic *interop.Context) error { return nil } +// InitializeCache implements the Contract interface. +func (g *GAS) InitializeCache(blockHeight uint32, d *dao.Simple) error { + return nil +} + // OnPersist implements the Contract interface. func (g *GAS) OnPersist(ic *interop.Context) error { if len(ic.Block.Transactions) == 0 { diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 844d27361..6c8742dbb 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -305,7 +305,8 @@ func (n *NEO) Initialize(ic *interop.Context) error { // InitializeCache initializes all NEO cache with the proper values from the storage. // Cache initialization should be done apart from Initialize because Initialize is -// called only when deploying native contracts. +// called only when deploying native contracts. InitializeCache implements the Contract +// interface. func (n *NEO) InitializeCache(blockHeight uint32, d *dao.Simple) error { cache := &NeoCache{ gasPerVoteCache: make(map[string]big.Int), diff --git a/pkg/core/native/notary.go b/pkg/core/native/notary.go index 93f2af788..f58e628a7 100644 --- a/pkg/core/native/notary.go +++ b/pkg/core/native/notary.go @@ -152,7 +152,7 @@ func (n *Notary) Initialize(ic *interop.Context) error { return nil } -func (n *Notary) InitializeCache(d *dao.Simple) error { +func (n *Notary) InitializeCache(blockHeight uint32, d *dao.Simple) error { cache := &NotaryCache{ maxNotValidBeforeDelta: uint32(getIntWithKey(n.ID, d, maxNotValidBeforeDeltaKey)), notaryServiceFeePerKey: getIntWithKey(n.ID, d, notaryServiceFeeKey), diff --git a/pkg/core/native/oracle.go b/pkg/core/native/oracle.go index 0189f4fd3..ef943966e 100644 --- a/pkg/core/native/oracle.go +++ b/pkg/core/native/oracle.go @@ -251,10 +251,11 @@ func (o *Oracle) Initialize(ic *interop.Context) error { return nil } -func (o *Oracle) InitializeCache(d *dao.Simple) { +func (o *Oracle) InitializeCache(blockHeight uint32, d *dao.Simple) error { cache := &OracleCache{} cache.requestPrice = getIntWithKey(o.ID, d, prefixRequestPrice) d.SetCache(o.ID, cache) + return nil } func getResponse(tx *transaction.Transaction) *transaction.OracleResponse { diff --git a/pkg/core/native/policy.go b/pkg/core/native/policy.go index 570dfc40a..d45972c73 100644 --- a/pkg/core/native/policy.go +++ b/pkg/core/native/policy.go @@ -153,7 +153,7 @@ func (p *Policy) Initialize(ic *interop.Context) error { return nil } -func (p *Policy) InitializeCache(d *dao.Simple) error { +func (p *Policy) InitializeCache(blockHeight uint32, d *dao.Simple) error { cache := &PolicyCache{} err := p.fillCacheFromDAO(cache, d) if err != nil { diff --git a/pkg/core/native/std.go b/pkg/core/native/std.go index 733fd7338..18dabccc5 100644 --- a/pkg/core/native/std.go +++ b/pkg/core/native/std.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/mr-tron/base58" + "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" base58neogo "github.com/nspcc-dev/neo-go/pkg/encoding/base58" @@ -429,6 +430,11 @@ func (s *Std) Initialize(ic *interop.Context) error { return nil } +// InitializeCache implements the Contract interface. +func (s *Std) InitializeCache(blockHeight uint32, d *dao.Simple) error { + return nil +} + // OnPersist implements the Contract interface. func (s *Std) OnPersist(ic *interop.Context) error { return nil From edb2d46d5b7dfdd05597f90f5da91fa7fe966253 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 26 Apr 2023 13:22:13 +0300 Subject: [PATCH 052/125] core: initialize natives cache wrt NativeActivations If the contract was deployed then cache must be initialized after in-memory data reset. If the contract isn't active yet, then no cache will be initialized on deploy (i.e. on call to Initialize() method by native Management). Close #2984. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 11 +++-- pkg/core/blockchain_neotest_test.go | 65 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index a70f7bb3a..064453ca5 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1012,9 +1012,14 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error { for _, c := range bc.contracts.Contracts { - err := c.InitializeCache(blockHeight, d) - if err != nil { - return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err) + for _, h := range c.Metadata().UpdateHistory { + if blockHeight >= h { // check that contract was deployed. + err := c.InitializeCache(blockHeight, d) + if err != nil { + return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err) + } + break + } } } return nil diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index 8a99ad04d..f5e2edcbf 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -299,6 +299,71 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { }) } +// This test enables Notary native contract at non-zero height and checks that no +// Notary cache initialization is performed before that height on node restart. +func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) { + const notaryEnabledHeight = 3 + ps, path := newLevelDBForTestingWithPath(t, "") + customConfig := func(c *config.Blockchain) { + c.P2PSigExtensions = true + c.NativeUpdateHistories = make(map[string][]uint32) + for _, n := range []string{ + nativenames.Neo, + nativenames.Gas, + nativenames.Designation, + nativenames.Management, + nativenames.CryptoLib, + nativenames.Ledger, + nativenames.Management, + nativenames.Oracle, + nativenames.Policy, + nativenames.StdLib, + nativenames.Notary, + } { + if n == nativenames.Notary { + c.NativeUpdateHistories[n] = []uint32{notaryEnabledHeight} + } else { + c.NativeUpdateHistories[n] = []uint32{0} + } + } + } + bc, validators, committee, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, ps) + require.NoError(t, err) + go bc.Run() + e := neotest.NewExecutor(t, bc, validators, committee) + e.AddNewBlock(t) + bc.Close() // Ensure persist is done and persistent store is properly closed. + + ps, _ = newLevelDBForTestingWithPath(t, path) + + // If NativeActivations are not taken into account during native cache initialization, + // bs.init() will panic on Notary cache initialization as it's not deployed yet. + require.NotPanics(t, func() { + bc, _, _, err = chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, ps) + require.NoError(t, err) + }) + go bc.Run() + defer bc.Close() + e = neotest.NewExecutor(t, bc, validators, committee) + h := e.Chain.BlockHeight() + + // Notary isn't initialized yet, so accessing Notary cache should panic. + require.Panics(t, func() { + _ = e.Chain.GetMaxNotValidBeforeDelta() + }) + + // Ensure Notary will be properly initialized and accessing Notary cache works + // as expected. + for i := 0; i < notaryEnabledHeight; i++ { + require.NotPanics(t, func() { + e.AddNewBlock(t) + }, h+uint32(i)+1) + } + require.NotPanics(t, func() { + _ = e.Chain.GetMaxNotValidBeforeDelta() + }) +} + func TestBlockchain_AddHeaders(t *testing.T) { bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.StateRootInHeader = true From 67d4d891ef847a8979fce36a37073ff4d74316b6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 26 Apr 2023 14:10:12 +0300 Subject: [PATCH 053/125] core: prevent direct access to Notary contract if not active Otherwise it will cause panic, which isn't expected behaviour. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 14 ++++++++++---- pkg/core/blockchain_neotest_test.go | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 064453ca5..67c6f8b9e 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2567,7 +2567,10 @@ func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transact nvb := tx.Attributes[i].Value.(*transaction.NotValidBefore).Height curHeight := bc.BlockHeight() if isPartialTx { - maxNVBDelta := bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao) + maxNVBDelta, err := bc.GetMaxNotValidBeforeDelta() + if err != nil { + return fmt.Errorf("%w: failed to retrieve MaxNotValidBeforeDelta value from native Notary contract: %v", ErrInvalidAttribute, err) + } if curHeight+maxNVBDelta < nvb { return fmt.Errorf("%w: NotValidBefore (%d) bigger than MaxNVBDelta (%d) allows at height %d", ErrInvalidAttribute, nvb, maxNVBDelta, curHeight) } @@ -2972,11 +2975,14 @@ func (bc *Blockchain) GetMaxVerificationGAS() int64 { } // GetMaxNotValidBeforeDelta returns maximum NotValidBeforeDelta Notary limit. -func (bc *Blockchain) GetMaxNotValidBeforeDelta() uint32 { +func (bc *Blockchain) GetMaxNotValidBeforeDelta() (uint32, error) { if !bc.config.P2PSigExtensions { - panic("disallowed call to Notary") + panic("disallowed call to Notary") // critical error, thus panic. } - return bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao) + if bc.contracts.Notary.Metadata().UpdateHistory[0] > bc.BlockHeight() { + return 0, fmt.Errorf("native Notary is active starting from %d", bc.contracts.Notary.Metadata().UpdateHistory[0]) + } + return bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao), nil } // GetStoragePrice returns current storage price. diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index f5e2edcbf..3e64fadd5 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -347,10 +347,9 @@ func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) { e = neotest.NewExecutor(t, bc, validators, committee) h := e.Chain.BlockHeight() - // Notary isn't initialized yet, so accessing Notary cache should panic. - require.Panics(t, func() { - _ = e.Chain.GetMaxNotValidBeforeDelta() - }) + // Notary isn't initialized yet, so accessing Notary cache should return error. + _, err = e.Chain.GetMaxNotValidBeforeDelta() + require.Error(t, err) // Ensure Notary will be properly initialized and accessing Notary cache works // as expected. @@ -359,9 +358,8 @@ func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) { e.AddNewBlock(t) }, h+uint32(i)+1) } - require.NotPanics(t, func() { - _ = e.Chain.GetMaxNotValidBeforeDelta() - }) + _, err = e.Chain.GetMaxNotValidBeforeDelta() + require.NoError(t, err) } func TestBlockchain_AddHeaders(t *testing.T) { @@ -1949,11 +1947,15 @@ func TestBlockchain_VerifyTx(t *testing.T) { require.Error(t, bc.PoolTxWithData(tx, 5, mp, bc, verificationF)) }) t.Run("bad NVB: too big", func(t *testing.T) { - tx := getPartiallyFilledTx(bc.BlockHeight()+bc.GetMaxNotValidBeforeDelta()+1, bc.BlockHeight()+1) + maxNVB, err := bc.GetMaxNotValidBeforeDelta() + require.NoError(t, err) + tx := getPartiallyFilledTx(bc.BlockHeight()+maxNVB+1, bc.BlockHeight()+1) require.True(t, errors.Is(bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute)) }) t.Run("bad ValidUntilBlock: too small", func(t *testing.T) { - tx := getPartiallyFilledTx(bc.BlockHeight(), bc.BlockHeight()+bc.GetMaxNotValidBeforeDelta()+1) + maxNVB, err := bc.GetMaxNotValidBeforeDelta() + require.NoError(t, err) + tx := getPartiallyFilledTx(bc.BlockHeight(), bc.BlockHeight()+maxNVB+1) require.True(t, errors.Is(bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute)) }) t.Run("good", func(t *testing.T) { From 2567c4c672d2c630bfe37699e7c7ebb3e3f2c140 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 27 Apr 2023 18:38:06 +0300 Subject: [PATCH 054/125] oracle: update NeoFS SDK to 1.0.0-rc.8 We were using _very_ old version, so there is a number of changes, including: * fix for unlimited reads * UTF-8 check for HTTP requests Signed-off-by: Roman Khimov --- go.mod | 25 ++-- go.sum | 173 ++++++------------------ pkg/services/oracle/neofs/neofs.go | 142 +++++++++++++------ pkg/services/oracle/neofs/neofs_test.go | 25 +--- pkg/services/oracle/request.go | 10 +- pkg/services/oracle/response.go | 13 +- 6 files changed, 178 insertions(+), 210 deletions(-) diff --git a/go.mod b/go.mod index 26f3534d7..3b93aba5b 100644 --- a/go.mod +++ b/go.mod @@ -5,47 +5,51 @@ require ( github.com/consensys/gnark-crypto v0.9.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.4.2 - github.com/hashicorp/golang-lru v0.5.4 + github.com/hashicorp/golang-lru v0.6.0 github.com/holiman/uint256 v1.2.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/mr-tron/base58 v1.2.0 github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a - github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 + github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8 github.com/nspcc-dev/rfc6979 v0.2.0 github.com/pierrec/lz4 v2.6.1+incompatible github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.13.0 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 github.com/twmb/murmur3 v1.1.5 github.com/urfave/cli v1.22.5 go.etcd.io/bbolt v1.3.6 - go.uber.org/atomic v1.9.0 + go.uber.org/atomic v1.10.0 go.uber.org/zap v1.24.0 golang.org/x/crypto v0.4.0 golang.org/x/term v0.5.0 golang.org/x/text v0.7.0 - golang.org/x/tools v0.1.12 + golang.org/x/tools v0.2.0 gopkg.in/yaml.v3 v3.0.1 ) require ( + github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/frankban/quicktest v1.14.5 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.1 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/nspcc-dev/hrw v1.0.9 // indirect - github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 // indirect + github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 // indirect github.com/nspcc-dev/neofs-crypto v0.4.0 // indirect + github.com/nspcc-dev/tzhash v1.6.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.37.0 // indirect @@ -53,13 +57,14 @@ require ( github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20221227203929-1b447090c38c // indirect + golang.org/x/mod v0.6.0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.5.0 // indirect google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect - google.golang.org/grpc v1.41.0 // indirect + google.golang.org/grpc v1.48.0 // indirect google.golang.org/protobuf v1.28.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 35421089b..5fbce655d 100644 --- a/go.sum +++ b/go.sum @@ -33,44 +33,21 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0= -github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig= -github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I= -github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA= -github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= -github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= -github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs= -github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= -github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521073959-f0d4d129b7f1/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 h1:npHgfD4Tl2WJS3AJaMUi5ynGDPUBfkg3U3fCzDyXZ+4= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -83,7 +60,10 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.9.1 h1:mru55qKdWl3E035hAoh1jj9d7hVnYY5pfb6tmovSmII= @@ -91,26 +71,20 @@ github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjz github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -126,9 +100,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -141,7 +113,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -159,10 +130,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -175,7 +144,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -189,8 +159,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -198,18 +168,14 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= +github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -220,25 +186,17 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= @@ -249,57 +207,40 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw= -github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY= -github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= -github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= -github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd h1:PYJbdSrB4S2Sp5e28CD0pxGE5xsCGO/6DZVQtBnllRc= github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= -github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= -github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= -github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= -github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= -github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= +github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk= +github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 h1:rpMCoRa7expLc9gMiOP724gz6YSykZzmMALR/CmiwnU= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= -github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8 h1:bsg3o7Oiae2xHYAs1M5yg8GDOs46x/IW5jCh/4dt8uo= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8/go.mod h1:kq/KoRhj/Ye8b7ctykiXej42Kq09lUg2E5FXGCbLOWs= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nspcc-dev/tzhash v1.6.1 h1:8dUrWFpjkmoHF+7GxuGUmarj9LLHWFcuyF3CTrqq9JE= +github.com/nspcc-dev/tzhash v1.6.1/go.mod h1:BoflzCVp+DO/f1mvbcsJQWoFzidIFBhWFZMglbUW648= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -308,7 +249,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -320,7 +260,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= @@ -328,7 +267,6 @@ github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8 github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= @@ -336,8 +274,8 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -350,20 +288,20 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/twmb/murmur3 v1.1.5 h1:i9OLS9fkuLzBXjt6dptlAEyk58fJsSTXbRg3SgVyqgk= github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= @@ -371,10 +309,6 @@ github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -383,30 +317,19 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -419,6 +342,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20221227203929-1b447090c38c h1:Govq2W3bnHJimHT2ium65kXcI7ZzTniZHcFATnLJM0Q= +golang.org/x/exp v0.0.0-20221227203929-1b447090c38c/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -439,9 +364,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -474,7 +398,6 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -495,7 +418,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= @@ -504,9 +426,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -515,18 +435,14 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -546,6 +462,7 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -555,7 +472,6 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -571,7 +487,6 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -587,7 +502,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -613,9 +527,8 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -688,8 +601,8 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -705,7 +618,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -720,7 +632,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/pkg/services/oracle/neofs/neofs.go b/pkg/services/oracle/neofs/neofs.go index e7d67fc51..771e92404 100644 --- a/pkg/services/oracle/neofs/neofs.go +++ b/pkg/services/oracle/neofs/neofs.go @@ -4,18 +4,24 @@ import ( "context" "errors" "fmt" + "io" "net/url" "strconv" "strings" - "unicode/utf8" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neofs-sdk-go/client" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/object" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" ) +// ResultReader is a function that reads required amount of data and +// checks it. +type ResultReader func(io.Reader) ([]byte, error) + const ( // URIScheme is the name of neofs URI scheme. URIScheme = "neofs" @@ -41,26 +47,32 @@ var ( // Get returns a neofs object from the provided url. // URI scheme is "neofs://". // If Command is not provided, full object is requested. -func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string) ([]byte, error) { +func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string, resReader ResultReader) ([]byte, error) { objectAddr, ps, err := parseNeoFSURL(u) if err != nil { return nil, err } - c, err := client.New( - client.WithDefaultPrivateKey(&priv.PrivateKey), - client.WithURIAddress(addr, nil), - client.WithNeoFSErrorParsing(), - ) + var c = new(client.Client) + var prmi client.PrmInit + prmi.ResolveNeoFSFailures() + prmi.SetDefaultSigner(neofsecdsa.Signer(priv.PrivateKey)) + c.Init(prmi) + + var prmd client.PrmDial + prmd.SetServerURI(addr) + prmd.SetContext(ctx) + err = c.Dial(prmd) //nolint:contextcheck // contextcheck: Function `Dial->Balance->SendUnary->Init->setNeoFSAPIServer` should pass the context parameter if err != nil { return nil, err } + defer c.Close() switch { case len(ps) == 0 || ps[0] == "": // Get request - return getPayload(ctx, c, objectAddr) + return getPayload(ctx, c, objectAddr, resReader) case ps[0] == rangeCmd: - return getRange(ctx, c, objectAddr, ps[1:]...) + return getRange(ctx, c, objectAddr, resReader, ps[1:]...) case ps[0] == headerCmd: return getHeader(ctx, c, objectAddr) case ps[0] == hashCmd: @@ -71,7 +83,7 @@ func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string) ([ } // parseNeoFSURL returns parsed neofs address. -func parseNeoFSURL(u *url.URL) (*object.Address, []string, error) { +func parseNeoFSURL(u *url.URL) (*oid.Address, []string, error) { if u.Scheme != URIScheme { return nil, nil, ErrInvalidScheme } @@ -81,31 +93,43 @@ func parseNeoFSURL(u *url.URL) (*object.Address, []string, error) { return nil, nil, ErrMissingObject } - containerID := cid.New() - if err := containerID.Parse(ps[0]); err != nil { + var containerID cid.ID + if err := containerID.DecodeString(ps[0]); err != nil { return nil, nil, fmt.Errorf("%w: %v", ErrInvalidContainer, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } - objectID := object.NewID() - if err := objectID.Parse(ps[1]); err != nil { + var objectID oid.ID + if err := objectID.DecodeString(ps[1]); err != nil { return nil, nil, fmt.Errorf("%w: %v", ErrInvalidObject, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } - - objectAddr := object.NewAddress() - objectAddr.SetContainerID(containerID) - objectAddr.SetObjectID(objectID) - return objectAddr, ps[2:], nil + var objAddr = new(oid.Address) + objAddr.SetContainer(containerID) + objAddr.SetObject(objectID) + return objAddr, ps[2:], nil } -func getPayload(ctx context.Context, c *client.Client, addr *object.Address) ([]byte, error) { - res, err := c.GetObject(ctx, new(client.GetObjectParams).WithAddress(addr)) +func getPayload(ctx context.Context, c *client.Client, addr *oid.Address, resReader ResultReader) ([]byte, error) { + var getPrm client.PrmObjectGet + getPrm.FromContainer(addr.Container()) + getPrm.ByID(addr.Object()) + + objR, err := c.ObjectGetInit(ctx, getPrm) if err != nil { return nil, err } - return checkUTF8(res.Object().Payload()) + resp, err := resReader(objR) + if err != nil { + return nil, err + } + _, err = objR.Close() // Using ResolveNeoFSFailures. + if err != nil { + return nil, err + } + + return resp, nil } -func getRange(ctx context.Context, c *client.Client, addr *object.Address, ps ...string) ([]byte, error) { +func getRange(ctx context.Context, c *client.Client, addr *oid.Address, resReader ResultReader, ps ...string) ([]byte, error) { if len(ps) == 0 { return nil, ErrInvalidRange } @@ -113,39 +137,78 @@ func getRange(ctx context.Context, c *client.Client, addr *object.Address, ps .. if err != nil { return nil, err } - res, err := c.ObjectPayloadRangeData(ctx, new(client.RangeDataParams).WithAddress(addr).WithRange(r)) + var rangePrm client.PrmObjectRange + rangePrm.FromContainer(addr.Container()) + rangePrm.ByID(addr.Object()) + rangePrm.SetLength(r.GetLength()) + rangePrm.SetOffset(r.GetOffset()) + + rangeR, err := c.ObjectRangeInit(ctx, rangePrm) if err != nil { return nil, err } - return checkUTF8(res.Data()) -} - -func getHeader(ctx context.Context, c *client.Client, addr *object.Address) ([]byte, error) { - res, err := c.HeadObject(ctx, new(client.ObjectHeaderParams).WithAddress(addr)) + resp, err := resReader(rangeR) if err != nil { return nil, err } - return res.Object().MarshalHeaderJSON() + _, err = rangeR.Close() // Using ResolveNeoFSFailures. + if err != nil { + return nil, err + } + + return resp, nil } -func getHash(ctx context.Context, c *client.Client, addr *object.Address, ps ...string) ([]byte, error) { +func getObjHeader(ctx context.Context, c *client.Client, addr *oid.Address) (*object.Object, error) { + var headPrm client.PrmObjectHead + headPrm.FromContainer(addr.Container()) + headPrm.ByID(addr.Object()) + + res, err := c.ObjectHead(ctx, headPrm) + if err != nil { + return nil, err + } + var obj = object.New() + if !res.ReadHeader(obj) { + return nil, errors.New("missing header in the reply") + } + return obj, nil +} + +func getHeader(ctx context.Context, c *client.Client, addr *oid.Address) ([]byte, error) { + obj, err := getObjHeader(ctx, c, addr) + if err != nil { + return nil, err + } + return obj.MarshalHeaderJSON() +} + +func getHash(ctx context.Context, c *client.Client, addr *oid.Address, ps ...string) ([]byte, error) { if len(ps) == 0 || ps[0] == "" { // hash of the full payload - res, err := c.HeadObject(ctx, new(client.ObjectHeaderParams).WithAddress(addr)) + obj, err := getObjHeader(ctx, c, addr) if err != nil { return nil, err } - return res.Object().PayloadChecksum().Sum(), nil + sum, flag := obj.PayloadChecksum() + if !flag { + return nil, errors.New("missing checksum in the reply") + } + return sum.Value(), nil } r, err := parseRange(ps[0]) if err != nil { return nil, err } - res, err := c.HashObjectPayloadRanges(ctx, - new(client.RangeChecksumParams).WithAddress(addr).WithRangeList(r)) + var hashPrm client.PrmObjectHash + hashPrm.FromContainer(addr.Container()) + hashPrm.ByID(addr.Object()) + hashPrm.SetRangeList(r.GetOffset(), r.GetLength()) + + res, err := c.ObjectHash(ctx, hashPrm) if err != nil { return nil, err } - hashes := res.Hashes() + hashes := res.Checksums() // Using ResolveNeoFSFailures. if len(hashes) == 0 { return nil, fmt.Errorf("%w: empty response", ErrInvalidRange) } @@ -175,10 +238,3 @@ func parseRange(s string) (*object.Range, error) { r.SetLength(length) return r, nil } - -func checkUTF8(v []byte) ([]byte, error) { - if !utf8.Valid(v) { - return nil, errors.New("invalid UTF-8") - } - return v, nil -} diff --git a/pkg/services/oracle/neofs/neofs_test.go b/pkg/services/oracle/neofs/neofs_test.go index 1ad79920d..03c85db4c 100644 --- a/pkg/services/oracle/neofs/neofs_test.go +++ b/pkg/services/oracle/neofs/neofs_test.go @@ -5,8 +5,7 @@ import ( "net/url" "testing" - cid "github.com/nspcc-dev/neofs-sdk-go/container/id" - "github.com/nspcc-dev/neofs-sdk-go/object" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/stretchr/testify/require" ) @@ -37,17 +36,11 @@ func TestParseRange(t *testing.T) { func TestParseNeoFSURL(t *testing.T) { cStr := "C3swfg8MiMJ9bXbeFG6dWJTCoHp9hAEZkHezvbSwK1Cc" - containerID := cid.New() - require.NoError(t, containerID.Parse(cStr)) - oStr := "3nQH1L8u3eM9jt2mZCs6MyjzdjerdSzBkXCYYj4M4Znk" - oid := object.NewID() - require.NoError(t, oid.Parse(oStr)) + var objectAddr oid.Address + require.NoError(t, objectAddr.DecodeString(cStr+"/"+oStr)) validPrefix := "neofs:" + cStr + "/" + oStr - objectAddr := object.NewAddress() - objectAddr.SetContainerID(containerID) - objectAddr.SetObjectID(oid) testCases := []struct { url string @@ -72,7 +65,7 @@ func TestParseNeoFSURL(t *testing.T) { return } require.NoError(t, err) - require.Equal(t, objectAddr, oa) + require.Equal(t, objectAddr, *oa) require.Equal(t, len(tc.params), len(ps)) if len(ps) != 0 { require.Equal(t, tc.params, ps) @@ -80,13 +73,3 @@ func TestParseNeoFSURL(t *testing.T) { }) } } - -func Test_checkUTF8(t *testing.T) { - _, err := checkUTF8([]byte{0xFF}) - require.Error(t, err) - - a := []byte{1, 2, 3} - b, err := checkUTF8(a) - require.NoError(t, err) - require.Equal(t, a, b) -} diff --git a/pkg/services/oracle/request.go b/pkg/services/oracle/request.go index fddc9d771..a8bd75490 100644 --- a/pkg/services/oracle/request.go +++ b/pkg/services/oracle/request.go @@ -146,7 +146,7 @@ func (o *Oracle) processRequest(priv *keys.PrivateKey, req request) error { break } - resp.Result, err = readResponse(r.Body, transaction.MaxOracleResultSize) + resp.Result, err = readResponse(r.Body) if err != nil { if errors.Is(err, ErrResponseTooLarge) { resp.Code = transaction.ResponseTooLarge @@ -169,10 +169,14 @@ func (o *Oracle) processRequest(priv *keys.PrivateKey, req request) error { ctx, cancel := context.WithTimeout(context.Background(), o.MainCfg.NeoFS.Timeout) defer cancel() index := (int(req.ID) + incTx.attempts) % len(o.MainCfg.NeoFS.Nodes) - resp.Result, err = neofs.Get(ctx, priv, u, o.MainCfg.NeoFS.Nodes[index]) + resp.Result, err = neofs.Get(ctx, priv, u, o.MainCfg.NeoFS.Nodes[index], readResponse) if err != nil { + if errors.Is(err, ErrResponseTooLarge) { + resp.Code = transaction.ResponseTooLarge + } else { + resp.Code = transaction.Error + } o.Log.Warn("oracle request failed", zap.String("url", req.Req.URL), zap.Error(err)) - resp.Code = transaction.Error } default: resp.Code = transaction.ProtocolNotSupported diff --git a/pkg/services/oracle/response.go b/pkg/services/oracle/response.go index f2d3667c0..6b1563e84 100644 --- a/pkg/services/oracle/response.go +++ b/pkg/services/oracle/response.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" gio "io" + "unicode/utf8" "github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/interop" @@ -67,11 +68,12 @@ func (o *Oracle) AddResponse(pub *keys.PublicKey, reqID uint64, txSig []byte) { // ErrResponseTooLarge is returned when a response exceeds the max allowed size. var ErrResponseTooLarge = errors.New("too big response") -func readResponse(rc gio.ReadCloser, limit int) ([]byte, error) { +func readResponse(rc gio.Reader) ([]byte, error) { + const limit = transaction.MaxOracleResultSize buf := make([]byte, limit+1) n, err := gio.ReadFull(rc, buf) if errors.Is(err, gio.ErrUnexpectedEOF) && n <= limit { - return buf[:n], nil + return checkUTF8(buf[:n]) } if err == nil || n > limit { return nil, ErrResponseTooLarge @@ -79,6 +81,13 @@ func readResponse(rc gio.ReadCloser, limit int) ([]byte, error) { return nil, err } +func checkUTF8(v []byte) ([]byte, error) { + if !utf8.Valid(v) { + return nil, errors.New("invalid UTF-8") + } + return v, nil +} + // CreateResponseTx creates an unsigned oracle response transaction. func (o *Oracle) CreateResponseTx(gasForResponse int64, vub uint32, resp *transaction.OracleResponse) (*transaction.Transaction, error) { tx := transaction.New(o.oracleResponse, 0) From 0a160ee93b16a0e7596abc3134615aa6d6243055 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 27 Apr 2023 18:49:19 +0300 Subject: [PATCH 055/125] *: use CompareAndSwap instead of CAS for atomics go.uber.org/atomic deprecated CAS methods in version 1.10 (that introduced CompareAndSwap), so we need to fix it. Signed-off-by: Roman Khimov --- pkg/consensus/consensus.go | 4 ++-- pkg/network/bqueue/queue.go | 2 +- pkg/network/server.go | 6 +++--- pkg/rpcclient/wsclient.go | 2 +- pkg/services/metrics/metrics.go | 4 ++-- pkg/services/notary/notary.go | 4 ++-- pkg/services/rpcsrv/server.go | 4 ++-- pkg/services/rpcsrv/subscription_test.go | 14 +++++++------- pkg/services/stateroot/validators.go | 4 ++-- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 7cd1e52d0..9a29f8c2d 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -276,7 +276,7 @@ func (s *service) Name() string { } func (s *service) Start() { - if s.started.CAS(false, true) { + if s.started.CompareAndSwap(false, true) { s.log.Info("starting consensus service") b, _ := s.Chain.GetBlock(s.Chain.CurrentBlockHash()) // Can't fail, we have some current block! s.lastTimestamp = b.Timestamp @@ -288,7 +288,7 @@ func (s *service) Start() { // Shutdown implements the Service interface. func (s *service) Shutdown() { - if s.started.CAS(true, false) { + if s.started.CompareAndSwap(true, false) { s.log.Info("stopping consensus service") close(s.quit) <-s.finished diff --git a/pkg/network/bqueue/queue.go b/pkg/network/bqueue/queue.go index 1cf8ec548..c80c6e04a 100644 --- a/pkg/network/bqueue/queue.go +++ b/pkg/network/bqueue/queue.go @@ -153,7 +153,7 @@ func (bq *Queue) LastQueued() (uint32, int) { // Discard stops the queue and prevents it from accepting more blocks to enqueue. func (bq *Queue) Discard() { - if bq.discarded.CAS(false, true) { + if bq.discarded.CompareAndSwap(false, true) { bq.queueLock.Lock() close(bq.checkBlocks) // Technically we could bq.queue = nil, but this would cost diff --git a/pkg/network/server.go b/pkg/network/server.go index 1cb62d637..4e5fc6363 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -541,7 +541,7 @@ func (s *Server) tryStartServices() { return } - if s.IsInSync() && s.syncReached.CAS(false, true) { + if s.IsInSync() && s.syncReached.CompareAndSwap(false, true) { s.log.Info("node reached synchronized state, starting services") if s.chain.P2PSigExtensionsEnabled() { s.notaryRequestPool.RunSubscriptions() // WSClient is also a subscriber. @@ -1277,14 +1277,14 @@ func getRequestBlocksPayload(p Peer, currHeight uint32, lastRequestedHeight *ato old := lastRequestedHeight.Load() if old <= currHeight { needHeight = currHeight + 1 - if !lastRequestedHeight.CAS(old, needHeight) { + if !lastRequestedHeight.CompareAndSwap(old, needHeight) { continue } } else if old < currHeight+(bqueue.CacheSize-payload.MaxHashesCount) { needHeight = currHeight + 1 if peerHeight > old+payload.MaxHashesCount { needHeight = old + payload.MaxHashesCount - if !lastRequestedHeight.CAS(old, needHeight) { + if !lastRequestedHeight.CompareAndSwap(old, needHeight) { continue } } diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index b77e03f4b..3ec07198f 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -509,7 +509,7 @@ func NewWS(ctx context.Context, endpoint string, opts WSOptions) (*WSClient, err // Close closes connection to the remote side rendering this client instance // unusable. func (c *WSClient) Close() { - if c.closeCalled.CAS(false, true) { + if c.closeCalled.CompareAndSwap(false, true) { c.setCloseErr(errConnClosedByUser) // Closing shutdown channel sends a signal to wsWriter to break out of the // loop. In doing so it does ws.Close() closing the network connection diff --git a/pkg/services/metrics/metrics.go b/pkg/services/metrics/metrics.go index e814e1eff..883c1fabd 100644 --- a/pkg/services/metrics/metrics.go +++ b/pkg/services/metrics/metrics.go @@ -35,7 +35,7 @@ func NewService(name string, httpServers []*http.Server, cfg config.BasicService // Start runs http service with the exposed endpoint on the configured port. func (ms *Service) Start() error { if ms.config.Enabled { - if !ms.started.CAS(false, true) { + if !ms.started.CompareAndSwap(false, true) { ms.log.Info("service already started") return nil } @@ -66,7 +66,7 @@ func (ms *Service) ShutDown() { if !ms.config.Enabled { return } - if !ms.started.CAS(true, false) { + if !ms.started.CompareAndSwap(true, false) { return } for _, srv := range ms.http { diff --git a/pkg/services/notary/notary.go b/pkg/services/notary/notary.go index e3b6bea96..d2a47e2ae 100644 --- a/pkg/services/notary/notary.go +++ b/pkg/services/notary/notary.go @@ -171,7 +171,7 @@ func (n *Notary) Name() string { // Start runs a Notary module in a separate goroutine. // The Notary only starts once, subsequent calls to Start are no-op. func (n *Notary) Start() { - if !n.started.CAS(false, true) { + if !n.started.CompareAndSwap(false, true) { return } n.Config.Log.Info("starting notary service") @@ -221,7 +221,7 @@ drainLoop: // to Shutdown on the same instance are no-op. The instance that was stopped can // not be started again by calling Start (use a new instance if needed). func (n *Notary) Shutdown() { - if !n.started.CAS(true, false) { + if !n.started.CompareAndSwap(true, false) { return } n.Config.Log.Info("stopping notary service") diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index 116f56c29..b57d227a5 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -342,7 +342,7 @@ func (s *Server) Start() { s.log.Info("RPC server is not enabled") return } - if !s.started.CAS(false, true) { + if !s.started.CompareAndSwap(false, true) { s.log.Info("RPC server already started") return } @@ -397,7 +397,7 @@ func (s *Server) Start() { // that was stopped can not be started again by calling Start (use a new // instance if needed). func (s *Server) Shutdown() { - if !s.started.CAS(true, false) { + if !s.started.CompareAndSwap(true, false) { return } // Signal to websocket writer routines and handleSubEvents. diff --git a/pkg/services/rpcsrv/subscription_test.go b/pkg/services/rpcsrv/subscription_test.go index ba654a5b3..52ff0c6fb 100644 --- a/pkg/services/rpcsrv/subscription_test.go +++ b/pkg/services/rpcsrv/subscription_test.go @@ -156,7 +156,7 @@ func TestSubscriptions(t *testing.T) { for _, id := range subIDs { callUnsubscribe(t, c, respMsgs, id) } - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() } @@ -312,7 +312,7 @@ func TestFilteredSubscriptions(t *testing.T) { callUnsubscribe(t, c, respMsgs, subID) callUnsubscribe(t, c, respMsgs, blockSubID) - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() }) } @@ -408,7 +408,7 @@ func TestFilteredNotaryRequestSubscriptions(t *testing.T) { callUnsubscribe(t, c, respMsgs, subID) }) } - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() } @@ -448,7 +448,7 @@ func TestFilteredBlockSubscriptions(t *testing.T) { require.Equal(t, 3, int(primary)) } callUnsubscribe(t, c, respMsgs, blockSubID) - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() } @@ -477,7 +477,7 @@ func TestMaxSubscriptions(t *testing.T) { } } - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() } @@ -519,7 +519,7 @@ func TestBadSubUnsub(t *testing.T) { t.Run("subscribe", testF(t, subCases)) t.Run("unsubscribe", testF(t, unsubCases)) - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() } @@ -614,6 +614,6 @@ func TestSubscriptionOverflow(t *testing.T) { // `Missed` is the last event and there is nothing afterwards. require.Equal(t, 0, len(respMsgs)) - finishedFlag.CAS(false, true) + finishedFlag.CompareAndSwap(false, true) c.Close() } diff --git a/pkg/services/stateroot/validators.go b/pkg/services/stateroot/validators.go index 4e266cb1c..a62e75892 100644 --- a/pkg/services/stateroot/validators.go +++ b/pkg/services/stateroot/validators.go @@ -25,7 +25,7 @@ func (s *service) Name() string { // Start runs service instance in a separate goroutine. // The service only starts once, subsequent calls to Start are no-op. func (s *service) Start() { - if !s.started.CAS(false, true) { + if !s.started.CompareAndSwap(false, true) { return } s.log.Info("starting state validation service") @@ -68,7 +68,7 @@ drainloop: // to Shutdown on the same instance are no-op. The instance that was stopped can // not be started again by calling Start (use a new instance if needed). func (s *service) Shutdown() { - if !s.started.CAS(true, false) { + if !s.started.CompareAndSwap(true, false) { return } s.log.Info("stopping state validation service") From 9c0a45c65ed2b5447beb817163faf2240879f96e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 28 Apr 2023 12:12:20 +0300 Subject: [PATCH 056/125] core: add nolint comment for deprecated error format style Should be a part of 67d4d891ef847a8979fce36a37073ff4d74316b6. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 67c6f8b9e..e6e659b7b 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2569,7 +2569,7 @@ func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transact if isPartialTx { maxNVBDelta, err := bc.GetMaxNotValidBeforeDelta() if err != nil { - return fmt.Errorf("%w: failed to retrieve MaxNotValidBeforeDelta value from native Notary contract: %v", ErrInvalidAttribute, err) + return fmt.Errorf("%w: failed to retrieve MaxNotValidBeforeDelta value from native Notary contract: %v", ErrInvalidAttribute, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } if curHeight+maxNVBDelta < nvb { return fmt.Errorf("%w: NotValidBefore (%d) bigger than MaxNVBDelta (%d) allows at height %d", ErrInvalidAttribute, nvb, maxNVBDelta, curHeight) From 98d29570d3d84785a3315310e4323864200de9c2 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 28 Apr 2023 12:17:08 +0300 Subject: [PATCH 057/125] github: use minimum supported go version for Linter job It should be this way because we can't provide some features golangci-lint require us to do due to the need to support not only the latest Go version, but also two versions below. Signed-off-by: Anna Shaleva --- .github/workflows/run_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index bab9e99fb..0613c7e09 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.18' - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 From fcaa24f9280e0e06f5dcda69c8bf8db241e9bc30 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 3 May 2023 16:01:46 +0300 Subject: [PATCH 058/125] rpcclient: provide some exported error for disconnected WSClient Regular Client doesn't care much about connections, because HTTP client's Do method can reuse old ones or create additional ones on the fly. So one request can fail and the next one easily succeed. WSClient is different, it works via a single connection and if it breaks, it breaks forever for this client. Callers will get some error on every request afterwards and it'd be nice for this error to be the same so that API users could detect disconnection this way too. Related to nspcc-dev/neofs-node#2325. Signed-off-by: Roman Khimov --- pkg/rpcclient/wsclient.go | 13 +++++++++---- pkg/rpcclient/wsclient_test.go | 3 ++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pkg/rpcclient/wsclient.go b/pkg/rpcclient/wsclient.go index 3ec07198f..e4f11a0f0 100644 --- a/pkg/rpcclient/wsclient.go +++ b/pkg/rpcclient/wsclient.go @@ -454,6 +454,11 @@ const ( // ErrNilNotificationReceiver is returned when notification receiver channel is nil. var ErrNilNotificationReceiver = errors.New("nil notification receiver") +// ErrWSConnLost is a WSClient-specific error that will be returned for any +// requests after disconnection (including intentional ones via +// (*WSClient).Close). +var ErrWSConnLost = errors.New("connection lost") + // errConnClosedByUser is a WSClient error used iff the user calls (*WSClient).Close method by himself. var errConnClosedByUser = errors.New("connection closed by user") @@ -735,22 +740,22 @@ func (c *WSClient) makeWsRequest(r *neorpc.Request) (*neorpc.Response, error) { select { case <-c.done: c.respLock.Unlock() - return nil, errors.New("connection lost before registering response channel") + return nil, fmt.Errorf("%w: before registering response channel", ErrWSConnLost) default: c.respChannels[r.ID] = ch c.respLock.Unlock() } select { case <-c.done: - return nil, errors.New("connection lost before sending the request") + return nil, fmt.Errorf("%w: before sending the request", ErrWSConnLost) case c.requests <- r: } select { case <-c.done: - return nil, errors.New("connection lost while waiting for the response") + return nil, fmt.Errorf("%w: while waiting for the response", ErrWSConnLost) case resp, ok := <-ch: if !ok { - return nil, errors.New("connection lost while waiting for the response") + return nil, fmt.Errorf("%w: while waiting for the response", ErrWSConnLost) } c.unregisterRespChannel(r.ID) return resp, nil diff --git a/pkg/rpcclient/wsclient_test.go b/pkg/rpcclient/wsclient_test.go index ccd272e3b..f414d4c80 100644 --- a/pkg/rpcclient/wsclient_test.go +++ b/pkg/rpcclient/wsclient_test.go @@ -3,6 +3,7 @@ package rpcclient import ( "context" "encoding/json" + "errors" "fmt" "net/http" "net/http/httptest" @@ -752,7 +753,7 @@ func TestWS_RequestAfterClose(t *testing.T) { _, err = c.GetBlockCount() }) require.Error(t, err) - require.True(t, strings.Contains(err.Error(), "connection lost before registering response channel")) + require.True(t, errors.Is(err, ErrWSConnLost)) } func TestWSClient_ConnClosedError(t *testing.T) { From 433275265f4acdd542efbcb5816f47ca32004057 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 4 May 2023 17:03:06 +0300 Subject: [PATCH 059/125] *: use require.ErrorIs instead of require.True(t, error.Is()) This is just a much better way to do the same thing. Inspired by nspcc-dev/neofs-sdk-go#407. Signed-off-by: Roman Khimov --- pkg/consensus/consensus_test.go | 3 +- pkg/core/block/block_test.go | 3 +- pkg/core/blockchain_core_test.go | 7 ++-- pkg/core/blockchain_neotest_test.go | 38 +++++++++---------- pkg/core/chaindump/dump_test.go | 2 +- pkg/core/dao/dao_test.go | 5 +-- pkg/core/interop/interopnames/convert_test.go | 3 +- pkg/core/interop/storage/storage_test.go | 5 +-- pkg/core/mempool/mem_pool_test.go | 13 +++---- pkg/core/mpt/billet_test.go | 23 ++++++----- pkg/core/native_designate_test.go | 11 +++--- pkg/core/transaction/oracle_test.go | 5 +-- pkg/core/transaction/transaction_test.go | 21 +++++----- pkg/network/extpool/pool_test.go | 2 +- pkg/network/payload/extensible_test.go | 5 +-- pkg/network/payload/merkleblock_test.go | 3 +- pkg/network/server_test.go | 4 +- pkg/rpcclient/rpc_test.go | 3 +- pkg/rpcclient/wsclient_test.go | 3 +- pkg/services/oracle/neofs/neofs_test.go | 3 +- pkg/services/oracle/network_test.go | 4 +- pkg/services/stateroot/service_test.go | 3 +- .../manifest/standard/comply_test.go | 21 +++++----- pkg/smartcontract/nef/method_token_test.go | 5 +-- pkg/smartcontract/nef/nef_test.go | 5 +-- pkg/vm/stackitem/json_test.go | 27 +++++++------ pkg/vm/stackitem/serialization_test.go | 15 ++++---- 27 files changed, 109 insertions(+), 133 deletions(-) diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index 469e14767..07eeb99ed 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -1,7 +1,6 @@ package consensus import ( - "errors" "testing" "time" @@ -343,7 +342,7 @@ func TestService_PrepareRequest(t *testing.T) { require.NoError(t, err) return } - require.True(t, errors.Is(err, expectedErr), "got: %v", err) + require.ErrorIs(t, err, expectedErr) } checkRequest(t, errInvalidVersion, &prepareRequest{version: 0xFF, prevHash: prevHash}) diff --git a/pkg/core/block/block_test.go b/pkg/core/block/block_test.go index 90d434627..f0e708f22 100644 --- a/pkg/core/block/block_test.go +++ b/pkg/core/block/block_test.go @@ -4,7 +4,6 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "errors" "strings" "testing" @@ -236,7 +235,7 @@ func TestBlockEncodeDecode(t *testing.T) { data, err := testserdes.EncodeBinary(b) require.NoError(t, err) - require.True(t, errors.Is(testserdes.DecodeBinary(data, new(Block)), ErrMaxContentsPerBlock)) + require.ErrorIs(t, testserdes.DecodeBinary(data, new(Block)), ErrMaxContentsPerBlock) }) } diff --git a/pkg/core/blockchain_core_test.go b/pkg/core/blockchain_core_test.go index 5b1944c52..f9f3e0275 100644 --- a/pkg/core/blockchain_core_test.go +++ b/pkg/core/blockchain_core_test.go @@ -2,7 +2,6 @@ package core import ( "encoding/binary" - "errors" "fmt" "strings" "sync/atomic" @@ -33,16 +32,16 @@ func TestVerifyHeader(t *testing.T) { h := prev.Hash() h[0] = ^h[0] hdr := newBlock(bc.config.ProtocolConfiguration, 1, h).Header - require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrHashMismatch)) + require.ErrorIs(t, bc.verifyHeader(&hdr, &prev), ErrHdrHashMismatch) }) t.Run("Index", func(t *testing.T) { hdr := newBlock(bc.config.ProtocolConfiguration, 3, prev.Hash()).Header - require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrIndexMismatch)) + require.ErrorIs(t, bc.verifyHeader(&hdr, &prev), ErrHdrIndexMismatch) }) t.Run("Timestamp", func(t *testing.T) { hdr := newBlock(bc.config.ProtocolConfiguration, 1, prev.Hash()).Header hdr.Timestamp = 0 - require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrInvalidTimestamp)) + require.ErrorIs(t, bc.verifyHeader(&hdr, &prev), ErrHdrInvalidTimestamp) }) }) t.Run("Valid", func(t *testing.T) { diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index 3e64fadd5..69463f5c6 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -427,7 +427,7 @@ func TestBlockchain_AddBlockStateRoot(t *testing.T) { b.PrevStateRoot = util.Uint256{} e.SignBlock(b) err = bc.AddBlock(b) - require.True(t, errors.Is(err, core.ErrHdrStateRootSetting), "got: %v", err) + require.ErrorIs(t, err, core.ErrHdrStateRootSetting) u := sr.Root u[0] ^= 0xFF @@ -435,7 +435,7 @@ func TestBlockchain_AddBlockStateRoot(t *testing.T) { b.PrevStateRoot = u e.SignBlock(b) err = bc.AddBlock(b) - require.True(t, errors.Is(err, core.ErrHdrInvalidStateRoot), "got: %v", err) + require.ErrorIs(t, err, core.ErrHdrInvalidStateRoot) b = e.NewUnsignedBlock(t) e.SignBlock(b) @@ -455,7 +455,7 @@ func TestBlockchain_AddHeadersStateRoot(t *testing.T) { // invalid stateroot h1.PrevStateRoot[0] ^= 0xFF - require.True(t, errors.Is(bc.AddHeaders(&h1), core.ErrHdrInvalidStateRoot)) + require.ErrorIs(t, bc.AddHeaders(&h1), core.ErrHdrInvalidStateRoot) // valid stateroot h1.PrevStateRoot = r @@ -597,12 +597,12 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { newH[0] = ^newH[0] w := &transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH4)}} _, err := bc.VerifyWitness(newH, nil, w, gas) - require.True(t, errors.Is(err, core.ErrUnknownVerificationContract)) + require.ErrorIs(t, err, core.ErrUnknownVerificationContract) }) t.Run("Invalid", func(t *testing.T) { w := &transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH4)}} _, err := bc.VerifyWitness(csInvalid.Hash, nil, w, gas) - require.True(t, errors.Is(err, core.ErrInvalidVerificationContract)) + require.ErrorIs(t, err, core.ErrInvalidVerificationContract) }) t.Run("ValidSignature", func(t *testing.T) { w := &transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH4)}} @@ -612,7 +612,7 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { t.Run("InvalidSignature", func(t *testing.T) { w := &transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH3)}} _, err := bc.VerifyWitness(cs.Hash, nil, w, gas) - require.True(t, errors.Is(err, core.ErrVerificationFailed)) + require.ErrorIs(t, err, core.ErrVerificationFailed) }) }) t.Run("NotEnoughGas", func(t *testing.T) { @@ -622,7 +622,7 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { VerificationScript: verif, } _, err := bc.VerifyWitness(hash.Hash160(verif), nil, w, 1) - require.True(t, errors.Is(err, core.ErrVerificationFailed)) + require.ErrorIs(t, err, core.ErrVerificationFailed) }) t.Run("NoResult", func(t *testing.T) { verif := []byte{byte(opcode.DROP)} @@ -631,7 +631,7 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { VerificationScript: verif, } _, err := bc.VerifyWitness(hash.Hash160(verif), nil, w, gas) - require.True(t, errors.Is(err, core.ErrVerificationFailed)) + require.ErrorIs(t, err, core.ErrVerificationFailed) }) t.Run("BadResult", func(t *testing.T) { verif := make([]byte, keys.SignatureLen+2) @@ -642,7 +642,7 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { VerificationScript: verif, } _, err := bc.VerifyWitness(hash.Hash160(verif), nil, w, gas) - require.True(t, errors.Is(err, core.ErrVerificationFailed)) + require.ErrorIs(t, err, core.ErrVerificationFailed) }) t.Run("TooManyResults", func(t *testing.T) { verif := []byte{byte(opcode.NOP)} @@ -651,7 +651,7 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { VerificationScript: verif, } _, err := bc.VerifyWitness(hash.Hash160(verif), nil, w, gas) - require.True(t, errors.Is(err, core.ErrVerificationFailed)) + require.ErrorIs(t, err, core.ErrVerificationFailed) }) } @@ -1165,7 +1165,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { checkErr := func(t *testing.T, expectedErr error, tx *transaction.Transaction) { err := bc.VerifyTx(tx) - require.True(t, errors.Is(err, expectedErr), "expected: %v, got: %v", expectedErr, err) + require.ErrorIs(t, err, expectedErr) } testScript := []byte{byte(opcode.PUSH1)} @@ -1321,7 +1321,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { tx2.NetworkFee = balance / 2 require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx2)) err := bc.PoolTx(tx2) - require.True(t, errors.Is(err, core.ErrMemPoolConflict)) + require.ErrorIs(t, err, core.ErrMemPoolConflict) }) t.Run("InvalidWitnessHash", func(t *testing.T) { tx := newTestTx(t, h, testScript) @@ -1358,7 +1358,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { require.NoError(t, bc.PoolTx(tx)) err := bc.PoolTx(tx) - require.True(t, errors.Is(err, core.ErrAlreadyExists)) + require.ErrorIs(t, err, core.ErrAlreadyExists) }) t.Run("MemPoolOOM", func(t *testing.T) { mp := mempool.New(1, 0, false, nil) @@ -1370,7 +1370,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { tx2 := newTestTx(t, h, testScript) require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx2)) err := bc.PoolTx(tx2, mp) - require.True(t, errors.Is(err, core.ErrOOM)) + require.ErrorIs(t, err, core.ErrOOM) }) t.Run("Attribute", func(t *testing.T) { t.Run("InvalidHighPriority", func(t *testing.T) { @@ -1476,7 +1476,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { emit.String(w.BinWriter, nativenames.Oracle) tx.Scripts[len(tx.Scripts)-1].VerificationScript = w.Bytes() err := bc.VerifyTx(tx) - require.True(t, errors.Is(err, core.ErrNativeContractWitness), "got: %v", err) + require.ErrorIs(t, err, core.ErrNativeContractWitness) }) t.Run("Good", func(t *testing.T) { tx.Scripts[len(tx.Scripts)-1].VerificationScript = nil @@ -1549,7 +1549,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { t.Run("Enabled", func(t *testing.T) { t.Run("NotYetValid", func(t *testing.T) { tx := getNVBTx(e, bc.BlockHeight()+1) - require.True(t, errors.Is(bc.VerifyTx(tx), core.ErrInvalidAttribute)) + require.ErrorIs(t, bc.VerifyTx(tx), core.ErrInvalidAttribute) }) t.Run("positive", func(t *testing.T) { tx := getNVBTx(e, bc.BlockHeight()) @@ -1655,7 +1655,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { conflicting.NetworkFee = 1000_0000 require.NoError(t, validator.SignTx(netmode.UnitTestNet, conflicting)) e.AddNewBlock(t, conflicting) - require.True(t, errors.Is(bc.VerifyTx(tx), core.ErrHasConflicts)) + require.ErrorIs(t, bc.VerifyTx(tx), core.ErrHasConflicts) }) t.Run("attribute on-chain conflict", func(t *testing.T) { tx := neoValidatorsInvoker.Invoke(t, stackitem.NewBool(true), "transfer", neoOwner, neoOwner, 1, nil) @@ -1950,13 +1950,13 @@ func TestBlockchain_VerifyTx(t *testing.T) { maxNVB, err := bc.GetMaxNotValidBeforeDelta() require.NoError(t, err) tx := getPartiallyFilledTx(bc.BlockHeight()+maxNVB+1, bc.BlockHeight()+1) - require.True(t, errors.Is(bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute)) + require.ErrorIs(t, bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute) }) t.Run("bad ValidUntilBlock: too small", func(t *testing.T) { maxNVB, err := bc.GetMaxNotValidBeforeDelta() require.NoError(t, err) tx := getPartiallyFilledTx(bc.BlockHeight(), bc.BlockHeight()+maxNVB+1) - require.True(t, errors.Is(bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute)) + require.ErrorIs(t, bc.PoolTxWithData(tx, 5, mp, bc, verificationF), core.ErrInvalidAttribute) }) t.Run("good", func(t *testing.T) { tx := getPartiallyFilledTx(bc.BlockHeight(), bc.BlockHeight()+1) diff --git a/pkg/core/chaindump/dump_test.go b/pkg/core/chaindump/dump_test.go index 3ae6b3bb9..06531ff31 100644 --- a/pkg/core/chaindump/dump_test.go +++ b/pkg/core/chaindump/dump_test.go @@ -85,7 +85,7 @@ func testDumpAndRestore(t *testing.T, dumpF, restoreF func(c *config.Blockchain) r = io.NewBinReaderFromBuf(buf) err := chaindump.Restore(bc2, r, 4, bc.BlockHeight()-bc2.BlockHeight(), f) - require.True(t, errors.Is(err, errStopped)) + require.ErrorIs(t, err, errStopped) require.Equal(t, bc.BlockHeight()-1, lastIndex) }) }) diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index 6583319e7..c9eea92b8 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -2,7 +2,6 @@ package dao import ( "encoding/binary" - "errors" "testing" "github.com/nspcc-dev/neo-go/internal/random" @@ -219,9 +218,9 @@ func TestStoreAsTransaction(t *testing.T) { err := dao.StoreAsTransaction(tx, 0, aer) require.NoError(t, err) err = dao.HasTransaction(hash) - require.True(t, errors.Is(err, ErrAlreadyExists)) + require.ErrorIs(t, err, ErrAlreadyExists) err = dao.HasTransaction(conflictsH) - require.True(t, errors.Is(err, ErrHasConflicts)) + require.ErrorIs(t, err, ErrHasConflicts) gotAppExecResult, err := dao.GetAppExecResults(hash, trigger.All) require.NoError(t, err) require.Equal(t, 1, len(gotAppExecResult)) diff --git a/pkg/core/interop/interopnames/convert_test.go b/pkg/core/interop/interopnames/convert_test.go index 1ec2c1f21..a17592e7a 100644 --- a/pkg/core/interop/interopnames/convert_test.go +++ b/pkg/core/interop/interopnames/convert_test.go @@ -1,7 +1,6 @@ package interopnames import ( - "errors" "testing" "github.com/stretchr/testify/require" @@ -16,6 +15,6 @@ func TestFromID(t *testing.T) { }) t.Run("Invalid", func(t *testing.T) { _, err := FromID(0x42424242) - require.True(t, errors.Is(err, errNotFound)) + require.ErrorIs(t, err, errNotFound) }) } diff --git a/pkg/core/interop/storage/storage_test.go b/pkg/core/interop/storage/storage_test.go index a4f3e5449..ed2394c6d 100644 --- a/pkg/core/interop/storage/storage_test.go +++ b/pkg/core/interop/storage/storage_test.go @@ -1,7 +1,6 @@ package storage_test import ( - "errors" "math/big" "testing" @@ -42,7 +41,7 @@ func TestPut(t *testing.T) { t.Run("create, not enough gas", func(t *testing.T) { initVM(t, []byte{1}, []byte{2, 3}, 2*native.DefaultStoragePrice) err := istorage.Put(ic) - require.True(t, errors.Is(err, istorage.ErrGasLimitExceeded), "got: %v", err) + require.ErrorIs(t, err, istorage.ErrGasLimitExceeded) }) initVM(t, []byte{4}, []byte{5, 6}, 3*native.DefaultStoragePrice) @@ -52,7 +51,7 @@ func TestPut(t *testing.T) { t.Run("not enough gas", func(t *testing.T) { initVM(t, []byte{4}, []byte{5, 6, 7, 8}, native.DefaultStoragePrice) err := istorage.Put(ic) - require.True(t, errors.Is(err, istorage.ErrGasLimitExceeded), "got: %v", err) + require.ErrorIs(t, err, istorage.ErrGasLimitExceeded) }) initVM(t, []byte{4}, []byte{5, 6, 7, 8}, 3*native.DefaultStoragePrice) require.NoError(t, istorage.Put(ic)) diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index 66882e4f3..dfd9e3ac7 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -1,7 +1,6 @@ package mempool import ( - "errors" "math/big" "sort" "testing" @@ -380,7 +379,7 @@ func TestMempoolAddRemoveOracleResponse(t *testing.T) { // smaller network fee tx2 := newTx(5, 1) err := mp.Add(tx2, fs) - require.True(t, errors.Is(err, ErrOracleResponse)) + require.ErrorIs(t, err, ErrOracleResponse) // ok if old tx is removed mp.Remove(tx1.Hash(), fs) @@ -457,7 +456,7 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { // tx2 conflicts with tx1 and has smaller netfee (Step 2, negative) tx2 := getConflictsTx(smallNetFee-1, tx1.Hash()) - require.True(t, errors.Is(mp.Add(tx2, fs), ErrConflictsAttribute)) + require.ErrorIs(t, mp.Add(tx2, fs), ErrConflictsAttribute) // tx3 conflicts with mempooled tx1 and has larger netfee => tx1 should be replaced by tx3 (Step 2, positive) tx3 := getConflictsTx(smallNetFee+1, tx1.Hash()) @@ -468,7 +467,7 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { // tx1 still does not conflicts with anyone, but tx3 is mempooled, conflicts with tx1 // and has larger netfee => tx1 shouldn't be added again (Step 1, negative) - require.True(t, errors.Is(mp.Add(tx1, fs), ErrConflictsAttribute)) + require.ErrorIs(t, mp.Add(tx1, fs), ErrConflictsAttribute) // tx2 can now safely be added because conflicting tx1 is not in mempool => we // cannot check that tx2 is signed by tx1.Sender @@ -541,7 +540,7 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { }} _, ok := mp.TryGetValue(tx13.Hash()) require.Equal(t, false, ok) - require.True(t, errors.Is(mp.Add(tx13, fs), ErrConflictsAttribute)) + require.ErrorIs(t, mp.Add(tx13, fs), ErrConflictsAttribute) } func TestMempoolAddWithDataGetData(t *testing.T) { @@ -570,7 +569,7 @@ func TestMempoolAddWithDataGetData(t *testing.T) { MainTransaction: newTx(t, 0), FallbackTransaction: newTx(t, fs.balance+1), } - require.True(t, errors.Is(mp.Add(r1.FallbackTransaction, fs, r1), ErrInsufficientFunds)) + require.ErrorIs(t, mp.Add(r1.FallbackTransaction, fs, r1), ErrInsufficientFunds) // good r2 := &payload.P2PNotaryRequest{ @@ -584,7 +583,7 @@ func TestMempoolAddWithDataGetData(t *testing.T) { require.Equal(t, r2, data) // bad, already in pool - require.True(t, errors.Is(mp.Add(r2.FallbackTransaction, fs, r2), ErrDup)) + require.ErrorIs(t, mp.Add(r2.FallbackTransaction, fs, r2), ErrDup) // good, higher priority than r2. The resulting mp.verifiedTxes: [r3, r2] r3 := &payload.P2PNotaryRequest{ diff --git a/pkg/core/mpt/billet_test.go b/pkg/core/mpt/billet_test.go index ff77b6436..4946926e7 100644 --- a/pkg/core/mpt/billet_test.go +++ b/pkg/core/mpt/billet_test.go @@ -2,7 +2,6 @@ package mpt import ( "encoding/binary" - "errors" "testing" "github.com/nspcc-dev/neo-go/pkg/core/storage" @@ -21,7 +20,7 @@ func TestBillet_RestoreHashNode(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedRefCount, binary.LittleEndian.Uint32(expectedBytes[len(expectedBytes)-4:])) } else { - require.True(t, errors.Is(err, storage.ErrKeyNotFound)) + require.ErrorIs(t, err, storage.ErrKeyNotFound) } } @@ -49,11 +48,11 @@ func TestBillet_RestoreHashNode(t *testing.T) { check(t, tr, expected, n.Node, 1) // Same path, but wrong hash => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(path, NewBranchNode()), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(path, NewBranchNode()), ErrRestoreFailed) check(t, tr, expected, n.Node, 1) // New path (changes in the MPT structure are not allowed) => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(toNibbles([]byte{0xAB}), n.Node), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(toNibbles([]byte{0xAB}), n.Node), ErrRestoreFailed) check(t, tr, expected, n.Node, 1) }) @@ -75,11 +74,11 @@ func TestBillet_RestoreHashNode(t *testing.T) { check(t, tr, expected, l, 1) // Same path, but wrong hash => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(path, NewLeafNode([]byte{0xAB, 0xEF})), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(path, NewLeafNode([]byte{0xAB, 0xEF})), ErrRestoreFailed) check(t, tr, expected, l, 1) // New path (changes in the MPT structure are not allowed) => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(toNibbles([]byte{0xAB}), l), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(toNibbles([]byte{0xAB}), l), ErrRestoreFailed) check(t, tr, expected, l, 1) }) @@ -91,7 +90,7 @@ func TestBillet_RestoreHashNode(t *testing.T) { tr.root = e // no-op - require.True(t, errors.Is(tr.RestoreHashNode(path, h), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(path, h), ErrRestoreFailed) check(t, tr, e, h, 0) }) }) @@ -108,10 +107,10 @@ func TestBillet_RestoreHashNode(t *testing.T) { }) // Same path, but wrong hash => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(path, NewLeafNode([]byte{0xAB, 0xEF})), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(path, NewLeafNode([]byte{0xAB, 0xEF})), ErrRestoreFailed) // Non-nil path, but MPT structure can't be changed => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(toNibbles([]byte{0xAC}), NewLeafNode([]byte{0xAB, 0xEF})), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(toNibbles([]byte{0xAC}), NewLeafNode([]byte{0xAB, 0xEF})), ErrRestoreFailed) }) t.Run("parent is Branch", func(t *testing.T) { @@ -138,11 +137,11 @@ func TestBillet_RestoreHashNode(t *testing.T) { check(t, tr, b, l1, 1) // Same path, but wrong hash => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(path, NewLeafNode([]byte{0xAD})), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(path, NewLeafNode([]byte{0xAD})), ErrRestoreFailed) check(t, tr, b, l1, 1) // New path pointing to the empty HashNode (changes in the MPT structure are not allowed) => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode([]byte{0x01}, l1), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode([]byte{0x01}, l1), ErrRestoreFailed) check(t, tr, b, l1, 1) }) @@ -169,7 +168,7 @@ func TestBillet_RestoreHashNode(t *testing.T) { check(t, tr, b, l2, 1) // Same path, but wrong hash => error expected, no refcount changes - require.True(t, errors.Is(tr.RestoreHashNode(path, NewLeafNode([]byte{0xAD})), ErrRestoreFailed)) + require.ErrorIs(t, tr.RestoreHashNode(path, NewLeafNode([]byte{0xAD})), ErrRestoreFailed) check(t, tr, b, l2, 1) }) diff --git a/pkg/core/native_designate_test.go b/pkg/core/native_designate_test.go index 533127859..27685b671 100644 --- a/pkg/core/native_designate_test.go +++ b/pkg/core/native_designate_test.go @@ -1,7 +1,6 @@ package core import ( - "errors" "testing" "github.com/nspcc-dev/neo-go/internal/testchain" @@ -30,7 +29,7 @@ func TestDesignate_DesignateAsRole(t *testing.T) { ic.VM.LoadScript([]byte{byte(opcode.RET)}) _, _, err := des.GetDesignatedByRole(bc.dao, 0xFF, 255) - require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err) + require.ErrorIs(t, err, native.ErrInvalidRole) pubs, index, err := des.GetDesignatedByRole(bc.dao, noderoles.Oracle, 255) require.NoError(t, err) @@ -38,20 +37,20 @@ func TestDesignate_DesignateAsRole(t *testing.T) { require.Equal(t, uint32(0), index) err = des.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{}) - require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err) + require.ErrorIs(t, err, native.ErrEmptyNodeList) err = des.DesignateAsRole(ic, noderoles.Oracle, make(keys.PublicKeys, 32+1)) - require.True(t, errors.Is(err, native.ErrLargeNodeList), "got: %v", err) + require.ErrorIs(t, err, native.ErrLargeNodeList) priv, err := keys.NewPrivateKey() require.NoError(t, err) pub := priv.PublicKey() err = des.DesignateAsRole(ic, 0xFF, keys.PublicKeys{pub}) - require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err) + require.ErrorIs(t, err, native.ErrInvalidRole) err = des.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{pub}) - require.True(t, errors.Is(err, native.ErrInvalidWitness), "got: %v", err) + require.ErrorIs(t, err, native.ErrInvalidWitness) setSigner(tx, testchain.CommitteeScriptHash()) err = des.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{pub}) diff --git a/pkg/core/transaction/oracle_test.go b/pkg/core/transaction/oracle_test.go index afc61f441..89c4d392e 100644 --- a/pkg/core/transaction/oracle_test.go +++ b/pkg/core/transaction/oracle_test.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/json" - "errors" "math/rand" "testing" @@ -41,7 +40,7 @@ func TestOracleResponse_EncodeBinary(t *testing.T) { require.NoError(t, err) err = testserdes.DecodeBinary(bs, new(OracleResponse)) - require.True(t, errors.Is(err, ErrInvalidResponseCode), "got: %v", err) + require.ErrorIs(t, err, ErrInvalidResponseCode) }) t.Run("InvalidResult", func(t *testing.T) { r := &OracleResponse{ @@ -53,7 +52,7 @@ func TestOracleResponse_EncodeBinary(t *testing.T) { require.NoError(t, err) err = testserdes.DecodeBinary(bs, new(OracleResponse)) - require.True(t, errors.Is(err, ErrInvalidResult), "got: %v", err) + require.ErrorIs(t, err, ErrInvalidResult) }) }) } diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 23c274bfc..9f8340bc4 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -4,7 +4,6 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "errors" "math" "testing" @@ -125,7 +124,7 @@ func TestDecodingTxWithInvalidWitnessesNumber(t *testing.T) { tx.Scripts = []Witness{{InvocationScript: []byte{}, VerificationScript: []byte{}}, {InvocationScript: []byte{}, VerificationScript: []byte{}}} data, err := testserdes.EncodeBinary(tx) require.NoError(t, err) - require.True(t, errors.Is(testserdes.DecodeBinary(data, new(Transaction)), ErrInvalidWitnessNum)) + require.ErrorIs(t, testserdes.DecodeBinary(data, new(Transaction)), ErrInvalidWitnessNum) } func TestUnmarshalNeoFSTX(t *testing.T) { @@ -216,32 +215,32 @@ func TestTransaction_isValid(t *testing.T) { t.Run("InvalidVersion", func(t *testing.T) { tx := newTx() tx.Version = 1 - require.True(t, errors.Is(tx.isValid(), ErrInvalidVersion)) + require.ErrorIs(t, tx.isValid(), ErrInvalidVersion) }) t.Run("NegativeSystemFee", func(t *testing.T) { tx := newTx() tx.SystemFee = -1 - require.True(t, errors.Is(tx.isValid(), ErrNegativeSystemFee)) + require.ErrorIs(t, tx.isValid(), ErrNegativeSystemFee) }) t.Run("NegativeNetworkFee", func(t *testing.T) { tx := newTx() tx.NetworkFee = -1 - require.True(t, errors.Is(tx.isValid(), ErrNegativeNetworkFee)) + require.ErrorIs(t, tx.isValid(), ErrNegativeNetworkFee) }) t.Run("TooBigFees", func(t *testing.T) { tx := newTx() tx.SystemFee = math.MaxInt64 - tx.NetworkFee + 1 - require.True(t, errors.Is(tx.isValid(), ErrTooBigFees)) + require.ErrorIs(t, tx.isValid(), ErrTooBigFees) }) t.Run("EmptySigners", func(t *testing.T) { tx := newTx() tx.Signers = tx.Signers[:0] - require.True(t, errors.Is(tx.isValid(), ErrEmptySigners)) + require.ErrorIs(t, tx.isValid(), ErrEmptySigners) }) t.Run("NonUniqueSigners", func(t *testing.T) { tx := newTx() tx.Signers[1].Account = tx.Signers[0].Account - require.True(t, errors.Is(tx.isValid(), ErrNonUniqueSigners)) + require.ErrorIs(t, tx.isValid(), ErrNonUniqueSigners) }) t.Run("MultipleHighPriority", func(t *testing.T) { tx := newTx() @@ -249,7 +248,7 @@ func TestTransaction_isValid(t *testing.T) { {Type: HighPriority}, {Type: HighPriority}, } - require.True(t, errors.Is(tx.isValid(), ErrInvalidAttribute)) + require.ErrorIs(t, tx.isValid(), ErrInvalidAttribute) }) t.Run("MultipleOracle", func(t *testing.T) { tx := newTx() @@ -257,12 +256,12 @@ func TestTransaction_isValid(t *testing.T) { {Type: OracleResponseT}, {Type: OracleResponseT}, } - require.True(t, errors.Is(tx.isValid(), ErrInvalidAttribute)) + require.ErrorIs(t, tx.isValid(), ErrInvalidAttribute) }) t.Run("NoScript", func(t *testing.T) { tx := newTx() tx.Script = []byte{} - require.True(t, errors.Is(tx.isValid(), ErrEmptyScript)) + require.ErrorIs(t, tx.isValid(), ErrEmptyScript) }) } diff --git a/pkg/network/extpool/pool_test.go b/pkg/network/extpool/pool_test.go index 49486caed..89802a257 100644 --- a/pkg/network/extpool/pool_test.go +++ b/pkg/network/extpool/pool_test.go @@ -107,7 +107,7 @@ func TestRemoveStale(t *testing.T) { func (p *Pool) testAdd(t *testing.T, expectedOk bool, expectedErr error, ep *payload.Extensible) { ok, err := p.Add(ep) if expectedErr != nil { - require.True(t, errors.Is(err, expectedErr), "got: %v", err) + require.ErrorIs(t, err, expectedErr) } else { require.NoError(t, err) } diff --git a/pkg/network/payload/extensible_test.go b/pkg/network/payload/extensible_test.go index f1f6b28c8..a849d8f2c 100644 --- a/pkg/network/payload/extensible_test.go +++ b/pkg/network/payload/extensible_test.go @@ -1,7 +1,6 @@ package payload import ( - "errors" gio "io" "testing" @@ -34,11 +33,11 @@ func TestExtensible_Serializable(t *testing.T) { t.Run("unexpected EOF", func(t *testing.T) { err := testserdes.DecodeBinary(unsigned, new(Extensible)) - require.True(t, errors.Is(err, gio.EOF)) + require.ErrorIs(t, err, gio.EOF) }) t.Run("invalid padding", func(t *testing.T) { err := testserdes.DecodeBinary(append(unsigned, 42), new(Extensible)) - require.True(t, errors.Is(err, errInvalidPadding)) + require.ErrorIs(t, err, errInvalidPadding) }) t.Run("too large data size", func(t *testing.T) { expected.Data = make([]byte, MaxSize+1) diff --git a/pkg/network/payload/merkleblock_test.go b/pkg/network/payload/merkleblock_test.go index 5bcd1e47c..811574705 100644 --- a/pkg/network/payload/merkleblock_test.go +++ b/pkg/network/payload/merkleblock_test.go @@ -1,7 +1,6 @@ package payload import ( - "errors" "testing" "github.com/stretchr/testify/require" @@ -52,7 +51,7 @@ func TestMerkleBlock_EncodeDecodeBinary(t *testing.T) { } data, err := testserdes.EncodeBinary(expected) require.NoError(t, err) - require.True(t, errors.Is(block.ErrMaxContentsPerBlock, testserdes.DecodeBinary(data, new(MerkleBlock)))) + require.ErrorIs(t, testserdes.DecodeBinary(data, new(MerkleBlock)), block.ErrMaxContentsPerBlock) }) t.Run("bad flags size", func(t *testing.T) { diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index 4b95eee4a..71849a82f 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -104,7 +104,7 @@ func TestServerStartAndShutdown(t *testing.T) { require.True(t, s.transports[0].(*fakeTransp).closed.Load()) err, ok := p.droppedWith.Load().(error) require.True(t, ok) - require.True(t, errors.Is(err, errServerShutdown)) + require.ErrorIs(t, err, errServerShutdown) }) t.Run("with consensus", func(t *testing.T) { s := newTestServer(t, ServerConfig{}) @@ -161,7 +161,7 @@ func TestServerRegisterPeer(t *testing.T) { require.True(t, index >= 0) err, ok := ps[index].droppedWith.Load().(error) require.True(t, ok) - require.True(t, errors.Is(err, errMaxPeers)) + require.ErrorIs(t, err, errMaxPeers) index = (index + 1) % peerCount s.unregister <- peerDrop{ps[index], errIdenticalID} diff --git a/pkg/rpcclient/rpc_test.go b/pkg/rpcclient/rpc_test.go index c60e77ec5..590b82872 100644 --- a/pkg/rpcclient/rpc_test.go +++ b/pkg/rpcclient/rpc_test.go @@ -6,7 +6,6 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "errors" "fmt" "math/big" "net/http" @@ -2013,7 +2012,7 @@ func TestGetNetwork(t *testing.T) { c.getNextRequestID = getTestRequestID // network was not initialised _, err = c.GetNetwork() - require.True(t, errors.Is(err, errNetworkNotInitialized)) + require.ErrorIs(t, err, errNetworkNotInitialized) require.Equal(t, false, c.cache.initDone) }) diff --git a/pkg/rpcclient/wsclient_test.go b/pkg/rpcclient/wsclient_test.go index f414d4c80..7f3db1d27 100644 --- a/pkg/rpcclient/wsclient_test.go +++ b/pkg/rpcclient/wsclient_test.go @@ -3,7 +3,6 @@ package rpcclient import ( "context" "encoding/json" - "errors" "fmt" "net/http" "net/http/httptest" @@ -753,7 +752,7 @@ func TestWS_RequestAfterClose(t *testing.T) { _, err = c.GetBlockCount() }) require.Error(t, err) - require.True(t, errors.Is(err, ErrWSConnLost)) + require.ErrorIs(t, err, ErrWSConnLost) } func TestWSClient_ConnClosedError(t *testing.T) { diff --git a/pkg/services/oracle/neofs/neofs_test.go b/pkg/services/oracle/neofs/neofs_test.go index 03c85db4c..aa3308a32 100644 --- a/pkg/services/oracle/neofs/neofs_test.go +++ b/pkg/services/oracle/neofs/neofs_test.go @@ -1,7 +1,6 @@ package neofs import ( - "errors" "net/url" "testing" @@ -61,7 +60,7 @@ func TestParseNeoFSURL(t *testing.T) { require.NoError(t, err) oa, ps, err := parseNeoFSURL(u) if tc.err != nil { - require.True(t, errors.Is(err, tc.err), "got: %#v", err) + require.ErrorIs(t, err, tc.err) return } require.NoError(t, err) diff --git a/pkg/services/oracle/network_test.go b/pkg/services/oracle/network_test.go index de132508a..b3ba2a96a 100644 --- a/pkg/services/oracle/network_test.go +++ b/pkg/services/oracle/network_test.go @@ -1,7 +1,6 @@ package oracle import ( - "errors" "net" "strings" "testing" @@ -41,8 +40,7 @@ func TestDefaultClient_RestrictedRedirectErr(t *testing.T) { for _, c := range testCases { t.Run(c, func(t *testing.T) { _, err := cl.Get(c) //nolint:bodyclose // It errors out and it's a test. - require.Error(t, err) - require.True(t, errors.Is(err, ErrRestrictedRedirect), err) + require.ErrorIs(t, err, ErrRestrictedRedirect) require.True(t, strings.Contains(err.Error(), "IP is not global unicast"), err) }) } diff --git a/pkg/services/stateroot/service_test.go b/pkg/services/stateroot/service_test.go index 544e30d24..f4e2eb5fd 100644 --- a/pkg/services/stateroot/service_test.go +++ b/pkg/services/stateroot/service_test.go @@ -2,7 +2,6 @@ package stateroot_test import ( "crypto/elliptic" - "errors" "path/filepath" "sort" "testing" @@ -133,7 +132,7 @@ func TestStateRoot(t *testing.T) { require.NoError(t, err) data := testSignStateRoot(t, r, pubs, accInv) err = srv.OnPayload(&payload.Extensible{Data: data}) - require.True(t, errors.Is(err, core.ErrWitnessHashMismatch), "got: %v", err) + require.ErrorIs(t, err, core.ErrWitnessHashMismatch) require.EqualValues(t, 0, bc.GetStateModule().CurrentValidatedHeight()) }) diff --git a/pkg/smartcontract/manifest/standard/comply_test.go b/pkg/smartcontract/manifest/standard/comply_test.go index 360a7c1de..c867411f6 100644 --- a/pkg/smartcontract/manifest/standard/comply_test.go +++ b/pkg/smartcontract/manifest/standard/comply_test.go @@ -1,7 +1,6 @@ package standard import ( - "errors" "testing" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -39,14 +38,14 @@ func TestComplyMissingMethod(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Name = "notafoo" err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrMethodMissing)) + require.ErrorIs(t, err, ErrMethodMissing) } func TestComplyInvalidReturnType(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).ReturnType = smartcontract.VoidType err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrInvalidReturnType)) + require.ErrorIs(t, err, ErrInvalidReturnType) } func TestComplyMethodParameterCount(t *testing.T) { @@ -55,14 +54,14 @@ func TestComplyMethodParameterCount(t *testing.T) { f := m.ABI.GetMethod("foo", -1) f.Parameters = append(f.Parameters, manifest.Parameter{Type: smartcontract.BoolType}) err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrMethodMissing)) + require.ErrorIs(t, err, ErrMethodMissing) }) t.Run("Event", func(t *testing.T) { m := fooMethodBarEvent() ev := m.ABI.GetEvent("bar") ev.Parameters = ev.Parameters[:0] err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrInvalidParameterCount)) + require.ErrorIs(t, err, ErrInvalidParameterCount) }) } @@ -71,13 +70,13 @@ func TestComplyParameterType(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Parameters[0].Type = smartcontract.InteropInterfaceType err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrInvalidParameterType)) + require.ErrorIs(t, err, ErrInvalidParameterType) }) t.Run("Event", func(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetEvent("bar").Parameters[0].Type = smartcontract.InteropInterfaceType err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrInvalidParameterType)) + require.ErrorIs(t, err, ErrInvalidParameterType) }) } @@ -87,7 +86,7 @@ func TestComplyParameterName(t *testing.T) { m.ABI.GetMethod("foo", -1).Parameters[0].Name = "hehe" s := &Standard{Manifest: *fooMethodBarEvent()} err := Comply(m, s) - require.True(t, errors.Is(err, ErrInvalidParameterName)) + require.ErrorIs(t, err, ErrInvalidParameterName) require.NoError(t, ComplyABI(m, s)) }) t.Run("Event", func(t *testing.T) { @@ -95,7 +94,7 @@ func TestComplyParameterName(t *testing.T) { m.ABI.GetEvent("bar").Parameters[0].Name = "hehe" s := &Standard{Manifest: *fooMethodBarEvent()} err := Comply(m, s) - require.True(t, errors.Is(err, ErrInvalidParameterName)) + require.ErrorIs(t, err, ErrInvalidParameterName) require.NoError(t, ComplyABI(m, s)) }) } @@ -104,14 +103,14 @@ func TestMissingEvent(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetEvent("bar").Name = "notabar" err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrEventMissing)) + require.ErrorIs(t, err, ErrEventMissing) } func TestSafeFlag(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Safe = false err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) - require.True(t, errors.Is(err, ErrSafeMethodMismatch)) + require.ErrorIs(t, err, ErrSafeMethodMismatch) } func TestComplyValid(t *testing.T) { diff --git a/pkg/smartcontract/nef/method_token_test.go b/pkg/smartcontract/nef/method_token_test.go index 05072723d..b293ff3d3 100644 --- a/pkg/smartcontract/nef/method_token_test.go +++ b/pkg/smartcontract/nef/method_token_test.go @@ -1,7 +1,6 @@ package nef import ( - "errors" "strings" "testing" @@ -37,7 +36,7 @@ func TestMethodToken_Serializable(t *testing.T) { data, err := testserdes.EncodeBinary(tok) require.NoError(t, err) err = testserdes.DecodeBinary(data, new(MethodToken)) - require.True(t, errors.Is(err, errInvalidMethodName)) + require.ErrorIs(t, err, errInvalidMethodName) }) t.Run("invalid call flag", func(t *testing.T) { tok := getToken() @@ -45,6 +44,6 @@ func TestMethodToken_Serializable(t *testing.T) { data, err := testserdes.EncodeBinary(tok) require.NoError(t, err) err = testserdes.DecodeBinary(data, new(MethodToken)) - require.True(t, errors.Is(err, errInvalidCallFlag)) + require.ErrorIs(t, err, errInvalidCallFlag) }) } diff --git a/pkg/smartcontract/nef/nef_test.go b/pkg/smartcontract/nef/nef_test.go index f265d2ad7..133513276 100644 --- a/pkg/smartcontract/nef/nef_test.go +++ b/pkg/smartcontract/nef/nef_test.go @@ -3,7 +3,6 @@ package nef import ( "encoding/base64" "encoding/json" - "errors" "strconv" "testing" @@ -87,12 +86,12 @@ func TestEncodeDecodeBinary(t *testing.T) { sz := io.GetVarSize(&expected.Header) bytes[sz] = 1 err = testserdes.DecodeBinary(bytes, new(File)) - require.True(t, errors.Is(err, errInvalidReserved), "got: %v", err) + require.ErrorIs(t, err, errInvalidReserved) bytes[sz] = 0 bytes[sz+3] = 1 err = testserdes.DecodeBinary(bytes, new(File)) - require.True(t, errors.Is(err, errInvalidReserved), "got: %v", err) + require.ErrorIs(t, err, errInvalidReserved) }) } diff --git a/pkg/vm/stackitem/json_test.go b/pkg/vm/stackitem/json_test.go index 45227feaf..59cc1d1a0 100644 --- a/pkg/vm/stackitem/json_test.go +++ b/pkg/vm/stackitem/json_test.go @@ -1,7 +1,6 @@ package stackitem import ( - "errors" "math/big" "testing" @@ -56,7 +55,7 @@ func TestFromToJSON(t *testing.T) { require.NoError(t, err) _, err = FromJSON([]byte(js), 3) - require.True(t, errors.Is(err, errTooBigElements), err) + require.ErrorIs(t, err, errTooBigElements) }) }) t.Run("Map", func(t *testing.T) { @@ -79,7 +78,7 @@ func TestFromToJSON(t *testing.T) { require.NoError(t, err) _, err = FromJSON([]byte(js), 4) - require.True(t, errors.Is(err, errTooBigElements), err) + require.ErrorIs(t, err, errTooBigElements) }) }) t.Run("Invalid", func(t *testing.T) { @@ -126,7 +125,7 @@ func TestFromToJSON(t *testing.T) { func testToJSON(t *testing.T, expectedErr error, item Item) { data, err := ToJSON(item) if expectedErr != nil { - require.True(t, errors.Is(err, expectedErr), err) + require.ErrorIs(t, err, expectedErr) return } require.NoError(t, err) @@ -313,16 +312,16 @@ func TestToJSONWithTypesBadCases(t *testing.T) { items[i] = NewBuffer(bigBuf) } _, err := ToJSONWithTypes(NewArray(items)) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on primitive item", func(t *testing.T) { _, err := ToJSONWithTypes(NewBuffer(bigBuf)) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on array element", func(t *testing.T) { b := NewBuffer(bigBuf[:MaxSize/2]) _, err := ToJSONWithTypes(NewArray([]Item{b, b})) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on map key", func(t *testing.T) { m := NewMapWithValue([]MapElement{ @@ -330,7 +329,7 @@ func TestToJSONWithTypesBadCases(t *testing.T) { {NewByteArray(bigBuf), NewBool(true)}, }) _, err := ToJSONWithTypes(m) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on the last byte of array", func(t *testing.T) { // Construct big enough buffer and pad with integer digits @@ -340,7 +339,7 @@ func TestToJSONWithTypesBadCases(t *testing.T) { NewBigInteger(big.NewInt(1234)), }) _, err := ToJSONWithTypes(arr) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on the item prefix", func(t *testing.T) { arr := NewArray([]Item{ @@ -348,7 +347,7 @@ func TestToJSONWithTypesBadCases(t *testing.T) { NewBool(true), }) _, err := ToJSONWithTypes(arr) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on null", func(t *testing.T) { arr := NewArray([]Item{ @@ -356,7 +355,7 @@ func TestToJSONWithTypesBadCases(t *testing.T) { Null{}, }) _, err := ToJSONWithTypes(arr) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on interop", func(t *testing.T) { arr := NewArray([]Item{ @@ -364,17 +363,17 @@ func TestToJSONWithTypesBadCases(t *testing.T) { NewInterop(42), }) _, err := ToJSONWithTypes(arr) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("overflow on cached item", func(t *testing.T) { b := NewArray([]Item{NewByteArray(bigBuf[:MaxSize/2])}) arr := NewArray([]Item{b, b}) _, err := ToJSONWithTypes(arr) - require.True(t, errors.Is(err, errTooBigSize), "got: %v", err) + require.ErrorIs(t, err, errTooBigSize) }) t.Run("invalid type", func(t *testing.T) { _, err := ToJSONWithTypes(nil) - require.True(t, errors.Is(err, ErrUnserializable), "got: %v", err) + require.ErrorIs(t, err, ErrUnserializable) }) } diff --git a/pkg/vm/stackitem/serialization_test.go b/pkg/vm/stackitem/serialization_test.go index 3c0b64190..4722df88b 100644 --- a/pkg/vm/stackitem/serialization_test.go +++ b/pkg/vm/stackitem/serialization_test.go @@ -1,7 +1,6 @@ package stackitem import ( - "errors" "testing" "github.com/nspcc-dev/neo-go/pkg/io" @@ -20,13 +19,13 @@ func TestSerializationMaxErr(t *testing.T) { require.NoError(t, err) _, err = Serialize(aitem) - require.True(t, errors.Is(err, ErrTooBig), err) + require.ErrorIs(t, err, ErrTooBig) } func testSerialize(t *testing.T, expectedErr error, item Item) { data, err := Serialize(item) if expectedErr != nil { - require.True(t, errors.Is(err, expectedErr), err) + require.ErrorIs(t, err, expectedErr) return } require.NoError(t, err) @@ -62,7 +61,7 @@ func TestSerialize(t *testing.T) { data, err := Serialize(newItem(items)) require.NoError(t, err) _, err = Deserialize(data) - require.True(t, errors.Is(err, ErrTooBig), err) + require.ErrorIs(t, err, ErrTooBig) } t.Run("array", func(t *testing.T) { testArray(t, func(items []Item) Item { return NewArray(items) }) @@ -169,7 +168,7 @@ func TestSerialize(t *testing.T) { data, err := Serialize(m) require.NoError(t, err) _, err = Deserialize(data) - require.True(t, errors.Is(err, ErrTooBig), err) + require.ErrorIs(t, err, ErrTooBig) }) } @@ -189,7 +188,7 @@ func TestMapDeserializationError(t *testing.T) { EncodeBinaryProtected(m, w.BinWriter) require.NoError(t, w.Err) _, err := Deserialize(w.Bytes()) - require.True(t, errors.Is(err, ErrInvalidType), err) + require.ErrorIs(t, err, ErrInvalidType) } func TestDeserializeTooManyElements(t *testing.T) { @@ -206,7 +205,7 @@ func TestDeserializeTooManyElements(t *testing.T) { data, err = Serialize(item) require.NoError(t, err) _, err = Deserialize(data) - require.True(t, errors.Is(err, ErrTooBig), err) + require.ErrorIs(t, err, ErrTooBig) } func TestDeserializeLimited(t *testing.T) { @@ -226,7 +225,7 @@ func TestDeserializeLimited(t *testing.T) { require.NoError(t, err) _, err = DeserializeLimited(data, customLimit) require.Error(t, err) - require.True(t, errors.Is(err, ErrTooBig), err) + require.ErrorIs(t, err, ErrTooBig) } func BenchmarkEncodeBinary(b *testing.B) { From 778ddfb277fc0f16617d8aa92482859638032c5e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 10 May 2023 18:55:03 +0300 Subject: [PATCH 060/125] github: automatically attach binaries to the release Close #3001. Signed-off-by: Anna Shaleva --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c062c509f..e453dd35a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,6 +76,12 @@ jobs: path: ./bin/neo-go* if-no-files-found: error + - name: Attach binary to the release as an asset + if: ${{ github.event_name == 'release' }} + run: gh release upload ${{ github.event.release.tag_name }} ./bin/neo-go-${{ matrix.os.bin-name }}-${{ matrix.arch }}${{ (matrix.os.bin-name == 'windows' && '.exe') || '' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + build_image: needs: build_cli name: Build and push docker image From 649b9ac7b04da665d99690017dbf3532763462d0 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 10 May 2023 17:10:56 +0300 Subject: [PATCH 061/125] network: add `neogo_version` metric, deprecate `serv_node_version` Close #2999. Signed-off-by: Anna Shaleva --- ROADMAP.md | 11 ++++++++++- pkg/network/prometheus.go | 30 ++++++++++++++++++++++++++++++ pkg/network/server.go | 2 ++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 0bbaf59eb..bfe2aa845 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -129,4 +129,13 @@ Removal of Peer unmarshalling with string based ports is scheduled for ~Septembe We check struct items count before convert LastGasPerVote to let RPC client be compatible with old versions. -Removal of this compatiblility code is scheduled for Sep-Oct 2023. +Removal of this compatiblility code is scheduled for Sep-Oct 2023. + +## `serv_node_version` Prometheus gauge metric + +This metric is replaced by the new `neogo_version` and `server_id` Prometheus gauge +metrics with proper version formatting. `neogo_version` contains NeoGo version +hidden under `version` label and `server_id` contains network server ID hidden +under `server_id` label. + +Removal of `serv_node_version` is scheduled for Sep-Oct 2023 (~0.105.0 release). diff --git a/pkg/network/prometheus.go b/pkg/network/prometheus.go index 483e877f7..b0ed5982b 100644 --- a/pkg/network/prometheus.go +++ b/pkg/network/prometheus.go @@ -25,6 +25,7 @@ var ( }, ) + // Deprecated: please, use neogoVersion and serverID instead. servAndNodeVersion = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Help: "Server and Node versions", @@ -34,6 +35,22 @@ var ( []string{"description", "value"}, ) + neogoVersion = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Help: "NeoGo version", + Name: "version", + Namespace: "neogo", + }, + []string{"version"}) + + serverID = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Help: "network server ID", + Name: "server_id", + Namespace: "neogo", + }, + []string{"server_id"}) + poolCount = prometheus.NewGauge( prometheus.GaugeOpts{ Help: "Number of available node addresses", @@ -66,6 +83,8 @@ func init() { estimatedNetworkSize, peersConnected, servAndNodeVersion, + neogoVersion, + serverID, poolCount, blockQueueLength, notarypoolUnsortedTx, @@ -102,10 +121,21 @@ func updatePoolCountMetric(pCount int) { func updatePeersConnectedMetric(pConnected int) { peersConnected.Set(float64(pConnected)) } + +// Deprecated: please, use setNeoGoVersion and setSeverID instead. func setServerAndNodeVersions(nodeVer string, serverID string) { servAndNodeVersion.WithLabelValues("Node version: ", nodeVer).Add(0) servAndNodeVersion.WithLabelValues("Server id: ", serverID).Add(0) } + +func setNeoGoVersion(nodeVer string) { + neogoVersion.WithLabelValues(nodeVer).Add(1) +} + +func setSeverID(id string) { + serverID.WithLabelValues(id).Add(1) +} + func addCmdTimeMetric(cmd CommandType, t time.Duration) { // Shouldn't happen, message decoder checks the type, but better safe than sorry. if p2pCmds[cmd] == nil { diff --git a/pkg/network/server.go b/pkg/network/server.go index 4e5fc6363..5a8f7027d 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -285,6 +285,8 @@ func (s *Server) Start() { go tr.Accept() } setServerAndNodeVersions(s.UserAgent, strconv.FormatUint(uint64(s.id), 10)) + setNeoGoVersion(config.Version) + setSeverID(strconv.FormatUint(uint64(s.id), 10)) s.run() } From 4be9e4347aae23923c546c2b027089dc80db7ad1 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 12 May 2023 16:53:57 +0300 Subject: [PATCH 062/125] cli: allow to provide network-specific node config file Close #2978. Signed-off-by: Anna Shaleva --- cli/options/options.go | 21 ++++++++++++++++----- cli/server/server.go | 10 +++++----- cli/server/server_test.go | 26 +++++++++++++++++++------- cli/vm/vm.go | 2 +- docs/cli.md | 4 ++++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/cli/options/options.go b/cli/options/options.go index e5e5f45b3..09bb08572 100644 --- a/cli/options/options.go +++ b/cli/options/options.go @@ -35,9 +35,9 @@ const RPCEndpointFlag = "rpc-endpoint" // Network is a set of flags for choosing the network to operate on // (privnet/mainnet/testnet). var Network = []cli.Flag{ - cli.BoolFlag{Name: "privnet, p", Usage: "use private network configuration"}, - cli.BoolFlag{Name: "mainnet, m", Usage: "use mainnet network configuration"}, - cli.BoolFlag{Name: "testnet, t", Usage: "use testnet network configuration"}, + cli.BoolFlag{Name: "privnet, p", Usage: "use private network configuration (if --config-file option is not specified)"}, + cli.BoolFlag{Name: "mainnet, m", Usage: "use mainnet network configuration (if --config-file option is not specified)"}, + cli.BoolFlag{Name: "testnet, t", Usage: "use testnet network configuration (if --config-file option is not specified)"}, cli.BoolFlag{Name: "unittest", Hidden: true}, } @@ -63,7 +63,14 @@ var Historic = cli.StringFlag{ // Config is a flag for commands that use node configuration. var Config = cli.StringFlag{ Name: "config-path", - Usage: "path to directory with configuration files", + Usage: "path to directory with per-network configuration files (may be overridden by --config-file option for the configuration file)", +} + +// ConfigFile is a flag for commands that use node configuration and provide +// path to the specific config file instead of config path. +var ConfigFile = cli.StringFlag{ + Name: "config-file", + Usage: "path to the node configuration file (overrides --config-path option)", } // Debug is a flag for commands that allow node in debug mode usage. @@ -152,7 +159,11 @@ func GetRPCWithInvoker(gctx context.Context, ctx *cli.Context, signers []transac // GetConfigFromContext looks at the path and the mode flags in the given config and // returns an appropriate config. func GetConfigFromContext(ctx *cli.Context) (config.Config, error) { - configPath := "./config" + var configFile = ctx.String("config-file") + if len(configFile) != 0 { + return config.LoadFile(configFile) + } + var configPath = "./config" if argCp := ctx.String("config-path"); argCp != "" { configPath = argCp } diff --git a/cli/server/server.go b/cli/server/server.go index 1caa4f099..8dd586e9a 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -34,7 +34,7 @@ import ( // NewCommands returns 'node' command. func NewCommands() []cli.Command { - cfgFlags := []cli.Flag{options.Config} + cfgFlags := []cli.Flag{options.Config, options.ConfigFile} cfgFlags = append(cfgFlags, options.Network...) var cfgWithCountFlags = make([]cli.Flag, len(cfgFlags)) copy(cfgWithCountFlags, cfgFlags) @@ -85,7 +85,7 @@ func NewCommands() []cli.Command { { Name: "node", Usage: "start a NeoGo node", - UsageText: "neo-go node [--config-path path] [-d] [-p/-m/-t]", + UsageText: "neo-go node [--config-path path] [-d] [-p/-m/-t] [--config-file file]", Action: startServer, Flags: cfgFlags, }, @@ -96,21 +96,21 @@ func NewCommands() []cli.Command { { Name: "dump", Usage: "dump blocks (starting with block #1) to the file", - UsageText: "neo-go db dump -o file [-s start] [-c count] [--config-path path] [-p/-m/-t]", + UsageText: "neo-go db dump -o file [-s start] [-c count] [--config-path path] [-p/-m/-t] [--config-file file]", Action: dumpDB, Flags: cfgCountOutFlags, }, { Name: "restore", Usage: "restore blocks from the file", - UsageText: "neo-go db restore -i file [--dump] [-n] [-c count] [--config-path path] [-p/-m/-t]", + UsageText: "neo-go db restore -i file [--dump] [-n] [-c count] [--config-path path] [-p/-m/-t] [--config-file file]", Action: restoreDB, Flags: cfgCountInFlags, }, { Name: "reset", Usage: "reset database to the previous state", - UsageText: "neo-go db reset --height height [--config-path path] [-p/-m/-t]", + UsageText: "neo-go db reset --height height [--config-path path] [-p/-m/-t] [--config-file file]", Action: resetDB, Flags: cfgHeightFlags, }, diff --git a/cli/server/server_test.go b/cli/server/server_test.go index 5a7a36948..62ff9b11b 100644 --- a/cli/server/server_test.go +++ b/cli/server/server_test.go @@ -30,13 +30,25 @@ func init() { } func TestGetConfigFromContext(t *testing.T) { - set := flag.NewFlagSet("flagSet", flag.ExitOnError) - set.String("config-path", "../../config", "") - set.Bool("testnet", true, "") - ctx := cli.NewContext(cli.NewApp(), set, nil) - cfg, err := options.GetConfigFromContext(ctx) - require.NoError(t, err) - require.Equal(t, netmode.TestNet, cfg.ProtocolConfiguration.Magic) + t.Run("config-path", func(t *testing.T) { + set := flag.NewFlagSet("flagSet", flag.ExitOnError) + set.String("config-path", "../../config", "") + set.Bool("testnet", true, "") + ctx := cli.NewContext(cli.NewApp(), set, nil) + cfg, err := options.GetConfigFromContext(ctx) + require.NoError(t, err) + require.Equal(t, netmode.TestNet, cfg.ProtocolConfiguration.Magic) + }) + t.Run("config-file", func(t *testing.T) { + set := flag.NewFlagSet("flagSet", flag.ExitOnError) + set.String("config-path", "../../config", "") + set.Bool("testnet", true, "") + set.String("config-file", "../../config/protocol.testnet.yml", "") + ctx := cli.NewContext(cli.NewApp(), set, nil) + cfg, err := options.GetConfigFromContext(ctx) + require.NoError(t, err) + require.Equal(t, netmode.TestNet, cfg.ProtocolConfiguration.Magic) + }) } func TestHandleLoggingParams(t *testing.T) { diff --git a/cli/vm/vm.go b/cli/vm/vm.go index 23b9938de..89dd351bb 100644 --- a/cli/vm/vm.go +++ b/cli/vm/vm.go @@ -13,7 +13,7 @@ import ( // NewCommands returns 'vm' command. func NewCommands() []cli.Command { - cfgFlags := []cli.Flag{options.Config} + cfgFlags := []cli.Flag{options.Config, options.ConfigFile} cfgFlags = append(cfgFlags, options.Network...) return []cli.Command{{ Name: "vm", diff --git a/docs/cli.md b/docs/cli.md index 310ad9562..1f734ad07 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -35,6 +35,10 @@ If you want to use some non-default configuration directory path, specify The file loaded is chosen automatically depending on network mode flag. +Or just provide path to the configuration file using `--config-file` flag: + +`./bin/neo-go node --config-file /user/yourConfigPath/yourConfigFile.yml` + Refer to the [node configuration documentation](./node-configuration.md) for detailed configuration file description. From 8599e25fc398c075f39c3f2a8a64abf0521c1d6a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 16 May 2023 16:01:36 +0300 Subject: [PATCH 063/125] gomod: fetch dBFT update Send PrepareRequest on timeout only: https://github.com/nspcc-dev/dbft/pull/75. Signed-off-by: Anna Shaleva --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b93aba5b..10305632c 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/holiman/uint256 v1.2.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/mr-tron/base58 v1.2.0 - github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd + github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8 diff --git a/go.sum b/go.sum index 5fbce655d..a49806751 100644 --- a/go.sum +++ b/go.sum @@ -211,8 +211,8 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd h1:PYJbdSrB4S2Sp5e28CD0pxGE5xsCGO/6DZVQtBnllRc= -github.com/nspcc-dev/dbft v0.0.0-20230404091436-0108387748cd/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= +github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c h1:uyK5aLbAhrnZtnvobJLN24gGUrlxIJAAFqiWl+liZuo= +github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y= From 8e085d3ca3a2e760c6d69f84bb78280595f5cceb Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 15 May 2023 18:03:46 +0300 Subject: [PATCH 064/125] vm: allow to make stackitem from *Uint160 and *Uint256 Signed-off-by: Anna Shaleva --- pkg/vm/stackitem/item.go | 10 ++++++++++ pkg/vm/stackitem/item_test.go | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/pkg/vm/stackitem/item.go b/pkg/vm/stackitem/item.go index 8e5952a46..7f86879b5 100644 --- a/pkg/vm/stackitem/item.go +++ b/pkg/vm/stackitem/item.go @@ -132,6 +132,16 @@ func Make(v any) Item { return Make(val.BytesBE()) case util.Uint256: return Make(val.BytesBE()) + case *util.Uint160: + if val == nil { + return Null{} + } + return Make(*val) + case *util.Uint256: + if val == nil { + return Null{} + } + return Make(*val) case nil: return Null{} default: diff --git a/pkg/vm/stackitem/item_test.go b/pkg/vm/stackitem/item_test.go index c90763b84..afdfee213 100644 --- a/pkg/vm/stackitem/item_test.go +++ b/pkg/vm/stackitem/item_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -81,6 +82,22 @@ var makeStackItemTestCases = []struct { input: nil, result: Null{}, }, + { + input: &util.Uint160{1, 2, 3}, + result: NewByteArray(util.Uint160{1, 2, 3}.BytesBE()), + }, + { + input: &util.Uint256{1, 2, 3}, + result: NewByteArray(util.Uint256{1, 2, 3}.BytesBE()), + }, + { + input: (*util.Uint160)(nil), + result: Null{}, + }, + { + input: (*util.Uint256)(nil), + result: Null{}, + }, } var makeStackItemErrorCases = []struct { From 15138b2004a080213912ad46556dff2254c4658e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 15 May 2023 18:04:32 +0300 Subject: [PATCH 065/125] vm: allow to emit convertible Signed-off-by: Anna Shaleva --- pkg/core/native/native_test/notary_test.go | 23 +- pkg/rpcclient/nep11/base_test.go | 40 +++- pkg/rpcclient/nep11/divisible_test.go | 24 +- pkg/rpcclient/nep17/nep17_test.go | 40 +++- pkg/rpcclient/notary/contract.go | 52 ++++ pkg/rpcclient/notary/contract_test.go | 75 ++++++ pkg/rpcclient/notary/doc_test.go | 2 +- pkg/smartcontract/builder.go | 7 +- pkg/vm/emit/emit.go | 72 +++++- pkg/vm/emit/emit_test.go | 262 ++++++++++++++++++++- 10 files changed, 574 insertions(+), 23 deletions(-) diff --git a/pkg/core/native/native_test/notary_test.go b/pkg/core/native/native_test/notary_test.go index c4a58ac71..1f846cd3e 100644 --- a/pkg/core/native/native_test/notary_test.go +++ b/pkg/core/native/native_test/notary_test.go @@ -12,6 +12,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/neotest" "github.com/nspcc-dev/neo-go/pkg/neotest/chain" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/notary" "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" @@ -75,19 +76,19 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, false, "lockDepositUntil", multisigHash, int64(depositLock+1)) // `onPayment`: bad token - neoCommitteeInvoker.InvokeFail(t, "only GAS can be accepted for deposit", "transfer", multisigHash, notaryHash, int64(1), []any{nil, int64(depositLock)}) + neoCommitteeInvoker.InvokeFail(t, "only GAS can be accepted for deposit", "transfer", multisigHash, notaryHash, int64(1), ¬ary.OnNEP17PaymentData{Till: uint32(depositLock)}) // `onPayment`: insufficient first deposit - gasCommitteeInvoker.InvokeFail(t, "first deposit can not be less then", "transfer", multisigHash, notaryHash, int64(2*feePerKey-1), []any{nil, int64(depositLock)}) + gasCommitteeInvoker.InvokeFail(t, "first deposit can not be less then", "transfer", multisigHash, notaryHash, int64(2*feePerKey-1), ¬ary.OnNEP17PaymentData{Till: uint32(depositLock)}) // `onPayment`: invalid `data` (missing `till` parameter) gasCommitteeInvoker.InvokeFail(t, "`data` parameter should be an array of 2 elements", "transfer", multisigHash, notaryHash, 2*feePerKey, []any{nil}) // `onPayment`: invalid `data` (outdated `till` parameter) - gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, 2*feePerKey, []any{nil, int64(0)}) + gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, 2*feePerKey, ¬ary.OnNEP17PaymentData{}) // `onPayment`: good - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, []any{nil, int64(depositLock)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, ¬ary.OnNEP17PaymentData{Till: uint32(depositLock)}) checkBalanceOf(t, notaryHash, 2*feePerKey) // `expirationOf`: check `till` was set @@ -97,7 +98,7 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, 2*feePerKey, "balanceOf", multisigHash) // `onPayment`: good second deposit and explicit `to` paramenter - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, []any{multisigHash, int64(depositLock + 1)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, ¬ary.OnNEP17PaymentData{Account: &multisigHash, Till: uint32(depositLock + 1)}) checkBalanceOf(t, notaryHash, 3*feePerKey) // `balanceOf`: check deposited amount for the multisig account @@ -107,17 +108,17 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, depositLock+1, "expirationOf", multisigHash) // `onPayment`: empty payment, should fail because `till` less then the previous one - gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the previous value", "transfer", multisigHash, notaryHash, int64(0), []any{multisigHash, int64(depositLock)}) + gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the previous value", "transfer", multisigHash, notaryHash, int64(0), ¬ary.OnNEP17PaymentData{Account: &multisigHash, Till: uint32(depositLock)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, depositLock+1, "expirationOf", multisigHash) // `onPayment`: empty payment, should fail because `till` less then the chain height - gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, int64(0), []any{multisigHash, int64(1)}) + gasCommitteeInvoker.InvokeFail(t, "`till` shouldn't be less then the chain's height", "transfer", multisigHash, notaryHash, int64(0), ¬ary.OnNEP17PaymentData{Account: &multisigHash, Till: uint32(1)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, depositLock+1, "expirationOf", multisigHash) // `onPayment`: empty payment, should successfully update `till` - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, int64(0), []any{multisigHash, int64(depositLock + 2)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, int64(0), ¬ary.OnNEP17PaymentData{Account: &multisigHash, Till: uint32(depositLock + 2)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, depositLock+2, "expirationOf", multisigHash) @@ -159,12 +160,12 @@ func TestNotary_Pipeline(t *testing.T) { notaryCommitteeInvoker.Invoke(t, false, "withdraw", multisigHash, accHash) // `onPayment`: good first deposit to other account, should set default `till` even if other `till` value is provided - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, []any{accHash, int64(math.MaxUint32 - 1)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, 2*feePerKey, ¬ary.OnNEP17PaymentData{Account: &accHash, Till: uint32(math.MaxUint32 - 1)}) checkBalanceOf(t, notaryHash, 2*feePerKey) notaryCommitteeInvoker.Invoke(t, 5760+e.Chain.BlockHeight()-1, "expirationOf", accHash) // `onPayment`: good second deposit to other account, shouldn't update `till` even if other `till` value is provided - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, []any{accHash, int64(math.MaxUint32 - 1)}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, feePerKey, ¬ary.OnNEP17PaymentData{Account: &accHash, Till: uint32(math.MaxUint32 - 1)}) checkBalanceOf(t, notaryHash, 3*feePerKey) notaryCommitteeInvoker.Invoke(t, 5760+e.Chain.BlockHeight()-3, "expirationOf", accHash) } @@ -201,7 +202,7 @@ func TestNotary_NotaryNodesReward(t *testing.T) { if !spendFullDeposit { depositAmount += 1_0000 } - gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, depositAmount, []any{multisigHash, e.Chain.BlockHeight() + 1}) + gasCommitteeInvoker.Invoke(t, true, "transfer", multisigHash, notaryHash, depositAmount, ¬ary.OnNEP17PaymentData{Account: &multisigHash, Till: e.Chain.BlockHeight() + 1}) // send transaction with Notary contract as a sender tx := transaction.New([]byte{byte(opcode.PUSH1)}, 1_000_000) diff --git a/pkg/rpcclient/nep11/base_test.go b/pkg/rpcclient/nep11/base_test.go index 9ba9b3aa2..0aacd9f73 100644 --- a/pkg/rpcclient/nep11/base_test.go +++ b/pkg/rpcclient/nep11/base_test.go @@ -217,6 +217,22 @@ func TestReaderTokensOf(t *testing.T) { } } +type tData struct { + someInt int + someString string +} + +func (d *tData) ToStackItem() (stackitem.Item, error) { + return stackitem.NewStruct([]stackitem.Item{ + stackitem.Make(d.someInt), + stackitem.Make(d.someString), + }), nil +} + +func (d *tData) FromStackItem(si stackitem.Item) error { + panic("TODO") +} + func TestTokenTransfer(t *testing.T) { ta := new(testAct) tok := NewBase(ta, util.Uint160{1, 2, 3}) @@ -233,7 +249,18 @@ func TestTokenTransfer(t *testing.T) { require.Equal(t, ta.txh, h) require.Equal(t, ta.vub, vub) - _, _, err = tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, stackitem.NewMap()) + ta.err = nil + ta.txh = util.Uint256{1, 2, 3} + ta.vub = 42 + h, vub, err = tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, &tData{ + someInt: 5, + someString: "ur", + }) + require.NoError(t, err) + require.Equal(t, ta.txh, h) + require.Equal(t, ta.vub, vub) + + _, _, err = tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, stackitem.NewPointer(123, []byte{123})) require.Error(t, err) } @@ -255,7 +282,16 @@ func TestTokenTransferTransaction(t *testing.T) { require.NoError(t, err) require.Equal(t, ta.tx, tx) - _, err = fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, stackitem.NewMap()) + ta.err = nil + ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42} + tx, err = fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, &tData{ + someInt: 5, + someString: "ur", + }) + require.NoError(t, err) + require.Equal(t, ta.tx, tx) + + _, err = fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, stackitem.NewInterop(nil)) require.Error(t, err) } } diff --git a/pkg/rpcclient/nep11/divisible_test.go b/pkg/rpcclient/nep11/divisible_test.go index dd9a1e26d..84be9469b 100644 --- a/pkg/rpcclient/nep11/divisible_test.go +++ b/pkg/rpcclient/nep11/divisible_test.go @@ -190,7 +190,18 @@ func TestDivisibleTransfer(t *testing.T) { require.Equal(t, ta.txh, h) require.Equal(t, ta.vub, vub) - _, _, err = tok.TransferD(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}, big.NewInt(10), []byte{3, 2, 1}, stackitem.NewMap()) + ta.err = nil + ta.txh = util.Uint256{1, 2, 3} + ta.vub = 42 + h, vub, err = tok.TransferD(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}, big.NewInt(10), []byte{3, 2, 1}, &tData{ + someInt: 5, + someString: "ur", + }) + require.NoError(t, err) + require.Equal(t, ta.txh, h) + require.Equal(t, ta.vub, vub) + + _, _, err = tok.TransferD(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}, big.NewInt(10), []byte{3, 2, 1}, stackitem.NewInterop(nil)) require.Error(t, err) } @@ -212,7 +223,16 @@ func TestDivisibleTransferTransaction(t *testing.T) { require.NoError(t, err) require.Equal(t, ta.tx, tx) - _, err = fun(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}, big.NewInt(10), []byte{3, 2, 1}, stackitem.NewMap()) + ta.err = nil + ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42} + tx, err = fun(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}, big.NewInt(10), []byte{3, 2, 1}, &tData{ + someInt: 5, + someString: "ur", + }) + require.NoError(t, err) + require.Equal(t, ta.tx, tx) + + _, err = fun(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}, big.NewInt(10), []byte{3, 2, 1}, stackitem.NewInterop(nil)) require.Error(t, err) } } diff --git a/pkg/rpcclient/nep17/nep17_test.go b/pkg/rpcclient/nep17/nep17_test.go index 0fe260cbd..ca9908646 100644 --- a/pkg/rpcclient/nep17/nep17_test.go +++ b/pkg/rpcclient/nep17/nep17_test.go @@ -62,6 +62,22 @@ func TestReaderBalanceOf(t *testing.T) { require.Error(t, err) } +type tData struct { + someInt int + someString string +} + +func (d *tData) ToStackItem() (stackitem.Item, error) { + return stackitem.NewStruct([]stackitem.Item{ + stackitem.Make(d.someInt), + stackitem.Make(d.someString), + }), nil +} + +func (d *tData) FromStackItem(si stackitem.Item) error { + panic("TODO") +} + func TestTokenTransfer(t *testing.T) { ta := new(testAct) tok := New(ta, util.Uint160{1, 2, 3}) @@ -85,7 +101,18 @@ func TestTokenTransfer(t *testing.T) { require.Equal(t, ta.txh, h) require.Equal(t, ta.vub, vub) - _, _, err = fun(util.Uint160{3, 2, 1}, util.Uint160{3, 2, 1}, big.NewInt(1), stackitem.NewMap()) + ta.err = nil + ta.txh = util.Uint256{1, 2, 3} + ta.vub = 42 + h, vub, err = fun(util.Uint160{3, 2, 1}, util.Uint160{3, 2, 1}, big.NewInt(1), &tData{ + someInt: 5, + someString: "ur", + }) + require.NoError(t, err) + require.Equal(t, ta.txh, h) + require.Equal(t, ta.vub, vub) + + _, _, err = fun(util.Uint160{3, 2, 1}, util.Uint160{3, 2, 1}, big.NewInt(1), stackitem.NewInterop(nil)) require.Error(t, err) }) } @@ -120,7 +147,16 @@ func TestTokenTransferTransaction(t *testing.T) { require.NoError(t, err) require.Equal(t, ta.tx, tx) - _, err = fun(util.Uint160{3, 2, 1}, util.Uint160{3, 2, 1}, big.NewInt(1), stackitem.NewMap()) + ta.err = nil + ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42} + tx, err = fun(util.Uint160{3, 2, 1}, util.Uint160{3, 2, 1}, big.NewInt(1), &tData{ + someInt: 5, + someString: "ur", + }) + require.NoError(t, err) + require.Equal(t, ta.tx, tx) + + _, err = fun(util.Uint160{3, 2, 1}, util.Uint160{3, 2, 1}, big.NewInt(1), stackitem.NewInterop(nil)) require.Error(t, err) }) } diff --git a/pkg/rpcclient/notary/contract.go b/pkg/rpcclient/notary/contract.go index 749003f1c..3ded21bc5 100644 --- a/pkg/rpcclient/notary/contract.go +++ b/pkg/rpcclient/notary/contract.go @@ -8,6 +8,8 @@ creation of notary requests. package notary import ( + "errors" + "fmt" "math" "math/big" @@ -18,6 +20,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) const ( @@ -68,6 +71,10 @@ type OnNEP17PaymentData struct { Till uint32 } +// OnNEP17PaymentData have to implement stackitem.Convertible interface to be +// compatible with emit package. +var _ = stackitem.Convertible(&OnNEP17PaymentData{}) + // Hash stores the hash of the native Notary contract. var Hash = state.CreateNativeContractHash(nativenames.Notary) @@ -234,3 +241,48 @@ func withdrawScript(from util.Uint160, to util.Uint160) []byte { script, _ := smartcontract.CreateCallWithAssertScript(Hash, "withdraw", from.BytesBE(), to.BytesBE()) return script } + +// ToStackItem implements stackitem.Convertible interface. +func (d *OnNEP17PaymentData) ToStackItem() (stackitem.Item, error) { + return stackitem.NewArray([]stackitem.Item{ + stackitem.Make(d.Account), + stackitem.Make(d.Till), + }), nil +} + +// FromStackItem implements stackitem.Convertible interface. +func (d *OnNEP17PaymentData) FromStackItem(si stackitem.Item) error { + arr, ok := si.Value().([]stackitem.Item) + if !ok { + return fmt.Errorf("unexpected stackitem type: %s", si.Type()) + } + if len(arr) != 2 { + return fmt.Errorf("unexpected number of fields: %d vs %d", len(arr), 2) + } + + if arr[0] != stackitem.Item(stackitem.Null{}) { + accBytes, err := arr[0].TryBytes() + if err != nil { + return fmt.Errorf("failed to retrieve account bytes: %w", err) + } + acc, err := util.Uint160DecodeBytesBE(accBytes) + if err != nil { + return fmt.Errorf("failed to decode account bytes: %w", err) + } + d.Account = &acc + } + till, err := arr[1].TryInteger() + if err != nil { + return fmt.Errorf("failed to retrieve till: %w", err) + } + if !till.IsInt64() { + return errors.New("till is not an int64") + } + val := till.Int64() + if val > math.MaxUint32 { + return fmt.Errorf("till is larger than max uint32 value: %d", val) + } + d.Till = uint32(val) + + return nil +} diff --git a/pkg/rpcclient/notary/contract_test.go b/pkg/rpcclient/notary/contract_test.go index 1e50f8db5..336c6ce88 100644 --- a/pkg/rpcclient/notary/contract_test.go +++ b/pkg/rpcclient/notary/contract_test.go @@ -2,9 +2,12 @@ package notary import ( "errors" + "math" "math/big" + "strings" "testing" + "github.com/nspcc-dev/neo-go/internal/testserdes" "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/util" @@ -197,3 +200,75 @@ func TestTxMakers(t *testing.T) { }) } } + +func TestOnNEP17PaymentData_Convertible(t *testing.T) { + t.Run("non-empty owner", func(t *testing.T) { + d := &OnNEP17PaymentData{ + Account: &util.Uint160{1, 2, 3}, + Till: 123, + } + testserdes.ToFromStackItem(t, d, new(OnNEP17PaymentData)) + }) + t.Run("empty owner", func(t *testing.T) { + d := &OnNEP17PaymentData{ + Account: nil, + Till: 123, + } + testserdes.ToFromStackItem(t, d, new(OnNEP17PaymentData)) + }) +} + +func TestOnNEP17PaymentDataToStackItem(t *testing.T) { + testCases := map[string]struct { + data *OnNEP17PaymentData + expected stackitem.Item + }{ + "non-empty owner": { + data: &OnNEP17PaymentData{ + Account: &util.Uint160{1, 2, 3}, + Till: 123, + }, + expected: stackitem.NewArray([]stackitem.Item{ + stackitem.Make(util.Uint160{1, 2, 3}), + stackitem.Make(123), + }), + }, + "empty owner": { + data: &OnNEP17PaymentData{ + Account: nil, + Till: 123, + }, + expected: stackitem.NewArray([]stackitem.Item{ + stackitem.Null{}, + stackitem.Make(123), + }), + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + actual, err := tc.data.ToStackItem() + require.NoError(t, err) + require.Equal(t, tc.expected, actual) + }) + } +} + +func TestOnNEP17PaymentData_FromStackItem(t *testing.T) { + errCases := map[string]stackitem.Item{ + "unexpected stackitem type": stackitem.NewBool(true), + "unexpected number of fields": stackitem.NewArray([]stackitem.Item{stackitem.NewBool(true)}), + "failed to retrieve account bytes": stackitem.NewArray([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Make(1)}), + "failed to decode account bytes": stackitem.NewArray([]stackitem.Item{stackitem.Make([]byte{1}), stackitem.Make(1)}), + "failed to retrieve till": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.NewInterop(nil)}), + "till is not an int64": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.NewBigInteger(new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)))}), + "till is larger than max uint32 value": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.Make(math.MaxUint32 + 1)}), + } + for name, errCase := range errCases { + t.Run(name, func(t *testing.T) { + d := new(OnNEP17PaymentData) + err := d.FromStackItem(errCase) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), name), name) + }) + } +} diff --git a/pkg/rpcclient/notary/doc_test.go b/pkg/rpcclient/notary/doc_test.go index 33e2524f8..fa6f6909a 100644 --- a/pkg/rpcclient/notary/doc_test.go +++ b/pkg/rpcclient/notary/doc_test.go @@ -32,7 +32,7 @@ func ExampleActor() { // Transfer some GAS to the Notary contract to be able to send notary requests // from the first account. gasSingle := gas.New(single) - txid, vub, _ := gasSingle.Transfer(single.Sender(), notary.Hash, big.NewInt(10_0000_0000), notary.OnNEP17PaymentData{Till: 10000000}) + txid, vub, _ := gasSingle.Transfer(single.Sender(), notary.Hash, big.NewInt(10_0000_0000), ¬ary.OnNEP17PaymentData{Till: 10000000}) var depositOK bool // Wait for transaction to be persisted, either it gets in and we get diff --git a/pkg/smartcontract/builder.go b/pkg/smartcontract/builder.go index 6d5d03331..016dd5dd5 100644 --- a/pkg/smartcontract/builder.go +++ b/pkg/smartcontract/builder.go @@ -41,9 +41,10 @@ func NewBuilder() *Builder { // InvokeMethod is the most generic contract method invoker, the code it produces // packs all of the arguments given into an array and calls some method of the -// contract. The correctness of this invocation (number and type of parameters) is -// out of scope of this method, as well as return value, if contract's method returns -// something this value just remains on the execution stack. +// contract. It accepts as parameters everything that emit.Array accepts. The +// correctness of this invocation (number and type of parameters) is out of scope +// of this method, as well as return value, if contract's method returns something +// this value just remains on the execution stack. func (b *Builder) InvokeMethod(contract util.Uint160, method string, params ...any) { emit.AppCall(b.bw.BinWriter, contract, method, callflag.All, params...) } diff --git a/pkg/vm/emit/emit.go b/pkg/vm/emit/emit.go index b79fcdeac..4cae72f65 100644 --- a/pkg/vm/emit/emit.go +++ b/pkg/vm/emit/emit.go @@ -98,7 +98,16 @@ func bigInt(w *io.BinWriter, n *big.Int, trySmall bool) { w.WriteBytes(padRight(1<= 0; i-- { + StackItem(w, arr[i]) + } + + Int(w, int64(len(arr))) + Opcodes(w, opcode.PACKSTRUCT) + case stackitem.MapT: + arr := si.Value().([]stackitem.MapElement) + for i := len(arr) - 1; i >= 0; i-- { + StackItem(w, arr[i].Value) + StackItem(w, arr[i].Key) + } + + Int(w, int64(len(arr))) + Opcodes(w, opcode.PACKMAP) + default: + w.Err = fmt.Errorf("%s is unsuppoted", t) + return + } +} + // String emits a string to the given buffer. func String(w *io.BinWriter, s string) { Bytes(w, []byte(s)) diff --git a/pkg/vm/emit/emit_test.go b/pkg/vm/emit/emit_test.go index 63b35cfdb..d19c75962 100644 --- a/pkg/vm/emit/emit_test.go +++ b/pkg/vm/emit/emit_test.go @@ -5,6 +5,7 @@ import ( "errors" "math" "math/big" + "strings" "testing" "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" @@ -223,7 +224,32 @@ func TestEmitArray(t *testing.T) { u256 := util.Uint256{1, 2, 3} veryBig := new(big.Int).SetUint64(math.MaxUint64) veryBig.Add(veryBig, big.NewInt(1)) - Array(buf.BinWriter, p160, p256, &u160, &u256, u160, u256, big.NewInt(0), veryBig, + Array(buf.BinWriter, + stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.Make(1), + Value: stackitem.Make("str1"), + }, + { + Key: stackitem.Make(2), + Value: stackitem.Make("str2"), + }, + }), + stackitem.NewStruct([]stackitem.Item{ + stackitem.Make(4), + stackitem.Make("str"), + }), + &ConvertibleStruct{ + SomeInt: 5, + SomeString: "str", + }, + stackitem.Make(5), + stackitem.Make("str"), + stackitem.NewArray([]stackitem.Item{ + stackitem.Make(true), + stackitem.Make("str"), + }), + p160, p256, &u160, &u256, u160, u256, big.NewInt(0), veryBig, []any{int64(1), int64(2)}, nil, int64(1), "str", false, true, []byte{0xCA, 0xFE}) require.NoError(t, buf.Err) @@ -259,6 +285,52 @@ func TestEmitArray(t *testing.T) { assert.EqualValues(t, u160.BytesBE(), res[127:147]) assert.EqualValues(t, opcode.PUSHNULL, res[147]) assert.EqualValues(t, opcode.PUSHNULL, res[148]) + // Array of two stackitems: + assert.EqualValues(t, opcode.PUSHDATA1, res[149]) + assert.EqualValues(t, 3, res[150]) + assert.EqualValues(t, []byte("str"), res[151:154]) + assert.EqualValues(t, opcode.PUSHT, res[154]) + assert.EqualValues(t, opcode.PUSH2, res[155]) + assert.EqualValues(t, opcode.PACK, res[156]) + // ByteString stackitem ("str"): + assert.EqualValues(t, opcode.PUSHDATA1, res[157]) + assert.EqualValues(t, 3, res[158]) + assert.EqualValues(t, []byte("str"), res[159:162]) + // Integer stackitem (5): + assert.EqualValues(t, opcode.PUSH5, res[162]) + // Convertible struct: + assert.EqualValues(t, opcode.PUSHDATA1, res[163]) + assert.EqualValues(t, 3, res[164]) + assert.EqualValues(t, []byte("str"), res[165:168]) + assert.EqualValues(t, opcode.PUSH5, res[168]) + assert.EqualValues(t, opcode.PUSH2, res[169]) + assert.EqualValues(t, opcode.PACK, res[170]) + // Struct stackitem (4, "str") + assert.EqualValues(t, opcode.PUSHDATA1, res[171]) + assert.EqualValues(t, 3, res[172]) + assert.EqualValues(t, []byte("str"), res[173:176]) + assert.EqualValues(t, opcode.PUSH4, res[176]) + assert.EqualValues(t, opcode.PUSH2, res[177]) + assert.EqualValues(t, opcode.PACKSTRUCT, res[178]) + // Map stackitem (1:"str1", 2:"str2") + assert.EqualValues(t, opcode.PUSHDATA1, res[179]) + assert.EqualValues(t, 4, res[180]) + assert.EqualValues(t, []byte("str2"), res[181:185]) + assert.EqualValues(t, opcode.PUSH2, res[185]) + assert.EqualValues(t, opcode.PUSHDATA1, res[186]) + assert.EqualValues(t, 4, res[187]) + assert.EqualValues(t, []byte("str1"), res[188:192]) + assert.EqualValues(t, opcode.PUSH1, res[192]) + assert.EqualValues(t, opcode.PUSH2, res[193]) + assert.EqualValues(t, opcode.PACKMAP, res[194]) + + // Values packing: + assert.EqualValues(t, opcode.PUSHINT8, res[195]) + assert.EqualValues(t, byte(21), res[196]) + assert.EqualValues(t, opcode.PACK, res[197]) + + // Overall script length: + assert.EqualValues(t, 198, len(res)) }) t.Run("empty", func(t *testing.T) { @@ -374,3 +446,191 @@ func TestEmitCall(t *testing.T) { label := binary.LittleEndian.Uint16(result[1:3]) assert.Equal(t, label, uint16(100)) } + +func TestEmitStackitem(t *testing.T) { + t.Run("good", func(t *testing.T) { + buf := io.NewBufBinWriter() + itms := []stackitem.Item{ + stackitem.Make(true), + stackitem.Make(false), + stackitem.Make(5), + stackitem.Make("str"), + stackitem.Make([]stackitem.Item{ + stackitem.Make(true), + stackitem.Make([]stackitem.Item{ + stackitem.Make(1), + stackitem.Make("str"), + }), + }), + stackitem.NewStruct([]stackitem.Item{ + stackitem.Make(true), + stackitem.Make(7), + }), + stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.Make(7), + Value: stackitem.Make("str1"), + }, + { + Key: stackitem.Make(8), + Value: stackitem.Make("str2"), + }, + }), + stackitem.Null{}, + } + for _, si := range itms { + StackItem(buf.BinWriter, si) + } + require.NoError(t, buf.Err) + res := buf.Bytes() + + // Single values: + assert.EqualValues(t, opcode.PUSHT, res[0]) + assert.EqualValues(t, opcode.PUSHF, res[1]) + assert.EqualValues(t, opcode.PUSH5, res[2]) + assert.EqualValues(t, opcode.PUSHDATA1, res[3]) + assert.EqualValues(t, 3, res[4]) + assert.EqualValues(t, []byte("str"), res[5:8]) + // Nested array: + assert.EqualValues(t, opcode.PUSHDATA1, res[8]) + assert.EqualValues(t, 3, res[9]) + assert.EqualValues(t, []byte("str"), res[10:13]) + assert.EqualValues(t, opcode.PUSH1, res[13]) + assert.EqualValues(t, opcode.PUSH2, res[14]) + assert.EqualValues(t, opcode.PACK, res[15]) + assert.EqualValues(t, opcode.PUSHT, res[16]) + assert.EqualValues(t, opcode.PUSH2, res[17]) + assert.EqualValues(t, opcode.PACK, res[18]) + // Struct (true, 7): + assert.EqualValues(t, opcode.PUSH7, res[19]) + assert.EqualValues(t, opcode.PUSHT, res[20]) + assert.EqualValues(t, opcode.PUSH2, res[21]) + assert.EqualValues(t, opcode.PACKSTRUCT, res[22]) + // Map (7:"str1", 8:"str2"): + assert.EqualValues(t, opcode.PUSHDATA1, res[23]) + assert.EqualValues(t, 4, res[24]) + assert.EqualValues(t, []byte("str2"), res[25:29]) + assert.EqualValues(t, opcode.PUSH8, res[29]) + assert.EqualValues(t, opcode.PUSHDATA1, res[30]) + assert.EqualValues(t, 4, res[31]) + assert.EqualValues(t, []byte("str1"), res[32:36]) + assert.EqualValues(t, opcode.PUSH7, res[36]) + assert.EqualValues(t, opcode.PUSH2, res[37]) + assert.EqualValues(t, opcode.PACKMAP, res[38]) + // Null: + assert.EqualValues(t, opcode.PUSHNULL, res[39]) + + // Overall script length: + require.Equal(t, 40, len(res)) + }) + + t.Run("unsupported", func(t *testing.T) { + itms := []stackitem.Item{ + stackitem.NewInterop(nil), + stackitem.NewPointer(123, []byte{123}), + } + for _, si := range itms { + buf := io.NewBufBinWriter() + StackItem(buf.BinWriter, si) + require.Error(t, buf.Err) + } + }) + + t.Run("invalid any", func(t *testing.T) { + buf := io.NewBufBinWriter() + StackItem(buf.BinWriter, StrangeStackItem{}) + actualErr := buf.Err + require.Error(t, actualErr) + require.True(t, strings.Contains(actualErr.Error(), "only nil value supported"), actualErr.Error()) + }) +} + +type StrangeStackItem struct{} + +var _ = stackitem.Item(StrangeStackItem{}) + +func (StrangeStackItem) Value() any { + return struct{}{} +} +func (StrangeStackItem) Type() stackitem.Type { + return stackitem.AnyT +} +func (StrangeStackItem) String() string { + panic("TODO") +} +func (StrangeStackItem) Dup() stackitem.Item { + panic("TODO") +} +func (StrangeStackItem) TryBool() (bool, error) { + panic("TODO") +} +func (StrangeStackItem) TryBytes() ([]byte, error) { + panic("TODO") +} +func (StrangeStackItem) TryInteger() (*big.Int, error) { + panic("TODO") +} +func (StrangeStackItem) Equals(stackitem.Item) bool { + panic("TODO") +} +func (StrangeStackItem) Convert(stackitem.Type) (stackitem.Item, error) { + panic("TODO") +} + +type ConvertibleStruct struct { + SomeInt int + SomeString string + err error +} + +var _ = stackitem.Convertible(&ConvertibleStruct{}) + +func (s *ConvertibleStruct) ToStackItem() (stackitem.Item, error) { + if s.err != nil { + return nil, s.err + } + return stackitem.NewArray([]stackitem.Item{ + stackitem.Make(s.SomeInt), + stackitem.Make(s.SomeString), + }), nil +} + +func (s *ConvertibleStruct) FromStackItem(si stackitem.Item) error { + panic("TODO") +} + +func TestEmitConvertible(t *testing.T) { + t.Run("good", func(t *testing.T) { + buf := io.NewBufBinWriter() + str := &ConvertibleStruct{ + SomeInt: 5, + SomeString: "str", + } + Convertible(buf.BinWriter, str) + require.NoError(t, buf.Err) + res := buf.Bytes() + + // The struct itself: + assert.EqualValues(t, opcode.PUSHDATA1, res[0]) + assert.EqualValues(t, 3, res[1]) + assert.EqualValues(t, []byte("str"), res[2:5]) + assert.EqualValues(t, opcode.PUSH5, res[5]) + assert.EqualValues(t, opcode.PUSH2, res[6]) + assert.EqualValues(t, opcode.PACK, res[7]) + + // Overall length: + assert.EqualValues(t, 8, len(res)) + }) + + t.Run("error on conversion", func(t *testing.T) { + buf := io.NewBufBinWriter() + expectedErr := errors.New("error on conversion") + str := &ConvertibleStruct{ + err: expectedErr, + } + Convertible(buf.BinWriter, str) + actualErr := buf.Err + require.Error(t, actualErr) + require.ErrorIs(t, actualErr, expectedErr) + }) +} From 3dbb7333245acbeff31688eed8223a6e69ba1ef9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 16 May 2023 14:00:44 +0300 Subject: [PATCH 066/125] cli: require contract config file for bindings generation It's an error if config file isn't provided and bindings config needs to be generated. Signed-off-by: Anna Shaleva --- cli/smartcontract/smart_contract.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 818f07ac2..b478f076f 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -400,7 +400,8 @@ func contractCompile(ctx *cli.Context) error { manifestFile := ctx.String("manifest") confFile := ctx.String("config") debugFile := ctx.String("debug") - if len(confFile) == 0 && (len(manifestFile) != 0 || len(debugFile) != 0) { + bindings := ctx.String("bindings") + if len(confFile) == 0 && (len(manifestFile) != 0 || len(debugFile) != 0 || len(bindings) != 0) { return cli.NewExitError(errNoConfFile, 1) } @@ -409,7 +410,7 @@ func contractCompile(ctx *cli.Context) error { DebugInfo: debugFile, ManifestFile: manifestFile, - BindingsFile: ctx.String("bindings"), + BindingsFile: bindings, NoStandardCheck: ctx.Bool("no-standards"), NoEventsCheck: ctx.Bool("no-events"), From a2449ae8aefb0c95f618904a95ba3200eeeb8ae3 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 12 May 2023 13:49:31 +0300 Subject: [PATCH 067/125] cli: autocomplete output filenames for `contract compile` cmd It's enough to specify the input file only to get the standard output: ``` $ neo-go contract compile -i ./1-print/1-print.go $ neo-go contract compile -i ./1-print/ ``` Signed-off-by: Anna Shaleva --- cli/smartcontract/contract_test.go | 16 +++++++++++- cli/smartcontract/smart_contract.go | 38 ++++++++++++++++++++++++++--- docs/compiler.md | 8 ++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/cli/smartcontract/contract_test.go b/cli/smartcontract/contract_test.go index 917f07221..bb41a4a30 100644 --- a/cli/smartcontract/contract_test.go +++ b/cli/smartcontract/contract_test.go @@ -237,7 +237,8 @@ func TestContractInitAndCompile(t *testing.T) { e.RunWithError(t, "neo-go", "contract", "init", "--name", ctrPath) }) - srcPath := filepath.Join(ctrPath, "main.go") + ctrRootPath := filepath.Join(ctrPath, "main") + srcPath := ctrRootPath + ".go" cfgPath := filepath.Join(ctrPath, "neo-go.yml") nefPath := filepath.Join(tmpDir, "testcontract.nef") manifestPath := filepath.Join(tmpDir, "testcontract.manifest.json") @@ -288,6 +289,19 @@ func TestContractInitAndCompile(t *testing.T) { e.Run(t, append(cmd, "--verbose")...) e.CheckNextLine(t, "^[0-9a-hA-H]+$") }) + + t.Run("autocomplete outputs", func(t *testing.T) { + cfg, err := os.ReadFile(cfgPath) + require.NoError(t, err) + require.NoError(t, os.WriteFile(filepath.Join(ctrPath, "main.yml"), cfg, os.ModePerm)) + e.Run(t, "neo-go", "contract", "compile", "--in", srcPath) + defaultNefPath := ctrRootPath + ".nef" + defaultManifestPath := ctrRootPath + ".manifest.json" + defaultBindingsPath := ctrRootPath + ".bindings.yml" + require.FileExists(t, defaultNefPath) + require.FileExists(t, defaultManifestPath) + require.FileExists(t, defaultBindingsPath) + }) } // Checks that error is returned if GAS available for test-invoke exceeds diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index b478f076f..5a2af4685 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -126,11 +126,18 @@ func NewCommands() []cli.Command { Name: "compile", Usage: "compile a smart contract to a .nef file", UsageText: "neo-go contract compile -i path [-o nef] [-v] [-d] [-m manifest] [-c yaml] [--bindings file] [--no-standards] [--no-events] [--no-permissions]", - Action: contractCompile, + Description: `Compiles given smart contract to a .nef file and emits other associated + information (manifest, bindings configuration, debug information files) if + asked to. If none of --out, --manifest, --config, --bindings flags are specified, + then the output filenames for these flags will be guessed using the contract + name or path provided via --in option by trimming/adding corresponding suffixes + to the common part of the path. In the latter case the configuration filepath + will be guessed from the --in option using the same rule."`, + Action: contractCompile, Flags: []cli.Flag{ cli.StringFlag{ Name: "in, i", - Usage: "Input file for the smart contract to be compiled", + Usage: "Input file for the smart contract to be compiled (*.go file or directory)", }, cli.StringFlag{ Name: "out, o", @@ -400,13 +407,38 @@ func contractCompile(ctx *cli.Context) error { manifestFile := ctx.String("manifest") confFile := ctx.String("config") debugFile := ctx.String("debug") + out := ctx.String("out") bindings := ctx.String("bindings") if len(confFile) == 0 && (len(manifestFile) != 0 || len(debugFile) != 0 || len(bindings) != 0) { return cli.NewExitError(errNoConfFile, 1) } + autocomplete := len(manifestFile) == 0 && + len(confFile) == 0 && + len(out) == 0 && + len(bindings) == 0 + if autocomplete { + var root string + fileInfo, err := os.Stat(src) + if err != nil { + return cli.NewExitError(fmt.Errorf("failed to stat source file or directory: %w", err), 1) + } + if fileInfo.IsDir() { + base := filepath.Base(fileInfo.Name()) + if base == string(filepath.Separator) { + base = "contract" + } + root = filepath.Join(src, base) + } else { + root = strings.TrimSuffix(src, ".go") + } + manifestFile = root + ".manifest.json" + confFile = root + ".yml" + out = root + ".nef" + bindings = root + ".bindings.yml" + } o := &compiler.Options{ - Outfile: ctx.String("out"), + Outfile: out, DebugInfo: debugFile, ManifestFile: manifestFile, diff --git a/docs/compiler.md b/docs/compiler.md index a38a2dcf6..d4d17efb4 100644 --- a/docs/compiler.md +++ b/docs/compiler.md @@ -80,6 +80,14 @@ $ go mod tidy By default, the filename will be the name of your .go file with the .nef extension, the file will be located in the same directory with your Go contract. +Along with the compiled contract and if the contract configuration file +`contract.yml` exist, the following files will be generated: +* smart-contract manifest file (`contract.manifest.json`) that is needed to deploy + the contract to the network +* bindings configuration file (`contract.bindings.yml`) that is needed to generate + code-based or RPC contract bindings +All of them will be located in the same directory with your Go contract. + If you want another location for your compiled contract: ``` From ed2b59e077b4f11e39e1f9b3727bbdbcc21f5d21 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 16 May 2023 17:54:41 +0300 Subject: [PATCH 068/125] cli: use cosigners separator for VM CLI commands where appropriate Needed for further VM CLI commands improvement, we'll add another positional args. Signed-off-by: Anna Shaleva --- cli/vm/cli.go | 55 ++++++++++++++++++++++++++-------- cli/vm/cli_test.go | 74 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 95 insertions(+), 34 deletions(-) diff --git a/cli/vm/cli.go b/cli/vm/cli.go index a8c246b66..7ee1cb366 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -151,7 +151,7 @@ Example: { Name: "loadnef", Usage: "Load a NEF-consistent script into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadnef [--historic ] [--gas ] [, ...]`, + UsageText: `loadnef [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` and parameters are mandatory. @@ -164,7 +164,7 @@ Example: { Name: "loadbase64", Usage: "Load a base64-encoded script string into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadbase64 [--historic ] [--gas ] [, ...]`, + UsageText: `loadbase64 [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` is mandatory parameter. @@ -177,7 +177,7 @@ Example: { Name: "loadhex", Usage: "Load a hex-encoded script string into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadhex [--historic ] [--gas ] [, ...]`, + UsageText: `loadhex [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` is mandatory parameter. @@ -190,7 +190,7 @@ Example: { Name: "loadgo", Usage: "Compile and load a Go file with the manifest into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadgo [--historic ] [--gas ] [, ...]`, + UsageText: `loadgo [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: ` is mandatory parameter. @@ -220,7 +220,7 @@ Example: { Name: "loaddeployed", Usage: "Load deployed contract into the VM from chain optionally attaching to it provided signers with scopes", - UsageText: `loaddeployed [--historic ] [--gas ] [, ...]`, + UsageText: `loaddeployed [--historic ] [--gas ] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, Description: `Load deployed contract into the VM from chain optionally attaching to it provided signers with scopes. If '--historic' flag specified, then the historic contract state (historic script and manifest) will be loaded. @@ -688,7 +688,13 @@ func handleLoadNEF(c *cli.Context) error { } var signers []transaction.Signer if len(args) > 2 { - signers, err = cmdargs.ParseSigners(c.Args()[2:]) + if args[2] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: `%s` was expected as the third parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[2]) + } + if len(args) < 4 { + return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator) + } + signers, err = cmdargs.ParseSigners(c.Args()[3:]) if err != nil { return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } @@ -715,7 +721,13 @@ func handleLoadBase64(c *cli.Context) error { } var signers []transaction.Signer if len(args) > 1 { - signers, err = cmdargs.ParseSigners(args[1:]) + if args[1] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1]) + } + if len(args) < 3 { + return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator) + } + signers, err = cmdargs.ParseSigners(args[2:]) if err != nil { return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } @@ -749,7 +761,13 @@ func handleLoadHex(c *cli.Context) error { } var signers []transaction.Signer if len(args) > 1 { - signers, err = cmdargs.ParseSigners(args[1:]) + if args[1] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1]) + } + if len(args) < 3 { + return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator) + } + signers, err = cmdargs.ParseSigners(args[2:]) if err != nil { return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } @@ -783,7 +801,13 @@ func handleLoadGo(c *cli.Context) error { } var signers []transaction.Signer if len(args) > 1 { - signers, err = cmdargs.ParseSigners(args[1:]) + if args[1] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1]) + } + if len(args) < 3 { + return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator) + } + signers, err = cmdargs.ParseSigners(args[2:]) if err != nil { return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } @@ -849,7 +873,8 @@ func handleLoadDeployed(c *cli.Context) error { if !c.Args().Present() { return errors.New("contract hash, address or ID is mandatory argument") } - hashOrID := c.Args().Get(0) + args := c.Args() + hashOrID := args[0] ic := getInteropContextFromContext(c.App) h, err := flags.ParseAddress(hashOrID) if err != nil { @@ -868,8 +893,14 @@ func handleLoadDeployed(c *cli.Context) error { } var signers []transaction.Signer - if len(c.Args()) > 1 { - signers, err = cmdargs.ParseSigners(c.Args()[1:]) + if len(args) > 1 { + if args[1] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: %s was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1]) + } + if len(args) < 3 { + return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator) + } + signers, err = cmdargs.ParseSigners(args[2:]) if err != nil { return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index 78f0c30d1..843782143 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -18,6 +18,7 @@ import ( "time" "github.com/chzyer/readline" + "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/cli/paramcontext" "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/internal/random" @@ -298,21 +299,27 @@ func TestLoad(t *testing.T) { "loadhex", "loadhex notahex", "loadhex "+hex.EncodeToString(script), - "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAddress, // owner:DefaultScope => true + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator, + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+"not-a-separator", + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"not-a-signer", + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true "run", - "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAddress+":None", // owner:None => false + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false "run", - "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true "run", - "loadhex "+hex.EncodeToString(checkWitnessScript)+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true "run", - "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false + "loadhex "+hex.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false "run", ) e.checkError(t, ErrMissingParameter) e.checkError(t, ErrInvalidParameter) e.checkNextLine(t, "READY: loaded 3 instructions") + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkStack(t, true) e.checkNextLine(t, "READY: loaded \\d+ instructions") @@ -330,21 +337,27 @@ func TestLoad(t *testing.T) { "loadbase64", "loadbase64 not_a_base64", "loadbase64 "+base64.StdEncoding.EncodeToString(script), - "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAddress, // owner:DefaultScope => true + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator, + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+"not-a-separator", + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" not-a-signer", + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true "run", - "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAddress+":None", // owner:None => false + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false "run", - "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true "run", - "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true "run", - "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false + "loadbase64 "+base64.StdEncoding.EncodeToString(checkWitnessScript)+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false "run", ) e.checkError(t, ErrMissingParameter) e.checkError(t, ErrInvalidParameter) e.checkNextLine(t, "READY: loaded 3 instructions") + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkStack(t, true) e.checkNextLine(t, "READY: loaded \\d+ instructions") @@ -440,12 +453,23 @@ go 1.18`) } ` filename := prepareLoadgoSrc(t, srcCheckWitness) + t.Run("invalid", func(t *testing.T) { + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename+" "+cmdargs.CosignersSeparator, + "loadgo "+filename+" "+"not-a-separator", + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" not-a-signer", + ) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + }) t.Run("address", func(t *testing.T) { e := newTestVMCLI(t) e.runProg(t, - "loadgo "+filename+" "+ownerAddress, // owner:DefaultScope => true + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true "run main", - "loadgo "+filename+" "+ownerAddress+":None", // owner:None => false + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false "run main") e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkStack(t, true) @@ -455,9 +479,9 @@ go 1.18`) t.Run("string LE", func(t *testing.T) { e := newTestVMCLI(t) e.runProg(t, - "loadgo "+filename+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true "run main", - "loadgo "+filename+" 0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true "run main") e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkStack(t, true) @@ -467,7 +491,7 @@ go 1.18`) t.Run("nonwitnessed signer", func(t *testing.T) { e := newTestVMCLI(t) e.runProg(t, - "loadgo "+filename+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false "run main") e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkStack(t, false) @@ -1153,24 +1177,27 @@ func TestLoaddeployed(t *testing.T) { "run get 1", "loaddeployed --gas 420000 "+h.StringLE(), // gas-limited "run get 1", - "loaddeployed 0x"+h.StringLE(), // hash LE with 0x prefix + "loaddeployed "+"0x"+h.StringLE(), // hash LE with 0x prefix "run get 1", "loaddeployed 1", // contract ID "run get 1", "loaddeployed --historic 2 1", // historic state, check that hash is properly set "run get 1", // Check signers parsing: - "loaddeployed 2 "+ownerAddress, // check witness (owner:DefautScope => true) + "loaddeployed 2 "+cmdargs.CosignersSeparator, + "loaddeployed 2 "+"not-a-separator", + "loaddeployed 2 "+cmdargs.CosignersSeparator+" not-a-signer", + "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress, // check witness (owner:DefautScope => true) "run checkWitness", - "loaddeployed 2 "+ownerAddress+":None", // check witness (owner:None => false) + "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // check witness (owner:None => false) "run checkWitness", - "loaddeployed 2 "+ownerAddress+":CalledByEntry", // check witness (owner:CalledByEntry => true) + "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAddress+":CalledByEntry", // check witness (owner:CalledByEntry => true) "run checkWitness", - "loaddeployed 2 "+ownerAcc.StringLE()+":CalledByEntry", // check witness (ownerLE:CalledByEntry => true) + "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE()+":CalledByEntry", // check witness (ownerLE:CalledByEntry => true) "run checkWitness", - "loaddeployed 2 0x"+ownerAcc.StringLE()+":CalledByEntry", // check witness (owner0xLE:CalledByEntry => true) + "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE()+":CalledByEntry", // check witness (owner0xLE:CalledByEntry => true) "run checkWitness", - "loaddeployed 2 "+sideAcc.StringLE()+":Global", // check witness (sideLE:Global => false) + "loaddeployed 2 "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE()+":Global", // check witness (sideLE:Global => false) "run checkWitness", "loaddeployed", // missing argument "exit", @@ -1186,6 +1213,9 @@ func TestLoaddeployed(t *testing.T) { e.checkNextLine(t, "READY: loaded \\d+ instructions") e.checkStack(t, []byte{1}) // Check signers parsing: + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) e.checkNextLine(t, "READY: loaded \\d+ instructions") // check witness of owner:DefaultScope e.checkStack(t, true) e.checkNextLine(t, "READY: loaded \\d+ instructions") // check witness of owner:None From aace79065149a2a1f26e89585d566659e769e26d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 16 May 2023 17:57:13 +0300 Subject: [PATCH 069/125] cli: guess manifest filename from nef for `loadnef` VM CLI command Signed-off-by: Anna Shaleva --- cli/vm/cli.go | 52 +++++++++++++++++++++++++++++++++------------- cli/vm/cli_test.go | 21 ++++++++++++++++++- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/cli/vm/cli.go b/cli/vm/cli.go index 7ee1cb366..50e71ea45 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -151,9 +151,11 @@ Example: { Name: "loadnef", Usage: "Load a NEF-consistent script into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadnef [--historic ] [--gas ] [-- , ...]`, + UsageText: `loadnef [--historic ] [--gas ] [] [-- , ...]`, Flags: []cli.Flag{historicFlag, gasFlag}, - Description: ` and parameters are mandatory. + Description: ` parameter is mandatory, parameter (if omitted) will + be guessed from the parameter by replacing '.nef' suffix with '.manifest.json' + suffix. ` + cmdargs.SignersParsingDoc + ` @@ -671,10 +673,36 @@ func prepareVM(c *cli.Context, tx *transaction.Transaction) error { func handleLoadNEF(c *cli.Context) error { args := c.Args() - if len(args) < 2 { - return fmt.Errorf("%w: ", ErrMissingParameter) + if len(args) < 1 { + return fmt.Errorf("%w: is required", ErrMissingParameter) } - b, err := os.ReadFile(args[0]) + nefFile := args[0] + var ( + manifestFile string + signersStartOffset int + ) + if len(args) == 2 { + manifestFile = args[1] + } else if len(args) == 3 { + if args[1] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: `%s` was expected as the second parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[1]) + } + signersStartOffset = 2 + } else if len(args) > 3 { + if args[1] == cmdargs.CosignersSeparator { + signersStartOffset = 2 + } else { + manifestFile = args[1] + if args[2] != cmdargs.CosignersSeparator { + return fmt.Errorf("%w: `%s` was expected as the third parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[2]) + } + signersStartOffset = 3 + } + } + if len(manifestFile) == 0 { + manifestFile = strings.TrimSuffix(nefFile, ".nef") + ".manifest.json" + } + b, err := os.ReadFile(nefFile) if err != nil { return err } @@ -682,21 +710,15 @@ func handleLoadNEF(c *cli.Context) error { if err != nil { return fmt.Errorf("failed to decode NEF file: %w", err) } - m, err := getManifestFromFile(args[1]) + m, err := getManifestFromFile(manifestFile) if err != nil { return fmt.Errorf("failed to read manifest: %w", err) } var signers []transaction.Signer - if len(args) > 2 { - if args[2] != cmdargs.CosignersSeparator { - return fmt.Errorf("%w: `%s` was expected as the third parameter, got %s", ErrInvalidParameter, cmdargs.CosignersSeparator, args[2]) - } - if len(args) < 4 { - return fmt.Errorf("%w: signers expected after `%s`, got none", ErrInvalidParameter, cmdargs.CosignersSeparator) - } - signers, err = cmdargs.ParseSigners(c.Args()[3:]) + if signersStartOffset != 0 && len(args) > signersStartOffset { + signers, err = cmdargs.ParseSigners(c.Args()[signersStartOffset:]) if err != nil { - return fmt.Errorf("%w: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors + return fmt.Errorf("%w: failed to parse signers: %v", ErrInvalidParameter, err) //nolint:errorlint // errorlint: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors } } err = prepareVM(c, createFakeTransaction(nef.Script, signers)) diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index 843782143..8cae8d017 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -527,7 +527,17 @@ go 1.18`) "loadnef "+filename+" "+notExists, "loadnef "+filename+" "+filename, "loadnef "+filename+" "+manifestFile, - "run main add 3 5") + "run main add 3 5", + "loadnef "+filename, + "run main add 3 5", + "loadnef "+filename+" "+cmdargs.CosignersSeparator, + "loadnef "+filename+" "+manifestFile+" "+cmdargs.CosignersSeparator, + "loadnef "+filename+" "+manifestFile+" "+"not-a-separator", + "loadnef "+filename+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(), + "run main add 3 5", + "loadnef "+filename+" "+manifestFile+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(), + "run main add 3 5", + ) e.checkError(t, ErrMissingParameter) e.checkNextLine(t, "Error:") @@ -535,6 +545,15 @@ go 1.18`) e.checkNextLine(t, "Error:") e.checkNextLine(t, "READY: loaded \\d* instructions") e.checkStack(t, 8) + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkStack(t, 8) + e.checkNextLine(t, "Error:") // manifest missing, missing signer after -- + e.checkNextLine(t, "Error:") // manifest present, missing signer after -- + e.checkNextLine(t, "Error:") // manifest present, invalid separator + e.checkNextLine(t, "READY: loaded \\d* instructions") // manifest missing, signer present, OK + e.checkStack(t, 8) + e.checkNextLine(t, "READY: loaded \\d* instructions") // manifest present, signer present, OK + e.checkStack(t, 8) }) } From fc6029d006eaf7c8ded4ae7497c9ae7c15613600 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 17 May 2023 12:27:45 +0300 Subject: [PATCH 070/125] vm: allow to emit uint and uint64 as a part of array Signed-off-by: Anna Shaleva --- pkg/vm/emit/emit.go | 6 +++++- pkg/vm/emit/emit_test.go | 23 +++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pkg/vm/emit/emit.go b/pkg/vm/emit/emit.go index 4cae72f65..776af4594 100644 --- a/pkg/vm/emit/emit.go +++ b/pkg/vm/emit/emit.go @@ -100,7 +100,7 @@ func bigInt(w *io.BinWriter, n *big.Int, trySmall bool) { // Array emits an array of elements to the given buffer. It accepts elements of the following types: // - int8, int16, int32, int64, int -// - uint8, uint16, uint32 +// - uint8, uint16, uint32, uint64, uint // - *big.Int // - string, []byte // - util.Uint160, *util.Uint160, util.Uint256, *util.Uint256 @@ -119,6 +119,8 @@ func Array(w *io.BinWriter, es ...any) { Array(w, e...) case int64: Int(w, e) + case uint64: + BigInt(w, new(big.Int).SetUint64(e)) case int32: Int(w, int64(e)) case uint32: @@ -133,6 +135,8 @@ func Array(w *io.BinWriter, es ...any) { Int(w, int64(e)) case int: Int(w, int64(e)) + case uint: + BigInt(w, new(big.Int).SetUint64(uint64(e))) case *big.Int: BigInt(w, e) case string: diff --git a/pkg/vm/emit/emit_test.go b/pkg/vm/emit/emit_test.go index d19c75962..697a79b3b 100644 --- a/pkg/vm/emit/emit_test.go +++ b/pkg/vm/emit/emit_test.go @@ -225,6 +225,8 @@ func TestEmitArray(t *testing.T) { veryBig := new(big.Int).SetUint64(math.MaxUint64) veryBig.Add(veryBig, big.NewInt(1)) Array(buf.BinWriter, + uint64(math.MaxUint64), + uint(math.MaxUint32), // don't use MaxUint to keep test results the same throughout all platforms. stackitem.NewMapWithValue([]stackitem.MapElement{ { Key: stackitem.Make(1), @@ -323,14 +325,27 @@ func TestEmitArray(t *testing.T) { assert.EqualValues(t, opcode.PUSH1, res[192]) assert.EqualValues(t, opcode.PUSH2, res[193]) assert.EqualValues(t, opcode.PACKMAP, res[194]) + // uint (MaxUint32) + assert.EqualValues(t, opcode.PUSHINT64, res[195]) + assert.EqualValues(t, []byte{ + 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, + }, res[196:204]) + // uint64 (MaxUint64) + assert.EqualValues(t, opcode.PUSHINT128, res[204]) + assert.EqualValues(t, []byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, + 0, 0, 0, 0}, res[205:221]) // Values packing: - assert.EqualValues(t, opcode.PUSHINT8, res[195]) - assert.EqualValues(t, byte(21), res[196]) - assert.EqualValues(t, opcode.PACK, res[197]) + assert.EqualValues(t, opcode.PUSHINT8, res[221]) + assert.EqualValues(t, byte(23), res[222]) + assert.EqualValues(t, opcode.PACK, res[223]) // Overall script length: - assert.EqualValues(t, 198, len(res)) + assert.EqualValues(t, 224, len(res)) }) t.Run("empty", func(t *testing.T) { From 35c3518b371c11e0e5a5adbc2b2de0e29927042e Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 19 May 2023 12:55:52 +0300 Subject: [PATCH 071/125] examples: fix owner's verification of Runtime example contract `update` and `destroy` methods of the contract should check for owner witness without checking the trigger (and that's the way how Verify method works for this contract). Signed-off-by: Anna Shaleva --- examples/runtime/runtime.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/runtime/runtime.go b/examples/runtime/runtime.go index 4a2616499..a98d39d29 100644 --- a/examples/runtime/runtime.go +++ b/examples/runtime/runtime.go @@ -65,7 +65,7 @@ func Verify() bool { // Destroy destroys the contract, only the owner can do that. func Destroy() { - if !Verify() { + if !CheckWitness() { panic("only owner can destroy") } management.Destroy() @@ -74,7 +74,7 @@ func Destroy() { // Update updates the contract, only the owner can do that. _deploy will be called // after update. func Update(nef, manifest []byte) { - if !Verify() { + if !CheckWitness() { panic("only owner can update") } management.Update(nef, manifest) From b6b80f3abfdecb5f0e98296b0b2f745c1536a147 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 17 May 2023 19:01:24 +0300 Subject: [PATCH 072/125] cli: properly handle `run` VM CLI command Properly load the provided method using NEF and hash specified. It allows to have NEF properly set in the VM context and handle CALLT instruction correctly. Signed-off-by: Anna Shaleva --- cli/vm/cli.go | 113 +++++++++----- cli/vm/cli_test.go | 340 ++++++++++++++++++++++++++++++------------- pkg/vm/context.go | 7 + pkg/vm/debug_test.go | 19 +++ 4 files changed, 343 insertions(+), 136 deletions(-) diff --git a/cli/vm/cli.go b/cli/vm/cli.go index 50e71ea45..9b294ed08 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -28,12 +28,14 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/core/native" + "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig" "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/bigint" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" @@ -51,7 +53,7 @@ const ( chainKey = "chain" chainCfgKey = "chainCfg" icKey = "ic" - manifestKey = "manifest" + contractStateKey = "contractState" exitFuncKey = "exitFunc" readlineInstanceKey = "readlineKey" printLogoKey = "printLogoKey" @@ -64,6 +66,7 @@ const ( gasFlagFullName = "gas" backwardsFlagFullName = "backwards" diffFlagFullName = "diff" + hashFlagFullName = "hash" ) var ( @@ -76,6 +79,10 @@ var ( Name: gasFlagFullName, Usage: "GAS limit for this execution (integer number, satoshi).", } + hashFlag = cli.StringFlag{ + Name: hashFlagFullName, + Usage: "Smart-contract hash in LE form or address", + } ) var commands = []cli.Command{ @@ -150,9 +157,9 @@ Example: }, { Name: "loadnef", - Usage: "Load a NEF-consistent script into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadnef [--historic ] [--gas ] [] [-- , ...]`, - Flags: []cli.Flag{historicFlag, gasFlag}, + Usage: "Load a NEF (possibly with a contract hash) into the VM optionally using provided scoped signers in the context", + UsageText: `loadnef [--historic ] [--gas ] [--hash ] [] [-- , ...]`, + Flags: []cli.Flag{historicFlag, gasFlag, hashFlag}, Description: ` parameter is mandatory, parameter (if omitted) will be guessed from the parameter by replacing '.nef' suffix with '.manifest.json' suffix. @@ -191,9 +198,9 @@ Example: }, { Name: "loadgo", - Usage: "Compile and load a Go file with the manifest into the VM optionally attaching to it provided signers with scopes", - UsageText: `loadgo [--historic ] [--gas ] [-- , ...]`, - Flags: []cli.Flag{historicFlag, gasFlag}, + Usage: "Compile and load a Go file with the manifest into the VM optionally attaching to it provided signers with scopes and setting provided hash", + UsageText: `loadgo [--historic ] [--gas ] [--hash ] [-- , ...]`, + Flags: []cli.Flag{historicFlag, gasFlag, hashFlag}, Description: ` is mandatory parameter. ` + cmdargs.SignersParsingDoc + ` @@ -489,7 +496,7 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg chainKey: chain, chainCfgKey: cfg, icKey: ic, - manifestKey: new(manifest.Manifest), + contractStateKey: new(state.ContractBase), exitFuncKey: exitF, readlineInstanceKey: l, printLogoKey: printLogotype, @@ -522,8 +529,8 @@ func getInteropContextFromContext(app *cli.App) *interop.Context { return app.Metadata[icKey].(*interop.Context) } -func getManifestFromContext(app *cli.App) *manifest.Manifest { - return app.Metadata[manifestKey].(*manifest.Manifest) +func getContractStateFromContext(app *cli.App) *state.ContractBase { + return app.Metadata[contractStateKey].(*state.ContractBase) } func getPrintLogoFromContext(app *cli.App) bool { @@ -534,8 +541,8 @@ func setInteropContextInContext(app *cli.App, ic *interop.Context) { app.Metadata[icKey] = ic } -func setManifestInContext(app *cli.App, m *manifest.Manifest) { - app.Metadata[manifestKey] = m +func setContractStateInContext(app *cli.App, cs *state.ContractBase) { + app.Metadata[contractStateKey] = cs } func checkVMIsReady(app *cli.App) bool { @@ -671,6 +678,17 @@ func prepareVM(c *cli.Context, tx *transaction.Transaction) error { return nil } +func getHashFlag(c *cli.Context) (util.Uint160, error) { + if !c.IsSet(hashFlagFullName) { + return util.Uint160{}, nil + } + h, err := flags.ParseAddress(c.String(hashFlagFullName)) + if err != nil { + return util.Uint160{}, fmt.Errorf("failed to parse contract hash: %w", err) + } + return h, nil +} + func handleLoadNEF(c *cli.Context) error { args := c.Args() if len(args) < 1 { @@ -725,9 +743,19 @@ func handleLoadNEF(c *cli.Context) error { if err != nil { return err } + h, err := getHashFlag(c) + if err != nil { + return err + } + cs := &state.ContractBase{ + Hash: h, + NEF: nef, + Manifest: *m, + } + setContractStateInContext(c.App, cs) + v := getVMFromContext(c.App) fmt.Fprintf(c.App.Writer, "READY: loaded %d instructions\n", v.Context().LenInstr()) - setManifestInContext(c.App, m) changePrompt(c.App) return nil } @@ -811,7 +839,7 @@ func handleLoadGo(c *cli.Context) error { } name := strings.TrimSuffix(args[0], ".go") - b, di, err := compiler.CompileWithOptions(args[0], nil, &compiler.Options{Name: name}) + ne, di, err := compiler.CompileWithOptions(args[0], nil, &compiler.Options{Name: name}) if err != nil { return fmt.Errorf("failed to compile: %w", err) } @@ -835,12 +863,22 @@ func handleLoadGo(c *cli.Context) error { } } - err = prepareVM(c, createFakeTransaction(b.Script, signers)) + err = prepareVM(c, createFakeTransaction(ne.Script, signers)) if err != nil { return err } + h, err := getHashFlag(c) + if err != nil { + return err + } + cs := &state.ContractBase{ + Hash: h, + NEF: *ne, + Manifest: *m, + } + setContractStateInContext(c.App, cs) + v := getVMFromContext(c.App) - setManifestInContext(c.App, m) fmt.Fprintf(c.App.Writer, "READY: loaded %d instructions\n", v.Context().LenInstr()) changePrompt(c.App) return nil @@ -937,7 +975,7 @@ func handleLoadDeployed(c *cli.Context) error { ic.VM.GasLimit = gasLimit ic.VM.LoadScriptWithHash(cs.NEF.Script, cs.Hash, callflag.All) fmt.Fprintf(c.App.Writer, "READY: loaded %d instructions\n", ic.VM.Context().LenInstr()) - setManifestInContext(c.App, &cs.Manifest) + setContractStateInContext(c.App, &cs.ContractBase) changePrompt(c.App) return nil } @@ -992,9 +1030,9 @@ func resetInteropContext(app *cli.App, tx *transaction.Transaction, height ...ui return nil } -// resetManifest removes manifest from app context. -func resetManifest(app *cli.App) { - setManifestInContext(app, nil) +// resetContractState removes loaded contract state from app context. +func resetContractState(app *cli.App) { + setContractStateInContext(app, nil) } // resetState resets state of the app (clear interop context and manifest) so that it's ready @@ -1004,7 +1042,7 @@ func resetState(app *cli.App, tx *transaction.Transaction, height ...uint32) err if err != nil { return err } - resetManifest(app) + resetContractState(app) return nil } @@ -1023,7 +1061,7 @@ func getManifestFromFile(name string) (*manifest.Manifest, error) { func handleRun(c *cli.Context) error { v := getVMFromContext(c.App) - m := getManifestFromContext(c.App) + cs := getContractStateFromContext(c.App) args := c.Args() if len(args) != 0 { var ( @@ -1031,6 +1069,7 @@ func handleRun(c *cli.Context) error { offset int err error runCurrent = args[0] != "_" + hasRet bool ) _, scParams, err := cmdargs.ParseParams(args[1:], true) @@ -1045,27 +1084,35 @@ func handleRun(c *cli.Context) error { } } if runCurrent { - if m == nil { + if cs == nil { return fmt.Errorf("manifest is not loaded; either use 'run' command to run loaded script from the start or use 'loadgo' and 'loadnef' commands to provide manifest") } - md := m.ABI.GetMethod(args[0], len(params)) + md := cs.Manifest.ABI.GetMethod(args[0], len(params)) if md == nil { return fmt.Errorf("%w: method not found", ErrInvalidParameter) } + hasRet = md.ReturnType != smartcontract.VoidType offset = md.Offset + var initOff = -1 + if initMD := cs.Manifest.ABI.GetMethod(manifest.MethodInit, 0); initMD != nil { + initOff = initMD.Offset + } + + // Clear context loaded by 'loadgo', 'loadnef' or 'loaddeployed' to properly handle LoadNEFMethod. + // At the same time, preserve previously set gas limit and the set of breakpoints. + ic := getInteropContextFromContext(c.App) + gasLimit := v.GasLimit + breaks := v.Context().BreakPoints() // We ensure that there's a context loaded. + ic.ReuseVM(v) + v.GasLimit = gasLimit + v.LoadNEFMethod(&cs.NEF, util.Uint160{}, cs.Hash, callflag.All, hasRet, offset, initOff, nil) + for _, bp := range breaks { + v.AddBreakPoint(bp) + } } for i := len(params) - 1; i >= 0; i-- { v.Estack().PushVal(params[i]) } - if runCurrent { - if !v.Ready() { - return errors.New("no program loaded") - } - v.Context().Jump(offset) - if initMD := m.ABI.GetMethod(manifest.MethodInit, 0); initMD != nil { - v.Call(initMD.Offset) - } - } } runVMWithHandling(c) changePrompt(c.App) diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index 8cae8d017..65252aa9b 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -281,6 +281,97 @@ func (e *executor) checkSlot(t *testing.T, items ...any) { require.NoError(t, err) } +func TestRun_WithNewVMContextAndBreakpoints(t *testing.T) { + t.Run("contract without init", func(t *testing.T) { + src := `package kek + func Main(a, b int) int { + var c = a + b + return c + 5 + }` + tmpDir := t.TempDir() + filename := prepareLoadgoSrc(t, tmpDir, src) + + e := newTestVMCLI(t) + e.runProgWithTimeout(t, 10*time.Second, + "loadgo "+filename, + "break 8", + "run main 3 5", + "run", + ) + + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkNextLine(t, "breakpoint added at instruction 8") + e.checkNextLine(t, "at breakpoint 8 (PUSH5)*") + e.checkStack(t, 13) + }) + t.Run("contract with init", func(t *testing.T) { + src := `package kek + var I = 5 + func Main(a, b int) int { + var c = a + b + return c + I + }` + + tmpDir := t.TempDir() + filename := prepareLoadgoSrc(t, tmpDir, src) + + e := newTestVMCLI(t) + e.runProgWithTimeout(t, 10*time.Second, + "loadgo "+filename, + "break 10", + "run main 3 5", + "run", + ) + + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkNextLine(t, "breakpoint added at instruction 10") + e.checkNextLine(t, "at breakpoint 10 (ADD)*") + e.checkStack(t, 13) + }) +} + +// prepareLoadgoSrc prepares provided SC source file for loading into VM via `loadgo` command. +func prepareLoadgoSrc(t *testing.T, tmpDir, src string) string { + filename := filepath.Join(tmpDir, "vmtestcontract.go") + require.NoError(t, os.WriteFile(filename, []byte(src), os.ModePerm)) + filename = "'" + filename + "'" + wd, err := os.Getwd() + require.NoError(t, err) + goMod := []byte(`module test.example/kek +require ( + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0 +) +replace github.com/nspcc-dev/neo-go/pkg/interop => ` + filepath.Join(wd, "../../pkg/interop") + ` +go 1.18`) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm)) + return filename +} + +// prepareLoadnefSrc compiles provided SC source and prepares NEF and manifest for loading into VM +// via `loadnef` command. It returns the name of manifest and NEF files ready to be used in CLI +// commands. +func prepareLoadnefSrc(t *testing.T, tmpDir, src string) (string, string) { + config.Version = "0.92.0-test" + + nefFile, di, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) + require.NoError(t, err) + filename := filepath.Join(tmpDir, "vmtestcontract.nef") + rawNef, err := nefFile.Bytes() + require.NoError(t, err) + require.NoError(t, os.WriteFile(filename, rawNef, os.ModePerm)) + m, err := di.ConvertToManifest(&compiler.Options{}) + require.NoError(t, err) + manifestFile := filepath.Join(tmpDir, "vmtestcontract.manifest.json") + rawManifest, err := json.Marshal(m) + require.NoError(t, err) + require.NoError(t, os.WriteFile(manifestFile, rawManifest, os.ModePerm)) + + manifestFile = "'" + manifestFile + "'" + filename = "'" + filename + "'" + + return manifestFile, filename +} + func TestLoad(t *testing.T) { script := []byte{byte(opcode.PUSH3), byte(opcode.PUSH4), byte(opcode.ADD)} @@ -378,10 +469,11 @@ func TestLoad(t *testing.T) { return a * b } }` - tmpDir := t.TempDir() - checkLoadgo := func(t *testing.T, tName, cName, cErrName string) { - t.Run("loadgo "+tName, func(t *testing.T) { + t.Run("loadgo", func(t *testing.T) { + tmpDir := t.TempDir() + + checkLoadgo := func(t *testing.T, cName, cErrName string) { filename := filepath.Join(tmpDir, cName) require.NoError(t, os.WriteFile(filename, []byte(src), os.ModePerm)) filename = "'" + filename + "'" @@ -403,46 +495,34 @@ go 1.18`) e.checkNextLine(t, "Error:") e.checkNextLine(t, "READY: loaded \\d* instructions") e.checkStack(t, 8) + } + + t.Run("simple", func(t *testing.T) { + checkLoadgo(t, "vmtestcontract.go", "vmtestcontract_err.go") + }) + t.Run("utf-8 with spaces", func(t *testing.T) { + checkLoadgo(t, "тестовый контракт.go", "тестовый контракт с ошибкой.go") }) - } - checkLoadgo(t, "simple", "vmtestcontract.go", "vmtestcontract_err.go") - checkLoadgo(t, "utf-8 with spaces", "тестовый контракт.go", "тестовый контракт с ошибкой.go") - - prepareLoadgoSrc := func(t *testing.T, srcAllowNotify string) string { - filename := filepath.Join(tmpDir, "vmtestcontract.go") - require.NoError(t, os.WriteFile(filename, []byte(srcAllowNotify), os.ModePerm)) - filename = "'" + filename + "'" - wd, err := os.Getwd() - require.NoError(t, err) - goMod := []byte(`module test.example/kek -require ( - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0 -) -replace github.com/nspcc-dev/neo-go/pkg/interop => ` + filepath.Join(wd, "../../pkg/interop") + ` -go 1.18`) - require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm)) - return filename - } - t.Run("loadgo, check calling flags", func(t *testing.T) { - srcAllowNotify := `package kek + t.Run("check calling flags", func(t *testing.T) { + srcAllowNotify := `package kek import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" func Main() int { runtime.Log("Hello, world!") return 1 } ` - filename := prepareLoadgoSrc(t, srcAllowNotify) + filename := prepareLoadgoSrc(t, tmpDir, srcAllowNotify) - e := newTestVMCLI(t) - e.runProg(t, - "loadgo "+filename, - "run main") - e.checkNextLine(t, "READY: loaded \\d* instructions") - e.checkStack(t, 1) - }) - t.Run("loadgo, check signers", func(t *testing.T) { - srcCheckWitness := `package kek + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename, + "run main") + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkStack(t, 1) + }) + t.Run("check signers", func(t *testing.T) { + srcCheckWitness := `package kek import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/lib/address" @@ -452,90 +532,78 @@ go 1.18`) return runtime.CheckWitness(owner) } ` - filename := prepareLoadgoSrc(t, srcCheckWitness) - t.Run("invalid", func(t *testing.T) { - e := newTestVMCLI(t) - e.runProg(t, - "loadgo "+filename+" "+cmdargs.CosignersSeparator, - "loadgo "+filename+" "+"not-a-separator", - "loadgo "+filename+" "+cmdargs.CosignersSeparator+" not-a-signer", - ) - e.checkError(t, ErrInvalidParameter) - e.checkError(t, ErrInvalidParameter) - e.checkError(t, ErrInvalidParameter) - }) - t.Run("address", func(t *testing.T) { - e := newTestVMCLI(t) - e.runProg(t, - "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true - "run main", - "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false - "run main") - e.checkNextLine(t, "READY: loaded \\d+ instructions") - e.checkStack(t, true) - e.checkNextLine(t, "READY: loaded \\d+ instructions") - e.checkStack(t, false) - }) - t.Run("string LE", func(t *testing.T) { - e := newTestVMCLI(t) - e.runProg(t, - "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true - "run main", - "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true - "run main") - e.checkNextLine(t, "READY: loaded \\d+ instructions") - e.checkStack(t, true) - e.checkNextLine(t, "READY: loaded \\d+ instructions") - e.checkStack(t, true) - }) - t.Run("nonwitnessed signer", func(t *testing.T) { - e := newTestVMCLI(t) - e.runProg(t, - "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false - "run main") - e.checkNextLine(t, "READY: loaded \\d+ instructions") - e.checkStack(t, false) + filename := prepareLoadgoSrc(t, tmpDir, srcCheckWitness) + t.Run("invalid", func(t *testing.T) { + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename+" "+cmdargs.CosignersSeparator, + "loadgo "+filename+" "+"not-a-separator", + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" not-a-signer", + ) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + e.checkError(t, ErrInvalidParameter) + }) + t.Run("address", func(t *testing.T) { + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress, // owner:DefaultScope => true + "run main", + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAddress+":None", // owner:None => false + "run main") + e.checkNextLine(t, "READY: loaded \\d+ instructions") + e.checkStack(t, true) + e.checkNextLine(t, "READY: loaded \\d+ instructions") + e.checkStack(t, false) + }) + t.Run("string LE", func(t *testing.T) { + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+ownerAcc.StringLE(), // ownerLE:DefaultScope => true + "run main", + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+"0x"+ownerAcc.StringLE(), // owner0xLE:DefaultScope => true + "run main") + e.checkNextLine(t, "READY: loaded \\d+ instructions") + e.checkStack(t, true) + e.checkNextLine(t, "READY: loaded \\d+ instructions") + e.checkStack(t, true) + }) + t.Run("nonwitnessed signer", func(t *testing.T) { + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename+" "+cmdargs.CosignersSeparator+" "+sideAcc.StringLE(), // sideLE:DefaultScope => false + "run main") + e.checkNextLine(t, "READY: loaded \\d+ instructions") + e.checkStack(t, false) + }) }) }) + t.Run("loadnef", func(t *testing.T) { - config.Version = "0.92.0-test" + tmpDir := t.TempDir() - nefFile, di, err := compiler.CompileWithOptions("test.go", strings.NewReader(src), nil) - require.NoError(t, err) - filename := filepath.Join(tmpDir, "vmtestcontract.nef") - rawNef, err := nefFile.Bytes() - require.NoError(t, err) - require.NoError(t, os.WriteFile(filename, rawNef, os.ModePerm)) - m, err := di.ConvertToManifest(&compiler.Options{}) - require.NoError(t, err) - manifestFile := filepath.Join(tmpDir, "vmtestcontract.manifest.json") - rawManifest, err := json.Marshal(m) - require.NoError(t, err) - require.NoError(t, os.WriteFile(manifestFile, rawManifest, os.ModePerm)) + manifestFile, nefFile := prepareLoadnefSrc(t, tmpDir, src) filenameErr := filepath.Join(tmpDir, "vmtestcontract_err.nef") - require.NoError(t, os.WriteFile(filenameErr, append([]byte{1, 2, 3, 4}, rawNef...), os.ModePerm)) + require.NoError(t, os.WriteFile(filenameErr, []byte{1, 2, 3, 4}, os.ModePerm)) notExists := filepath.Join(tmpDir, "notexists.json") - - manifestFile = "'" + manifestFile + "'" - filename = "'" + filename + "'" filenameErr = "'" + filenameErr + "'" e := newTestVMCLI(t) e.runProg(t, "loadnef", "loadnef "+filenameErr+" "+manifestFile, - "loadnef "+filename+" "+notExists, - "loadnef "+filename+" "+filename, - "loadnef "+filename+" "+manifestFile, + "loadnef "+nefFile+" "+notExists, + "loadnef "+nefFile+" "+nefFile, + "loadnef "+nefFile+" "+manifestFile, "run main add 3 5", - "loadnef "+filename, + "loadnef "+nefFile, "run main add 3 5", - "loadnef "+filename+" "+cmdargs.CosignersSeparator, - "loadnef "+filename+" "+manifestFile+" "+cmdargs.CosignersSeparator, - "loadnef "+filename+" "+manifestFile+" "+"not-a-separator", - "loadnef "+filename+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(), + "loadnef "+nefFile+" "+cmdargs.CosignersSeparator, + "loadnef "+nefFile+" "+manifestFile+" "+cmdargs.CosignersSeparator, + "loadnef "+nefFile+" "+manifestFile+" "+"not-a-separator", + "loadnef "+nefFile+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(), "run main add 3 5", - "loadnef "+filename+" "+manifestFile+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(), + "loadnef "+nefFile+" "+manifestFile+" "+cmdargs.CosignersSeparator+" "+util.Uint160{1, 2, 3}.StringLE(), "run main add 3 5", ) @@ -557,6 +625,72 @@ go 1.18`) }) } +func TestLoad_RunWithCALLT(t *testing.T) { + // Our smart compiler will generate CALLT instruction for the following StdLib call: + src := `package kek + import "github.com/nspcc-dev/neo-go/pkg/interop/native/std" + func Main() int { + return std.Atoi("123", 10) + }` + + t.Run("loadgo", func(t *testing.T) { + tmp := t.TempDir() + filename := prepareLoadgoSrc(t, tmp, src) + e := newTestVMCLI(t) + e.runProg(t, + "loadgo "+filename, + "run main", + ) + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkStack(t, 123) + }) + + t.Run("loadnef", func(t *testing.T) { + tmpDir := t.TempDir() + manifestFile, nefFile := prepareLoadnefSrc(t, tmpDir, src) + + e := newTestVMCLI(t) + e.runProg(t, + "loadnef "+nefFile+" "+manifestFile, + "run main", + ) + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkStack(t, 123) + }) + + t.Run("loaddeployed", func(t *testing.T) { + // We'll use `Runtime example` example contract which has a call to native Management + // inside performed via CALLT instruction (`destroy` method). + e := newTestVMClIWithState(t) + var ( + cH util.Uint160 + cName = "Runtime example" + bc = e.cli.chain + ) + for i := int32(1); ; i++ { + h, err := bc.GetContractScriptHash(i) + if err != nil { + break + } + cs := bc.GetContractState(h) + if cs == nil { + break + } + if cs.Manifest.Name == cName { + cH = cs.Hash + break + } + } + require.NotEmpty(t, cH, fmt.Sprintf("failed to locate `%s` example contract with CALLT usage in the simple chain", cName)) + e.runProg(t, + "loaddeployed "+cH.StringLE()+" -- NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB:Global", // the contract's owner got from the contract's code. + "run destroy", + ) + e.checkNextLine(t, "READY: loaded \\d* instructions") + e.checkStack(t) // Nothing on stack, successful execution. + }) +} + func TestRunWithDifferentArguments(t *testing.T) { src := `package kek var a = 1 diff --git a/pkg/vm/context.go b/pkg/vm/context.go index 95d693296..78c0f43ac 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -350,3 +350,10 @@ func DynamicOnUnload(v *VM, ctx *Context, commit bool) error { } return nil } + +// BreakPoints returns the current set of Context's breakpoints. +func (c *Context) BreakPoints() []int { + res := make([]int, len(c.sc.breakPoints)) + copy(res, c.sc.breakPoints) + return res +} diff --git a/pkg/vm/debug_test.go b/pkg/vm/debug_test.go index c30964b82..ea985aa24 100644 --- a/pkg/vm/debug_test.go +++ b/pkg/vm/debug_test.go @@ -4,6 +4,8 @@ import ( "math/big" "testing" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/require" ) @@ -40,3 +42,20 @@ func TestVM_Debug(t *testing.T) { require.Equal(t, big.NewInt(5), v.estack.Top().Value()) }) } + +func TestContext_BreakPoints(t *testing.T) { + prog := makeProgram(opcode.CALL, 3, opcode.RET, + opcode.PUSH2, opcode.PUSH3, opcode.ADD, opcode.RET) + v := load(prog) + v.AddBreakPoint(3) + v.AddBreakPoint(5) + require.Equal(t, []int{3, 5}, v.Context().BreakPoints()) + + // Preserve the set of breakpoints on Call. + v.Call(3) + require.Equal(t, []int{3, 5}, v.Context().BreakPoints()) + + // New context -> clean breakpoints. + v.loadScriptWithCallingHash(prog, nil, util.Uint160{}, util.Uint160{}, callflag.All, 1, 3, nil) + require.Equal(t, []int{}, v.Context().BreakPoints()) +} From 2f4fb3a0791d4b78f6266462638cc6846a1447c8 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 17 May 2023 19:03:02 +0300 Subject: [PATCH 073/125] cli: fix error description for `run` VM CLI command Signed-off-by: Anna Shaleva --- cli/vm/cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/vm/cli.go b/cli/vm/cli.go index 9b294ed08..ed6b685d9 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -1085,7 +1085,7 @@ func handleRun(c *cli.Context) error { } if runCurrent { if cs == nil { - return fmt.Errorf("manifest is not loaded; either use 'run' command to run loaded script from the start or use 'loadgo' and 'loadnef' commands to provide manifest") + return fmt.Errorf("manifest is not loaded; either use 'run' command to run loaded script from the start or use 'loadgo', 'loadnef' or 'loaddeployed' commands to provide manifest") } md := cs.Manifest.ABI.GetMethod(args[0], len(params)) if md == nil { From ddfbf7a4349d72aa63a19a4423844812652fb8b5 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 19 May 2023 13:22:20 +0300 Subject: [PATCH 074/125] cli: remove code duplication in test Signed-off-by: Anna Shaleva --- cli/vm/cli_test.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index 65252aa9b..4ccc29606 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -474,15 +474,8 @@ func TestLoad(t *testing.T) { tmpDir := t.TempDir() checkLoadgo := func(t *testing.T, cName, cErrName string) { - filename := filepath.Join(tmpDir, cName) - require.NoError(t, os.WriteFile(filename, []byte(src), os.ModePerm)) - filename = "'" + filename + "'" + filename := prepareLoadgoSrc(t, tmpDir, src) filenameErr := filepath.Join(tmpDir, cErrName) - require.NoError(t, os.WriteFile(filenameErr, []byte(src+"invalid_token"), os.ModePerm)) - filenameErr = "'" + filenameErr + "'" - goMod := []byte(`module test.example/vmcli -go 1.18`) - require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "go.mod"), goMod, os.ModePerm)) e := newTestVMCLI(t) e.runProgWithTimeout(t, 10*time.Second, From 7a06cea885a735708d819777935b92986984cf72 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 May 2023 10:42:27 +0300 Subject: [PATCH 075/125] cli: allow to rewrite expected test output Don't perform it manually every time. Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 33 ++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index ae0ef741f..6756adb82 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -324,6 +324,10 @@ func (c *ContractReader) Get() (*big.Int, error) { `, string(data)) } +// rewriteExpectedOutputs denotes whether expected output files should be rewritten +// for TestGenerateRPCBindings and TestAssistedRPCBindings. +const rewriteExpectedOutputs = false + func TestGenerateRPCBindings(t *testing.T) { tmpDir := t.TempDir() app := cli.NewApp() @@ -341,10 +345,14 @@ func TestGenerateRPCBindings(t *testing.T) { data, err := os.ReadFile(outFile) require.NoError(t, err) data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows. - expected, err := os.ReadFile(good) - require.NoError(t, err) - expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows. - require.Equal(t, string(expected), string(data)) + if rewriteExpectedOutputs { + require.NoError(t, os.WriteFile(good, data, os.ModePerm)) + } else { + expected, err := os.ReadFile(good) + require.NoError(t, err) + expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows. + require.Equal(t, string(expected), string(data)) + } }) } @@ -363,6 +371,8 @@ func TestGenerateRPCBindings(t *testing.T) { checkBinding(filepath.Join("testdata", "nonepiter", "iter.manifest.json"), "0x00112233445566778899aabbccddeeff00112233", filepath.Join("testdata", "nonepiter", "iter.go")) + + require.False(t, rewriteExpectedOutputs) } func TestAssistedRPCBindings(t *testing.T) { @@ -393,15 +403,22 @@ func TestAssistedRPCBindings(t *testing.T) { data, err := os.ReadFile(outFile) require.NoError(t, err) data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows. - expected, err := os.ReadFile(filepath.Join(source, "rpcbindings.out")) - require.NoError(t, err) - expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows. - require.Equal(t, string(expected), string(data)) + expectedFile := filepath.Join(source, "rpcbindings.out") + if rewriteExpectedOutputs { + require.NoError(t, os.WriteFile(expectedFile, data, os.ModePerm)) + } else { + expected, err := os.ReadFile(expectedFile) + require.NoError(t, err) + expected = bytes.ReplaceAll(expected, []byte("\r"), []byte{}) // Windows. + require.Equal(t, string(expected), string(data)) + } }) } checkBinding(filepath.Join("testdata", "types")) checkBinding(filepath.Join("testdata", "structs")) + + require.False(t, rewriteExpectedOutputs) } func TestGenerate_Errors(t *testing.T) { From b5ec1271d5ae3ff1daff5c7453320d2a4cfe9310 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 May 2023 14:16:43 +0300 Subject: [PATCH 076/125] .gitignore: do not ignore compiler testdata cli's testdata folder stores contracts examples and expected compilation output, thus doesn't need to be ignored. *.out files are the bindings outputs only, do not ignore them as far. Signed-off-by: Anna Shaleva --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index fbc04a091..3262aa4e4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,6 @@ # Test binary, build with `go test -c` *.test -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - # Added by CoZ developers vendor/ bin/ @@ -54,6 +51,7 @@ testdata/ !pkg/services/notary/testdata !pkg/services/oracle/testdata !pkg/smartcontract/testdata +!cli/smartcontract/testdata pkg/vm/testdata/fuzz !pkg/vm/testdata !pkg/wallet/testdata From 36af361c2bf51833933ed5bf4868e957cc5564f6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 3 May 2023 14:55:02 +0300 Subject: [PATCH 077/125] smartcontract: add FromStackItem wrapper for RPC bindings Make it exported and reusable from the user's code. Signed-off-by: Anna Shaleva --- .../testdata/structs/rpcbindings.out | 454 ++++++++++++------ pkg/smartcontract/rpcbinding/binding.go | 22 +- 2 files changed, 318 insertions(+), 158 deletions(-) diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index cbe2a6e67..039b15e7e 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -195,16 +195,26 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { if err != nil { return nil, err } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given stack item +// and returns an error if so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 9 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(LedgerBlock) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { b, err := item.TryBytes() @@ -218,13 +228,13 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Hash: %w", err) + return fmt.Errorf("field Hash: %w", err) } index++ res.Version, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Version: %w", err) + return fmt.Errorf("field Version: %w", err) } index++ @@ -240,7 +250,7 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field PrevHash: %w", err) + return fmt.Errorf("field PrevHash: %w", err) } index++ @@ -256,25 +266,25 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field MerkleRoot: %w", err) + return fmt.Errorf("field MerkleRoot: %w", err) } index++ res.Timestamp, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Timestamp: %w", err) + return fmt.Errorf("field Timestamp: %w", err) } index++ res.Nonce, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Nonce: %w", err) + return fmt.Errorf("field Nonce: %w", err) } index++ res.Index, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Index: %w", err) + return fmt.Errorf("field Index: %w", err) } index++ @@ -290,17 +300,17 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field NextConsensus: %w", err) + return fmt.Errorf("field NextConsensus: %w", err) } index++ res.TransactionsLength, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field TransactionsLength: %w", err) + return fmt.Errorf("field TransactionsLength: %w", err) } - return res, err + return nil } // itemToLedgerBlockSR converts stack item into *LedgerBlockSR. @@ -308,16 +318,26 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) if err != nil { return nil, err } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given stack item +// and returns an error if so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 10 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(LedgerBlockSR) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { b, err := item.TryBytes() @@ -331,13 +351,13 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Hash: %w", err) + return fmt.Errorf("field Hash: %w", err) } index++ res.Version, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Version: %w", err) + return fmt.Errorf("field Version: %w", err) } index++ @@ -353,7 +373,7 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field PrevHash: %w", err) + return fmt.Errorf("field PrevHash: %w", err) } index++ @@ -369,25 +389,25 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field MerkleRoot: %w", err) + return fmt.Errorf("field MerkleRoot: %w", err) } index++ res.Timestamp, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Timestamp: %w", err) + return fmt.Errorf("field Timestamp: %w", err) } index++ res.Nonce, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Nonce: %w", err) + return fmt.Errorf("field Nonce: %w", err) } index++ res.Index, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Index: %w", err) + return fmt.Errorf("field Index: %w", err) } index++ @@ -403,13 +423,13 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field NextConsensus: %w", err) + return fmt.Errorf("field NextConsensus: %w", err) } index++ res.TransactionsLength, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field TransactionsLength: %w", err) + return fmt.Errorf("field TransactionsLength: %w", err) } index++ @@ -425,11 +445,11 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field PrevStateRoot: %w", err) + return fmt.Errorf("field PrevStateRoot: %w", err) } - return res, err + return nil } // itemToLedgerTransaction converts stack item into *LedgerTransaction. @@ -437,16 +457,26 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction if err != nil { return nil, err } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given stack item +// and returns an error if so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 8 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(LedgerTransaction) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { b, err := item.TryBytes() @@ -460,19 +490,19 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Hash: %w", err) + return fmt.Errorf("field Hash: %w", err) } index++ res.Version, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Version: %w", err) + return fmt.Errorf("field Version: %w", err) } index++ res.Nonce, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Nonce: %w", err) + return fmt.Errorf("field Nonce: %w", err) } index++ @@ -488,35 +518,35 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Sender: %w", err) + return fmt.Errorf("field Sender: %w", err) } index++ res.SysFee, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field SysFee: %w", err) + return fmt.Errorf("field SysFee: %w", err) } index++ res.NetFee, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field NetFee: %w", err) + return fmt.Errorf("field NetFee: %w", err) } index++ res.ValidUntilBlock, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field ValidUntilBlock: %w", err) + return fmt.Errorf("field ValidUntilBlock: %w", err) } index++ res.Script, err = arr[index].TryBytes() if err != nil { - return nil, fmt.Errorf("field Script: %w", err) + return fmt.Errorf("field Script: %w", err) } - return res, err + return nil } // itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. @@ -524,16 +554,26 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans if err != nil { return nil, err } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item +// and returns an error if so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 5 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(LedgerTransactionSigner) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Account, err = func (item stackitem.Item) (util.Uint160, error) { b, err := item.TryBytes() @@ -547,13 +587,13 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Account: %w", err) + return fmt.Errorf("field Account: %w", err) } index++ res.Scopes, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Scopes: %w", err) + return fmt.Errorf("field Scopes: %w", err) } index++ @@ -582,7 +622,7 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field AllowedContracts: %w", err) + return fmt.Errorf("field AllowedContracts: %w", err) } index++ @@ -611,7 +651,7 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field AllowedGroups: %w", err) + return fmt.Errorf("field AllowedGroups: %w", err) } index++ @@ -630,11 +670,11 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Rules: %w", err) + return fmt.Errorf("field Rules: %w", err) } - return res, err + return nil } // itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. @@ -642,30 +682,40 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes if err != nil { return nil, err } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item +// and returns an error if so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(LedgerWitnessCondition) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Type, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Type: %w", err) + return fmt.Errorf("field Type: %w", err) } index++ res.Value, err = arr[index].Value(), nil if err != nil { - return nil, fmt.Errorf("field Value: %w", err) + return fmt.Errorf("field Value: %w", err) } - return res, err + return nil } // itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. @@ -673,30 +723,40 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule if err != nil { return nil, err } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item +// and returns an error if so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(LedgerWitnessRule) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Action, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Action: %w", err) + return fmt.Errorf("field Action: %w", err) } index++ res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) if err != nil { - return nil, fmt.Errorf("field Condition: %w", err) + return fmt.Errorf("field Condition: %w", err) } - return res, err + return nil } // itemToManagementABI converts stack item into *ManagementABI. @@ -704,16 +764,26 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) if err != nil { return nil, err } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given stack item +// and returns an error if so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementABI) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { arr, ok := item.Value().([]stackitem.Item) @@ -730,7 +800,7 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Methods: %w", err) + return fmt.Errorf("field Methods: %w", err) } index++ @@ -749,11 +819,11 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Events: %w", err) + return fmt.Errorf("field Events: %w", err) } - return res, err + return nil } // itemToManagementContract converts stack item into *ManagementContract. @@ -761,26 +831,36 @@ func itemToManagementContract(item stackitem.Item, err error) (*ManagementContra if err != nil { return nil, err } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given stack item +// and returns an error if so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 5 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementContract) - var index = -1 + var ( + index = -1 + err error + ) index++ res.ID, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field ID: %w", err) + return fmt.Errorf("field ID: %w", err) } index++ res.UpdateCounter, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field UpdateCounter: %w", err) + return fmt.Errorf("field UpdateCounter: %w", err) } index++ @@ -796,23 +876,23 @@ func itemToManagementContract(item stackitem.Item, err error) (*ManagementContra return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Hash: %w", err) + return fmt.Errorf("field Hash: %w", err) } index++ res.NEF, err = arr[index].TryBytes() if err != nil { - return nil, fmt.Errorf("field NEF: %w", err) + return fmt.Errorf("field NEF: %w", err) } index++ res.Manifest, err = itemToManagementManifest(arr[index], nil) if err != nil { - return nil, fmt.Errorf("field Manifest: %w", err) + return fmt.Errorf("field Manifest: %w", err) } - return res, err + return nil } // itemToManagementEvent converts stack item into *ManagementEvent. @@ -820,16 +900,26 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er if err != nil { return nil, err } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given stack item +// and returns an error if so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementEvent) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Name, err = func (item stackitem.Item) (string, error) { b, err := item.TryBytes() @@ -842,7 +932,7 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er return string(b), nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Name: %w", err) + return fmt.Errorf("field Name: %w", err) } index++ @@ -861,11 +951,11 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Params: %w", err) + return fmt.Errorf("field Params: %w", err) } - return res, err + return nil } // itemToManagementGroup converts stack item into *ManagementGroup. @@ -873,16 +963,26 @@ func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, er if err != nil { return nil, err } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given stack item +// and returns an error if so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementGroup) - var index = -1 + var ( + index = -1 + err error + ) index++ res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { b, err := item.TryBytes() @@ -896,17 +996,17 @@ func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, er return k, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field PublicKey: %w", err) + return fmt.Errorf("field PublicKey: %w", err) } index++ res.Signature, err = arr[index].TryBytes() if err != nil { - return nil, fmt.Errorf("field Signature: %w", err) + return fmt.Errorf("field Signature: %w", err) } - return res, err + return nil } // itemToManagementManifest converts stack item into *ManagementManifest. @@ -914,16 +1014,26 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife if err != nil { return nil, err } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given stack item +// and returns an error if so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 8 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementManifest) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Name, err = func (item stackitem.Item) (string, error) { b, err := item.TryBytes() @@ -936,7 +1046,7 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return string(b), nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Name: %w", err) + return fmt.Errorf("field Name: %w", err) } index++ @@ -955,7 +1065,7 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Groups: %w", err) + return fmt.Errorf("field Groups: %w", err) } index++ @@ -997,7 +1107,7 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Features: %w", err) + return fmt.Errorf("field Features: %w", err) } index++ @@ -1025,13 +1135,13 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field SupportedStandards: %w", err) + return fmt.Errorf("field SupportedStandards: %w", err) } index++ res.ABI, err = itemToManagementABI(arr[index], nil) if err != nil { - return nil, fmt.Errorf("field ABI: %w", err) + return fmt.Errorf("field ABI: %w", err) } index++ @@ -1050,7 +1160,7 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Permissions: %w", err) + return fmt.Errorf("field Permissions: %w", err) } index++ @@ -1079,17 +1189,17 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Trusts: %w", err) + return fmt.Errorf("field Trusts: %w", err) } index++ res.Extra, err = arr[index].Value(), nil if err != nil { - return nil, fmt.Errorf("field Extra: %w", err) + return fmt.Errorf("field Extra: %w", err) } - return res, err + return nil } // itemToManagementMethod converts stack item into *ManagementMethod. @@ -1097,16 +1207,26 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, if err != nil { return nil, err } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given stack item +// and returns an error if so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 5 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementMethod) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Name, err = func (item stackitem.Item) (string, error) { b, err := item.TryBytes() @@ -1119,7 +1239,7 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, return string(b), nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Name: %w", err) + return fmt.Errorf("field Name: %w", err) } index++ @@ -1138,29 +1258,29 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Params: %w", err) + return fmt.Errorf("field Params: %w", err) } index++ res.ReturnType, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field ReturnType: %w", err) + return fmt.Errorf("field ReturnType: %w", err) } index++ res.Offset, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Offset: %w", err) + return fmt.Errorf("field Offset: %w", err) } index++ res.Safe, err = arr[index].TryBool() if err != nil { - return nil, fmt.Errorf("field Safe: %w", err) + return fmt.Errorf("field Safe: %w", err) } - return res, err + return nil } // itemToManagementParameter converts stack item into *ManagementParameter. @@ -1168,16 +1288,26 @@ func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParam if err != nil { return nil, err } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given stack item +// and returns an error if so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementParameter) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Name, err = func (item stackitem.Item) (string, error) { b, err := item.TryBytes() @@ -1190,17 +1320,17 @@ func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParam return string(b), nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Name: %w", err) + return fmt.Errorf("field Name: %w", err) } index++ res.Type, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Type: %w", err) + return fmt.Errorf("field Type: %w", err) } - return res, err + return nil } // itemToManagementPermission converts stack item into *ManagementPermission. @@ -1208,16 +1338,26 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm if err != nil { return nil, err } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given stack item +// and returns an error if so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 2 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(ManagementPermission) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { b, err := item.TryBytes() @@ -1231,7 +1371,7 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Contract: %w", err) + return fmt.Errorf("field Contract: %w", err) } index++ @@ -1259,11 +1399,11 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Methods: %w", err) + return fmt.Errorf("field Methods: %w", err) } - return res, err + return nil } // itemToStructsInternal converts stack item into *StructsInternal. @@ -1271,32 +1411,42 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er if err != nil { return nil, err } + var res = new(StructsInternal) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of StructsInternal from the given stack item +// and returns an error if so. +func (res *StructsInternal) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != 13 { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new(StructsInternal) - var index = -1 + var ( + index = -1 + err error + ) index++ res.Bool, err = arr[index].TryBool() if err != nil { - return nil, fmt.Errorf("field Bool: %w", err) + return fmt.Errorf("field Bool: %w", err) } index++ res.Int, err = arr[index].TryInteger() if err != nil { - return nil, fmt.Errorf("field Int: %w", err) + return fmt.Errorf("field Int: %w", err) } index++ res.Bytes, err = arr[index].TryBytes() if err != nil { - return nil, fmt.Errorf("field Bytes: %w", err) + return fmt.Errorf("field Bytes: %w", err) } index++ @@ -1311,7 +1461,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return string(b), nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field String: %w", err) + return fmt.Errorf("field String: %w", err) } index++ @@ -1327,7 +1477,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field H160: %w", err) + return fmt.Errorf("field H160: %w", err) } index++ @@ -1343,7 +1493,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return u, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field H256: %w", err) + return fmt.Errorf("field H256: %w", err) } index++ @@ -1359,7 +1509,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return k, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field PK: %w", err) + return fmt.Errorf("field PK: %w", err) } index++ @@ -1375,13 +1525,13 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return k, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field PubKey: %w", err) + return fmt.Errorf("field PubKey: %w", err) } index++ res.Sign, err = arr[index].TryBytes() if err != nil { - return nil, fmt.Errorf("field Sign: %w", err) + return fmt.Errorf("field Sign: %w", err) } index++ @@ -1400,7 +1550,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field ArrOfBytes: %w", err) + return fmt.Errorf("field ArrOfBytes: %w", err) } index++ @@ -1429,7 +1579,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field ArrOfH160: %w", err) + return fmt.Errorf("field ArrOfH160: %w", err) } index++ @@ -1476,15 +1626,15 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return res, nil } (arr[index]) if err != nil { - return nil, fmt.Errorf("field Map: %w", err) + return fmt.Errorf("field Map: %w", err) } index++ res.Struct, err = itemToStructsInternal(arr[index], nil) if err != nil { - return nil, fmt.Errorf("field Struct: %w", err) + return fmt.Errorf("field Struct: %w", err) } - return res, err + return nil } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 3db076bd7..310cee233 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -221,25 +221,35 @@ func itemTo{{toTypeName $name}}(item stackitem.Item, err error) (*{{toTypeName $ if err != nil { return nil, err } + var res = new({{toTypeName $name}}) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of {{toTypeName $name}} from the given stack item +// and returns an error if so. +func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { - return nil, errors.New("not an array") + return errors.New("not an array") } if len(arr) != {{len $typ.Fields}} { - return nil, errors.New("wrong number of structure elements") + return errors.New("wrong number of structure elements") } - var res = new({{toTypeName $name}}) -{{if len .Fields}} var index = -1 +{{if len .Fields}} var ( + index = -1 + err error + ) {{- range $m := $typ.Fields}} index++ res.{{.Field}}, err = {{etTypeConverter .ExtendedType "arr[index]"}} if err != nil { - return nil, fmt.Errorf("field {{.Field}}: %w", err) + return fmt.Errorf("field {{.Field}}: %w", err) } {{end}} {{end}} - return res, err + return nil } {{end}}` From 8beb9f23c3471e4e8d91c85a4de5c12b8eb2618a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 May 2023 12:18:26 +0300 Subject: [PATCH 078/125] smartcontract: add comments to binding config fields Signed-off-by: Anna Shaleva --- pkg/smartcontract/binding/generate.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/pkg/smartcontract/binding/generate.go b/pkg/smartcontract/binding/generate.go index c02bbd49a..3f9bca863 100644 --- a/pkg/smartcontract/binding/generate.go +++ b/pkg/smartcontract/binding/generate.go @@ -48,14 +48,22 @@ const Hash = "{{ .Hash }}" type ( // Config contains parameter for the generated binding. Config struct { - Package string `yaml:"package,omitempty"` - Manifest *manifest.Manifest `yaml:"-"` - Hash util.Uint160 `yaml:"hash,omitempty"` - Overrides map[string]Override `yaml:"overrides,omitempty"` - CallFlags map[string]callflag.CallFlag `yaml:"callflags,omitempty"` - NamedTypes map[string]ExtendedType `yaml:"namedtypes,omitempty"` - Types map[string]ExtendedType `yaml:"types,omitempty"` - Output io.Writer `yaml:"-"` + Package string `yaml:"package,omitempty"` + Manifest *manifest.Manifest `yaml:"-"` + Hash util.Uint160 `yaml:"hash,omitempty"` + Overrides map[string]Override `yaml:"overrides,omitempty"` + CallFlags map[string]callflag.CallFlag `yaml:"callflags,omitempty"` + // NamedTypes contains exported structured types that have some name (even + // if the original structure doesn't) and a number of internal fields. The + // map key is in the form of `namespace.name`, the value is fully-qualified + // and possibly nested description of the type structure. + NamedTypes map[string]ExtendedType `yaml:"namedtypes,omitempty"` + // Types contains type structure description for various types used in + // smartcontract. The map key has one of the following forms: + // - `methodName` for method return value; + // - `mathodName.paramName` for method's parameter value. + Types map[string]ExtendedType `yaml:"types,omitempty"` + Output io.Writer `yaml:"-"` } ExtendedType struct { From 0f0f7b364fcda76c52b9d94dde17cf8c80e45453 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 3 May 2023 19:18:43 +0300 Subject: [PATCH 079/125] rpcbinding: use typed return err value in etTypeConverter Otherwise the resulting code can't be compiled. Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/structs/rpcbindings.out | 4 ++-- cli/smartcontract/testdata/types/rpcbindings.out | 2 +- pkg/smartcontract/rpcbinding/binding.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index 039b15e7e..8b165ec20 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -709,7 +709,7 @@ func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { } index++ - res.Value, err = arr[index].Value(), nil + res.Value, err = arr[index].Value(), error(nil) if err != nil { return fmt.Errorf("field Value: %w", err) } @@ -1193,7 +1193,7 @@ func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { } index++ - res.Extra, err = arr[index].Value(), nil + res.Extra, err = arr[index].Value(), error(nil) if err != nil { return fmt.Errorf("field Extra: %w", err) } diff --git a/cli/smartcontract/testdata/types/rpcbindings.out b/cli/smartcontract/testdata/types/rpcbindings.out index e6a14ecea..94bf63910 100644 --- a/cli/smartcontract/testdata/types/rpcbindings.out +++ b/cli/smartcontract/testdata/types/rpcbindings.out @@ -96,7 +96,7 @@ func (c *ContractReader) Any(a any) (any, error) { if err != nil { return nil, err } - return item.Value(), nil + return item.Value(), error(nil) } (unwrap.Item(c.invoker.Call(Hash, "any", a))) } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 310cee233..6443f5c64 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -412,7 +412,7 @@ func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.Extended func etTypeConverter(et binding.ExtendedType, v string) string { switch et.Base { case smartcontract.AnyType: - return v + ".Value(), nil" + return v + ".Value(), error(nil)" case smartcontract.BoolType: return v + ".TryBool()" case smartcontract.IntegerType: From db812f7fa5601f7353a0e35f677cdb802851aee9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 26 May 2023 20:19:21 +0300 Subject: [PATCH 080/125] mempool: add test for concurrent conflicting tx addition Ref. https://github.com/neo-project/neo/pull/2818#discussion_r1206658847. Signed-off-by: Anna Shaleva --- pkg/core/mempool/mem_pool_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index dfd9e3ac7..1d6514ee8 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -541,6 +541,13 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { _, ok := mp.TryGetValue(tx13.Hash()) require.Equal(t, false, ok) require.ErrorIs(t, mp.Add(tx13, fs), ErrConflictsAttribute) + + tx14 := getConflictsTx(smallNetFee) + tx15 := getConflictsTx(smallNetFee, tx14.Hash()) + require.NoError(t, mp.Add(tx15, fs)) + require.NoError(t, mp.Add(tx14, fs)) + err := mp.Add(tx15, fs) + require.ErrorIs(t, err, ErrConflictsAttribute) } func TestMempoolAddWithDataGetData(t *testing.T) { From ae52b2c2fa8340552dbdc6025ae1cc67ea1b2d78 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 24 May 2023 11:44:31 +0300 Subject: [PATCH 081/125] rpcbinding: fix binding indentation New rule for writing blocks of code to our template: new line before the block starts and new line after the block ends. This rule is the same as the one we use during manual typing. Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 1 - cli/smartcontract/testdata/gas/gas.go | 1 - cli/smartcontract/testdata/nameservice/nns.go | 1 - cli/smartcontract/testdata/nex/nex.go | 1 - cli/smartcontract/testdata/nonepiter/iter.go | 1 - .../testdata/structs/rpcbindings.out | 18 +---- .../testdata/types/rpcbindings.out | 1 - .../testdata/verifyrpc/verify.go | 1 - pkg/smartcontract/rpcbinding/binding.go | 79 ++++++++++--------- 9 files changed, 42 insertions(+), 62 deletions(-) diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index 6756adb82..b274e99f3 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -316,7 +316,6 @@ func NewReader(invoker Invoker) *ContractReader { return &ContractReader{invoker} } - // Get invokes `+"`get`"+` method of contract. func (c *ContractReader) Get() (*big.Int, error) { return unwrap.BigInt(c.invoker.Call(Hash, "get")) diff --git a/cli/smartcontract/testdata/gas/gas.go b/cli/smartcontract/testdata/gas/gas.go index d3c938c29..d12bbb8ee 100644 --- a/cli/smartcontract/testdata/gas/gas.go +++ b/cli/smartcontract/testdata/gas/gas.go @@ -44,4 +44,3 @@ func New(actor Actor) *Contract { var nep17t = nep17.New(actor, Hash) return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} } - diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index efdfcabfe..c279951ea 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -59,7 +59,6 @@ func New(actor Actor) *Contract { return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor}, nep11ndt.BaseWriter, actor} } - // Roots invokes `roots` method of contract. func (c *ContractReader) Roots() (uuid.UUID, result.Iterator, error) { return unwrap.SessionIterator(c.invoker.Call(Hash, "roots")) diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 4a4a46de4..068fc1987 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -56,7 +56,6 @@ func New(actor Actor) *Contract { return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} } - // Cap invokes `cap` method of contract. func (c *ContractReader) Cap() (*big.Int, error) { return unwrap.BigInt(c.invoker.Call(Hash, "cap")) diff --git a/cli/smartcontract/testdata/nonepiter/iter.go b/cli/smartcontract/testdata/nonepiter/iter.go index e04f6953c..f298ab8de 100644 --- a/cli/smartcontract/testdata/nonepiter/iter.go +++ b/cli/smartcontract/testdata/nonepiter/iter.go @@ -30,7 +30,6 @@ func NewReader(invoker Invoker) *ContractReader { return &ContractReader{invoker} } - // Tokens invokes `tokens` method of contract. func (c *ContractReader) Tokens() (uuid.UUID, result.Iterator, error) { return unwrap.SessionIterator(c.invoker.Call(Hash, "tokens")) diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index 8b165ec20..29af22323 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -17,7 +17,6 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} - // LedgerBlock is a contract-specific ledger.Block type used by its methods. type LedgerBlock struct { Hash util.Uint256 @@ -154,6 +153,7 @@ type StructsInternal struct { Map map[*big.Int]keys.PublicKeys Struct *StructsInternal } + // Invoker is used by ContractReader to call various safe methods. type Invoker interface { Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) @@ -169,7 +169,6 @@ func NewReader(invoker Invoker) *ContractReader { return &ContractReader{invoker} } - // Block invokes `block` method of contract. func (c *ContractReader) Block(b *LedgerBlock) (*LedgerBlock, error) { return itemToLedgerBlock(unwrap.Item(c.invoker.Call(Hash, "block", b))) @@ -309,7 +308,6 @@ func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field TransactionsLength: %w", err) } - return nil } @@ -448,7 +446,6 @@ func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field PrevStateRoot: %w", err) } - return nil } @@ -545,7 +542,6 @@ func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Script: %w", err) } - return nil } @@ -673,7 +669,6 @@ func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Rules: %w", err) } - return nil } @@ -714,7 +709,6 @@ func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Value: %w", err) } - return nil } @@ -755,7 +749,6 @@ func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Condition: %w", err) } - return nil } @@ -822,7 +815,6 @@ func (res *ManagementABI) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Events: %w", err) } - return nil } @@ -891,7 +883,6 @@ func (res *ManagementContract) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Manifest: %w", err) } - return nil } @@ -954,7 +945,6 @@ func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Params: %w", err) } - return nil } @@ -1005,7 +995,6 @@ func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Signature: %w", err) } - return nil } @@ -1198,7 +1187,6 @@ func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Extra: %w", err) } - return nil } @@ -1279,7 +1267,6 @@ func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Safe: %w", err) } - return nil } @@ -1329,7 +1316,6 @@ func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Type: %w", err) } - return nil } @@ -1402,7 +1388,6 @@ func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Methods: %w", err) } - return nil } @@ -1635,6 +1620,5 @@ func (res *StructsInternal) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field Struct: %w", err) } - return nil } diff --git a/cli/smartcontract/testdata/types/rpcbindings.out b/cli/smartcontract/testdata/types/rpcbindings.out index 94bf63910..ca4f0ce36 100644 --- a/cli/smartcontract/testdata/types/rpcbindings.out +++ b/cli/smartcontract/testdata/types/rpcbindings.out @@ -31,7 +31,6 @@ func NewReader(invoker Invoker) *ContractReader { return &ContractReader{invoker} } - // AAAStrings invokes `aAAStrings` method of contract. func (c *ContractReader) AAAStrings(s [][][]string) ([][][]string, error) { return func (item stackitem.Item, err error) ([][][]string, error) { diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index 4a9af0156..a614c36cf 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -30,7 +30,6 @@ func New(actor Actor) *Contract { return &Contract{actor} } - func scriptForVerify() ([]byte, error) { return smartcontract.CreateCallWithAssertScript(Hash, "verify") } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 6443f5c64..58ed76240 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -12,8 +12,12 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest/standard" ) -const srcTmpl = ` -{{- define "SAFEMETHOD" -}} +// The set of constants containing parts of RPC binding template. Each block of code +// including template definition and var/type/method definitions contain new line at the +// start and ends with a new line. On adding new block of code to the template, please, +// ensure that this block has new line at the start and in the end of the block. +const ( + safemethodDefinition = `{{ define "SAFEMETHOD" }} // {{.Name}} {{.Comment}} func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} @@ -32,8 +36,7 @@ func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}} {{- range $arg := .Arguments -}}, {{.Name}}{{end}}) {{- end}} } -{{- if eq .Unwrapper "SessionIterator"}} - +{{ if eq .Unwrapper "SessionIterator" }} // {{.Name}}Expanded is similar to {{.Name}} (uses the same contract // method), but can be useful if the server used doesn't support sessions and // doesn't expand iterators. It creates a script that will get the specified @@ -42,17 +45,16 @@ func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}} func (c *ContractReader) {{.Name}}Expanded({{range $index, $arg := .Arguments}}{{.Name}} {{.Type}}, {{end}}_numOfIteratorItems int) ([]stackitem.Item, error) { return unwrap.Array(c.invoker.CallAndExpandIterator(Hash, "{{.NameABI}}", _numOfIteratorItems{{range $arg := .Arguments}}, {{.Name}}{{end}})) } -{{- end -}} -{{- end -}} -{{- define "METHOD" -}} -{{- if eq .ReturnType "bool"}}func scriptFor{{.Name}}({{range $index, $arg := .Arguments -}} +{{ end }}{{ end }}` + methodDefinition = `{{ define "METHOD" }}{{ if eq .ReturnType "bool"}} +func scriptFor{{.Name}}({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} {{- .Name}} {{.Type}} {{- end}}) ([]byte, error) { return smartcontract.CreateCallWithAssertScript(Hash, "{{ .NameABI }}"{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}) } - -{{end}}// {{.Name}} {{.Comment}} +{{ end }} +// {{.Name}} {{.Comment}} // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) {{.Name}}({{range $index, $arg := .Arguments -}} @@ -97,8 +99,9 @@ func (c *Contract) {{.Name}}Unsigned({{range $index, $arg := .Arguments -}} } return c.actor.MakeUnsignedRun(script, nil){{end}} } -{{- end -}} -// Package {{.PackageName}} contains RPC wrappers for {{.ContractName}} contract. +{{end}}` + + bindingDefinition = `// Package {{.PackageName}} contains RPC wrappers for {{.ContractName}} contract. package {{.PackageName}} import ( @@ -107,16 +110,16 @@ import ( // Hash contains contract hash. var Hash = {{ .Hash }} - -{{range $name, $typ := .NamedTypes}} +{{ range $name, $typ := .NamedTypes }} // {{toTypeName $name}} is a contract-specific {{$name}} type used by its methods. type {{toTypeName $name}} struct { {{- range $m := $typ.Fields}} {{.Field}} {{etTypeToStr .ExtendedType}} {{- end}} } -{{end -}} -{{if .HasReader}}// Invoker is used by ContractReader to call various safe methods. +{{end}} +{{- if .HasReader}} +// Invoker is used by ContractReader to call various safe methods. type Invoker interface { {{if or .IsNep11D .IsNep11ND}} nep11.Invoker {{else -}} @@ -129,9 +132,9 @@ type Invoker interface { {{end -}} {{end -}} } - {{end -}} -{{if .HasWriter}}// Actor is used by Contract to call state-changing methods. +{{- if .HasWriter}} +// Actor is used by Contract to call state-changing methods. type Actor interface { {{- if .HasReader}} Invoker @@ -150,9 +153,9 @@ type Actor interface { SendRun(script []byte) (util.Uint256, uint32, error) {{end -}} } - {{end -}} -{{if .HasReader}}// ContractReader implements safe contract methods. +{{- if .HasReader}} +// ContractReader implements safe contract methods. type ContractReader struct { {{if .IsNep11D}}nep11.DivisibleReader {{end -}} @@ -162,9 +165,9 @@ type ContractReader struct { {{end -}} invoker Invoker } - {{end -}} -{{if .HasWriter}}// Contract implements all contract methods. +{{- if .HasWriter}} +// Contract implements all contract methods. type Contract struct { {{if .HasReader}}ContractReader {{end -}} @@ -176,9 +179,9 @@ type Contract struct { {{end -}} actor Actor } - {{end -}} -{{if .HasReader}}// NewReader creates an instance of ContractReader using Hash and the given Invoker. +{{- if .HasReader}} +// NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { return &ContractReader{ {{- if .IsNep11D}}*nep11.NewDivisibleReader(invoker, Hash), {{end}} @@ -186,9 +189,9 @@ func NewReader(invoker Invoker) *ContractReader { {{- if .IsNep17}}*nep17.NewReader(invoker, Hash), {{end -}} invoker} } - {{end -}} -{{if .HasWriter}}// New creates an instance of Contract using Hash and the given Actor. +{{- if .HasWriter}} +// New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { {{if .IsNep11D}}var nep11dt = nep11.NewDivisible(actor, Hash) {{end -}} @@ -207,15 +210,10 @@ func New(actor Actor) *Contract { {{- if .IsNep17}}nep17t.TokenWriter, {{end -}} actor} } - {{end -}} -{{range $m := .SafeMethods}} -{{template "SAFEMETHOD" $m }} -{{end}} -{{- range $m := .Methods}} -{{template "METHOD" $m }} -{{end}} -{{- range $name, $typ := .NamedTypes}} +{{- range $m := .SafeMethods }}{{template "SAFEMETHOD" $m }}{{ end -}} +{{- range $m := .Methods -}}{{template "METHOD" $m }}{{ end -}} +{{- range $name, $typ := .NamedTypes }} // itemTo{{toTypeName $name}} converts stack item into *{{toTypeName $name}}. func itemTo{{toTypeName $name}}(item stackitem.Item, err error) (*{{toTypeName $name}}, error) { if err != nil { @@ -236,8 +234,8 @@ func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { if len(arr) != {{len $typ.Fields}} { return errors.New("wrong number of structure elements") } - -{{if len .Fields}} var ( +{{if len .Fields}} + var ( index = -1 err error ) @@ -248,10 +246,15 @@ func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { return fmt.Errorf("field {{.Field}}: %w", err) } {{end}} -{{end}} +{{- end}} return nil } -{{end}}` +{{end -}}` + + srcTmpl = bindingDefinition + + safemethodDefinition + + methodDefinition +) type ( ContractTmpl struct { From 044ae477ca08ada8879cf438cc53b5c8463ca711 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 24 May 2023 11:52:14 +0300 Subject: [PATCH 082/125] smartconract: generate RPC binding wrappers for events Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/gas/gas.go | 96 ++++++ cli/smartcontract/testdata/nameservice/nns.go | 280 ++++++++++++++++++ cli/smartcontract/testdata/nex/nex.go | 193 ++++++++++++ .../testdata/verifyrpc/verify.go | 74 +++++ pkg/compiler/codegen.go | 4 +- pkg/compiler/compiler.go | 37 ++- pkg/compiler/debug.go | 19 +- pkg/compiler/inline.go | 62 ++-- pkg/smartcontract/binding/generate.go | 1 + pkg/smartcontract/rpcbinding/binding.go | 174 ++++++++++- 10 files changed, 896 insertions(+), 44 deletions(-) diff --git a/cli/smartcontract/testdata/gas/gas.go b/cli/smartcontract/testdata/gas/gas.go index d12bbb8ee..2b4cf920a 100644 --- a/cli/smartcontract/testdata/gas/gas.go +++ b/cli/smartcontract/testdata/gas/gas.go @@ -2,13 +2,25 @@ package gastoken import ( + "errors" + "fmt" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" ) // Hash contains contract hash. var Hash = util.Uint160{0xcf, 0x76, 0xe2, 0x8b, 0xd0, 0x6, 0x2c, 0x4a, 0x47, 0x8e, 0xe3, 0x55, 0x61, 0x1, 0x13, 0x19, 0xf3, 0xcf, 0xa4, 0xd2} +// TransferEvent represents "Transfer" event emitted by the contract. +type TransferEvent struct { + From util.Uint160 + To util.Uint160 + Amount *big.Int +} + // Invoker is used by ContractReader to call various safe methods. type Invoker interface { nep17.Invoker @@ -44,3 +56,87 @@ func New(actor Actor) *Contract { var nep17t = nep17.New(actor, Hash) return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} } + +// TransferEventsFromApplicationLog retrieves a set of all emitted events +// with "Transfer" name from the provided ApplicationLog. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to TransferEvent and +// returns an error if so. +func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index c279951ea..8bb311bb9 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -2,6 +2,8 @@ package nameservice import ( + "errors" + "fmt" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" @@ -16,6 +18,28 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0xde, 0x46, 0x5f, 0x5d, 0x50, 0x57, 0xcf, 0x33, 0x28, 0x47, 0x94, 0xc5, 0xcf, 0xc2, 0xc, 0x69, 0x37, 0x1c, 0xac, 0x50} +// TransferEvent represents "Transfer" event emitted by the contract. +type TransferEvent struct { + From util.Uint160 + To util.Uint160 + Amount *big.Int + TokenId []byte +} + +// SetAdminEvent represents "SetAdmin" event emitted by the contract. +type SetAdminEvent struct { + Name string + OldAdmin util.Uint160 + NewAdmin util.Uint160 +} + +// RenewEvent represents "Renew" event emitted by the contract. +type RenewEvent struct { + Name string + OldExpiration *big.Int + NewExpiration *big.Int +} + // Invoker is used by ContractReader to call various safe methods. type Invoker interface { nep11.Invoker @@ -320,3 +344,259 @@ func (c *Contract) DeleteRecordTransaction(name string, typev *big.Int) (*transa func (c *Contract) DeleteRecordUnsigned(name string, typev *big.Int) (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(Hash, "deleteRecord", nil, name, typev) } + +// TransferEventsFromApplicationLog retrieves a set of all emitted events +// with "Transfer" name from the provided ApplicationLog. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to TransferEvent and +// returns an error if so. +func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.TokenId, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field TokenId: %w", err) + } + + return nil +} + +// SetAdminEventsFromApplicationLog retrieves a set of all emitted events +// with "SetAdmin" name from the provided ApplicationLog. +func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SetAdminEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SetAdmin" { + continue + } + event := new(SetAdminEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SetAdminEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SetAdminEvent and +// returns an error if so. +func (e *SetAdminEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + e.OldAdmin, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field OldAdmin: %w", err) + } + + index++ + e.NewAdmin, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NewAdmin: %w", err) + } + + return nil +} + +// RenewEventsFromApplicationLog retrieves a set of all emitted events +// with "Renew" name from the provided ApplicationLog. +func RenewEventsFromApplicationLog(log *result.ApplicationLog) ([]*RenewEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*RenewEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Renew" { + continue + } + event := new(RenewEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize RenewEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to RenewEvent and +// returns an error if so. +func (e *RenewEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + e.OldExpiration, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field OldExpiration: %w", err) + } + + index++ + e.NewExpiration, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NewExpiration: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 068fc1987..41de92d02 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -2,17 +2,36 @@ package nextoken import ( + "errors" + "fmt" "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/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "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" "math/big" ) // Hash contains contract hash. var Hash = util.Uint160{0xa8, 0x1a, 0xa1, 0xf0, 0x4b, 0xf, 0xdc, 0x4a, 0xa2, 0xce, 0xd5, 0xbf, 0xc6, 0x22, 0xcf, 0xe8, 0x9, 0x7f, 0xa6, 0xa2} +// TransferEvent represents "Transfer" event emitted by the contract. +type TransferEvent struct { + From util.Uint160 + To util.Uint160 + Amount *big.Int +} + +// OnMintEvent represents "OnMint" event emitted by the contract. +type OnMintEvent struct { + From util.Uint160 + To util.Uint160 + Amount *big.Int + SwapId *big.Int +} + // Invoker is used by ContractReader to call various safe methods. type Invoker interface { nep17.Invoker @@ -229,3 +248,177 @@ func (c *Contract) UpdateCapTransaction(newCap *big.Int) (*transaction.Transacti func (c *Contract) UpdateCapUnsigned(newCap *big.Int) (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(Hash, "updateCap", nil, newCap) } + +// TransferEventsFromApplicationLog retrieves a set of all emitted events +// with "Transfer" name from the provided ApplicationLog. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to TransferEvent and +// returns an error if so. +func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + return nil +} + +// OnMintEventsFromApplicationLog retrieves a set of all emitted events +// with "OnMint" name from the provided ApplicationLog. +func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*OnMintEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "OnMint" { + continue + } + event := new(OnMintEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize OnMintEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to OnMintEvent and +// returns an error if so. +func (e *OnMintEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.From, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field From: %w", err) + } + + index++ + e.To, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field To: %w", err) + } + + index++ + e.Amount, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Amount: %w", err) + } + + index++ + e.SwapId, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SwapId: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index a614c36cf..6835a7e4e 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -2,14 +2,23 @@ package verify import ( + "errors" + "fmt" "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" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // Hash contains contract hash. var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} +// HelloWorldEvent represents "Hello world!" event emitted by the contract. +type HelloWorldEvent struct { + Args []any +} + // Actor is used by Contract to call state-changing methods. type Actor interface { MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) @@ -67,3 +76,68 @@ func (c *Contract) VerifyUnsigned() (*transaction.Transaction, error) { } return c.actor.MakeUnsignedRun(script, nil) } + +// HelloWorldEventsFromApplicationLog retrieves a set of all emitted events +// with "Hello world!" name from the provided ApplicationLog. +func HelloWorldEventsFromApplicationLog(log *result.ApplicationLog) ([]*HelloWorldEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*HelloWorldEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Hello world!" { + continue + } + event := new(HelloWorldEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize HelloWorldEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to HelloWorldEvent and +// returns an error if so. +func (e *HelloWorldEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.Args, err = func (item stackitem.Item) ([]any, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]any, len(arr)) + for i := range res { + res[i], err = arr[i].Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Args: %w", err) + } + + return nil +} diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 14793c8ad..4ee702626 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -110,7 +110,7 @@ type codegen struct { docIndex map[string]int // emittedEvents contains all events emitted by the contract. - emittedEvents map[string][][]string + emittedEvents map[string][]EmittedEventInfo // invokedContracts contains invoked methods of other contracts. invokedContracts map[util.Uint160][]string @@ -2269,7 +2269,7 @@ func newCodegen(info *buildInfo, pkg *packages.Package) *codegen { initEndOffset: -1, deployEndOffset: -1, - emittedEvents: make(map[string][][]string), + emittedEvents: make(map[string][]EmittedEventInfo), invokedContracts: make(map[util.Uint160][]string), sequencePoints: make(map[string][]DebugSeqPoint), } diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 60a45525c..aec697006 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -309,6 +309,22 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { if len(di.NamedTypes) > 0 { cfg.NamedTypes = di.NamedTypes } + if len(di.EmittedEvents) > 0 { + for eventName, eventUsages := range di.EmittedEvents { + for typeName, extType := range eventUsages[0].ExtTypes { + cfg.NamedTypes[typeName] = extType + } + for _, p := range eventUsages[0].Params { + pname := eventName + "." + p.Name + if p.RealType.TypeName != "" { + cfg.Overrides[pname] = p.RealType + } + if p.ExtendedType != nil { + cfg.Types[pname] = *p.ExtendedType + } + } + } + } data, err := yaml.Marshal(&cfg) if err != nil { return nil, fmt.Errorf("can't marshal bindings configuration: %w", err) @@ -366,24 +382,23 @@ func CreateManifest(di *DebugInfo, o *Options) (*manifest.Manifest, error) { } if !o.NoEventsCheck { for name := range di.EmittedEvents { - ev := m.ABI.GetEvent(name) - if ev == nil { + expected := m.ABI.GetEvent(name) + if expected == nil { return nil, fmt.Errorf("event '%s' is emitted but not specified in manifest", name) } - argsList := di.EmittedEvents[name] - for i := range argsList { - if len(argsList[i]) != len(ev.Parameters) { + for _, emitted := range di.EmittedEvents[name] { + if len(emitted.Params) != len(expected.Parameters) { return nil, fmt.Errorf("event '%s' should have %d parameters but has %d", - name, len(ev.Parameters), len(argsList[i])) + name, len(expected.Parameters), len(emitted.Params)) } - for j := range ev.Parameters { - if ev.Parameters[j].Type == smartcontract.AnyType { + for j := range expected.Parameters { + if expected.Parameters[j].Type == smartcontract.AnyType { continue } - expected := ev.Parameters[j].Type.String() - if argsList[i][j] != expected { + expectedT := expected.Parameters[j].Type + if emitted.Params[j].TypeSC != expectedT { return nil, fmt.Errorf("event '%s' should have '%s' as type of %d parameter, "+ - "got: %s", name, expected, j+1, argsList[i][j]) + "got: %s", name, expectedT, j+1, emitted.Params[j].TypeSC) } } } diff --git a/pkg/compiler/debug.go b/pkg/compiler/debug.go index 82e2e49f7..88fcbb119 100644 --- a/pkg/compiler/debug.go +++ b/pkg/compiler/debug.go @@ -29,9 +29,14 @@ type DebugInfo struct { // NamedTypes are exported structured types that have some name (even // if the original structure doesn't) and a number of internal fields. NamedTypes map[string]binding.ExtendedType `json:"-"` - Events []EventDebugInfo `json:"events"` - // EmittedEvents contains events occurring in code. - EmittedEvents map[string][][]string `json:"-"` + // Events are the events that contract is allowed to emit and that have to + // be presented in the resulting contract manifest and debug info file. + Events []EventDebugInfo `json:"events"` + // EmittedEvents contains events occurring in code, i.e. events emitted + // via runtime.Notify(...) call in the contract code if they have constant + // names and doesn't have ellipsis arguments. EmittedEvents are not related + // to the debug info and are aimed to serve bindings generation. + EmittedEvents map[string][]EmittedEventInfo `json:"-"` // InvokedContracts contains foreign contract invocations. InvokedContracts map[util.Uint160][]string `json:"-"` // StaticVariables contains a list of static variable names and types. @@ -112,6 +117,14 @@ type DebugParam struct { TypeSC smartcontract.ParamType `json:"-"` } +// EmittedEventInfo describes information about single emitted event got from +// the contract code. It has the map of extended types used as the parameters to +// runtime.Notify(...) call (if any) and the parameters info itself. +type EmittedEventInfo struct { + ExtTypes map[string]binding.ExtendedType + Params []DebugParam +} + func (c *codegen) saveSequencePoint(n ast.Node) { name := "init" if c.scope != nil { diff --git a/pkg/compiler/inline.go b/pkg/compiler/inline.go index 1653d8638..b6cd03d3b 100644 --- a/pkg/compiler/inline.go +++ b/pkg/compiler/inline.go @@ -7,6 +7,7 @@ import ( "go/types" "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/binding" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -172,11 +173,21 @@ func (c *codegen) processNotify(f *funcScope, args []ast.Expr, hasEllipsis bool) return nil } - params := make([]string, 0, len(args[1:])) + params := make([]DebugParam, 0, len(args[1:])) vParams := make([]*stackitem.Type, 0, len(args[1:])) + // extMap holds the extended parameter types used for the given event call. + // It will be unified with the common extMap later during bindings config + // generation. + extMap := make(map[string]binding.ExtendedType) for _, p := range args[1:] { - st, vt, _, _ := c.scAndVMTypeFromExpr(p, nil) - params = append(params, st.String()) + st, vt, over, extT := c.scAndVMTypeFromExpr(p, extMap) + params = append(params, DebugParam{ + Name: "", // Parameter name will be filled in several lines below if the corresponding event exists in the buildinfo.options. + Type: vt.String(), + RealType: over, + ExtendedType: extT, + TypeSC: st, + }) vParams = append(vParams, &vt) } @@ -187,36 +198,43 @@ func (c *codegen) processNotify(f *funcScope, args []ast.Expr, hasEllipsis bool) return nil } var eventFound bool - if c.buildInfo.options != nil && c.buildInfo.options.ContractEvents != nil && !c.buildInfo.options.NoEventsCheck { + if c.buildInfo.options != nil && c.buildInfo.options.ContractEvents != nil { for _, e := range c.buildInfo.options.ContractEvents { if e.Name == name && len(e.Parameters) == len(vParams) { eventFound = true for i, scParam := range e.Parameters { - expectedType := scParam.Type.ConvertToStackitemType() - // No need to cast if the desired type is unknown. - if expectedType == stackitem.AnyT || - // Do not cast if desired type is Interop, the actual type is likely to be Any, leave the resolving to runtime.Notify. - expectedType == stackitem.InteropT || - // No need to cast if actual parameter type matches the desired one. - *vParams[i] == expectedType || - // expectedType doesn't contain Buffer anyway, but if actual variable type is Buffer, - // then runtime.Notify will convert it to ByteArray automatically, thus no need to emit conversion code. - (*vParams[i] == stackitem.BufferT && expectedType == stackitem.ByteArrayT) { - vParams[i] = nil - } else { - // For other cases the conversion code will be emitted using vParams... - vParams[i] = &expectedType - // ...thus, update emitted notification info in advance. - params[i] = scParam.Type.String() + params[i].Name = scParam.Name + if !c.buildInfo.options.NoEventsCheck { + expectedType := scParam.Type.ConvertToStackitemType() + // No need to cast if the desired type is unknown. + if expectedType == stackitem.AnyT || + // Do not cast if desired type is Interop, the actual type is likely to be Any, leave the resolving to runtime.Notify. + expectedType == stackitem.InteropT || + // No need to cast if actual parameter type matches the desired one. + *vParams[i] == expectedType || + // expectedType doesn't contain Buffer anyway, but if actual variable type is Buffer, + // then runtime.Notify will convert it to ByteArray automatically, thus no need to emit conversion code. + (*vParams[i] == stackitem.BufferT && expectedType == stackitem.ByteArrayT) { + vParams[i] = nil + } else { + // For other cases the conversion code will be emitted using vParams... + vParams[i] = &expectedType + // ...thus, update emitted notification info in advance. + params[i].Type = scParam.Type.String() + params[i].TypeSC = scParam.Type + } } } } } } - c.emittedEvents[name] = append(c.emittedEvents[name], params) + c.emittedEvents[name] = append(c.emittedEvents[name], EmittedEventInfo{ + ExtTypes: extMap, + Params: params, + }) // Do not enforce perfect expected/actual events match on this step, the final // check wil be performed after compilation if --no-events option is off. - if eventFound { + if eventFound && !c.buildInfo.options.NoEventsCheck { return vParams } return nil diff --git a/pkg/smartcontract/binding/generate.go b/pkg/smartcontract/binding/generate.go index 3f9bca863..bf3e3d9a1 100644 --- a/pkg/smartcontract/binding/generate.go +++ b/pkg/smartcontract/binding/generate.go @@ -62,6 +62,7 @@ type ( // smartcontract. The map key has one of the following forms: // - `methodName` for method return value; // - `mathodName.paramName` for method's parameter value. + // - `eventName.paramName` for event's parameter value. Types map[string]ExtendedType `yaml:"types,omitempty"` Output io.Writer `yaml:"-"` } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 58ed76240..973264c78 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -5,6 +5,7 @@ import ( "sort" "strings" "text/template" + "unicode" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/binding" @@ -17,6 +18,15 @@ import ( // start and ends with a new line. On adding new block of code to the template, please, // ensure that this block has new line at the start and in the end of the block. const ( + eventDefinition = `{{ define "EVENT" }} +// {{.Name}}Event represents "{{.ManifestName}}" event emitted by the contract. +type {{.Name}}Event struct { + {{- range $index, $arg := .Parameters}} + {{toPascalCase .Name}} {{.Type}} + {{- end}} +} +{{ end }}` + safemethodDefinition = `{{ define "SAFEMETHOD" }} // {{.Name}} {{.Comment}} func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}} @@ -118,6 +128,7 @@ type {{toTypeName $name}} struct { {{- end}} } {{end}} +{{- range $e := .CustomEvents }}{{template "EVENT" $e }}{{ end -}} {{- if .HasReader}} // Invoker is used by ContractReader to call various safe methods. type Invoker interface { @@ -249,9 +260,65 @@ func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { {{- end}} return nil } +{{ end -}} +{{- range $e := .CustomEvents }} +// {{$e.Name}}EventsFromApplicationLog retrieves a set of all emitted events +// with "{{$e.ManifestName}}" name from the provided ApplicationLog. +func {{$e.Name}}EventsFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}Event, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*{{$e.Name}}Event + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "{{$e.ManifestName}}" { + continue + } + event := new({{$e.Name}}Event) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize {{$e.Name}}Event from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to {{$e.Name}}Event and +// returns an error if so. +func (e *{{$e.Name}}Event) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != {{len $e.Parameters}} { + return errors.New("wrong number of structure elements") + } + + {{if len $e.Parameters}}var ( + index = -1 + err error + ) + {{- range $p := $e.Parameters}} + index++ + e.{{toPascalCase .Name}}, err = {{etTypeConverter .ExtType "arr[index]"}} + if err != nil { + return fmt.Errorf("field {{toPascalCase .Name}}: %w", err) + } +{{end}} +{{- end}} + return nil +} {{end -}}` srcTmpl = bindingDefinition + + eventDefinition + safemethodDefinition + methodDefinition ) @@ -260,8 +327,9 @@ type ( ContractTmpl struct { binding.ContractTmpl - SafeMethods []SafeMethodTmpl - NamedTypes map[string]binding.ExtendedType + SafeMethods []SafeMethodTmpl + CustomEvents []CustomEventTemplate + NamedTypes map[string]binding.ExtendedType IsNep11D bool IsNep11ND bool @@ -278,6 +346,25 @@ type ( ItemTo string ExtendedReturn binding.ExtendedType } + + CustomEventTemplate struct { + // Name is the event's name that will be used as the event structure name in + // the resulting RPC binding. It is a valid go structure name and may differ + // from ManifestName. + Name string + // ManifestName is the event's name declared in the contract manifest. + // It may contain any UTF8 character. + ManifestName string + Parameters []EventParamTmpl + } + + EventParamTmpl struct { + binding.ParamTmpl + + // ExtType holds the event parameter's type information provided by Manifest, + // i.e. simple types only. + ExtType binding.ExtendedType + } ) // NewConfig initializes and returns a new config instance. @@ -328,7 +415,7 @@ func Generate(cfg binding.Config) error { } ctr.ContractTmpl = binding.TemplateFromManifest(cfg, scTypeToGo) - ctr = scTemplateToRPC(cfg, ctr, imports) + ctr = scTemplateToRPC(cfg, ctr, imports, scTypeToGo) ctr.NamedTypes = cfg.NamedTypes var srcTemplate = template.Must(template.New("generate").Funcs(template.FuncMap{ @@ -338,8 +425,9 @@ func Generate(cfg binding.Config) error { r, _ := extendedTypeToGo(et, ctr.NamedTypes) return r }, - "toTypeName": toTypeName, - "cutPointer": cutPointer, + "toTypeName": toTypeName, + "cutPointer": cutPointer, + "toPascalCase": toPascalCase, }).Parse(srcTmpl)) return srcTemplate.Execute(cfg.Output, ctr) @@ -533,7 +621,7 @@ func scTypeToGo(name string, typ smartcontract.ParamType, cfg *binding.Config) ( return extendedTypeToGo(et, cfg.NamedTypes) } -func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]struct{}) ContractTmpl { +func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]struct{}, scTypeConverter func(string, smartcontract.ParamType, *binding.Config) (string, string)) ContractTmpl { for i := range ctr.Imports { imports[ctr.Imports[i]] = struct{}{} } @@ -564,6 +652,51 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st if len(cfg.NamedTypes) > 0 { imports["errors"] = struct{}{} } + for _, abiEvent := range cfg.Manifest.ABI.Events { + eTmp := CustomEventTemplate{ + // TODO: proper event name is better to be set right into config binding in normal form. + Name: toPascalCase(abiEvent.Name), + ManifestName: abiEvent.Name, + } + var varnames = make(map[string]bool) + for i := range abiEvent.Parameters { + name := abiEvent.Parameters[i].Name + fullPName := abiEvent.Name + "." + name + typeStr, pkg := scTypeConverter(fullPName, abiEvent.Parameters[i].Type, &cfg) + if pkg != "" { + imports[pkg] = struct{}{} + } + for varnames[name] { + name = name + "_" + } + varnames[name] = true + + var ( + extType binding.ExtendedType + ok bool + ) + if extType, ok = cfg.Types[fullPName]; !ok { + extType = binding.ExtendedType{ + Base: abiEvent.Parameters[i].Type, + } + } + eTmp.Parameters = append(eTmp.Parameters, EventParamTmpl{ + ParamTmpl: binding.ParamTmpl{ + Name: name, + Type: typeStr, + }, + ExtType: extType, + }) + } + ctr.CustomEvents = append(ctr.CustomEvents, eTmp) + } + + if len(ctr.CustomEvents) > 0 { + imports["github.com/nspcc-dev/neo-go/pkg/neorpc/result"] = struct{}{} + imports["github.com/nspcc-dev/neo-go/pkg/vm/stackitem"] = struct{}{} + imports["fmt"] = struct{}{} + imports["errors"] = struct{}{} + } for i := range ctr.SafeMethods { switch ctr.SafeMethods[i].ReturnType { @@ -693,3 +826,32 @@ func toTypeName(s string) string { func addIndent(str string, ind string) string { return strings.ReplaceAll(str, "\n", "\n"+ind) } + +// toPascalCase removes all non-unicode characters from the provided string and +// converts it to pascal case using space as delimiter. +func toPascalCase(s string) string { + var res string + ss := strings.Split(s, " ") + for i := range ss { // TODO: use DecodeRuneInString instead. + var word string + for _, ch := range ss[i] { + var ok bool + if len(res) == 0 && len(word) == 0 { + ok = unicode.IsLetter(ch) + } else { + ok = unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_' + } + if ok { + word += string(ch) + } + } + if len(word) > 0 { + res += upperFirst(word) + } + } + return res +} + +func upperFirst(s string) string { + return strings.ToUpper(s[0:1]) + s[1:] +} From 194639bb153f9cab3655c8c92927561133aaaded Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 5 May 2023 16:57:07 +0300 Subject: [PATCH 083/125] compiler: fix typo in the method description Signed-off-by: Anna Shaleva --- pkg/compiler/debug.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/compiler/debug.go b/pkg/compiler/debug.go index 88fcbb119..c720fcbc5 100644 --- a/pkg/compiler/debug.go +++ b/pkg/compiler/debug.go @@ -108,7 +108,7 @@ type DebugRange struct { End uint16 } -// DebugParam represents the variables's name and type. +// DebugParam represents the variable's name and type. type DebugParam struct { Name string `json:"name"` Type string `json:"type"` From e2580187a1447bca3169a8a87fc6249f05f2e6d4 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 8 May 2023 21:58:28 +0300 Subject: [PATCH 084/125] cli: fetch extended evet types from contract config The user should specify it via parameter's `extendedtype` field and via upper-level `namedtypes` field of the contract configuration YAML. Also, as we have proper event structure source, make the `--guess-eventtype` compilation option and make event types guess optional. Signed-off-by: Anna Shaleva --- cli/smartcontract/smart_contract.go | 25 +++++-- docs/compiler.md | 105 +++++++++++++++++++++++++++- internal/testchain/transaction.go | 1 + pkg/compiler/compiler.go | 77 ++++++++++++++++---- pkg/compiler/compiler_test.go | 22 +++--- pkg/compiler/debug.go | 13 +++- pkg/compiler/interop_test.go | 8 +-- pkg/neotest/compile.go | 1 + 8 files changed, 216 insertions(+), 36 deletions(-) diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 5a2af4685..38dea5f13 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -24,6 +24,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/binding" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" @@ -125,7 +126,7 @@ func NewCommands() []cli.Command { { Name: "compile", Usage: "compile a smart contract to a .nef file", - UsageText: "neo-go contract compile -i path [-o nef] [-v] [-d] [-m manifest] [-c yaml] [--bindings file] [--no-standards] [--no-events] [--no-permissions]", + UsageText: "neo-go contract compile -i path [-o nef] [-v] [-d] [-m manifest] [-c yaml] [--bindings file] [--no-standards] [--no-events] [--no-permissions] [--guess-eventtypes]", Description: `Compiles given smart contract to a .nef file and emits other associated information (manifest, bindings configuration, debug information files) if asked to. If none of --out, --manifest, --config, --bindings flags are specified, @@ -171,6 +172,10 @@ func NewCommands() []cli.Command { Name: "no-permissions", Usage: "do not check if invoked contracts are allowed in manifest", }, + cli.BoolFlag{ + Name: "guess-eventtypes", + Usage: "guess event types for smart-contract bindings configuration from the code usages", + }, cli.StringFlag{ Name: "bindings", Usage: "output file for smart-contract bindings configuration", @@ -352,13 +357,15 @@ func initSmartContract(ctx *cli.Context) error { SourceURL: "http://example.com/", SupportedStandards: []string{}, SafeMethods: []string{}, - Events: []manifest.Event{ + Events: []compiler.HybridEvent{ { Name: "Hello world!", - Parameters: []manifest.Parameter{ + Parameters: []compiler.HybridParameter{ { - Name: "args", - Type: smartcontract.ArrayType, + Parameter: manifest.Parameter{ + Name: "args", + Type: smartcontract.ArrayType, + }, }, }, }, @@ -447,6 +454,8 @@ func contractCompile(ctx *cli.Context) error { NoStandardCheck: ctx.Bool("no-standards"), NoEventsCheck: ctx.Bool("no-events"), NoPermissionsCheck: ctx.Bool("no-permissions"), + + GuessEventTypes: ctx.Bool("guess-eventtypes"), } if len(confFile) != 0 { @@ -457,6 +466,7 @@ func contractCompile(ctx *cli.Context) error { o.Name = conf.Name o.SourceURL = conf.SourceURL o.ContractEvents = conf.Events + o.DeclaredNamedTypes = conf.NamedTypes o.ContractSupportedStandards = conf.SupportedStandards o.Permissions = make([]manifest.Permission, len(conf.Permissions)) for i := range conf.Permissions { @@ -705,9 +715,10 @@ type ProjectConfig struct { SourceURL string SafeMethods []string SupportedStandards []string - Events []manifest.Event + Events []compiler.HybridEvent Permissions []permission - Overloads map[string]string `yaml:"overloads,omitempty"` + Overloads map[string]string `yaml:"overloads,omitempty"` + NamedTypes map[string]binding.ExtendedType `yaml:"namedtypes,omitempty"` } func inspect(ctx *cli.Context) error { diff --git a/docs/compiler.md b/docs/compiler.md index d4d17efb4..36c37409a 100644 --- a/docs/compiler.md +++ b/docs/compiler.md @@ -472,10 +472,113 @@ and structures. Notice that structured types returned by methods can't be Null at the moment (see #2795). ``` -$ ./bin/neo-go contract compile -i contract.go --config contract.yml -o contract.nef --manifest manifest.json --bindings contract.bindings.yml +$ ./bin/neo-go contract compile -i contract.go --config contract.yml -o contract.nef --manifest manifest.json --bindings contract.bindings.yml --guess-eventtypes $ ./bin/neo-go contract generate-rpcwrapper --manifest manifest.json --config contract.bindings.yml --out rpcwrapper.go --hash 0x1b4357bff5a01bdf2a6581247cf9ed1e24629176 ``` +Contract-specific RPC-bindings generated by "generate-rpcwrapper" command include +structure wrappers for each event declared in the contract manifest as far as the +set of helpers that allow to retrieve emitted event from the application log or +from stackitem. By default, event wrappers builder use event structure that was +described in the manifest. Since the type data available in the manifest is +limited, in some cases the resulting generated event structure may use generic +go types. Go contracts can make use of additional type data from bindings +configuration file generated during compilation. Like for any other contract +types, this can cover arrays, maps and structures. To reach the maximum +resemblance between the emitted events and the generated event wrappers, we +recommend either to fill in the extended events type information in the contract +configuration file before the compilation or to use `--guess-eventtypes` +compilation option. + +If using `--guess-eventtypes` compilation option, event parameter types will be +guessed from the arguments of `runtime.Notify` calls for each emitted event. If +multiple calls of `runtime.Notify` are found, then argument types will be checked +for matching (guessed types must be the same across the particular event usages). +After that, the extended types binding configuration will be generated according +to the emitted events parameter types. `--guess-eventtypes` compilation option +is able to recognize those events that has a constant name known at a compilation +time and do not include variadic arguments usage. Thus, use this option if your +contract suites these requirements. Otherwise, we recommend to manually specify +extended event parameter types information in the contract configuration file. + +Extended event parameter type information can be provided manually via contract +configuration file under the `events` section. Each event parameter specified in +this section may be supplied with additional parameter type information specified +under `extendedtype` subsection. The extended type information (`ExtendedType`) +has the following structure: + +| Field | Type | Required | Meaning | +|-------------|---------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| `base` | Any valid [NEP-14 parameter type](https://github.com/neo-project/proposals/blob/master/nep-14.mediawiki#parametertype) except `Void`. | Always required. | The base type of a parameter, e.g. `Array` for go structures and any nested arrays, `Map` for nested maps, `Hash160` for 160-bits integers, etc. | +| `name` | `string` | Required for structures, omitted for arrays, interfaces and maps. | Name of a structure that will be used in the resulting RPC binding. | +| `interface` | `string` | Required for `InteropInterface`-based types, currently `iterator` only is supported. | Underlying value of the `InteropInterface`. | +| `key` | Any simple [NEP-14 parameter type](https://github.com/neo-project/proposals/blob/master/nep-14.mediawiki#parametertype). | Required for `Map`-based types. | Key type for maps. | +| `value` | `ExtendedType`. | Required for iterators, arrays and maps. | Value type of iterators, arrays and maps. | +| `fields` | Array of `FieldExtendedType`. | Required for structures. | Ordered type data for structure fields. | + +The structure's field extended information (`FieldExtendedType`) has the following structure: + +| Field | Type | Required | Meaning | +|------------------------|----------------|------------------|-----------------------------------------------------------------------------| +| `field` | `string` | Always required. | Name of the structure field that will be used in the resulting RPC binding. | +| Inlined `ExtendedType` | `ExtendedType` | Always required. | The extended type information about structure field. | + + +Any named structures used in the `ExtendedType` description must be manually +specified in the contract configuration file under top-level `namedtypes` section +in the form of `map[string]ExtendedType`, where the map key is a name of the +described named structure that matches the one provided in the `name` field of +the event parameter's extended type. + +Here's the example of manually-created contract configuration file that uses +extended types for event parameters description: + +``` +name: "HelloWorld contract" +supportedstandards: [] +events: + - name: Some simple notification + parameters: + - name: intP + type: Integer + - name: boolP + type: Boolean + - name: stringP + type: String + - name: Structure notification + parameters: + - name: structure parameter + type: Array + extendedtype: + base: Array + name: transferData + - name: Map of structures notification + parameters: + - name: map parameter + type: Map + extendedtype: + base: Map + key: Integer + value: + base: Array + name: transferData + - name: Iterator notification + parameters: + - name: data + type: InteropInterface + extendedtype: + base: InteropInterface + interface: iterator +namedtypes: + transferData: + base: Array + fields: + - field: IntField + base: Integer + - field: BoolField + base: Boolean +``` + ## Smart contract examples Some examples are provided in the [examples directory](../examples). For more diff --git a/internal/testchain/transaction.go b/internal/testchain/transaction.go index 630902ac8..cce8dd49c 100644 --- a/internal/testchain/transaction.go +++ b/internal/testchain/transaction.go @@ -76,6 +76,7 @@ func NewDeployTx(bc Ledger, name string, sender util.Uint160, r gio.Reader, conf o.Name = conf.Name o.SourceURL = conf.SourceURL o.ContractEvents = conf.Events + o.DeclaredNamedTypes = conf.NamedTypes o.ContractSupportedStandards = conf.SupportedStandards o.Permissions = make([]manifest.Permission, len(conf.Permissions)) for i := range conf.Permissions { diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index aec697006..e44aead0a 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -52,14 +52,26 @@ type Options struct { // This setting has effect only if manifest is emitted. NoPermissionsCheck bool + // GuessEventTypes specifies if types of runtime notifications need to be guessed + // from the usage context. These types are used for RPC binding generation only and + // can be defined for events with name known at the compilation time and without + // variadic args usages. If some type is specified via config file, then the config's + // one is preferable. Currently, event's parameter type is defined from the first + // occurrence of event call. + GuessEventTypes bool + // Name is a contract's name to be written to manifest. Name string // SourceURL is a contract's source URL to be written to manifest. SourceURL string - // Runtime notifications. - ContractEvents []manifest.Event + // Runtime notifications declared in the contract configuration file. + ContractEvents []HybridEvent + + // DeclaredNamedTypes is the set of named types that were declared in the + // contract configuration type and are the part of manifest events. + DeclaredNamedTypes map[string]binding.ExtendedType // The list of standards supported by the contract. ContractSupportedStandards []string @@ -78,6 +90,23 @@ type Options struct { BindingsFile string } +// HybridEvent represents the description of event emitted by the contract squashed +// with extended event's parameters description. We have it as a separate type for +// the user's convenience. It is applied for the smart contract configuration file +// only. +type HybridEvent struct { + Name string `json:"name"` + Parameters []HybridParameter `json:"parameters"` +} + +// HybridParameter contains the manifest's event parameter description united with +// the extended type description for this parameter. It is applied for the smart +// contract configuration file only. +type HybridParameter struct { + manifest.Parameter `yaml:",inline"` + ExtendedType *binding.ExtendedType `yaml:"extendedtype,omitempty"` +} + type buildInfo struct { config *packages.Config program []*packages.Package @@ -309,18 +338,42 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { if len(di.NamedTypes) > 0 { cfg.NamedTypes = di.NamedTypes } - if len(di.EmittedEvents) > 0 { - for eventName, eventUsages := range di.EmittedEvents { - for typeName, extType := range eventUsages[0].ExtTypes { - cfg.NamedTypes[typeName] = extType + for name, et := range o.DeclaredNamedTypes { + // TODO: handle name conflict + cfg.NamedTypes[name] = et + } + for _, e := range o.ContractEvents { + for _, p := range e.Parameters { + // TODO: proper imports handling during bindings generation (see utf8 example). + if p.ExtendedType != nil { + pName := e.Name + "." + p.Name + cfg.Types[pName] = *p.ExtendedType } - for _, p := range eventUsages[0].Params { - pname := eventName + "." + p.Name - if p.RealType.TypeName != "" { - cfg.Overrides[pname] = p.RealType + } + } + if o.GuessEventTypes { + if len(di.EmittedEvents) > 0 { + for eventName, eventUsages := range di.EmittedEvents { + // Take into account the first usage only. + // TODO: extend it to the rest of invocations. + for typeName, extType := range eventUsages[0].ExtTypes { + if _, ok := cfg.NamedTypes[typeName]; !ok { + cfg.NamedTypes[typeName] = extType + } } - if p.ExtendedType != nil { - cfg.Types[pname] = *p.ExtendedType + for _, p := range eventUsages[0].Params { + // TODO: prettify notification name in-place. + pname := eventName + "." + p.Name + if p.RealType.TypeName != "" { + if _, ok := cfg.Overrides[pname]; !ok { + cfg.Overrides[pname] = p.RealType + } + } + if p.ExtendedType != nil { + if _, ok := cfg.Types[pname]; !ok { + cfg.Types[pname] = *p.ExtendedType + } + } } } } diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index 8a9ab207a..288aaf3c7 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -159,16 +159,16 @@ func TestEventWarnings(t *testing.T) { }) t.Run("wrong parameter number", func(t *testing.T) { _, err = compiler.CreateManifest(di, &compiler.Options{ - ContractEvents: []manifest.Event{{Name: "Event"}}, + ContractEvents: []compiler.HybridEvent{{Name: "Event"}}, Name: "payable", }) require.Error(t, err) }) t.Run("wrong parameter type", func(t *testing.T) { _, err = compiler.CreateManifest(di, &compiler.Options{ - ContractEvents: []manifest.Event{{ + ContractEvents: []compiler.HybridEvent{{ Name: "Event", - Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.StringType)}, + Parameters: []compiler.HybridParameter{{Parameter: manifest.NewParameter("number", smartcontract.StringType)}}, }}, Name: "payable", }) @@ -176,9 +176,9 @@ func TestEventWarnings(t *testing.T) { }) t.Run("any parameter type", func(t *testing.T) { _, err = compiler.CreateManifest(di, &compiler.Options{ - ContractEvents: []manifest.Event{{ + ContractEvents: []compiler.HybridEvent{{ Name: "Event", - Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.AnyType)}, + Parameters: []compiler.HybridParameter{{Parameter: manifest.NewParameter("number", smartcontract.AnyType)}}, }}, Name: "payable", }) @@ -186,9 +186,9 @@ func TestEventWarnings(t *testing.T) { }) t.Run("good", func(t *testing.T) { _, err = compiler.CreateManifest(di, &compiler.Options{ - ContractEvents: []manifest.Event{{ + ContractEvents: []compiler.HybridEvent{{ Name: "Event", - Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.IntegerType)}, + Parameters: []compiler.HybridParameter{{Parameter: manifest.NewParameter("number", smartcontract.IntegerType)}}, }}, Name: "payable", }) @@ -224,7 +224,7 @@ func TestEventWarnings(t *testing.T) { require.Error(t, err) _, err = compiler.CreateManifest(di, &compiler.Options{ - ContractEvents: []manifest.Event{{Name: "Event"}}, + ContractEvents: []compiler.HybridEvent{{Name: "Event"}}, Name: "eventTest", }) require.NoError(t, err) @@ -242,9 +242,9 @@ func TestEventWarnings(t *testing.T) { _, err = compiler.CreateManifest(di, &compiler.Options{ Name: "eventTest", - ContractEvents: []manifest.Event{{ + ContractEvents: []compiler.HybridEvent{{ Name: "Event", - Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.IntegerType)}, + Parameters: []compiler.HybridParameter{{Parameter: manifest.NewParameter("number", smartcontract.IntegerType)}}, }}, }) require.NoError(t, err) @@ -260,7 +260,7 @@ func TestNotifyInVerify(t *testing.T) { t.Run(name, func(t *testing.T) { src := fmt.Sprintf(srcTmpl, name) _, _, err := compiler.CompileWithOptions("eventTest.go", strings.NewReader(src), - &compiler.Options{ContractEvents: []manifest.Event{{Name: "Event"}}}) + &compiler.Options{ContractEvents: []compiler.HybridEvent{{Name: "Event"}}}) require.Error(t, err) t.Run("suppress", func(t *testing.T) { diff --git a/pkg/compiler/debug.go b/pkg/compiler/debug.go index c720fcbc5..0eb18bb5a 100644 --- a/pkg/compiler/debug.go +++ b/pkg/compiler/debug.go @@ -593,9 +593,20 @@ func (di *DebugInfo) ConvertToManifest(o *Options) (*manifest.Manifest, error) { if o.ContractSupportedStandards != nil { result.SupportedStandards = o.ContractSupportedStandards } + events := make([]manifest.Event, len(o.ContractEvents)) + for i, e := range o.ContractEvents { + params := make([]manifest.Parameter, len(e.Parameters)) + for j, p := range e.Parameters { + params[j] = p.Parameter + } + events[i] = manifest.Event{ + Name: o.ContractEvents[i].Name, + Parameters: params, + } + } result.ABI = manifest.ABI{ Methods: methods, - Events: o.ContractEvents, + Events: events, } if result.ABI.Events == nil { result.ABI.Events = make([]manifest.Event, 0) diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 1cd1c88f3..c8f77ce24 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -542,13 +542,13 @@ func TestForcedNotifyArgumentsConversion(t *testing.T) { if count != len(expectedVMParamTypes) { t.Fatalf("parameters count mismatch: %d vs %d", count, len(expectedVMParamTypes)) } - scParams := make([]manifest.Parameter, len(targetSCParamTypes)) + scParams := make([]compiler.HybridParameter, len(targetSCParamTypes)) vmParams := make([]stackitem.Item, len(expectedVMParamTypes)) for i := range scParams { - scParams[i] = manifest.Parameter{ + scParams[i] = compiler.HybridParameter{Parameter: manifest.Parameter{ Name: strconv.Itoa(i), Type: targetSCParamTypes[i], - } + }} defaultValue := stackitem.NewBigInteger(big.NewInt(int64(i))) var ( val stackitem.Item @@ -564,7 +564,7 @@ func TestForcedNotifyArgumentsConversion(t *testing.T) { } ctr := neotest.CompileSource(t, e.CommitteeHash, strings.NewReader(src), &compiler.Options{ Name: "Helper", - ContractEvents: []manifest.Event{ + ContractEvents: []compiler.HybridEvent{ { Name: methodWithoutEllipsis, Parameters: scParams, diff --git a/pkg/neotest/compile.go b/pkg/neotest/compile.go index fee77c17e..70645c11c 100644 --- a/pkg/neotest/compile.go +++ b/pkg/neotest/compile.go @@ -60,6 +60,7 @@ func CompileFile(t testing.TB, sender util.Uint160, srcPath string, configPath s o := &compiler.Options{} o.Name = conf.Name o.ContractEvents = conf.Events + o.DeclaredNamedTypes = conf.NamedTypes o.ContractSupportedStandards = conf.SupportedStandards o.Permissions = make([]manifest.Permission, len(conf.Permissions)) for i := range conf.Permissions { From 2c36802e23c220bd1aa892523a45bdf1c0f3f163 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 31 May 2023 15:32:53 +0300 Subject: [PATCH 085/125] binding: fix comment to the extended type field Signed-off-by: Anna Shaleva --- pkg/smartcontract/binding/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/smartcontract/binding/generate.go b/pkg/smartcontract/binding/generate.go index bf3e3d9a1..33bb21dd2 100644 --- a/pkg/smartcontract/binding/generate.go +++ b/pkg/smartcontract/binding/generate.go @@ -72,7 +72,7 @@ type ( Name string `yaml:"name,omitempty"` // Structure name, omitted for arrays, interfaces and maps. Interface string `yaml:"interface,omitempty"` // Interface type name, "iterator" only for now. Key smartcontract.ParamType `yaml:"key,omitempty"` // Key type (only simple types can be used for keys) for maps. - Value *ExtendedType `yaml:"value,omitempty"` // Value type for iterators and arrays. + Value *ExtendedType `yaml:"value,omitempty"` // Value type for iterators, arrays and maps. Fields []FieldExtendedType `yaml:"fields,omitempty"` // Ordered type data for structure fields. } From 41938ffa78f50938d72040bf58db45ae8405100a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Sun, 21 May 2023 15:08:29 +0300 Subject: [PATCH 086/125] smartcontract: drop standard events before RPC binging generation Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/gas/gas.go | 96 ------------------ cli/smartcontract/testdata/nameservice/nns.go | 98 ------------------- cli/smartcontract/testdata/nex/nex.go | 91 ----------------- pkg/rpcclient/nep11/base.go | 69 +++++++++++++ pkg/rpcclient/nep17/nep17.go | 66 +++++++++++++ pkg/smartcontract/rpcbinding/binding.go | 22 +++++ 6 files changed, 157 insertions(+), 285 deletions(-) diff --git a/cli/smartcontract/testdata/gas/gas.go b/cli/smartcontract/testdata/gas/gas.go index 2b4cf920a..d12bbb8ee 100644 --- a/cli/smartcontract/testdata/gas/gas.go +++ b/cli/smartcontract/testdata/gas/gas.go @@ -2,25 +2,13 @@ package gastoken import ( - "errors" - "fmt" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "math/big" ) // Hash contains contract hash. var Hash = util.Uint160{0xcf, 0x76, 0xe2, 0x8b, 0xd0, 0x6, 0x2c, 0x4a, 0x47, 0x8e, 0xe3, 0x55, 0x61, 0x1, 0x13, 0x19, 0xf3, 0xcf, 0xa4, 0xd2} -// TransferEvent represents "Transfer" event emitted by the contract. -type TransferEvent struct { - From util.Uint160 - To util.Uint160 - Amount *big.Int -} - // Invoker is used by ContractReader to call various safe methods. type Invoker interface { nep17.Invoker @@ -56,87 +44,3 @@ func New(actor Actor) *Contract { var nep17t = nep17.New(actor, Hash) return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} } - -// TransferEventsFromApplicationLog retrieves a set of all emitted events -// with "Transfer" name from the provided ApplicationLog. -func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*TransferEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "Transfer" { - continue - } - event := new(TransferEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided stackitem.Array to TransferEvent and -// returns an error if so. -func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { - if item == nil { - return errors.New("nil item") - } - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 3 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.From, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field From: %w", err) - } - - index++ - e.To, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field To: %w", err) - } - - index++ - e.Amount, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Amount: %w", err) - } - - return nil -} diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 8bb311bb9..2b19af793 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -18,14 +18,6 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0xde, 0x46, 0x5f, 0x5d, 0x50, 0x57, 0xcf, 0x33, 0x28, 0x47, 0x94, 0xc5, 0xcf, 0xc2, 0xc, 0x69, 0x37, 0x1c, 0xac, 0x50} -// TransferEvent represents "Transfer" event emitted by the contract. -type TransferEvent struct { - From util.Uint160 - To util.Uint160 - Amount *big.Int - TokenId []byte -} - // SetAdminEvent represents "SetAdmin" event emitted by the contract. type SetAdminEvent struct { Name string @@ -345,96 +337,6 @@ func (c *Contract) DeleteRecordUnsigned(name string, typev *big.Int) (*transacti return c.actor.MakeUnsignedCall(Hash, "deleteRecord", nil, name, typev) } -// TransferEventsFromApplicationLog retrieves a set of all emitted events -// with "Transfer" name from the provided ApplicationLog. -func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*TransferEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "Transfer" { - continue - } - event := new(TransferEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided stackitem.Array to TransferEvent and -// returns an error if so. -func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { - if item == nil { - return errors.New("nil item") - } - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 4 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.From, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field From: %w", err) - } - - index++ - e.To, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field To: %w", err) - } - - index++ - e.Amount, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Amount: %w", err) - } - - index++ - e.TokenId, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field TokenId: %w", err) - } - - return nil -} - // SetAdminEventsFromApplicationLog retrieves a set of all emitted events // with "SetAdmin" name from the provided ApplicationLog. func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEvent, error) { diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 41de92d02..f558fb513 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -17,13 +17,6 @@ import ( // Hash contains contract hash. var Hash = util.Uint160{0xa8, 0x1a, 0xa1, 0xf0, 0x4b, 0xf, 0xdc, 0x4a, 0xa2, 0xce, 0xd5, 0xbf, 0xc6, 0x22, 0xcf, 0xe8, 0x9, 0x7f, 0xa6, 0xa2} -// TransferEvent represents "Transfer" event emitted by the contract. -type TransferEvent struct { - From util.Uint160 - To util.Uint160 - Amount *big.Int -} - // OnMintEvent represents "OnMint" event emitted by the contract. type OnMintEvent struct { From util.Uint160 @@ -249,90 +242,6 @@ func (c *Contract) UpdateCapUnsigned(newCap *big.Int) (*transaction.Transaction, return c.actor.MakeUnsignedCall(Hash, "updateCap", nil, newCap) } -// TransferEventsFromApplicationLog retrieves a set of all emitted events -// with "Transfer" name from the provided ApplicationLog. -func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*TransferEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "Transfer" { - continue - } - event := new(TransferEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize TransferEvent from stackitem (execution %d, event %d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided stackitem.Array to TransferEvent and -// returns an error if so. -func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { - if item == nil { - return errors.New("nil item") - } - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 3 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.From, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field From: %w", err) - } - - index++ - e.To, err = func (item stackitem.Item) (util.Uint160, error) { - b, err := item.TryBytes() - if err != nil { - return util.Uint160{}, err - } - u, err := util.Uint160DecodeBytesBE(b) - if err != nil { - return util.Uint160{}, err - } - return u, nil - } (arr[index]) - if err != nil { - return fmt.Errorf("field To: %w", err) - } - - index++ - e.Amount, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Amount: %w", err) - } - - return nil -} - // OnMintEventsFromApplicationLog retrieves a set of all emitted events // with "OnMint" name from the provided ApplicationLog. func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, error) { diff --git a/pkg/rpcclient/nep11/base.go b/pkg/rpcclient/nep11/base.go index ed30df2af..db906cb3d 100644 --- a/pkg/rpcclient/nep11/base.go +++ b/pkg/rpcclient/nep11/base.go @@ -10,6 +10,7 @@ purposes, otherwise more specific types are recommended. package nep11 import ( + "errors" "fmt" "math/big" "unicode/utf8" @@ -246,3 +247,71 @@ func UnwrapKnownProperties(m *stackitem.Map, err error) (map[string]string, erro } return res, nil } + +// TransferEventsFromApplicationLog retrieves all emitted TransferEvents from the +// provided [result.ApplicationLog]. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to decode event from stackitem (event #%d, execution #%d): %w", j, i, err) + } + res = append(res, event) + } + } + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to TransferEvent or returns an +// error if it's not possible to do to so. +func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 4 { + return errors.New("wrong number of event parameters") + } + + b, err := arr[0].TryBytes() + if err != nil { + return fmt.Errorf("invalid From: %w", err) + } + e.From, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode From: %w", err) + } + + b, err = arr[1].TryBytes() + if err != nil { + return fmt.Errorf("invalid To: %w", err) + } + e.To, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode To: %w", err) + } + + e.Amount, err = arr[2].TryInteger() + if err != nil { + return fmt.Errorf("field to decode Avount: %w", err) + } + + e.ID, err = arr[3].TryBytes() + if err != nil { + return fmt.Errorf("failed to decode ID: %w", err) + } + + return nil +} diff --git a/pkg/rpcclient/nep17/nep17.go b/pkg/rpcclient/nep17/nep17.go index f91488e82..dec570a22 100644 --- a/pkg/rpcclient/nep17/nep17.go +++ b/pkg/rpcclient/nep17/nep17.go @@ -8,12 +8,15 @@ package nep17 import ( "errors" + "fmt" "math/big" "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/neptoken" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // Invoker is used by TokenReader to call various safe methods. @@ -147,3 +150,66 @@ func (t *TokenWriter) MultiTransferUnsigned(params []TransferParameters) (*trans } return t.actor.MakeUnsignedRun(script, nil) } + +// TransferEventsFromApplicationLog retrieves all emitted TransferEvents from the +// provided [result.ApplicationLog]. +func TransferEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + var res []*TransferEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "Transfer" { + continue + } + event := new(TransferEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to decode event from stackitem (event #%d, execution #%d): %w", j, i, err) + } + res = append(res, event) + } + } + return res, nil +} + +// FromStackItem converts provided [stackitem.Array] to TransferEvent or returns an +// error if it's not possible to do to so. +func (e *TransferEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 3 { + return errors.New("wrong number of event parameters") + } + + b, err := arr[0].TryBytes() + if err != nil { + return fmt.Errorf("invalid From: %w", err) + } + e.From, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode From: %w", err) + } + + b, err = arr[1].TryBytes() + if err != nil { + return fmt.Errorf("invalid To: %w", err) + } + e.To, err = util.Uint160DecodeBytesBE(b) + if err != nil { + return fmt.Errorf("failed to decode To: %w", err) + } + + e.Amount, err = arr[2].TryInteger() + if err != nil { + return fmt.Errorf("field to decode Avount: %w", err) + } + + return nil +} diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 973264c78..ba65361f1 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -396,12 +396,14 @@ func Generate(cfg binding.Config) error { mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep11NonDivisible) ctr.IsNep11ND = true } + mfst.ABI.Events = dropStdEvents(mfst.ABI.Events, standard.Nep11Base) break // Can't be NEP-17 at the same time. } if std == manifest.NEP17StandardName && standard.ComplyABI(cfg.Manifest, standard.Nep17) == nil { mfst.ABI.Methods = dropStdMethods(mfst.ABI.Methods, standard.Nep17) imports["github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"] = struct{}{} ctr.IsNep17 = true + mfst.ABI.Events = dropStdEvents(mfst.ABI.Events, standard.Nep17) break // Can't be NEP-11 at the same time. } } @@ -445,6 +447,18 @@ func dropManifestMethods(meths []manifest.Method, manifested []manifest.Method) return meths } +func dropManifestEvents(events []manifest.Event, manifested []manifest.Event) []manifest.Event { + for _, e := range manifested { + for i := 0; i < len(events); i++ { + if events[i].Name == e.Name && len(events[i].Parameters) == len(e.Parameters) { + events = append(events[:i], events[i+1:]...) + i-- + } + } + } + return events +} + func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest.Method { meths = dropManifestMethods(meths, std.Manifest.ABI.Methods) if std.Optional != nil { @@ -456,6 +470,14 @@ func dropStdMethods(meths []manifest.Method, std *standard.Standard) []manifest. return meths } +func dropStdEvents(events []manifest.Event, std *standard.Standard) []manifest.Event { + events = dropManifestEvents(events, std.Manifest.ABI.Events) + if std.Base != nil { + return dropStdEvents(events, std.Base) + } + return events +} + func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.ExtendedType) (string, string) { switch et.Base { case smartcontract.AnyType: From 19cc6c63696839888c0348cdd8b4d81ada4f21ab Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 May 2023 14:17:39 +0300 Subject: [PATCH 087/125] compiler: store ready-to-use notification names in bindings config Notification and its parameters may have any UTF8-compatible name which is inappropriate for bindings configuration and for the resulting RPC bindings file. This commit stores the prettified version of notification's name and parameters that are ready to be used in the resulting RPC binding without any changes. Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 1 + .../testdata/notifications/config.yml | 7 + .../testdata/notifications/notifications.go | 7 + .../testdata/notifications/rpcbindings.out | 748 ++++++++++++++++++ pkg/compiler/compiler.go | 14 +- pkg/smartcontract/rpcbinding/binding.go | 58 +- 6 files changed, 805 insertions(+), 30 deletions(-) create mode 100644 cli/smartcontract/testdata/notifications/config.yml create mode 100644 cli/smartcontract/testdata/notifications/notifications.go create mode 100644 cli/smartcontract/testdata/notifications/rpcbindings.out diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index b274e99f3..67a46fc12 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -416,6 +416,7 @@ func TestAssistedRPCBindings(t *testing.T) { checkBinding(filepath.Join("testdata", "types")) checkBinding(filepath.Join("testdata", "structs")) + checkBinding(filepath.Join("testdata", "notifications")) require.False(t, rewriteExpectedOutputs) } diff --git a/cli/smartcontract/testdata/notifications/config.yml b/cli/smartcontract/testdata/notifications/config.yml new file mode 100644 index 000000000..5bb9b8554 --- /dev/null +++ b/cli/smartcontract/testdata/notifications/config.yml @@ -0,0 +1,7 @@ +name: "Notifications" +sourceurl: https://github.com/nspcc-dev/neo-go/ +events: + - name: "! complicated name %$#" + parameters: + - name: ! complicated param @#$% + type: String diff --git a/cli/smartcontract/testdata/notifications/notifications.go b/cli/smartcontract/testdata/notifications/notifications.go new file mode 100644 index 000000000..369d1cdb6 --- /dev/null +++ b/cli/smartcontract/testdata/notifications/notifications.go @@ -0,0 +1,7 @@ +package structs + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +func Main() { + runtime.Notify("! complicated name %$#", "str1") +} diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out new file mode 100644 index 000000000..aeeb3ccd7 --- /dev/null +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -0,0 +1,748 @@ +// Package structs contains RPC wrappers for Notifications contract. +package structs + +import ( + "crypto/elliptic" + "errors" + "fmt" + "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/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" +) + +// Hash contains contract hash. +var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract. +type ComplicatedNameEvent struct { + ComplicatedParam string +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// Contract implements all contract methods. +type Contract struct { + actor Actor +} + +// New creates an instance of Contract using Hash and the given Actor. +func New(actor Actor) *Contract { + return &Contract{actor} +} + +// Main creates a transaction invoking `main` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Main() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "main") +} + +// MainTransaction creates a transaction invoking `main` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) MainTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "main") +} + +// MainUnsigned creates a transaction invoking `main` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "main", nil) +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given stack item +// and returns an error if so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given stack item +// and returns an error if so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given stack item +// and returns an error if so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item +// and returns an error if so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item +// and returns an error if so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item +// and returns an error if so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events +// with "! complicated name %$#" name from the provided ApplicationLog. +func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*ComplicatedNameEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "! complicated name %$#" { + continue + } + event := new(ComplicatedNameEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent and +// returns an error if so. +func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.ComplicatedParam, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field ComplicatedParam: %w", err) + } + + return nil +} diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index e44aead0a..6a711921a 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -18,6 +18,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest/standard" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding" "github.com/nspcc-dev/neo-go/pkg/util" "golang.org/x/tools/go/packages" "gopkg.in/yaml.v3" @@ -339,14 +340,17 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { cfg.NamedTypes = di.NamedTypes } for name, et := range o.DeclaredNamedTypes { - // TODO: handle name conflict + // TODO: handle name conflict (it can happen due to invalid user input e.g.) cfg.NamedTypes[name] = et } for _, e := range o.ContractEvents { + eStructName := rpcbinding.ToEventBindingName(e.Name) for _, p := range e.Parameters { + pStructName := rpcbinding.ToParameterBindingName(p.Name) // TODO: proper imports handling during bindings generation (see utf8 example). + // Probably, we should always add p type to the list of types. if p.ExtendedType != nil { - pName := e.Name + "." + p.Name + pName := eStructName + "." + pStructName cfg.Types[pName] = *p.ExtendedType } } @@ -354,6 +358,7 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { if o.GuessEventTypes { if len(di.EmittedEvents) > 0 { for eventName, eventUsages := range di.EmittedEvents { + eBindingName := rpcbinding.ToEventBindingName(eventName) // Take into account the first usage only. // TODO: extend it to the rest of invocations. for typeName, extType := range eventUsages[0].ExtTypes { @@ -361,9 +366,10 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { cfg.NamedTypes[typeName] = extType } } + for _, p := range eventUsages[0].Params { - // TODO: prettify notification name in-place. - pname := eventName + "." + p.Name + pBindingName := rpcbinding.ToParameterBindingName(p.Name) + pname := eBindingName + "." + pBindingName if p.RealType.TypeName != "" { if _, ok := cfg.Overrides[pname]; !ok { cfg.Overrides[pname] = p.RealType diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index ba65361f1..074b41c49 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -19,10 +19,10 @@ import ( // ensure that this block has new line at the start and in the end of the block. const ( eventDefinition = `{{ define "EVENT" }} -// {{.Name}}Event represents "{{.ManifestName}}" event emitted by the contract. -type {{.Name}}Event struct { +// {{.Name}} represents "{{.ManifestName}}" event emitted by the contract. +type {{.Name}} struct { {{- range $index, $arg := .Parameters}} - {{toPascalCase .Name}} {{.Type}} + {{.Name}} {{.Type}} {{- end}} } {{ end }}` @@ -262,23 +262,23 @@ func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { } {{ end -}} {{- range $e := .CustomEvents }} -// {{$e.Name}}EventsFromApplicationLog retrieves a set of all emitted events +// {{$e.Name}}sFromApplicationLog retrieves a set of all emitted events // with "{{$e.ManifestName}}" name from the provided ApplicationLog. -func {{$e.Name}}EventsFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}Event, error) { +func {{$e.Name}}sFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}, error) { if log == nil { return nil, errors.New("nil application log") } - var res []*{{$e.Name}}Event + var res []*{{$e.Name}} for i, ex := range log.Executions { for j, e := range ex.Events { if e.Name != "{{$e.ManifestName}}" { continue } - event := new({{$e.Name}}Event) + event := new({{$e.Name}}) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize {{$e.Name}}Event from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize {{$e.Name}} from stackitem (execution %d, event %d): %w", i, j, err) } res = append(res, event) } @@ -287,9 +287,9 @@ func {{$e.Name}}EventsFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Na return res, nil } -// FromStackItem converts provided stackitem.Array to {{$e.Name}}Event and +// FromStackItem converts provided stackitem.Array to {{$e.Name}} and // returns an error if so. -func (e *{{$e.Name}}Event) FromStackItem(item *stackitem.Array) error { +func (e *{{$e.Name}}) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") } @@ -307,9 +307,9 @@ func (e *{{$e.Name}}Event) FromStackItem(item *stackitem.Array) error { ) {{- range $p := $e.Parameters}} index++ - e.{{toPascalCase .Name}}, err = {{etTypeConverter .ExtType "arr[index]"}} + e.{{.Name}}, err = {{etTypeConverter .ExtType "arr[index]"}} if err != nil { - return fmt.Errorf("field {{toPascalCase .Name}}: %w", err) + return fmt.Errorf("field {{.Name}}: %w", err) } {{end}} {{- end}} @@ -427,9 +427,8 @@ func Generate(cfg binding.Config) error { r, _ := extendedTypeToGo(et, ctr.NamedTypes) return r }, - "toTypeName": toTypeName, - "cutPointer": cutPointer, - "toPascalCase": toPascalCase, + "toTypeName": toTypeName, + "cutPointer": cutPointer, }).Parse(srcTmpl)) return srcTemplate.Execute(cfg.Output, ctr) @@ -675,23 +674,18 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st imports["errors"] = struct{}{} } for _, abiEvent := range cfg.Manifest.ABI.Events { + eBindingName := ToEventBindingName(abiEvent.Name) eTmp := CustomEventTemplate{ - // TODO: proper event name is better to be set right into config binding in normal form. - Name: toPascalCase(abiEvent.Name), + Name: eBindingName, ManifestName: abiEvent.Name, } - var varnames = make(map[string]bool) for i := range abiEvent.Parameters { - name := abiEvent.Parameters[i].Name - fullPName := abiEvent.Name + "." + name + pBindingName := ToParameterBindingName(abiEvent.Parameters[i].Name) + fullPName := eBindingName + "." + pBindingName typeStr, pkg := scTypeConverter(fullPName, abiEvent.Parameters[i].Type, &cfg) if pkg != "" { imports[pkg] = struct{}{} } - for varnames[name] { - name = name + "_" - } - varnames[name] = true var ( extType binding.ExtendedType @@ -699,12 +693,12 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st ) if extType, ok = cfg.Types[fullPName]; !ok { extType = binding.ExtendedType{ - Base: abiEvent.Parameters[i].Type, + Base: abiEvent.Parameters[i].Type, // TODO: properly handle imports for this case (see utf8 example) } } eTmp.Parameters = append(eTmp.Parameters, EventParamTmpl{ ParamTmpl: binding.ParamTmpl{ - Name: name, + Name: pBindingName, Type: typeStr, }, ExtType: extType, @@ -849,6 +843,18 @@ func addIndent(str string, ind string) string { return strings.ReplaceAll(str, "\n", "\n"+ind) } +// ToEventBindingName converts event name specified in the contract manifest to +// a valid go exported event structure name. +func ToEventBindingName(eventName string) string { + return toPascalCase(eventName) + "Event" +} + +// ToParameterBindingName converts parameter name specified in the contract +// manifest to a valid go structure's exported field name. +func ToParameterBindingName(paramName string) string { + return toPascalCase(paramName) +} + // toPascalCase removes all non-unicode characters from the provided string and // converts it to pascal case using space as delimiter. func toPascalCase(s string) string { From 37af2031bb9fa299b5fc99834d7486f121fce586 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 May 2023 18:20:51 +0300 Subject: [PATCH 088/125] rpcbinding: properly add imports for simple types of event parameters There are two ways of doing this: first one is to emit all notifications parameter data into rpcbindings configuration on compile time (event if the parameter has a simple type), and the second one is to fetch parameter type from the manifest on rpcbinding file generation if needed (we always have manifest at this stage, thus it's not a problem to retrieve necessary information). The latter case is chosen to reduce the bindings configuration file size. Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/nameservice/nns.go | 1 + cli/smartcontract/testdata/notifications/rpcbindings.out | 1 + pkg/compiler/compiler.go | 2 -- pkg/smartcontract/rpcbinding/binding.go | 3 ++- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 2b19af793..4c3a76d6f 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -13,6 +13,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "math/big" + "unicode/utf8" ) // Hash contains contract hash. diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index aeeb3ccd7..a3717edd8 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "math/big" + "unicode/utf8" ) // Hash contains contract hash. diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 6a711921a..eac2bdced 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -347,8 +347,6 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { eStructName := rpcbinding.ToEventBindingName(e.Name) for _, p := range e.Parameters { pStructName := rpcbinding.ToParameterBindingName(p.Name) - // TODO: proper imports handling during bindings generation (see utf8 example). - // Probably, we should always add p type to the list of types. if p.ExtendedType != nil { pName := eStructName + "." + pStructName cfg.Types[pName] = *p.ExtendedType diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 074b41c49..a3eab9576 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -693,8 +693,9 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st ) if extType, ok = cfg.Types[fullPName]; !ok { extType = binding.ExtendedType{ - Base: abiEvent.Parameters[i].Type, // TODO: properly handle imports for this case (see utf8 example) + Base: abiEvent.Parameters[i].Type, } + addETImports(extType, ctr.NamedTypes, imports) } eTmp.Parameters = append(eTmp.Parameters, EventParamTmpl{ ParamTmpl: binding.ParamTmpl{ From a0d991a500203539cb3455d5b9c2980cc488bdb2 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 3 May 2023 19:13:05 +0300 Subject: [PATCH 089/125] rpcbinding: support map[any]any conversion for extended types Unfortunately, without pre-set user extended types configuration for events and without --guess-eventtypes flag set we are allowed to rely only on manifest information about types. Manifest can't give us a lot of information, but we still need to be able to generate RPC binding. Arrays and structs are correctly handled by the current code, but maps always rely on the fact that map's value type is set. It's not true in the described case, so make the maps type convertor handle this situation in a similar way how arrays are handled. Without this commit the following panic occurs on attempt to generate RPC binding: ``` --- FAIL: TestAssistedRPCBindings/testdata/notifications (0.01s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7f7c0e] goroutine 190 [running]: testing.tRunner.func1.2({0x109cb40, 0x1d58760}) /usr/local/go/src/testing/testing.go:1396 +0x24e testing.tRunner.func1() /usr/local/go/src/testing/testing.go:1399 +0x39f panic({0x109cb40, 0x1d58760}) /usr/local/go/src/runtime/panic.go:884 +0x212 github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding.extendedTypeToGo({0x22, {0x0, 0x0}, {0x0, 0x0}, 0x0, 0x0, {0x0, 0x0, 0x0}}, ...) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding/binding.go:515 +0x36e github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding.scTypeToGo({0xc000206d92?, 0xc000206d80?}, 0x22, 0xc0005d70e0) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding/binding.go:643 +0x138 github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding.scTemplateToRPC({{0xc00049bb07, 0x7}, 0xc0004c89c0, {0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, ...}, ...}, ...) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding/binding.go:686 +0xbc4 github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding.Generate({{0xc00049bb07, 0x7}, 0xc0004c89c0, {0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, ...}, ...}) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding/binding.go:421 +0x387 github.com/nspcc-dev/neo-go/cli/smartcontract.contractGenerateSomething(0xc00043e2c0, 0x137cd00) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/cli/smartcontract/generate.go:99 +0x855 github.com/nspcc-dev/neo-go/cli/smartcontract.contractGenerateRPCWrapper(0xc00043e2c0?) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/cli/smartcontract/generate.go:60 +0x25 github.com/urfave/cli.HandleAction({0x1048380?, 0x137c660?}, 0x13?) /home/anna/go/pkg/mod/github.com/urfave/cli@v1.22.5/app.go:524 +0x50 github.com/urfave/cli.Command.Run({{0x123539d, 0x13}, {0x0, 0x0}, {0x0, 0x0, 0x0}, {0x12577ad, 0x2a}, {0x127ad35, ...}, ...}, ...) /home/anna/go/pkg/mod/github.com/urfave/cli@v1.22.5/command.go:173 +0x65b github.com/urfave/cli.(*App).RunAsSubcommand(0xc0001f4000, 0xc00043e000) /home/anna/go/pkg/mod/github.com/urfave/cli@v1.22.5/app.go:405 +0x91b github.com/urfave/cli.Command.startApp({{0x12281e1, 0x8}, {0x0, 0x0}, {0x0, 0x0, 0x0}, {0x1254d8a, 0x28}, {0x0, ...}, ...}, ...) /home/anna/go/pkg/mod/github.com/urfave/cli@v1.22.5/command.go:372 +0x6e7 github.com/urfave/cli.Command.Run({{0x12281e1, 0x8}, {0x0, 0x0}, {0x0, 0x0, 0x0}, {0x1254d8a, 0x28}, {0x0, ...}, ...}, ...) /home/anna/go/pkg/mod/github.com/urfave/cli@v1.22.5/command.go:102 +0x825 github.com/urfave/cli.(*App).Run(0xc00024e000, {0xc0004f6420, 0xb, 0xb}) /home/anna/go/pkg/mod/github.com/urfave/cli@v1.22.5/app.go:277 +0x8a7 github.com/nspcc-dev/neo-go/cli/smartcontract.TestAssistedRPCBindings.func1.1(0x9f8829?) /home/anna/Documents/GitProjects/nspcc-dev/neo-go/cli/smartcontract/generate_test.go:395 +0x5fc testing.tRunner(0xc0006824e0, 0xc0004a3680) /usr/local/go/src/testing/testing.go:1446 +0x10b created by testing.(*T).Run /usr/local/go/src/testing/testing.go:1493 +0x35f ``` Signed-off-by: Anna Shaleva --- .../testdata/notifications/config.yml | 8 + .../testdata/notifications/notifications.go | 16 +- .../testdata/notifications/rpcbindings.out | 189 ++++++++++++++++++ cli/smartcontract/testdata/types/config.yml | 2 +- .../testdata/types/rpcbindings.out | 28 +++ cli/smartcontract/testdata/types/types.go | 4 + examples/events/events.go | 6 + examples/events/events.yml | 4 + pkg/smartcontract/rpcbinding/binding.go | 20 +- 9 files changed, 272 insertions(+), 5 deletions(-) diff --git a/cli/smartcontract/testdata/notifications/config.yml b/cli/smartcontract/testdata/notifications/config.yml index 5bb9b8554..5fd018d53 100644 --- a/cli/smartcontract/testdata/notifications/config.yml +++ b/cli/smartcontract/testdata/notifications/config.yml @@ -5,3 +5,11 @@ events: parameters: - name: ! complicated param @#$% type: String + - name: "SomeMap" + parameters: + - name: m + type: Map + - name: "SomeStruct" + parameters: + - name: s + type: Struct \ No newline at end of file diff --git a/cli/smartcontract/testdata/notifications/notifications.go b/cli/smartcontract/testdata/notifications/notifications.go index 369d1cdb6..f679901af 100644 --- a/cli/smartcontract/testdata/notifications/notifications.go +++ b/cli/smartcontract/testdata/notifications/notifications.go @@ -1,7 +1,21 @@ package structs -import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" +import ( + "github.com/nspcc-dev/neo-go/pkg/interop" + "github.com/nspcc-dev/neo-go/pkg/interop/runtime" +) func Main() { runtime.Notify("! complicated name %$#", "str1") } + +func CrazyMap() { + runtime.Notify("SomeMap", map[int][]map[string][]interop.Hash160{}) +} + +func Struct() { + runtime.Notify("SomeStruct", struct { + I int + B bool + }{I: 123, B: true}) +} diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index a3717edd8..ae0724975 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -82,6 +82,16 @@ type ComplicatedNameEvent struct { ComplicatedParam string } +// SomeMapEvent represents "SomeMap" event emitted by the contract. +type SomeMapEvent struct { + M map[any]any +} + +// SomeStructEvent represents "SomeStruct" event emitted by the contract. +type SomeStructEvent struct { + S []any +} + // Actor is used by Contract to call state-changing methods. type Actor interface { MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) @@ -102,6 +112,28 @@ func New(actor Actor) *Contract { return &Contract{actor} } +// CrazyMap creates a transaction invoking `crazyMap` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) CrazyMap() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "crazyMap") +} + +// CrazyMapTransaction creates a transaction invoking `crazyMap` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "crazyMap") +} + +// CrazyMapUnsigned creates a transaction invoking `crazyMap` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) CrazyMapUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "crazyMap", nil) +} + // Main creates a transaction invoking `main` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. @@ -124,6 +156,28 @@ func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { return c.actor.MakeUnsignedCall(Hash, "main", nil) } +// Struct creates a transaction invoking `struct` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Struct() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "struct") +} + +// StructTransaction creates a transaction invoking `struct` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) StructTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "struct") +} + +// StructUnsigned creates a transaction invoking `struct` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) StructUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "struct", nil) +} + // itemToLedgerBlock converts stack item into *LedgerBlock. func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { if err != nil { @@ -747,3 +801,138 @@ func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { return nil } + +// SomeMapEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeMap" name from the provided ApplicationLog. +func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeMapEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeMap" { + continue + } + event := new(SomeMapEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeMapEvent and +// returns an error if so. +func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.M, err = func (item stackitem.Item) (map[any]any, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[any]any) + for i := range m { + k, err := m[i].Key.Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := m[i].Value.Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field M: %w", err) + } + + return nil +} + +// SomeStructEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeStruct" name from the provided ApplicationLog. +func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStructEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeStructEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeStruct" { + continue + } + event := new(SomeStructEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeStructEvent and +// returns an error if so. +func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.S, err = func (item stackitem.Item) ([]any, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]any, len(arr)) + for i := range res { + res[i], err = arr[i].Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field S: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/types/config.yml b/cli/smartcontract/testdata/types/config.yml index b97936c40..98cb40d18 100644 --- a/cli/smartcontract/testdata/types/config.yml +++ b/cli/smartcontract/testdata/types/config.yml @@ -1,3 +1,3 @@ name: "Types" sourceurl: https://github.com/nspcc-dev/neo-go/ -safemethods: ["bool", "int", "bytes", "string", "any", "hash160", "hash256", "publicKey", "signature", "bools", "ints", "bytess", "strings", "hash160s", "hash256s", "publicKeys", "signatures", "aAAStrings", "maps", "crazyMaps"] +safemethods: ["bool", "int", "bytes", "string", "any", "hash160", "hash256", "publicKey", "signature", "bools", "ints", "bytess", "strings", "hash160s", "hash256s", "publicKeys", "signatures", "aAAStrings", "maps", "crazyMaps", "anyMaps"] diff --git a/cli/smartcontract/testdata/types/rpcbindings.out b/cli/smartcontract/testdata/types/rpcbindings.out index ca4f0ce36..49f6ac7e5 100644 --- a/cli/smartcontract/testdata/types/rpcbindings.out +++ b/cli/smartcontract/testdata/types/rpcbindings.out @@ -99,6 +99,34 @@ func (c *ContractReader) Any(a any) (any, error) { } (unwrap.Item(c.invoker.Call(Hash, "any", a))) } +// AnyMaps invokes `anyMaps` method of contract. +func (c *ContractReader) AnyMaps(m map[*big.Int]any) (map[*big.Int]any, error) { + return func (item stackitem.Item, err error) (map[*big.Int]any, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) (map[*big.Int]any, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[*big.Int]any) + for i := range m { + k, err := m[i].Key.TryInteger() + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := m[i].Value.Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(Hash, "anyMaps", m))) +} + // Bool invokes `bool` method of contract. func (c *ContractReader) Bool(b bool) (bool, error) { return unwrap.Bool(c.invoker.Call(Hash, "bool", b)) diff --git a/cli/smartcontract/testdata/types/types.go b/cli/smartcontract/testdata/types/types.go index c8d819dd5..fcf91a0be 100644 --- a/cli/smartcontract/testdata/types/types.go +++ b/cli/smartcontract/testdata/types/types.go @@ -83,3 +83,7 @@ func Maps(m map[string]string) map[string]string { func CrazyMaps(m map[int][]map[string][]interop.Hash160) map[int][]map[string][]interop.Hash160 { return m } + +func AnyMaps(m map[int]any) map[int]any { + return m +} diff --git a/examples/events/events.go b/examples/events/events.go index 28254ee4a..cd45ff15f 100644 --- a/examples/events/events.go +++ b/examples/events/events.go @@ -1,6 +1,7 @@ package events import ( + "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" ) @@ -24,6 +25,11 @@ func NotifySomeMap(arg map[string]int) { runtime.Notify("SomeMap", arg) } +// NotifySomeCrazyMap emits notification with complicated Map. +func NotifySomeCrazyMap(arg map[int][]map[string][]interop.Hash160) { + runtime.Notify("SomeCrazyMap", arg) +} + // NotifySomeArray emits notification with Array. func NotifySomeArray(arg []int) { runtime.Notify("SomeArray", arg) diff --git a/examples/events/events.yml b/examples/events/events.yml index f16bc347e..7b3c05a40 100644 --- a/examples/events/events.yml +++ b/examples/events/events.yml @@ -18,6 +18,10 @@ events: parameters: - name: m type: Map + - name: SomeCrazyMap + parameters: + - name: m + type: Map - name: SomeArray parameters: - name: a diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index a3eab9576..eb38be084 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -511,7 +511,12 @@ func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.Extended case smartcontract.MapType: kt, _ := extendedTypeToGo(binding.ExtendedType{Base: et.Key}, named) - vt, _ := extendedTypeToGo(*et.Value, named) + var vt string + if et.Value != nil { + vt, _ = extendedTypeToGo(*et.Value, named) + } else { + vt = "any" + } return "map[" + kt + "]" + vt, "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" case smartcontract.InteropInterfaceType: return "any", "" @@ -606,8 +611,9 @@ func etTypeConverter(et binding.ExtendedType, v string) string { }, v) case smartcontract.MapType: - at, _ := extendedTypeToGo(et, nil) - return `func (item stackitem.Item) (` + at + `, error) { + if et.Value != nil { + at, _ := extendedTypeToGo(et, nil) + return `func (item stackitem.Item) (` + at + `, error) { m, ok := item.Value().([]stackitem.MapElement) if !ok { return nil, fmt.Errorf("%s is not a map", item.Type().String()) @@ -626,6 +632,14 @@ func etTypeConverter(et binding.ExtendedType, v string) string { } return res, nil } (` + v + `)` + } + return etTypeConverter(binding.ExtendedType{ + Base: smartcontract.MapType, + Key: et.Key, + Value: &binding.ExtendedType{ + Base: smartcontract.AnyType, + }, + }, v) case smartcontract.InteropInterfaceType: return "item.Value(), nil" case smartcontract.VoidType: From 3e2755e66d95a9aa381b3b8156f3b0b3fed1fc7f Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 25 May 2023 18:03:05 +0300 Subject: [PATCH 090/125] smartcontract: add test for user-defined extended event types configuration config_extended.yml contains an example of user-defined configuration file with extended event types. User-defined event types are allowed to be named and complicated, i.e. properly support extended types notation. Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 18 +- .../testdata/notifications/config.yml | 6 +- .../notifications/config_extended.yml | 47 + .../testdata/notifications/notifications.go | 4 + .../testdata/notifications/rpcbindings.out | 92 ++ .../notifications/rpcbindings_extended.out | 1126 +++++++++++++++++ 6 files changed, 1288 insertions(+), 5 deletions(-) create mode 100644 cli/smartcontract/testdata/notifications/config_extended.yml create mode 100755 cli/smartcontract/testdata/notifications/rpcbindings_extended.out diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index 67a46fc12..a9dfaca67 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -379,14 +379,24 @@ func TestAssistedRPCBindings(t *testing.T) { app := cli.NewApp() app.Commands = NewCommands() - var checkBinding = func(source string) { - t.Run(source, func(t *testing.T) { + var checkBinding = func(source string, suffix ...string) { + testName := source + if len(suffix) != 0 { + testName += suffix[0] + } + t.Run(testName, func(t *testing.T) { + configFile := filepath.Join(source, "config.yml") + expectedFile := filepath.Join(source, "rpcbindings.out") + if len(suffix) != 0 { + configFile = filepath.Join(source, "config"+suffix[0]+".yml") + expectedFile = filepath.Join(source, "rpcbindings"+suffix[0]+".out") + } manifestF := filepath.Join(tmpDir, "manifest.json") bindingF := filepath.Join(tmpDir, "binding.yml") nefF := filepath.Join(tmpDir, "out.nef") require.NoError(t, app.Run([]string{"", "contract", "compile", "--in", source, - "--config", filepath.Join(source, "config.yml"), + "--config", configFile, "--manifest", manifestF, "--bindings", bindingF, "--out", nefF, @@ -402,7 +412,6 @@ func TestAssistedRPCBindings(t *testing.T) { data, err := os.ReadFile(outFile) require.NoError(t, err) data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows. - expectedFile := filepath.Join(source, "rpcbindings.out") if rewriteExpectedOutputs { require.NoError(t, os.WriteFile(expectedFile, data, os.ModePerm)) } else { @@ -417,6 +426,7 @@ func TestAssistedRPCBindings(t *testing.T) { checkBinding(filepath.Join("testdata", "types")) checkBinding(filepath.Join("testdata", "structs")) checkBinding(filepath.Join("testdata", "notifications")) + checkBinding(filepath.Join("testdata", "notifications"), "_extended") require.False(t, rewriteExpectedOutputs) } diff --git a/cli/smartcontract/testdata/notifications/config.yml b/cli/smartcontract/testdata/notifications/config.yml index 5fd018d53..ef2866318 100644 --- a/cli/smartcontract/testdata/notifications/config.yml +++ b/cli/smartcontract/testdata/notifications/config.yml @@ -12,4 +12,8 @@ events: - name: "SomeStruct" parameters: - name: s - type: Struct \ No newline at end of file + type: Struct + - name: "SomeArray" + parameters: + - name: a + type: Array \ No newline at end of file diff --git a/cli/smartcontract/testdata/notifications/config_extended.yml b/cli/smartcontract/testdata/notifications/config_extended.yml new file mode 100644 index 000000000..ac8f06d6d --- /dev/null +++ b/cli/smartcontract/testdata/notifications/config_extended.yml @@ -0,0 +1,47 @@ +name: "Notifications" +sourceurl: https://github.com/nspcc-dev/neo-go/ +events: + - name: "! complicated name %$#" + parameters: + - name: ! complicated param @#$% + type: String + - name: "SomeMap" + parameters: + - name: m + type: Map + extendedtype: + base: Map + key: Integer + value: + base: Map + key: String + value: + base: Array + value: + base: Hash160 + - name: "SomeStruct" + parameters: + - name: s + type: Struct + extendedtype: + base: Struct + name: crazyStruct + - name: "SomeArray" + parameters: + - name: a + type: Array + extendedtype: + base: Array + value: + base: Array + value: + base: Integer +namedtypes: + crazyStruct: + base: Struct + name: crazyStruct + fields: + - field: I + base: Integer + - field: B + base: Boolean \ No newline at end of file diff --git a/cli/smartcontract/testdata/notifications/notifications.go b/cli/smartcontract/testdata/notifications/notifications.go index f679901af..80564a4e4 100644 --- a/cli/smartcontract/testdata/notifications/notifications.go +++ b/cli/smartcontract/testdata/notifications/notifications.go @@ -19,3 +19,7 @@ func Struct() { B bool }{I: 123, B: true}) } + +func Array() { + runtime.Notify("SomeArray", [][]int{}) +} diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index ae0724975..ea40f64ea 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -92,6 +92,11 @@ type SomeStructEvent struct { S []any } +// SomeArrayEvent represents "SomeArray" event emitted by the contract. +type SomeArrayEvent struct { + A []any +} + // Actor is used by Contract to call state-changing methods. type Actor interface { MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) @@ -112,6 +117,28 @@ func New(actor Actor) *Contract { return &Contract{actor} } +// Array creates a transaction invoking `array` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Array() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "array") +} + +// ArrayTransaction creates a transaction invoking `array` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "array") +} + +// ArrayUnsigned creates a transaction invoking `array` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "array", nil) +} + // CrazyMap creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. @@ -936,3 +963,68 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { return nil } + +// SomeArrayEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeArray" name from the provided ApplicationLog. +func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeArrayEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeArray" { + continue + } + event := new(SomeArrayEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeArrayEvent and +// returns an error if so. +func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.A, err = func (item stackitem.Item) ([]any, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]any, len(arr)) + for i := range res { + res[i], err = arr[i].Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field A: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out new file mode 100755 index 000000000..0c64320a8 --- /dev/null +++ b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out @@ -0,0 +1,1126 @@ +// Package structs contains RPC wrappers for Notifications contract. +package structs + +import ( + "crypto/elliptic" + "errors" + "fmt" + "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/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// Hash contains contract hash. +var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} + +// CrazyStruct is a contract-specific crazyStruct type used by its methods. +type CrazyStruct struct { + I *big.Int + B bool +} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract. +type ComplicatedNameEvent struct { + ComplicatedParam string +} + +// SomeMapEvent represents "SomeMap" event emitted by the contract. +type SomeMapEvent struct { + M map[*big.Int]map[string][]util.Uint160 +} + +// SomeStructEvent represents "SomeStruct" event emitted by the contract. +type SomeStructEvent struct { + S *CrazyStruct +} + +// SomeArrayEvent represents "SomeArray" event emitted by the contract. +type SomeArrayEvent struct { + A [][]*big.Int +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// Contract implements all contract methods. +type Contract struct { + actor Actor +} + +// New creates an instance of Contract using Hash and the given Actor. +func New(actor Actor) *Contract { + return &Contract{actor} +} + +// Array creates a transaction invoking `array` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Array() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "array") +} + +// ArrayTransaction creates a transaction invoking `array` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "array") +} + +// ArrayUnsigned creates a transaction invoking `array` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "array", nil) +} + +// CrazyMap creates a transaction invoking `crazyMap` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) CrazyMap() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "crazyMap") +} + +// CrazyMapTransaction creates a transaction invoking `crazyMap` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "crazyMap") +} + +// CrazyMapUnsigned creates a transaction invoking `crazyMap` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) CrazyMapUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "crazyMap", nil) +} + +// Main creates a transaction invoking `main` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Main() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "main") +} + +// MainTransaction creates a transaction invoking `main` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) MainTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "main") +} + +// MainUnsigned creates a transaction invoking `main` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "main", nil) +} + +// Struct creates a transaction invoking `struct` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Struct() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "struct") +} + +// StructTransaction creates a transaction invoking `struct` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) StructTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "struct") +} + +// StructUnsigned creates a transaction invoking `struct` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) StructUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "struct", nil) +} + +// itemToCrazyStruct converts stack item into *CrazyStruct. +func itemToCrazyStruct(item stackitem.Item, err error) (*CrazyStruct, error) { + if err != nil { + return nil, err + } + var res = new(CrazyStruct) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of CrazyStruct from the given stack item +// and returns an error if so. +func (res *CrazyStruct) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + index++ + res.B, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field B: %w", err) + } + + return nil +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given stack item +// and returns an error if so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given stack item +// and returns an error if so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given stack item +// and returns an error if so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item +// and returns an error if so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item +// and returns an error if so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item +// and returns an error if so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events +// with "! complicated name %$#" name from the provided ApplicationLog. +func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*ComplicatedNameEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "! complicated name %$#" { + continue + } + event := new(ComplicatedNameEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent and +// returns an error if so. +func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.ComplicatedParam, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field ComplicatedParam: %w", err) + } + + return nil +} + +// SomeMapEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeMap" name from the provided ApplicationLog. +func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeMapEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeMap" { + continue + } + event := new(SomeMapEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeMapEvent and +// returns an error if so. +func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.M, err = func (item stackitem.Item) (map[*big.Int]map[string][]util.Uint160, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[*big.Int]map[string][]util.Uint160) + for i := range m { + k, err := m[i].Key.TryInteger() + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (map[string][]util.Uint160, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string][]util.Uint160) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field M: %w", err) + } + + return nil +} + +// SomeStructEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeStruct" name from the provided ApplicationLog. +func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStructEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeStructEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeStruct" { + continue + } + event := new(SomeStructEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeStructEvent and +// returns an error if so. +func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.S, err = itemToCrazyStruct(arr[index], nil) + if err != nil { + return fmt.Errorf("field S: %w", err) + } + + return nil +} + +// SomeArrayEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeArray" name from the provided ApplicationLog. +func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeArrayEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeArray" { + continue + } + event := new(SomeArrayEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeArrayEvent and +// returns an error if so. +func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.A, err = func (item stackitem.Item) ([][]*big.Int, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([][]*big.Int, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) ([]*big.Int, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*big.Int, len(arr)) + for i := range res { + res[i], err = arr[i].TryInteger() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field A: %w", err) + } + + return nil +} From 0195aae8248d0b565994933aa73095fcf14c58e9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 25 May 2023 18:39:27 +0300 Subject: [PATCH 091/125] cli: add test for --guessed-eventtypes RPC binding generator flag Currently we have problems with unnamed structs used as a parameter for notifications, because there's no one-to-one correspondence between notification parameter and the list of extended types used by the whole contract. Otherwise eventtypes guessing works OK. Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 19 +- .../testdata/notifications/config_guessed.yml | 19 + .../notifications/rpcbindings_guessed.out | 1152 +++++++++++++++++ 3 files changed, 1183 insertions(+), 7 deletions(-) create mode 100644 cli/smartcontract/testdata/notifications/config_guessed.yml create mode 100755 cli/smartcontract/testdata/notifications/rpcbindings_guessed.out diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index a9dfaca67..6b4d5aa2f 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -379,7 +379,7 @@ func TestAssistedRPCBindings(t *testing.T) { app := cli.NewApp() app.Commands = NewCommands() - var checkBinding = func(source string, suffix ...string) { + var checkBinding = func(source string, guessEventTypes bool, suffix ...string) { testName := source if len(suffix) != 0 { testName += suffix[0] @@ -394,13 +394,17 @@ func TestAssistedRPCBindings(t *testing.T) { manifestF := filepath.Join(tmpDir, "manifest.json") bindingF := filepath.Join(tmpDir, "binding.yml") nefF := filepath.Join(tmpDir, "out.nef") - require.NoError(t, app.Run([]string{"", "contract", "compile", + cmd := []string{"", "contract", "compile", "--in", source, "--config", configFile, "--manifest", manifestF, "--bindings", bindingF, "--out", nefF, - })) + } + if guessEventTypes { + cmd = append(cmd, "--guess-eventtypes") + } + require.NoError(t, app.Run(cmd)) outFile := filepath.Join(tmpDir, "out.go") require.NoError(t, app.Run([]string{"", "contract", "generate-rpcwrapper", "--config", bindingF, @@ -423,10 +427,11 @@ func TestAssistedRPCBindings(t *testing.T) { }) } - checkBinding(filepath.Join("testdata", "types")) - checkBinding(filepath.Join("testdata", "structs")) - checkBinding(filepath.Join("testdata", "notifications")) - checkBinding(filepath.Join("testdata", "notifications"), "_extended") + checkBinding(filepath.Join("testdata", "types"), false) + checkBinding(filepath.Join("testdata", "structs"), false) + checkBinding(filepath.Join("testdata", "notifications"), false) + checkBinding(filepath.Join("testdata", "notifications"), false, "_extended") + checkBinding(filepath.Join("testdata", "notifications"), true, "_guessed") require.False(t, rewriteExpectedOutputs) } diff --git a/cli/smartcontract/testdata/notifications/config_guessed.yml b/cli/smartcontract/testdata/notifications/config_guessed.yml new file mode 100644 index 000000000..ef2866318 --- /dev/null +++ b/cli/smartcontract/testdata/notifications/config_guessed.yml @@ -0,0 +1,19 @@ +name: "Notifications" +sourceurl: https://github.com/nspcc-dev/neo-go/ +events: + - name: "! complicated name %$#" + parameters: + - name: ! complicated param @#$% + type: String + - name: "SomeMap" + parameters: + - name: m + type: Map + - name: "SomeStruct" + parameters: + - name: s + type: Struct + - name: "SomeArray" + parameters: + - name: a + type: Array \ No newline at end of file diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out new file mode 100755 index 000000000..09bb03117 --- /dev/null +++ b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out @@ -0,0 +1,1152 @@ +// Package structs contains RPC wrappers for Notifications contract. +package structs + +import ( + "crypto/elliptic" + "errors" + "fmt" + "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/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// Hash contains contract hash. +var Hash = util.Uint160{0x33, 0x22, 0x11, 0x0, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x0} + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// Unnamed is a contract-specific unnamed type used by its methods. +type Unnamed struct { + I *big.Int + B bool +} + +// ComplicatedNameEvent represents "! complicated name %$#" event emitted by the contract. +type ComplicatedNameEvent struct { + ComplicatedParam string +} + +// SomeMapEvent represents "SomeMap" event emitted by the contract. +type SomeMapEvent struct { + M map[*big.Int][]map[string][]util.Uint160 +} + +// SomeStructEvent represents "SomeStruct" event emitted by the contract. +type SomeStructEvent struct { + S []any +} + +// SomeArrayEvent represents "SomeArray" event emitted by the contract. +type SomeArrayEvent struct { + A [][]*big.Int +} + +// Actor is used by Contract to call state-changing methods. +type Actor interface { + MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) + MakeRun(script []byte) (*transaction.Transaction, error) + MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) + MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) + SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) + SendRun(script []byte) (util.Uint256, uint32, error) +} + +// Contract implements all contract methods. +type Contract struct { + actor Actor +} + +// New creates an instance of Contract using Hash and the given Actor. +func New(actor Actor) *Contract { + return &Contract{actor} +} + +// Array creates a transaction invoking `array` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Array() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "array") +} + +// ArrayTransaction creates a transaction invoking `array` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "array") +} + +// ArrayUnsigned creates a transaction invoking `array` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "array", nil) +} + +// CrazyMap creates a transaction invoking `crazyMap` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) CrazyMap() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "crazyMap") +} + +// CrazyMapTransaction creates a transaction invoking `crazyMap` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "crazyMap") +} + +// CrazyMapUnsigned creates a transaction invoking `crazyMap` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) CrazyMapUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "crazyMap", nil) +} + +// Main creates a transaction invoking `main` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Main() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "main") +} + +// MainTransaction creates a transaction invoking `main` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) MainTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "main") +} + +// MainUnsigned creates a transaction invoking `main` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "main", nil) +} + +// Struct creates a transaction invoking `struct` method of the contract. +// This transaction is signed and immediately sent to the network. +// The values returned are its hash, ValidUntilBlock value and error if any. +func (c *Contract) Struct() (util.Uint256, uint32, error) { + return c.actor.SendCall(Hash, "struct") +} + +// StructTransaction creates a transaction invoking `struct` method of the contract. +// This transaction is signed, but not sent to the network, instead it's +// returned to the caller. +func (c *Contract) StructTransaction() (*transaction.Transaction, error) { + return c.actor.MakeCall(Hash, "struct") +} + +// StructUnsigned creates a transaction invoking `struct` method of the contract. +// This transaction is not signed, it's simply returned to the caller. +// Any fields of it that do not affect fees can be changed (ValidUntilBlock, +// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. +func (c *Contract) StructUnsigned() (*transaction.Transaction, error) { + return c.actor.MakeUnsignedCall(Hash, "struct", nil) +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given stack item +// and returns an error if so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given stack item +// and returns an error if so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given stack item +// and returns an error if so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item +// and returns an error if so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item +// and returns an error if so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item +// and returns an error if so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToUnnamed converts stack item into *Unnamed. +func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { + if err != nil { + return nil, err + } + var res = new(Unnamed) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of Unnamed from the given stack item +// and returns an error if so. +func (res *Unnamed) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.I, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field I: %w", err) + } + + index++ + res.B, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field B: %w", err) + } + + return nil +} + +// ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events +// with "! complicated name %$#" name from the provided ApplicationLog. +func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*ComplicatedNameEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "! complicated name %$#" { + continue + } + event := new(ComplicatedNameEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent and +// returns an error if so. +func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.ComplicatedParam, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field ComplicatedParam: %w", err) + } + + return nil +} + +// SomeMapEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeMap" name from the provided ApplicationLog. +func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeMapEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeMap" { + continue + } + event := new(SomeMapEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeMapEvent and +// returns an error if so. +func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.M, err = func (item stackitem.Item) (map[*big.Int][]map[string][]util.Uint160, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[*big.Int][]map[string][]util.Uint160) + for i := range m { + k, err := m[i].Key.TryInteger() + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) ([]map[string][]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]map[string][]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (map[string][]util.Uint160, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string][]util.Uint160) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field M: %w", err) + } + + return nil +} + +// SomeStructEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeStruct" name from the provided ApplicationLog. +func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStructEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeStructEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeStruct" { + continue + } + event := new(SomeStructEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeStructEvent and +// returns an error if so. +func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.S, err = func (item stackitem.Item) ([]any, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]any, len(arr)) + for i := range res { + res[i], err = arr[i].Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field S: %w", err) + } + + return nil +} + +// SomeArrayEventsFromApplicationLog retrieves a set of all emitted events +// with "SomeArray" name from the provided ApplicationLog. +func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) { + if log == nil { + return nil, errors.New("nil application log") + } + + var res []*SomeArrayEvent + for i, ex := range log.Executions { + for j, e := range ex.Events { + if e.Name != "SomeArray" { + continue + } + event := new(SomeArrayEvent) + err := event.FromStackItem(e.Item) + if err != nil { + return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err) + } + res = append(res, event) + } + } + + return res, nil +} + +// FromStackItem converts provided stackitem.Array to SomeArrayEvent and +// returns an error if so. +func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { + if item == nil { + return errors.New("nil item") + } + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 1 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + e.A, err = func (item stackitem.Item) ([][]*big.Int, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([][]*big.Int, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) ([]*big.Int, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*big.Int, len(arr)) + for i := range res { + res[i], err = arr[i].TryInteger() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field A: %w", err) + } + + return nil +} From 6379bcc15ac444cdc15bc968e23b235934a5f7e6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 25 May 2023 18:45:59 +0300 Subject: [PATCH 092/125] compiler: properly set extended type name for unnamed structs After the struct was registered as "unnamed", it has the own unique name. Signed-off-by: Anna Shaleva --- .../notifications/rpcbindings_guessed.out | 17 ++--------------- pkg/compiler/debug.go | 7 ++++++- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out index 09bb03117..c9c20ae5b 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out @@ -95,7 +95,7 @@ type SomeMapEvent struct { // SomeStructEvent represents "SomeStruct" event emitted by the contract. type SomeStructEvent struct { - S []any + S *Unnamed } // SomeArrayEvent represents "SomeArray" event emitted by the contract. @@ -1052,20 +1052,7 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { err error ) index++ - e.S, err = func (item stackitem.Item) ([]any, error) { - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("not an array") - } - res := make([]any, len(arr)) - for i := range res { - res[i], err = arr[i].Value(), error(nil) - if err != nil { - return nil, fmt.Errorf("item %d: %w", i, err) - } - } - return res, nil - } (arr[index]) + e.S, err = itemToUnnamed(arr[index], nil) if err != nil { return fmt.Errorf("field S: %w", err) } diff --git a/pkg/compiler/debug.go b/pkg/compiler/debug.go index 0eb18bb5a..a583fc3bd 100644 --- a/pkg/compiler/debug.go +++ b/pkg/compiler/debug.go @@ -386,10 +386,12 @@ func (c *codegen) scAndVMTypeFromType(t types.Type, exts map[string]binding.Exte over.TypeName = "map[" + t.Key().String() + "]" + over.TypeName return smartcontract.MapType, stackitem.MapT, over, et case *types.Struct: + var extName string if isNamed { over.Package = named.Obj().Pkg().Path() over.TypeName = named.Obj().Pkg().Name() + "." + named.Obj().Name() _ = c.genStructExtended(t, over.TypeName, exts) + extName = over.TypeName } else { name := "unnamed" if exts != nil { @@ -398,11 +400,14 @@ func (c *codegen) scAndVMTypeFromType(t types.Type, exts map[string]binding.Exte } _ = c.genStructExtended(t, name, exts) } + // For bindings configurator this structure becomes named in fact. Its name + // is "unnamed[X...X]". + extName = name } return smartcontract.ArrayType, stackitem.StructT, over, &binding.ExtendedType{ // Value-less, refer to exts. Base: smartcontract.ArrayType, - Name: over.TypeName, + Name: extName, } case *types.Slice: From 865bd6c9cc78be20587be7d64aacb815589ff8fe Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 25 May 2023 19:17:49 +0300 Subject: [PATCH 093/125] compiler: compare emitted event params if --guess-eventtypes enabled In this case emitted event parameters should match from invocation to invocation. It's an error otherwise (and if the type is not Any). Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 49 ++++ .../testdata/invalid5/invalid.go | 7 + .../testdata/invalid5/invalid.yml | 1 + .../testdata/invalid6/invalid.go | 7 + .../testdata/invalid6/invalid.yml | 6 + .../testdata/invalid7/invalid.go | 7 + .../testdata/invalid7/invalid.yml | 8 + .../testdata/invalid8/invalid.go | 17 ++ .../testdata/invalid8/invalid.yml | 6 + pkg/compiler/compiler.go | 35 ++- pkg/smartcontract/binding/generate.go | 31 +++ pkg/smartcontract/binding/generate_test.go | 229 ++++++++++++++++++ 12 files changed, 399 insertions(+), 4 deletions(-) create mode 100644 cli/smartcontract/testdata/invalid5/invalid.go create mode 100644 cli/smartcontract/testdata/invalid5/invalid.yml create mode 100644 cli/smartcontract/testdata/invalid6/invalid.go create mode 100644 cli/smartcontract/testdata/invalid6/invalid.yml create mode 100644 cli/smartcontract/testdata/invalid7/invalid.go create mode 100644 cli/smartcontract/testdata/invalid7/invalid.yml create mode 100644 cli/smartcontract/testdata/invalid8/invalid.go create mode 100644 cli/smartcontract/testdata/invalid8/invalid.yml create mode 100644 pkg/smartcontract/binding/generate_test.go diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index 6b4d5aa2f..e2a31d913 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -499,3 +499,52 @@ callflags: "--config", cfgPath, "--out", "zzz") }) } + +func TestCompile_GuessEventTypes(t *testing.T) { + app := cli.NewApp() + app.Commands = NewCommands() + app.ExitErrHandler = func(*cli.Context, error) {} + + checkError := func(t *testing.T, msg string, args ...string) { + // cli.ExitError doesn't implement wraping properly, so we check for an error message. + err := app.Run(args) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), msg), "got: %v", err) + } + check := func(t *testing.T, source string, expectedErrText string) { + tmpDir := t.TempDir() + configFile := filepath.Join(source, "invalid.yml") + manifestF := filepath.Join(tmpDir, "invalid.manifest.json") + bindingF := filepath.Join(tmpDir, "invalid.binding.yml") + nefF := filepath.Join(tmpDir, "invalid.out.nef") + cmd := []string{"", "contract", "compile", + "--in", source, + "--config", configFile, + "--manifest", manifestF, + "--bindings", bindingF, + "--out", nefF, + "--guess-eventtypes", + } + checkError(t, expectedErrText, cmd...) + } + + t.Run("not declared in manifest", func(t *testing.T) { + check(t, filepath.Join("testdata", "invalid5"), "inconsistent usages of event `Non declared event`: not declared in the contract config") + }) + t.Run("invalid number of params", func(t *testing.T) { + check(t, filepath.Join("testdata", "invalid6"), "inconsistent usages of event `SomeEvent` against config: number of params mismatch: 2 vs 1") + }) + /* + // TODO: this on is a controversial one. If event information is provided in the config file, then conversion code + // will be emitted by the compiler according to the parameter type provided via config. Thus, we can be sure that + // either event parameter has the type specified in the config file or the execution of the contract will fail. + // Thus, this testcase is always failing (no compilation error occures). + // Question: do we want to compare `RealType` of the emitted parameter with the one expected in the manifest? + t.Run("SC parameter type mismatch", func(t *testing.T) { + check(t, filepath.Join("testdata", "invalid7"), "inconsistent usages of event `SomeEvent` against config: number of params mismatch: 2 vs 1") + }) + */ + t.Run("extended types mismatch", func(t *testing.T) { + check(t, filepath.Join("testdata", "invalid8"), "inconsistent usages of event `SomeEvent`: extended type of param #0 mismatch") + }) +} diff --git a/cli/smartcontract/testdata/invalid5/invalid.go b/cli/smartcontract/testdata/invalid5/invalid.go new file mode 100644 index 000000000..0cae2ed71 --- /dev/null +++ b/cli/smartcontract/testdata/invalid5/invalid.go @@ -0,0 +1,7 @@ +package invalid5 + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +func Main() { + runtime.Notify("Non declared event") +} diff --git a/cli/smartcontract/testdata/invalid5/invalid.yml b/cli/smartcontract/testdata/invalid5/invalid.yml new file mode 100644 index 000000000..eda948267 --- /dev/null +++ b/cli/smartcontract/testdata/invalid5/invalid.yml @@ -0,0 +1 @@ +name: Test undeclared event \ No newline at end of file diff --git a/cli/smartcontract/testdata/invalid6/invalid.go b/cli/smartcontract/testdata/invalid6/invalid.go new file mode 100644 index 000000000..dd3a3ecdd --- /dev/null +++ b/cli/smartcontract/testdata/invalid6/invalid.go @@ -0,0 +1,7 @@ +package invalid6 + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +func Main() { + runtime.Notify("SomeEvent", "p1", "p2") +} diff --git a/cli/smartcontract/testdata/invalid6/invalid.yml b/cli/smartcontract/testdata/invalid6/invalid.yml new file mode 100644 index 000000000..13933803e --- /dev/null +++ b/cli/smartcontract/testdata/invalid6/invalid.yml @@ -0,0 +1,6 @@ +name: Test undeclared event +events: + - name: SomeEvent + parameters: + - name: p1 + type: String \ No newline at end of file diff --git a/cli/smartcontract/testdata/invalid7/invalid.go b/cli/smartcontract/testdata/invalid7/invalid.go new file mode 100644 index 000000000..41bc20c47 --- /dev/null +++ b/cli/smartcontract/testdata/invalid7/invalid.go @@ -0,0 +1,7 @@ +package invalid7 + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +func Main() { + runtime.Notify("SomeEvent", "p1", 5) +} diff --git a/cli/smartcontract/testdata/invalid7/invalid.yml b/cli/smartcontract/testdata/invalid7/invalid.yml new file mode 100644 index 000000000..a217deefd --- /dev/null +++ b/cli/smartcontract/testdata/invalid7/invalid.yml @@ -0,0 +1,8 @@ +name: Test undeclared event +events: + - name: SomeEvent + parameters: + - name: p1 + type: String + - name: p2 + type: String \ No newline at end of file diff --git a/cli/smartcontract/testdata/invalid8/invalid.go b/cli/smartcontract/testdata/invalid8/invalid.go new file mode 100644 index 000000000..dba9173ca --- /dev/null +++ b/cli/smartcontract/testdata/invalid8/invalid.go @@ -0,0 +1,17 @@ +package invalid8 + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +type SomeStruct1 struct { + Field1 int +} + +type SomeStruct2 struct { + Field2 string +} + +func Main() { + // Inconsistent event params usages (different named types throughout the usages). + runtime.Notify("SomeEvent", SomeStruct1{Field1: 123}) + runtime.Notify("SomeEvent", SomeStruct2{Field2: "str"}) +} diff --git a/cli/smartcontract/testdata/invalid8/invalid.yml b/cli/smartcontract/testdata/invalid8/invalid.yml new file mode 100644 index 000000000..6c0c34748 --- /dev/null +++ b/cli/smartcontract/testdata/invalid8/invalid.yml @@ -0,0 +1,6 @@ +name: Test undeclared event +events: + - name: SomeEvent + parameters: + - name: p1 + type: Array \ No newline at end of file diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index eac2bdced..2b90ac07e 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -356,16 +356,43 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { if o.GuessEventTypes { if len(di.EmittedEvents) > 0 { for eventName, eventUsages := range di.EmittedEvents { + var manifestEvent HybridEvent + for _, e := range o.ContractEvents { + if e.Name == eventName { + manifestEvent = e + break + } + } + if len(manifestEvent.Name) == 0 { + return nil, fmt.Errorf("inconsistent usages of event `%s`: not declared in the contract config", eventName) + } + exampleUsage := eventUsages[0] + for _, usage := range eventUsages { + if len(usage.Params) != len(manifestEvent.Parameters) { + return nil, fmt.Errorf("inconsistent usages of event `%s` against config: number of params mismatch: %d vs %d", eventName, len(exampleUsage.Params), len(manifestEvent.Parameters)) + } + for i, actual := range usage.Params { + mParam := manifestEvent.Parameters[i] + // TODO: see the TestCompile_GuessEventTypes, "SC parameter type mismatch" section, + // do we want to compare with actual.RealType? The conversion code is emitted by the + // compiler for it, so we expect the parameter to be of the proper type. + if !(mParam.Type == smartcontract.AnyType || actual.TypeSC == mParam.Type) { + return nil, fmt.Errorf("inconsistent usages of event `%s` against config: SC type of param #%d mismatch: %s vs %s", eventName, i, actual.TypeSC, mParam.Type) + } + expected := exampleUsage.Params[i] + if !actual.ExtendedType.Equals(expected.ExtendedType) { + return nil, fmt.Errorf("inconsistent usages of event `%s`: extended type of param #%d mismatch", eventName, i) + } + } + } eBindingName := rpcbinding.ToEventBindingName(eventName) - // Take into account the first usage only. - // TODO: extend it to the rest of invocations. - for typeName, extType := range eventUsages[0].ExtTypes { + for typeName, extType := range exampleUsage.ExtTypes { if _, ok := cfg.NamedTypes[typeName]; !ok { cfg.NamedTypes[typeName] = extType } } - for _, p := range eventUsages[0].Params { + for _, p := range exampleUsage.Params { pBindingName := rpcbinding.ToParameterBindingName(p.Name) pname := eBindingName + "." + pBindingName if p.RealType.TypeName != "" { diff --git a/pkg/smartcontract/binding/generate.go b/pkg/smartcontract/binding/generate.go index 33bb21dd2..bd7d42cbc 100644 --- a/pkg/smartcontract/binding/generate.go +++ b/pkg/smartcontract/binding/generate.go @@ -265,3 +265,34 @@ func TemplateFromManifest(cfg Config, scTypeConverter func(string, smartcontract func upperFirst(s string) string { return strings.ToUpper(s[0:1]) + s[1:] } + +// Equals compares two extended types field-by-field and returns true if they are +// equal. +func (e *ExtendedType) Equals(other *ExtendedType) bool { + if e == nil && other == nil { + return true + } + if e != nil && other == nil || + e == nil && other != nil { + return false + } + if !((e.Base == other.Base || (e.Base == smartcontract.ByteArrayType || e.Base == smartcontract.StringType) && + (other.Base == smartcontract.ByteArrayType || other.Base == smartcontract.StringType)) && + e.Name == other.Name && + e.Interface == other.Interface && + e.Key == other.Key) { + return false + } + if len(e.Fields) != len(other.Fields) { + return false + } + for i := range e.Fields { + if e.Fields[i].Field != other.Fields[i].Field { + return false + } + if !e.Fields[i].ExtendedType.Equals(&other.Fields[i].ExtendedType) { + return false + } + } + return (e.Value == nil && other.Value == nil) || (e.Value != nil && other.Value != nil && e.Value.Equals(other.Value)) +} diff --git a/pkg/smartcontract/binding/generate_test.go b/pkg/smartcontract/binding/generate_test.go new file mode 100644 index 000000000..64522d28c --- /dev/null +++ b/pkg/smartcontract/binding/generate_test.go @@ -0,0 +1,229 @@ +package binding + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/stretchr/testify/assert" +) + +func TestExtendedType_Equals(t *testing.T) { + crazyT := ExtendedType{ + Base: smartcontract.StringType, + Name: "qwertyu", + Interface: "qwerty", + Key: smartcontract.BoolType, + Value: &ExtendedType{ + Base: smartcontract.IntegerType, + }, + Fields: []FieldExtendedType{ + { + Field: "qwe", + ExtendedType: ExtendedType{ + Base: smartcontract.IntegerType, + Name: "qwer", + Interface: "qw", + Key: smartcontract.ArrayType, + Fields: []FieldExtendedType{ + { + Field: "as", + }, + }, + }, + }, + { + Field: "asf", + ExtendedType: ExtendedType{ + Base: smartcontract.BoolType, + }, + }, + { + Field: "sffg", + ExtendedType: ExtendedType{ + Base: smartcontract.AnyType, + }, + }, + }, + } + tcs := map[string]struct { + a *ExtendedType + b *ExtendedType + expectedRes bool + }{ + "both nil": { + a: nil, + b: nil, + expectedRes: true, + }, + "a is nil": { + a: nil, + b: &ExtendedType{}, + expectedRes: false, + }, + "b is nil": { + a: &ExtendedType{}, + b: nil, + expectedRes: false, + }, + "base mismatch": { + a: &ExtendedType{ + Base: smartcontract.StringType, + }, + b: &ExtendedType{ + Base: smartcontract.IntegerType, + }, + expectedRes: false, + }, + "name mismatch": { + a: &ExtendedType{ + Base: smartcontract.ArrayType, + Name: "q", + }, + b: &ExtendedType{ + Base: smartcontract.ArrayType, + Name: "w", + }, + expectedRes: false, + }, + "number of fields mismatch": { + a: &ExtendedType{ + Base: smartcontract.ArrayType, + Name: "q", + Fields: []FieldExtendedType{ + { + Field: "IntField", + ExtendedType: ExtendedType{Base: smartcontract.IntegerType}, + }, + }, + }, + b: &ExtendedType{ + Base: smartcontract.ArrayType, + Name: "w", + Fields: []FieldExtendedType{ + { + Field: "IntField", + ExtendedType: ExtendedType{Base: smartcontract.IntegerType}, + }, + { + Field: "BoolField", + ExtendedType: ExtendedType{Base: smartcontract.BoolType}, + }, + }, + }, + expectedRes: false, + }, + "field names mismatch": { + a: &ExtendedType{ + Base: smartcontract.ArrayType, + Fields: []FieldExtendedType{ + { + Field: "IntField", + ExtendedType: ExtendedType{Base: smartcontract.IntegerType}, + }, + }, + }, + b: &ExtendedType{ + Base: smartcontract.ArrayType, + Fields: []FieldExtendedType{ + { + Field: "BoolField", + ExtendedType: ExtendedType{Base: smartcontract.BoolType}, + }, + }, + }, + expectedRes: false, + }, + "field types mismatch": { + a: &ExtendedType{ + Base: smartcontract.ArrayType, + Fields: []FieldExtendedType{ + { + Field: "Field", + ExtendedType: ExtendedType{Base: smartcontract.IntegerType}, + }, + }, + }, + b: &ExtendedType{ + Base: smartcontract.ArrayType, + Fields: []FieldExtendedType{ + { + Field: "Field", + ExtendedType: ExtendedType{Base: smartcontract.BoolType}, + }, + }, + }, + expectedRes: false, + }, + "interface mismatch": { + a: &ExtendedType{Interface: "iterator"}, + b: &ExtendedType{Interface: "unknown"}, + expectedRes: false, + }, + "value is nil": { + a: &ExtendedType{ + Base: smartcontract.StringType, + }, + b: &ExtendedType{ + Base: smartcontract.StringType, + }, + expectedRes: true, + }, + "a value is not nil": { + a: &ExtendedType{ + Base: smartcontract.ArrayType, + Value: &ExtendedType{}, + }, + b: &ExtendedType{ + Base: smartcontract.ArrayType, + }, + expectedRes: false, + }, + "b value is not nil": { + a: &ExtendedType{ + Base: smartcontract.ArrayType, + }, + b: &ExtendedType{ + Base: smartcontract.ArrayType, + Value: &ExtendedType{}, + }, + expectedRes: false, + }, + "byte array tolerance for a": { + a: &ExtendedType{ + Base: smartcontract.StringType, + }, + b: &ExtendedType{ + Base: smartcontract.ByteArrayType, + }, + expectedRes: true, + }, + "byte array tolerance for b": { + a: &ExtendedType{ + Base: smartcontract.ByteArrayType, + }, + b: &ExtendedType{ + Base: smartcontract.StringType, + }, + expectedRes: true, + }, + "key mismatch": { + a: &ExtendedType{ + Key: smartcontract.StringType, + }, + b: &ExtendedType{ + Key: smartcontract.IntegerType, + }, + expectedRes: false, + }, + "good nested": { + a: &crazyT, + b: &crazyT, + expectedRes: true, + }, + } + for name, tc := range tcs { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.expectedRes, tc.a.Equals(tc.b)) + }) + } +} From 44dfe8342dea58c3f652907511a8d805204737cf Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 29 May 2023 18:50:36 +0300 Subject: [PATCH 094/125] compiler: disallow named types redeclaration via contract config Signed-off-by: Anna Shaleva --- cli/smartcontract/generate_test.go | 3 +++ cli/smartcontract/testdata/invalid9/invalid.go | 12 ++++++++++++ cli/smartcontract/testdata/invalid9/invalid.yml | 16 ++++++++++++++++ pkg/compiler/compiler.go | 4 +++- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 cli/smartcontract/testdata/invalid9/invalid.go create mode 100644 cli/smartcontract/testdata/invalid9/invalid.yml diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index e2a31d913..6c6a63f90 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -547,4 +547,7 @@ func TestCompile_GuessEventTypes(t *testing.T) { t.Run("extended types mismatch", func(t *testing.T) { check(t, filepath.Join("testdata", "invalid8"), "inconsistent usages of event `SomeEvent`: extended type of param #0 mismatch") }) + t.Run("named types redeclare", func(t *testing.T) { + check(t, filepath.Join("testdata", "invalid9"), "configured declared named type intersects with the contract's one: `invalid9.NamedStruct`") + }) } diff --git a/cli/smartcontract/testdata/invalid9/invalid.go b/cli/smartcontract/testdata/invalid9/invalid.go new file mode 100644 index 000000000..5036bca9f --- /dev/null +++ b/cli/smartcontract/testdata/invalid9/invalid.go @@ -0,0 +1,12 @@ +package invalid9 + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +type NamedStruct struct { + SomeInt int +} + +func Main() NamedStruct { + runtime.Notify("SomeEvent", []interface{}{123}) + return NamedStruct{SomeInt: 123} +} diff --git a/cli/smartcontract/testdata/invalid9/invalid.yml b/cli/smartcontract/testdata/invalid9/invalid.yml new file mode 100644 index 000000000..40bbf66db --- /dev/null +++ b/cli/smartcontract/testdata/invalid9/invalid.yml @@ -0,0 +1,16 @@ +name: Test undeclared event +events: + - name: SomeEvent + parameters: + - name: p1 + type: Array + extendedtype: + base: Array + name: invalid9.NamedStruct +namedtypes: + invalid9.NamedStruct: + base: Array + name: invalid9.NamedStruct + fields: + - field: SomeInt + base: Integer diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 2b90ac07e..a7826a552 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -340,7 +340,9 @@ func CompileAndSave(src string, o *Options) ([]byte, error) { cfg.NamedTypes = di.NamedTypes } for name, et := range o.DeclaredNamedTypes { - // TODO: handle name conflict (it can happen due to invalid user input e.g.) + if _, ok := cfg.NamedTypes[name]; ok { + return nil, fmt.Errorf("configured declared named type intersects with the contract's one: `%s`", name) + } cfg.NamedTypes[name] = et } for _, e := range o.ContractEvents { From 2ce1454ef51b733e2732f1895db11863296db259 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 30 May 2023 11:59:16 +0300 Subject: [PATCH 095/125] cli: improve error message for binding template Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/nameservice/nns.go | 4 ++-- cli/smartcontract/testdata/nex/nex.go | 2 +- cli/smartcontract/testdata/notifications/rpcbindings.out | 8 ++++---- .../testdata/notifications/rpcbindings_extended.out | 8 ++++---- .../testdata/notifications/rpcbindings_guessed.out | 8 ++++---- cli/smartcontract/testdata/verifyrpc/verify.go | 2 +- pkg/smartcontract/rpcbinding/binding.go | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 4c3a76d6f..076aaa438 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -354,7 +354,7 @@ func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEv event := new(SetAdminEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SetAdminEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SetAdminEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -447,7 +447,7 @@ func RenewEventsFromApplicationLog(log *result.ApplicationLog) ([]*RenewEvent, e event := new(RenewEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize RenewEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize RenewEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index f558fb513..ac530f79c 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -258,7 +258,7 @@ func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, event := new(OnMintEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize OnMintEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize OnMintEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index ea40f64ea..4b95b5a65 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -784,7 +784,7 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com event := new(ComplicatedNameEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -845,7 +845,7 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven event := new(SomeMapEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -915,7 +915,7 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru event := new(SomeStructEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -980,7 +980,7 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray event := new(SomeArrayEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out index 0c64320a8..9b269e2eb 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out @@ -830,7 +830,7 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com event := new(ComplicatedNameEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -891,7 +891,7 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven event := new(SomeMapEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -1011,7 +1011,7 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru event := new(SomeStructEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -1063,7 +1063,7 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray event := new(SomeArrayEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out index c9c20ae5b..0fba2708c 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out @@ -830,7 +830,7 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com event := new(ComplicatedNameEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize ComplicatedNameEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -891,7 +891,7 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven event := new(SomeMapEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeMapEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -1024,7 +1024,7 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru event := new(SomeStructEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeStructEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } @@ -1076,7 +1076,7 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray event := new(SomeArrayEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index 6835a7e4e..dd3539901 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -93,7 +93,7 @@ func HelloWorldEventsFromApplicationLog(log *result.ApplicationLog) ([]*HelloWor event := new(HelloWorldEvent) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize HelloWorldEvent from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize HelloWorldEvent from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index eb38be084..746dcb34b 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -278,7 +278,7 @@ func {{$e.Name}}sFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}, event := new({{$e.Name}}) err := event.FromStackItem(e.Item) if err != nil { - return nil, fmt.Errorf("failed to deserialize {{$e.Name}} from stackitem (execution %d, event %d): %w", i, j, err) + return nil, fmt.Errorf("failed to deserialize {{$e.Name}} from stackitem (execution #%d, event #%d): %w", i, j, err) } res = append(res, event) } From 8ae4a1e957a17087a3d28b7270561971d4566263 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 30 May 2023 17:34:51 +0300 Subject: [PATCH 096/125] rpcbinding: adjust comment of `FromStackItem` template methods Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/nameservice/nns.go | 8 ++--- cli/smartcontract/testdata/nex/nex.go | 4 +-- .../testdata/notifications/rpcbindings.out | 28 ++++++++--------- .../notifications/rpcbindings_extended.out | 30 +++++++++---------- .../notifications/rpcbindings_guessed.out | 30 +++++++++---------- .../testdata/structs/rpcbindings.out | 30 +++++++++---------- .../testdata/verifyrpc/verify.go | 4 +-- pkg/smartcontract/rpcbinding/binding.go | 6 ++-- 8 files changed, 70 insertions(+), 70 deletions(-) diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 076aaa438..82cc8374d 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -363,8 +363,8 @@ func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEv return res, nil } -// FromStackItem converts provided stackitem.Array to SetAdminEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SetAdminEvent or +// returns an error if it's not possible to do to so. func (e *SetAdminEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -456,8 +456,8 @@ func RenewEventsFromApplicationLog(log *result.ApplicationLog) ([]*RenewEvent, e return res, nil } -// FromStackItem converts provided stackitem.Array to RenewEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to RenewEvent or +// returns an error if it's not possible to do to so. func (e *RenewEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index ac530f79c..0d716adde 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -267,8 +267,8 @@ func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, return res, nil } -// FromStackItem converts provided stackitem.Array to OnMintEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to OnMintEvent or +// returns an error if it's not possible to do to so. func (e *OnMintEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index 4b95b5a65..1e873d611 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -216,7 +216,7 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { } // FromStackItem retrieves fields of LedgerBlock from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -338,7 +338,7 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) } // FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -476,7 +476,7 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction } // FromStackItem retrieves fields of LedgerTransaction from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -572,7 +572,7 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans } // FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -699,7 +699,7 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes } // FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -739,7 +739,7 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule } // FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -793,8 +793,8 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com return res, nil } -// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent or +// returns an error if it's not possible to do to so. func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -854,8 +854,8 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven return res, nil } -// FromStackItem converts provided stackitem.Array to SomeMapEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeMapEvent or +// returns an error if it's not possible to do to so. func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -924,8 +924,8 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru return res, nil } -// FromStackItem converts provided stackitem.Array to SomeStructEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeStructEvent or +// returns an error if it's not possible to do to so. func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -989,8 +989,8 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray return res, nil } -// FromStackItem converts provided stackitem.Array to SomeArrayEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeArrayEvent or +// returns an error if it's not possible to do to so. func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out index 9b269e2eb..3b2ab5c07 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out @@ -222,7 +222,7 @@ func itemToCrazyStruct(item stackitem.Item, err error) (*CrazyStruct, error) { } // FromStackItem retrieves fields of CrazyStruct from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *CrazyStruct) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -262,7 +262,7 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { } // FromStackItem retrieves fields of LedgerBlock from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -384,7 +384,7 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) } // FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -522,7 +522,7 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction } // FromStackItem retrieves fields of LedgerTransaction from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -618,7 +618,7 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans } // FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -745,7 +745,7 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes } // FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -785,7 +785,7 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule } // FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -839,8 +839,8 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com return res, nil } -// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent or +// returns an error if it's not possible to do to so. func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -900,8 +900,8 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven return res, nil } -// FromStackItem converts provided stackitem.Array to SomeMapEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeMapEvent or +// returns an error if it's not possible to do to so. func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -1020,8 +1020,8 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru return res, nil } -// FromStackItem converts provided stackitem.Array to SomeStructEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeStructEvent or +// returns an error if it's not possible to do to so. func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -1072,8 +1072,8 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray return res, nil } -// FromStackItem converts provided stackitem.Array to SomeArrayEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeArrayEvent or +// returns an error if it's not possible to do to so. func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out index 0fba2708c..5b4d429c1 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out @@ -222,7 +222,7 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { } // FromStackItem retrieves fields of LedgerBlock from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -344,7 +344,7 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) } // FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -482,7 +482,7 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction } // FromStackItem retrieves fields of LedgerTransaction from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -578,7 +578,7 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans } // FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -705,7 +705,7 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes } // FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -745,7 +745,7 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule } // FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -785,7 +785,7 @@ func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { } // FromStackItem retrieves fields of Unnamed from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *Unnamed) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -839,8 +839,8 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com return res, nil } -// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent or +// returns an error if it's not possible to do to so. func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -900,8 +900,8 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven return res, nil } -// FromStackItem converts provided stackitem.Array to SomeMapEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeMapEvent or +// returns an error if it's not possible to do to so. func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -1033,8 +1033,8 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru return res, nil } -// FromStackItem converts provided stackitem.Array to SomeStructEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeStructEvent or +// returns an error if it's not possible to do to so. func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") @@ -1085,8 +1085,8 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray return res, nil } -// FromStackItem converts provided stackitem.Array to SomeArrayEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to SomeArrayEvent or +// returns an error if it's not possible to do to so. func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index 29af22323..5ac5bdcd1 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -200,7 +200,7 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { } // FromStackItem retrieves fields of LedgerBlock from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -322,7 +322,7 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) } // FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -460,7 +460,7 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction } // FromStackItem retrieves fields of LedgerTransaction from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -556,7 +556,7 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans } // FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -683,7 +683,7 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes } // FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -723,7 +723,7 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule } // FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -763,7 +763,7 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) } // FromStackItem retrieves fields of ManagementABI from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementABI) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -829,7 +829,7 @@ func itemToManagementContract(item stackitem.Item, err error) (*ManagementContra } // FromStackItem retrieves fields of ManagementContract from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementContract) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -897,7 +897,7 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er } // FromStackItem retrieves fields of ManagementEvent from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -959,7 +959,7 @@ func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, er } // FromStackItem retrieves fields of ManagementGroup from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1009,7 +1009,7 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife } // FromStackItem retrieves fields of ManagementManifest from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1201,7 +1201,7 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, } // FromStackItem retrieves fields of ManagementMethod from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1281,7 +1281,7 @@ func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParam } // FromStackItem retrieves fields of ManagementParameter from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1330,7 +1330,7 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm } // FromStackItem retrieves fields of ManagementPermission from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1402,7 +1402,7 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er } // FromStackItem retrieves fields of StructsInternal from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *StructsInternal) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index dd3539901..be1f5c671 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -102,8 +102,8 @@ func HelloWorldEventsFromApplicationLog(log *result.ApplicationLog) ([]*HelloWor return res, nil } -// FromStackItem converts provided stackitem.Array to HelloWorldEvent and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to HelloWorldEvent or +// returns an error if it's not possible to do to so. func (e *HelloWorldEvent) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 746dcb34b..5f1495af3 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -236,7 +236,7 @@ func itemTo{{toTypeName $name}}(item stackitem.Item, err error) (*{{toTypeName $ } // FromStackItem retrieves fields of {{toTypeName $name}} from the given stack item -// and returns an error if so. +// or returns an error if it's not possible to do to so. func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -287,8 +287,8 @@ func {{$e.Name}}sFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}, return res, nil } -// FromStackItem converts provided stackitem.Array to {{$e.Name}} and -// returns an error if so. +// FromStackItem converts provided stackitem.Array to {{$e.Name}} or +// returns an error if it's not possible to do to so. func (e *{{$e.Name}}) FromStackItem(item *stackitem.Array) error { if item == nil { return errors.New("nil item") From 9f9cec53bd681287a625d8359753d6404c3e8d05 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 31 May 2023 15:47:10 +0300 Subject: [PATCH 097/125] rpcbinding: provide links to types in comments Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/nameservice/nns.go | 8 +-- cli/smartcontract/testdata/nex/nex.go | 4 +- .../testdata/notifications/rpcbindings.out | 40 ++++++------- .../notifications/rpcbindings_extended.out | 44 +++++++------- .../notifications/rpcbindings_guessed.out | 44 +++++++------- .../testdata/structs/rpcbindings.out | 60 +++++++++---------- .../testdata/verifyrpc/verify.go | 4 +- pkg/smartcontract/rpcbinding/binding.go | 8 +-- 8 files changed, 106 insertions(+), 106 deletions(-) diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 82cc8374d..3636fd333 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -339,7 +339,7 @@ func (c *Contract) DeleteRecordUnsigned(name string, typev *big.Int) (*transacti } // SetAdminEventsFromApplicationLog retrieves a set of all emitted events -// with "SetAdmin" name from the provided ApplicationLog. +// with "SetAdmin" name from the provided [result.ApplicationLog]. func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -363,7 +363,7 @@ func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEv return res, nil } -// FromStackItem converts provided stackitem.Array to SetAdminEvent or +// FromStackItem converts provided [stackitem.Array] to SetAdminEvent or // returns an error if it's not possible to do to so. func (e *SetAdminEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -432,7 +432,7 @@ func (e *SetAdminEvent) FromStackItem(item *stackitem.Array) error { } // RenewEventsFromApplicationLog retrieves a set of all emitted events -// with "Renew" name from the provided ApplicationLog. +// with "Renew" name from the provided [result.ApplicationLog]. func RenewEventsFromApplicationLog(log *result.ApplicationLog) ([]*RenewEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -456,7 +456,7 @@ func RenewEventsFromApplicationLog(log *result.ApplicationLog) ([]*RenewEvent, e return res, nil } -// FromStackItem converts provided stackitem.Array to RenewEvent or +// FromStackItem converts provided [stackitem.Array] to RenewEvent or // returns an error if it's not possible to do to so. func (e *RenewEvent) FromStackItem(item *stackitem.Array) error { if item == nil { diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 0d716adde..32e7526c8 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -243,7 +243,7 @@ func (c *Contract) UpdateCapUnsigned(newCap *big.Int) (*transaction.Transaction, } // OnMintEventsFromApplicationLog retrieves a set of all emitted events -// with "OnMint" name from the provided ApplicationLog. +// with "OnMint" name from the provided [result.ApplicationLog]. func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -267,7 +267,7 @@ func OnMintEventsFromApplicationLog(log *result.ApplicationLog) ([]*OnMintEvent, return res, nil } -// FromStackItem converts provided stackitem.Array to OnMintEvent or +// FromStackItem converts provided [stackitem.Array] to OnMintEvent or // returns an error if it's not possible to do to so. func (e *OnMintEvent) FromStackItem(item *stackitem.Array) error { if item == nil { diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index 1e873d611..a95cc1ea0 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -215,8 +215,8 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return res, err } -// FromStackItem retrieves fields of LedgerBlock from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -337,8 +337,8 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return res, err } -// FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -475,8 +475,8 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return res, err } -// FromStackItem retrieves fields of LedgerTransaction from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -571,8 +571,8 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, err } -// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -698,8 +698,8 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes return res, err } -// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -738,8 +738,8 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule return res, err } -// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -769,7 +769,7 @@ func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { } // ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events -// with "! complicated name %$#" name from the provided ApplicationLog. +// with "! complicated name %$#" name from the provided [result.ApplicationLog]. func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -793,7 +793,7 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com return res, nil } -// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent or +// FromStackItem converts provided [stackitem.Array] to ComplicatedNameEvent or // returns an error if it's not possible to do to so. func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -830,7 +830,7 @@ func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { } // SomeMapEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeMap" name from the provided ApplicationLog. +// with "SomeMap" name from the provided [result.ApplicationLog]. func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -854,7 +854,7 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven return res, nil } -// FromStackItem converts provided stackitem.Array to SomeMapEvent or +// FromStackItem converts provided [stackitem.Array] to SomeMapEvent or // returns an error if it's not possible to do to so. func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -900,7 +900,7 @@ func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { } // SomeStructEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeStruct" name from the provided ApplicationLog. +// with "SomeStruct" name from the provided [result.ApplicationLog]. func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStructEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -924,7 +924,7 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru return res, nil } -// FromStackItem converts provided stackitem.Array to SomeStructEvent or +// FromStackItem converts provided [stackitem.Array] to SomeStructEvent or // returns an error if it's not possible to do to so. func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -965,7 +965,7 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { } // SomeArrayEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeArray" name from the provided ApplicationLog. +// with "SomeArray" name from the provided [result.ApplicationLog]. func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -989,7 +989,7 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray return res, nil } -// FromStackItem converts provided stackitem.Array to SomeArrayEvent or +// FromStackItem converts provided [stackitem.Array] to SomeArrayEvent or // returns an error if it's not possible to do to so. func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { if item == nil { diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out index 3b2ab5c07..818c91993 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out @@ -221,8 +221,8 @@ func itemToCrazyStruct(item stackitem.Item, err error) (*CrazyStruct, error) { return res, err } -// FromStackItem retrieves fields of CrazyStruct from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of CrazyStruct from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *CrazyStruct) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -261,8 +261,8 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return res, err } -// FromStackItem retrieves fields of LedgerBlock from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -383,8 +383,8 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return res, err } -// FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -521,8 +521,8 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return res, err } -// FromStackItem retrieves fields of LedgerTransaction from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -617,8 +617,8 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, err } -// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -744,8 +744,8 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes return res, err } -// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -784,8 +784,8 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule return res, err } -// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -815,7 +815,7 @@ func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { } // ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events -// with "! complicated name %$#" name from the provided ApplicationLog. +// with "! complicated name %$#" name from the provided [result.ApplicationLog]. func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -839,7 +839,7 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com return res, nil } -// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent or +// FromStackItem converts provided [stackitem.Array] to ComplicatedNameEvent or // returns an error if it's not possible to do to so. func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -876,7 +876,7 @@ func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { } // SomeMapEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeMap" name from the provided ApplicationLog. +// with "SomeMap" name from the provided [result.ApplicationLog]. func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -900,7 +900,7 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven return res, nil } -// FromStackItem converts provided stackitem.Array to SomeMapEvent or +// FromStackItem converts provided [stackitem.Array] to SomeMapEvent or // returns an error if it's not possible to do to so. func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -996,7 +996,7 @@ func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { } // SomeStructEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeStruct" name from the provided ApplicationLog. +// with "SomeStruct" name from the provided [result.ApplicationLog]. func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStructEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -1020,7 +1020,7 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru return res, nil } -// FromStackItem converts provided stackitem.Array to SomeStructEvent or +// FromStackItem converts provided [stackitem.Array] to SomeStructEvent or // returns an error if it's not possible to do to so. func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -1048,7 +1048,7 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { } // SomeArrayEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeArray" name from the provided ApplicationLog. +// with "SomeArray" name from the provided [result.ApplicationLog]. func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -1072,7 +1072,7 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray return res, nil } -// FromStackItem converts provided stackitem.Array to SomeArrayEvent or +// FromStackItem converts provided [stackitem.Array] to SomeArrayEvent or // returns an error if it's not possible to do to so. func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { if item == nil { diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out index 5b4d429c1..883283d09 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out @@ -221,8 +221,8 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return res, err } -// FromStackItem retrieves fields of LedgerBlock from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -343,8 +343,8 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return res, err } -// FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -481,8 +481,8 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return res, err } -// FromStackItem retrieves fields of LedgerTransaction from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -577,8 +577,8 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, err } -// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -704,8 +704,8 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes return res, err } -// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -744,8 +744,8 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule return res, err } -// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -784,8 +784,8 @@ func itemToUnnamed(item stackitem.Item, err error) (*Unnamed, error) { return res, err } -// FromStackItem retrieves fields of Unnamed from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of Unnamed from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *Unnamed) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -815,7 +815,7 @@ func (res *Unnamed) FromStackItem(item stackitem.Item) error { } // ComplicatedNameEventsFromApplicationLog retrieves a set of all emitted events -// with "! complicated name %$#" name from the provided ApplicationLog. +// with "! complicated name %$#" name from the provided [result.ApplicationLog]. func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*ComplicatedNameEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -839,7 +839,7 @@ func ComplicatedNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*Com return res, nil } -// FromStackItem converts provided stackitem.Array to ComplicatedNameEvent or +// FromStackItem converts provided [stackitem.Array] to ComplicatedNameEvent or // returns an error if it's not possible to do to so. func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -876,7 +876,7 @@ func (e *ComplicatedNameEvent) FromStackItem(item *stackitem.Array) error { } // SomeMapEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeMap" name from the provided ApplicationLog. +// with "SomeMap" name from the provided [result.ApplicationLog]. func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -900,7 +900,7 @@ func SomeMapEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeMapEven return res, nil } -// FromStackItem converts provided stackitem.Array to SomeMapEvent or +// FromStackItem converts provided [stackitem.Array] to SomeMapEvent or // returns an error if it's not possible to do to so. func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -1009,7 +1009,7 @@ func (e *SomeMapEvent) FromStackItem(item *stackitem.Array) error { } // SomeStructEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeStruct" name from the provided ApplicationLog. +// with "SomeStruct" name from the provided [result.ApplicationLog]. func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStructEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -1033,7 +1033,7 @@ func SomeStructEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeStru return res, nil } -// FromStackItem converts provided stackitem.Array to SomeStructEvent or +// FromStackItem converts provided [stackitem.Array] to SomeStructEvent or // returns an error if it's not possible to do to so. func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { if item == nil { @@ -1061,7 +1061,7 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error { } // SomeArrayEventsFromApplicationLog retrieves a set of all emitted events -// with "SomeArray" name from the provided ApplicationLog. +// with "SomeArray" name from the provided [result.ApplicationLog]. func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -1085,7 +1085,7 @@ func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArray return res, nil } -// FromStackItem converts provided stackitem.Array to SomeArrayEvent or +// FromStackItem converts provided [stackitem.Array] to SomeArrayEvent or // returns an error if it's not possible to do to so. func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error { if item == nil { diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index 5ac5bdcd1..ba503be59 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -199,8 +199,8 @@ func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { return res, err } -// FromStackItem retrieves fields of LedgerBlock from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -321,8 +321,8 @@ func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) return res, err } -// FromStackItem retrieves fields of LedgerBlockSR from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -459,8 +459,8 @@ func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction return res, err } -// FromStackItem retrieves fields of LedgerTransaction from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -555,8 +555,8 @@ func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTrans return res, err } -// FromStackItem retrieves fields of LedgerTransactionSigner from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -682,8 +682,8 @@ func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnes return res, err } -// FromStackItem retrieves fields of LedgerWitnessCondition from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -722,8 +722,8 @@ func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule return res, err } -// FromStackItem retrieves fields of LedgerWitnessRule from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -762,8 +762,8 @@ func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) return res, err } -// FromStackItem retrieves fields of ManagementABI from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementABI) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -828,8 +828,8 @@ func itemToManagementContract(item stackitem.Item, err error) (*ManagementContra return res, err } -// FromStackItem retrieves fields of ManagementContract from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementContract) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -896,8 +896,8 @@ func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, er return res, err } -// FromStackItem retrieves fields of ManagementEvent from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -958,8 +958,8 @@ func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, er return res, err } -// FromStackItem retrieves fields of ManagementGroup from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1008,8 +1008,8 @@ func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManife return res, err } -// FromStackItem retrieves fields of ManagementManifest from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1200,8 +1200,8 @@ func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, return res, err } -// FromStackItem retrieves fields of ManagementMethod from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1280,8 +1280,8 @@ func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParam return res, err } -// FromStackItem retrieves fields of ManagementParameter from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1329,8 +1329,8 @@ func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPerm return res, err } -// FromStackItem retrieves fields of ManagementPermission from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -1401,8 +1401,8 @@ func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, er return res, err } -// FromStackItem retrieves fields of StructsInternal from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of StructsInternal from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *StructsInternal) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index be1f5c671..3a01b990c 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -78,7 +78,7 @@ func (c *Contract) VerifyUnsigned() (*transaction.Transaction, error) { } // HelloWorldEventsFromApplicationLog retrieves a set of all emitted events -// with "Hello world!" name from the provided ApplicationLog. +// with "Hello world!" name from the provided [result.ApplicationLog]. func HelloWorldEventsFromApplicationLog(log *result.ApplicationLog) ([]*HelloWorldEvent, error) { if log == nil { return nil, errors.New("nil application log") @@ -102,7 +102,7 @@ func HelloWorldEventsFromApplicationLog(log *result.ApplicationLog) ([]*HelloWor return res, nil } -// FromStackItem converts provided stackitem.Array to HelloWorldEvent or +// FromStackItem converts provided [stackitem.Array] to HelloWorldEvent or // returns an error if it's not possible to do to so. func (e *HelloWorldEvent) FromStackItem(item *stackitem.Array) error { if item == nil { diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 5f1495af3..caf6f4397 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -235,8 +235,8 @@ func itemTo{{toTypeName $name}}(item stackitem.Item, err error) (*{{toTypeName $ return res, err } -// FromStackItem retrieves fields of {{toTypeName $name}} from the given stack item -// or returns an error if it's not possible to do to so. +// FromStackItem retrieves fields of {{toTypeName $name}} from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { arr, ok := item.Value().([]stackitem.Item) if !ok { @@ -263,7 +263,7 @@ func (res *{{toTypeName $name}}) FromStackItem(item stackitem.Item) error { {{ end -}} {{- range $e := .CustomEvents }} // {{$e.Name}}sFromApplicationLog retrieves a set of all emitted events -// with "{{$e.ManifestName}}" name from the provided ApplicationLog. +// with "{{$e.ManifestName}}" name from the provided [result.ApplicationLog]. func {{$e.Name}}sFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}, error) { if log == nil { return nil, errors.New("nil application log") @@ -287,7 +287,7 @@ func {{$e.Name}}sFromApplicationLog(log *result.ApplicationLog) ([]*{{$e.Name}}, return res, nil } -// FromStackItem converts provided stackitem.Array to {{$e.Name}} or +// FromStackItem converts provided [stackitem.Array] to {{$e.Name}} or // returns an error if it's not possible to do to so. func (e *{{$e.Name}}) FromStackItem(item *stackitem.Array) error { if item == nil { From 8beb3f45152369cf22f84951cda11a86056bcea2 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 31 May 2023 18:31:20 +0300 Subject: [PATCH 098/125] *: drop legacy addresses from examples They can't even be used now because they'll fail the conversion. Signed-off-by: Roman Khimov --- cli/cmdargs/parser.go | 4 ++-- docs/compiler.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/cmdargs/parser.go b/cli/cmdargs/parser.go index b26c2ee91..cb46971dd 100644 --- a/cli/cmdargs/parser.go +++ b/cli/cmdargs/parser.go @@ -84,8 +84,8 @@ const ( * 'dead' is a byte array with a value of 'dead' * 'string:dead' is a string with a value of 'dead' * 'filebytes:my_data.txt' is bytes decoded from a content of my_data.txt - * 'AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y' is a hash160 with a value - of '23ba2703c53263e8d6e522dc32203339dcd8eee9' + * 'NSiVJYZej4XsxG5CUpdwn7VRQk8iiiDMPM' is a hash160 with a value + of '682cca3ebdc66210e5847d7f8115846586079d4a' * '\4\2' is an integer with a value of 42 * '\\4\2' is a string with a value of '\42' * 'string:string' is a string with a value of 'string' diff --git a/docs/compiler.md b/docs/compiler.md index d4d17efb4..0279d2196 100644 --- a/docs/compiler.md +++ b/docs/compiler.md @@ -411,11 +411,11 @@ see `contract` command help for more details. They all work via RPC, so it's a mandatory parameter. Example call (contract `f84d6a337fbc3d3a201d41da99e86b479e7a2554` with method -`balanceOf` and method's parameter `AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y` using +`balanceOf` and method's parameter `NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq` using given RPC server and wallet and paying 0.00001 extra GAS for this transaction): ``` -$ ./bin/neo-go contract invokefunction -r http://localhost:20331 -w my_wallet.json -g 0.00001 f84d6a337fbc3d3a201d41da99e86b479e7a2554 balanceOf AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y +$ ./bin/neo-go contract invokefunction -r http://localhost:20331 -w my_wallet.json -g 0.00001 f84d6a337fbc3d3a201d41da99e86b479e7a2554 balanceOf NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq ``` ### Generating contract bindings From 68b9ff1f17021fde9602516b565109ef85ab2af9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 31 May 2023 19:22:04 +0300 Subject: [PATCH 099/125] mempool: adjust the rule of conflicting transaction ranking Pay for all the conflicts if you'd like to went in. Close #3028. Signed-off-by: Anna Shaleva --- pkg/core/mempool/mem_pool.go | 16 +++-- pkg/core/mempool/mem_pool_test.go | 111 +++++++++++++++++++++++++----- 2 files changed, 103 insertions(+), 24 deletions(-) diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index 901b528bb..10512f946 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -520,14 +520,17 @@ func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) ([]*tran var expectedSenderFee utilityBalanceAndFees // Check Conflicts attributes. - var conflictsToBeRemoved []*transaction.Transaction + var ( + conflictsToBeRemoved []*transaction.Transaction + conflictingFee int64 + ) if fee.P2PSigExtensionsEnabled() { // Step 1: check if `tx` was in attributes of mempooled transactions. if conflictingHashes, ok := mp.conflicts[tx.Hash()]; ok { for _, hash := range conflictingHashes { existingTx := mp.verifiedMap[hash] - if existingTx.HasSigner(payer) && existingTx.NetworkFee > tx.NetworkFee { - return nil, fmt.Errorf("%w: conflicting transaction %s has bigger network fee", ErrConflictsAttribute, existingTx.Hash().StringBE()) + if existingTx.HasSigner(payer) { + conflictingFee += existingTx.NetworkFee } conflictsToBeRemoved = append(conflictsToBeRemoved, existingTx) } @@ -542,11 +545,12 @@ func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) ([]*tran if !tx.HasSigner(existingTx.Signers[mp.payerIndex].Account) { return nil, fmt.Errorf("%w: not signed by the sender of conflicting transaction %s", ErrConflictsAttribute, existingTx.Hash().StringBE()) } - if existingTx.NetworkFee >= tx.NetworkFee { - return nil, fmt.Errorf("%w: conflicting transaction %s has bigger or equal network fee", ErrConflictsAttribute, existingTx.Hash().StringBE()) - } + conflictingFee += existingTx.NetworkFee conflictsToBeRemoved = append(conflictsToBeRemoved, existingTx) } + if conflictingFee != 0 && tx.NetworkFee <= conflictingFee { + return nil, fmt.Errorf("%w: conflicting transactions have bigger or equal network fee: %d vs %d", ErrConflictsAttribute, tx.NetworkFee, conflictingFee) + } // Step 3: take into account sender's conflicting transactions before balance check. expectedSenderFee = actualSenderFee for _, conflictingTx := range conflictsToBeRemoved { diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index 1d6514ee8..d1d247dc9 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -1,13 +1,14 @@ package mempool import ( + "fmt" "math/big" "sort" + "strings" "testing" "time" "github.com/holiman/uint256" - "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/util" @@ -423,18 +424,23 @@ func TestMempoolAddRemoveOracleResponse(t *testing.T) { } func TestMempoolAddRemoveConflicts(t *testing.T) { - capacity := 6 - mp := New(capacity, 0, false, nil) + var ( + capacity = 6 + mp = New(capacity, 0, false, nil) + sender = transaction.Signer{Account: util.Uint160{1, 2, 3}} + maliciousSender = transaction.Signer{Account: util.Uint160{4, 5, 6}} + ) + var ( fs = &FeerStub{p2pSigExt: true, balance: 100000} nonce uint32 = 1 ) - getConflictsTx := func(netFee int64, hashes ...util.Uint256) *transaction.Transaction { + getTx := func(netFee int64, sender transaction.Signer, hashes ...util.Uint256) *transaction.Transaction { tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.NetworkFee = netFee tx.Nonce = nonce nonce++ - tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} + tx.Signers = []transaction.Signer{sender} tx.Attributes = make([]transaction.Attribute, len(hashes)) for i, h := range hashes { tx.Attributes[i] = transaction.Attribute{ @@ -448,6 +454,12 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { require.Equal(t, false, ok) return tx } + getConflictsTx := func(netFee int64, hashes ...util.Uint256) *transaction.Transaction { + return getTx(netFee, sender, hashes...) + } + getMaliciousTx := func(netFee int64, hashes ...util.Uint256) *transaction.Transaction { + return getTx(netFee, maliciousSender, hashes...) + } // tx1 in mempool and does not conflicts with anyone smallNetFee := int64(3) @@ -528,26 +540,89 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { assert.Equal(t, []util.Uint256{tx3.Hash(), tx2.Hash()}, mp.conflicts[tx1.Hash()]) // tx13 conflicts with tx2, but is not signed by tx2.Sender - tx13 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - tx13.NetworkFee = smallNetFee - tx13.Nonce = uint32(random.Int(0, 1e4)) - tx13.Signers = []transaction.Signer{{Account: util.Uint160{3, 2, 1}}} - tx13.Attributes = []transaction.Attribute{{ - Type: transaction.ConflictsT, - Value: &transaction.Conflicts{ - Hash: tx2.Hash(), - }, - }} + tx13 := getMaliciousTx(smallNetFee, tx2.Hash()) _, ok := mp.TryGetValue(tx13.Hash()) require.Equal(t, false, ok) require.ErrorIs(t, mp.Add(tx13, fs), ErrConflictsAttribute) + // tx15 conflicts with tx14, but added firstly and has the same network fee => tx14 must not be added. tx14 := getConflictsTx(smallNetFee) tx15 := getConflictsTx(smallNetFee, tx14.Hash()) require.NoError(t, mp.Add(tx15, fs)) - require.NoError(t, mp.Add(tx14, fs)) - err := mp.Add(tx15, fs) - require.ErrorIs(t, err, ErrConflictsAttribute) + err := mp.Add(tx14, fs) + require.Error(t, err) + + require.True(t, strings.Contains(err.Error(), fmt.Sprintf("conflicting transactions have bigger or equal network fee: %d vs %d", smallNetFee, smallNetFee))) + + check := func(t *testing.T, mainFee int64, fail bool) { + // Clear mempool. + mp.RemoveStale(func(t *transaction.Transaction) bool { + return false + }, fs) + + // mempooled tx17, tx18, tx19 conflict with tx16 + tx16 := getConflictsTx(mainFee) + tx17 := getConflictsTx(smallNetFee, tx16.Hash()) + tx18 := getConflictsTx(smallNetFee, tx16.Hash()) + tx19 := getMaliciousTx(smallNetFee, tx16.Hash()) // malicious, thus, doesn't take into account during fee evaluation + require.NoError(t, mp.Add(tx17, fs)) + require.NoError(t, mp.Add(tx18, fs)) + require.NoError(t, mp.Add(tx19, fs)) + if fail { + require.Error(t, mp.Add(tx16, fs)) + _, ok = mp.TryGetValue(tx17.Hash()) + require.True(t, ok) + _, ok = mp.TryGetValue(tx18.Hash()) + require.True(t, ok) + _, ok = mp.TryGetValue(tx19.Hash()) + require.True(t, ok) + } else { + require.NoError(t, mp.Add(tx16, fs)) + _, ok = mp.TryGetValue(tx17.Hash()) + require.False(t, ok) + _, ok = mp.TryGetValue(tx18.Hash()) + require.False(t, ok) + _, ok = mp.TryGetValue(tx19.Hash()) + require.False(t, ok) + } + } + check(t, smallNetFee*2, true) + check(t, smallNetFee*2+1, false) + + check = func(t *testing.T, mainFee int64, fail bool) { + // Clear mempool. + mp.RemoveStale(func(t *transaction.Transaction) bool { + return false + }, fs) + + // mempooled tx20, tx21, tx22 don't conflict with anyone, but tx23 conflicts with them + tx20 := getConflictsTx(smallNetFee) + tx21 := getConflictsTx(smallNetFee) + tx22 := getConflictsTx(smallNetFee) + tx23 := getConflictsTx(mainFee, tx20.Hash(), tx21.Hash(), tx22.Hash()) + require.NoError(t, mp.Add(tx20, fs)) + require.NoError(t, mp.Add(tx21, fs)) + require.NoError(t, mp.Add(tx22, fs)) + if fail { + require.Error(t, mp.Add(tx23, fs)) + _, ok = mp.TryGetData(tx20.Hash()) + require.True(t, ok) + _, ok = mp.TryGetData(tx21.Hash()) + require.True(t, ok) + _, ok = mp.TryGetData(tx22.Hash()) + require.True(t, ok) + } else { + require.NoError(t, mp.Add(tx23, fs)) + _, ok = mp.TryGetData(tx20.Hash()) + require.False(t, ok) + _, ok = mp.TryGetData(tx21.Hash()) + require.False(t, ok) + _, ok = mp.TryGetData(tx22.Hash()) + require.False(t, ok) + } + } + check(t, smallNetFee*3, true) + check(t, smallNetFee*3+1, false) } func TestMempoolAddWithDataGetData(t *testing.T) { From f97eaddfd16616b2bb387450282c206b48ba35b1 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 11 May 2023 13:25:45 +0300 Subject: [PATCH 100/125] cli: allow dynamic RPC binding contract hash Close #3006 and make a light base for #3007. Signed-off-by: Anna Shaleva --- cli/smartcontract/generate.go | 25 +- cli/smartcontract/generate_test.go | 39 +- cli/smartcontract/testdata/gas/gas.go | 10 +- cli/smartcontract/testdata/nameservice/nns.go | 76 +- cli/smartcontract/testdata/nex/nex.go | 60 +- cli/smartcontract/testdata/nonepiter/iter.go | 12 +- .../testdata/notifications/rpcbindings.out | 28 +- .../notifications/rpcbindings_extended.out | 28 +- .../notifications/rpcbindings_guessed.out | 28 +- .../testdata/structs/rpcbindings.out | 12 +- .../structs/rpcbindings_dynamic_hash.out | 1622 +++++++++++++++++ .../testdata/types/rpcbindings.out | 46 +- .../types/rpcbindings_dynamic_hash.out | 343 ++++ .../testdata/verifyrpc/verify.go | 6 +- pkg/smartcontract/binding/generate.go | 14 +- pkg/smartcontract/rpcbinding/binding.go | 58 +- 16 files changed, 2216 insertions(+), 191 deletions(-) create mode 100755 cli/smartcontract/testdata/structs/rpcbindings_dynamic_hash.out create mode 100755 cli/smartcontract/testdata/types/rpcbindings_dynamic_hash.out diff --git a/cli/smartcontract/generate.go b/cli/smartcontract/generate.go index 47c662865..0831fd494 100644 --- a/cli/smartcontract/generate.go +++ b/cli/smartcontract/generate.go @@ -29,9 +29,8 @@ var generatorFlags = []cli.Flag{ Usage: "Output of the compiled wrapper", }, cli.StringFlag{ - Name: "hash", - Required: true, - Usage: "Smart-contract hash", + Name: "hash", + Usage: "Smart-contract hash", }, } @@ -53,21 +52,29 @@ var generateRPCWrapperCmd = cli.Command{ } func contractGenerateWrapper(ctx *cli.Context) error { - return contractGenerateSomething(ctx, binding.Generate) + return contractGenerateSomething(ctx, binding.Generate, false) } func contractGenerateRPCWrapper(ctx *cli.Context) error { - return contractGenerateSomething(ctx, rpcbinding.Generate) + return contractGenerateSomething(ctx, rpcbinding.Generate, true) } // contractGenerateSomething reads generator parameters and calls the given callback. -func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error) error { +func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error, allowEmptyHash bool) error { if err := cmdargs.EnsureNone(ctx); err != nil { return err } - h, err := util.Uint160DecodeStringLE(strings.TrimPrefix(ctx.String("hash"), "0x")) - if err != nil { - return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1) + var ( + h util.Uint160 + err error + ) + if hStr := ctx.String("hash"); len(hStr) != 0 { + h, err = util.Uint160DecodeStringLE(strings.TrimPrefix(hStr, "0x")) + if err != nil { + return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1) + } + } else if !allowEmptyHash { + return cli.NewExitError("contract hash must be provided via --hash flag", 1) } m, _, err := readManifest(ctx.String("manifest"), h) if err != nil { diff --git a/cli/smartcontract/generate_test.go b/cli/smartcontract/generate_test.go index 6c6a63f90..be3cd313e 100644 --- a/cli/smartcontract/generate_test.go +++ b/cli/smartcontract/generate_test.go @@ -3,6 +3,7 @@ package smartcontract import ( "bytes" "encoding/json" + "fmt" "os" "path/filepath" "strings" @@ -309,16 +310,18 @@ type Invoker interface { // ContractReader implements safe contract methods. type ContractReader struct { invoker Invoker + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{invoker} + var hash = Hash + return &ContractReader{invoker, hash} } // Get invokes `+"`get`"+` method of contract. func (c *ContractReader) Get() (*big.Int, error) { - return unwrap.BigInt(c.invoker.Call(Hash, "get")) + return unwrap.BigInt(c.invoker.Call(c.hash, "get")) } `, string(data)) } @@ -379,17 +382,20 @@ func TestAssistedRPCBindings(t *testing.T) { app := cli.NewApp() app.Commands = NewCommands() - var checkBinding = func(source string, guessEventTypes bool, suffix ...string) { + var checkBinding = func(source string, hasDefinedHash bool, guessEventTypes bool, suffix ...string) { testName := source if len(suffix) != 0 { testName += suffix[0] } + testName += fmt.Sprintf(", predefined hash: %t", hasDefinedHash) t.Run(testName, func(t *testing.T) { configFile := filepath.Join(source, "config.yml") expectedFile := filepath.Join(source, "rpcbindings.out") if len(suffix) != 0 { configFile = filepath.Join(source, "config"+suffix[0]+".yml") expectedFile = filepath.Join(source, "rpcbindings"+suffix[0]+".out") + } else if !hasDefinedHash { + expectedFile = filepath.Join(source, "rpcbindings_dynamic_hash.out") } manifestF := filepath.Join(tmpDir, "manifest.json") bindingF := filepath.Join(tmpDir, "binding.yml") @@ -405,15 +411,18 @@ func TestAssistedRPCBindings(t *testing.T) { cmd = append(cmd, "--guess-eventtypes") } require.NoError(t, app.Run(cmd)) - outFile := filepath.Join(tmpDir, "out.go") - require.NoError(t, app.Run([]string{"", "contract", "generate-rpcwrapper", + + cmds := []string{"", "contract", "generate-rpcwrapper", "--config", bindingF, "--manifest", manifestF, - "--out", outFile, - "--hash", "0x00112233445566778899aabbccddeeff00112233", - })) + "--out", expectedFile, + } + if hasDefinedHash { + cmds = append(cmds, "--hash", "0x00112233445566778899aabbccddeeff00112233") + } + require.NoError(t, app.Run(cmds)) - data, err := os.ReadFile(outFile) + data, err := os.ReadFile(expectedFile) require.NoError(t, err) data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows. if rewriteExpectedOutputs { @@ -427,11 +436,13 @@ func TestAssistedRPCBindings(t *testing.T) { }) } - checkBinding(filepath.Join("testdata", "types"), false) - checkBinding(filepath.Join("testdata", "structs"), false) - checkBinding(filepath.Join("testdata", "notifications"), false) - checkBinding(filepath.Join("testdata", "notifications"), false, "_extended") - checkBinding(filepath.Join("testdata", "notifications"), true, "_guessed") + for _, hasDefinedHash := range []bool{true, false} { + checkBinding(filepath.Join("testdata", "types"), hasDefinedHash, false) + checkBinding(filepath.Join("testdata", "structs"), hasDefinedHash, false) + } + checkBinding(filepath.Join("testdata", "notifications"), true, false) + checkBinding(filepath.Join("testdata", "notifications"), true, false, "_extended") + checkBinding(filepath.Join("testdata", "notifications"), true, true, "_guessed") require.False(t, rewriteExpectedOutputs) } diff --git a/cli/smartcontract/testdata/gas/gas.go b/cli/smartcontract/testdata/gas/gas.go index d12bbb8ee..e83072fbb 100644 --- a/cli/smartcontract/testdata/gas/gas.go +++ b/cli/smartcontract/testdata/gas/gas.go @@ -25,6 +25,7 @@ type Actor interface { type ContractReader struct { nep17.TokenReader invoker Invoker + hash util.Uint160 } // Contract implements all contract methods. @@ -32,15 +33,18 @@ type Contract struct { ContractReader nep17.TokenWriter actor Actor + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{*nep17.NewReader(invoker, Hash), invoker} + var hash = Hash + return &ContractReader{*nep17.NewReader(invoker, hash), invoker, hash} } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - var nep17t = nep17.New(actor, Hash) - return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} + var hash = Hash + var nep17t = nep17.New(actor, hash) + return &Contract{ContractReader{nep17t.TokenReader, actor, hash}, nep17t.TokenWriter, actor, hash} } diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 3636fd333..da5f0311a 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -56,6 +56,7 @@ type Actor interface { type ContractReader struct { nep11.NonDivisibleReader invoker Invoker + hash util.Uint160 } // Contract implements all contract methods. @@ -63,22 +64,25 @@ type Contract struct { ContractReader nep11.BaseWriter actor Actor + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{*nep11.NewNonDivisibleReader(invoker, Hash), invoker} + var hash = Hash + return &ContractReader{*nep11.NewNonDivisibleReader(invoker, hash), invoker, hash} } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - var nep11ndt = nep11.NewNonDivisible(actor, Hash) - return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor}, nep11ndt.BaseWriter, actor} + var hash = Hash + var nep11ndt = nep11.NewNonDivisible(actor, hash) + return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor, hash}, nep11ndt.BaseWriter, actor, hash} } // Roots invokes `roots` method of contract. func (c *ContractReader) Roots() (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.invoker.Call(Hash, "roots")) + return unwrap.SessionIterator(c.invoker.Call(c.hash, "roots")) } // RootsExpanded is similar to Roots (uses the same contract @@ -87,27 +91,27 @@ func (c *ContractReader) Roots() (uuid.UUID, result.Iterator, error) { // number of result items from the iterator right in the VM and return them to // you. It's only limited by VM stack and GAS available for RPC invocations. func (c *ContractReader) RootsExpanded(_numOfIteratorItems int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.CallAndExpandIterator(Hash, "roots", _numOfIteratorItems)) + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "roots", _numOfIteratorItems)) } // GetPrice invokes `getPrice` method of contract. func (c *ContractReader) GetPrice(length *big.Int) (*big.Int, error) { - return unwrap.BigInt(c.invoker.Call(Hash, "getPrice", length)) + return unwrap.BigInt(c.invoker.Call(c.hash, "getPrice", length)) } // IsAvailable invokes `isAvailable` method of contract. func (c *ContractReader) IsAvailable(name string) (bool, error) { - return unwrap.Bool(c.invoker.Call(Hash, "isAvailable", name)) + return unwrap.Bool(c.invoker.Call(c.hash, "isAvailable", name)) } // GetRecord invokes `getRecord` method of contract. func (c *ContractReader) GetRecord(name string, typev *big.Int) (string, error) { - return unwrap.UTF8String(c.invoker.Call(Hash, "getRecord", name, typev)) + return unwrap.UTF8String(c.invoker.Call(c.hash, "getRecord", name, typev)) } // GetAllRecords invokes `getAllRecords` method of contract. func (c *ContractReader) GetAllRecords(name string) (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.invoker.Call(Hash, "getAllRecords", name)) + return unwrap.SessionIterator(c.invoker.Call(c.hash, "getAllRecords", name)) } // GetAllRecordsExpanded is similar to GetAllRecords (uses the same contract @@ -116,26 +120,26 @@ func (c *ContractReader) GetAllRecords(name string) (uuid.UUID, result.Iterator, // number of result items from the iterator right in the VM and return them to // you. It's only limited by VM stack and GAS available for RPC invocations. func (c *ContractReader) GetAllRecordsExpanded(name string, _numOfIteratorItems int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.CallAndExpandIterator(Hash, "getAllRecords", _numOfIteratorItems, name)) + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "getAllRecords", _numOfIteratorItems, name)) } // Resolve invokes `resolve` method of contract. func (c *ContractReader) Resolve(name string, typev *big.Int) (string, error) { - return unwrap.UTF8String(c.invoker.Call(Hash, "resolve", name, typev)) + return unwrap.UTF8String(c.invoker.Call(c.hash, "resolve", name, typev)) } // Update creates a transaction invoking `update` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Update(nef []byte, manifest string) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "update", nef, manifest) + return c.actor.SendCall(c.hash, "update", nef, manifest) } // UpdateTransaction creates a transaction invoking `update` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) UpdateTransaction(nef []byte, manifest string) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "update", nef, manifest) + return c.actor.MakeCall(c.hash, "update", nef, manifest) } // UpdateUnsigned creates a transaction invoking `update` method of the contract. @@ -143,21 +147,21 @@ func (c *Contract) UpdateTransaction(nef []byte, manifest string) (*transaction. // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) UpdateUnsigned(nef []byte, manifest string) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "update", nil, nef, manifest) + return c.actor.MakeUnsignedCall(c.hash, "update", nil, nef, manifest) } // AddRoot creates a transaction invoking `addRoot` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) AddRoot(root string) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "addRoot", root) + return c.actor.SendCall(c.hash, "addRoot", root) } // AddRootTransaction creates a transaction invoking `addRoot` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) AddRootTransaction(root string) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "addRoot", root) + return c.actor.MakeCall(c.hash, "addRoot", root) } // AddRootUnsigned creates a transaction invoking `addRoot` method of the contract. @@ -165,21 +169,21 @@ func (c *Contract) AddRootTransaction(root string) (*transaction.Transaction, er // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) AddRootUnsigned(root string) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "addRoot", nil, root) + return c.actor.MakeUnsignedCall(c.hash, "addRoot", nil, root) } // SetPrice creates a transaction invoking `setPrice` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) SetPrice(priceList []any) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "setPrice", priceList) + return c.actor.SendCall(c.hash, "setPrice", priceList) } // SetPriceTransaction creates a transaction invoking `setPrice` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) SetPriceTransaction(priceList []any) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "setPrice", priceList) + return c.actor.MakeCall(c.hash, "setPrice", priceList) } // SetPriceUnsigned creates a transaction invoking `setPrice` method of the contract. @@ -187,11 +191,11 @@ func (c *Contract) SetPriceTransaction(priceList []any) (*transaction.Transactio // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) SetPriceUnsigned(priceList []any) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "setPrice", nil, priceList) + return c.actor.MakeUnsignedCall(c.hash, "setPrice", nil, priceList) } func scriptForRegister(name string, owner util.Uint160) ([]byte, error) { - return smartcontract.CreateCallWithAssertScript(Hash, "register", name, owner) + return smartcontract.CreateCallWithAssertScript(c.hash, "register", name, owner) } // Register creates a transaction invoking `register` method of the contract. @@ -232,14 +236,14 @@ func (c *Contract) RegisterUnsigned(name string, owner util.Uint160) (*transacti // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Renew(name string) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "renew", name) + return c.actor.SendCall(c.hash, "renew", name) } // RenewTransaction creates a transaction invoking `renew` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) RenewTransaction(name string) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "renew", name) + return c.actor.MakeCall(c.hash, "renew", name) } // RenewUnsigned creates a transaction invoking `renew` method of the contract. @@ -247,21 +251,21 @@ func (c *Contract) RenewTransaction(name string) (*transaction.Transaction, erro // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) RenewUnsigned(name string) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "renew", nil, name) + return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name) } // Renew_2 creates a transaction invoking `renew` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Renew_2(name string, years *big.Int) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "renew", name, years) + return c.actor.SendCall(c.hash, "renew", name, years) } // Renew_2Transaction creates a transaction invoking `renew` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) Renew_2Transaction(name string, years *big.Int) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "renew", name, years) + return c.actor.MakeCall(c.hash, "renew", name, years) } // Renew_2Unsigned creates a transaction invoking `renew` method of the contract. @@ -269,21 +273,21 @@ func (c *Contract) Renew_2Transaction(name string, years *big.Int) (*transaction // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) Renew_2Unsigned(name string, years *big.Int) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "renew", nil, name, years) + return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name, years) } // SetAdmin creates a transaction invoking `setAdmin` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) SetAdmin(name string, admin util.Uint160) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "setAdmin", name, admin) + return c.actor.SendCall(c.hash, "setAdmin", name, admin) } // SetAdminTransaction creates a transaction invoking `setAdmin` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) SetAdminTransaction(name string, admin util.Uint160) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "setAdmin", name, admin) + return c.actor.MakeCall(c.hash, "setAdmin", name, admin) } // SetAdminUnsigned creates a transaction invoking `setAdmin` method of the contract. @@ -291,21 +295,21 @@ func (c *Contract) SetAdminTransaction(name string, admin util.Uint160) (*transa // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) SetAdminUnsigned(name string, admin util.Uint160) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "setAdmin", nil, name, admin) + return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, name, admin) } // SetRecord creates a transaction invoking `setRecord` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) SetRecord(name string, typev *big.Int, data string) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "setRecord", name, typev, data) + return c.actor.SendCall(c.hash, "setRecord", name, typev, data) } // SetRecordTransaction creates a transaction invoking `setRecord` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) SetRecordTransaction(name string, typev *big.Int, data string) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "setRecord", name, typev, data) + return c.actor.MakeCall(c.hash, "setRecord", name, typev, data) } // SetRecordUnsigned creates a transaction invoking `setRecord` method of the contract. @@ -313,21 +317,21 @@ func (c *Contract) SetRecordTransaction(name string, typev *big.Int, data string // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) SetRecordUnsigned(name string, typev *big.Int, data string) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "setRecord", nil, name, typev, data) + return c.actor.MakeUnsignedCall(c.hash, "setRecord", nil, name, typev, data) } // DeleteRecord creates a transaction invoking `deleteRecord` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) DeleteRecord(name string, typev *big.Int) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "deleteRecord", name, typev) + return c.actor.SendCall(c.hash, "deleteRecord", name, typev) } // DeleteRecordTransaction creates a transaction invoking `deleteRecord` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) DeleteRecordTransaction(name string, typev *big.Int) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "deleteRecord", name, typev) + return c.actor.MakeCall(c.hash, "deleteRecord", name, typev) } // DeleteRecordUnsigned creates a transaction invoking `deleteRecord` method of the contract. @@ -335,7 +339,7 @@ func (c *Contract) DeleteRecordTransaction(name string, typev *big.Int) (*transa // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) DeleteRecordUnsigned(name string, typev *big.Int) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "deleteRecord", nil, name, typev) + return c.actor.MakeUnsignedCall(c.hash, "deleteRecord", nil, name, typev) } // SetAdminEventsFromApplicationLog retrieves a set of all emitted events diff --git a/cli/smartcontract/testdata/nex/nex.go b/cli/smartcontract/testdata/nex/nex.go index 32e7526c8..296a3d0e3 100644 --- a/cli/smartcontract/testdata/nex/nex.go +++ b/cli/smartcontract/testdata/nex/nex.go @@ -48,6 +48,7 @@ type Actor interface { type ContractReader struct { nep17.TokenReader invoker Invoker + hash util.Uint160 } // Contract implements all contract methods. @@ -55,51 +56,54 @@ type Contract struct { ContractReader nep17.TokenWriter actor Actor + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{*nep17.NewReader(invoker, Hash), invoker} + var hash = Hash + return &ContractReader{*nep17.NewReader(invoker, hash), invoker, hash} } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - var nep17t = nep17.New(actor, Hash) - return &Contract{ContractReader{nep17t.TokenReader, actor}, nep17t.TokenWriter, actor} + var hash = Hash + var nep17t = nep17.New(actor, hash) + return &Contract{ContractReader{nep17t.TokenReader, actor, hash}, nep17t.TokenWriter, actor, hash} } // Cap invokes `cap` method of contract. func (c *ContractReader) Cap() (*big.Int, error) { - return unwrap.BigInt(c.invoker.Call(Hash, "cap")) + return unwrap.BigInt(c.invoker.Call(c.hash, "cap")) } // GetMinter invokes `getMinter` method of contract. func (c *ContractReader) GetMinter() (*keys.PublicKey, error) { - return unwrap.PublicKey(c.invoker.Call(Hash, "getMinter")) + return unwrap.PublicKey(c.invoker.Call(c.hash, "getMinter")) } // GetOwner invokes `getOwner` method of contract. func (c *ContractReader) GetOwner() (util.Uint160, error) { - return unwrap.Uint160(c.invoker.Call(Hash, "getOwner")) + return unwrap.Uint160(c.invoker.Call(c.hash, "getOwner")) } // TotalMinted invokes `totalMinted` method of contract. func (c *ContractReader) TotalMinted() (*big.Int, error) { - return unwrap.BigInt(c.invoker.Call(Hash, "totalMinted")) + return unwrap.BigInt(c.invoker.Call(c.hash, "totalMinted")) } // ChangeMinter creates a transaction invoking `changeMinter` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) ChangeMinter(newMinter *keys.PublicKey) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "changeMinter", newMinter) + return c.actor.SendCall(c.hash, "changeMinter", newMinter) } // ChangeMinterTransaction creates a transaction invoking `changeMinter` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) ChangeMinterTransaction(newMinter *keys.PublicKey) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "changeMinter", newMinter) + return c.actor.MakeCall(c.hash, "changeMinter", newMinter) } // ChangeMinterUnsigned creates a transaction invoking `changeMinter` method of the contract. @@ -107,21 +111,21 @@ func (c *Contract) ChangeMinterTransaction(newMinter *keys.PublicKey) (*transact // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) ChangeMinterUnsigned(newMinter *keys.PublicKey) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "changeMinter", nil, newMinter) + return c.actor.MakeUnsignedCall(c.hash, "changeMinter", nil, newMinter) } // ChangeOwner creates a transaction invoking `changeOwner` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) ChangeOwner(newOwner util.Uint160) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "changeOwner", newOwner) + return c.actor.SendCall(c.hash, "changeOwner", newOwner) } // ChangeOwnerTransaction creates a transaction invoking `changeOwner` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) ChangeOwnerTransaction(newOwner util.Uint160) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "changeOwner", newOwner) + return c.actor.MakeCall(c.hash, "changeOwner", newOwner) } // ChangeOwnerUnsigned creates a transaction invoking `changeOwner` method of the contract. @@ -129,21 +133,21 @@ func (c *Contract) ChangeOwnerTransaction(newOwner util.Uint160) (*transaction.T // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) ChangeOwnerUnsigned(newOwner util.Uint160) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "changeOwner", nil, newOwner) + return c.actor.MakeUnsignedCall(c.hash, "changeOwner", nil, newOwner) } // Destroy creates a transaction invoking `destroy` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Destroy() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "destroy") + return c.actor.SendCall(c.hash, "destroy") } // DestroyTransaction creates a transaction invoking `destroy` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) DestroyTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "destroy") + return c.actor.MakeCall(c.hash, "destroy") } // DestroyUnsigned creates a transaction invoking `destroy` method of the contract. @@ -151,21 +155,21 @@ func (c *Contract) DestroyTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) DestroyUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "destroy", nil) + return c.actor.MakeUnsignedCall(c.hash, "destroy", nil) } // MaxSupply creates a transaction invoking `maxSupply` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) MaxSupply() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "maxSupply") + return c.actor.SendCall(c.hash, "maxSupply") } // MaxSupplyTransaction creates a transaction invoking `maxSupply` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) MaxSupplyTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "maxSupply") + return c.actor.MakeCall(c.hash, "maxSupply") } // MaxSupplyUnsigned creates a transaction invoking `maxSupply` method of the contract. @@ -173,21 +177,21 @@ func (c *Contract) MaxSupplyTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) MaxSupplyUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "maxSupply", nil) + return c.actor.MakeUnsignedCall(c.hash, "maxSupply", nil) } // Mint creates a transaction invoking `mint` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Mint(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data any) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "mint", from, to, amount, swapId, signature, data) + return c.actor.SendCall(c.hash, "mint", from, to, amount, swapId, signature, data) } // MintTransaction creates a transaction invoking `mint` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) MintTransaction(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data any) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "mint", from, to, amount, swapId, signature, data) + return c.actor.MakeCall(c.hash, "mint", from, to, amount, swapId, signature, data) } // MintUnsigned creates a transaction invoking `mint` method of the contract. @@ -195,21 +199,21 @@ func (c *Contract) MintTransaction(from util.Uint160, to util.Uint160, amount *b // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) MintUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, swapId *big.Int, signature []byte, data any) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "mint", nil, from, to, amount, swapId, signature, data) + return c.actor.MakeUnsignedCall(c.hash, "mint", nil, from, to, amount, swapId, signature, data) } // Update creates a transaction invoking `update` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Update(nef []byte, manifest []byte) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "update", nef, manifest) + return c.actor.SendCall(c.hash, "update", nef, manifest) } // UpdateTransaction creates a transaction invoking `update` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) UpdateTransaction(nef []byte, manifest []byte) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "update", nef, manifest) + return c.actor.MakeCall(c.hash, "update", nef, manifest) } // UpdateUnsigned creates a transaction invoking `update` method of the contract. @@ -217,21 +221,21 @@ func (c *Contract) UpdateTransaction(nef []byte, manifest []byte) (*transaction. // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) UpdateUnsigned(nef []byte, manifest []byte) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "update", nil, nef, manifest) + return c.actor.MakeUnsignedCall(c.hash, "update", nil, nef, manifest) } // UpdateCap creates a transaction invoking `updateCap` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) UpdateCap(newCap *big.Int) (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "updateCap", newCap) + return c.actor.SendCall(c.hash, "updateCap", newCap) } // UpdateCapTransaction creates a transaction invoking `updateCap` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) UpdateCapTransaction(newCap *big.Int) (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "updateCap", newCap) + return c.actor.MakeCall(c.hash, "updateCap", newCap) } // UpdateCapUnsigned creates a transaction invoking `updateCap` method of the contract. @@ -239,7 +243,7 @@ func (c *Contract) UpdateCapTransaction(newCap *big.Int) (*transaction.Transacti // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) UpdateCapUnsigned(newCap *big.Int) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "updateCap", nil, newCap) + return c.actor.MakeUnsignedCall(c.hash, "updateCap", nil, newCap) } // OnMintEventsFromApplicationLog retrieves a set of all emitted events diff --git a/cli/smartcontract/testdata/nonepiter/iter.go b/cli/smartcontract/testdata/nonepiter/iter.go index f298ab8de..d9fac3f73 100644 --- a/cli/smartcontract/testdata/nonepiter/iter.go +++ b/cli/smartcontract/testdata/nonepiter/iter.go @@ -23,16 +23,18 @@ type Invoker interface { // ContractReader implements safe contract methods. type ContractReader struct { invoker Invoker + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{invoker} + var hash = Hash + return &ContractReader{invoker, hash} } // Tokens invokes `tokens` method of contract. func (c *ContractReader) Tokens() (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.invoker.Call(Hash, "tokens")) + return unwrap.SessionIterator(c.invoker.Call(c.hash, "tokens")) } // TokensExpanded is similar to Tokens (uses the same contract @@ -41,12 +43,12 @@ func (c *ContractReader) Tokens() (uuid.UUID, result.Iterator, error) { // number of result items from the iterator right in the VM and return them to // you. It's only limited by VM stack and GAS available for RPC invocations. func (c *ContractReader) TokensExpanded(_numOfIteratorItems int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.CallAndExpandIterator(Hash, "tokens", _numOfIteratorItems)) + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "tokens", _numOfIteratorItems)) } // GetAllRecords invokes `getAllRecords` method of contract. func (c *ContractReader) GetAllRecords(name string) (uuid.UUID, result.Iterator, error) { - return unwrap.SessionIterator(c.invoker.Call(Hash, "getAllRecords", name)) + return unwrap.SessionIterator(c.invoker.Call(c.hash, "getAllRecords", name)) } // GetAllRecordsExpanded is similar to GetAllRecords (uses the same contract @@ -55,5 +57,5 @@ func (c *ContractReader) GetAllRecords(name string) (uuid.UUID, result.Iterator, // number of result items from the iterator right in the VM and return them to // you. It's only limited by VM stack and GAS available for RPC invocations. func (c *ContractReader) GetAllRecordsExpanded(name string, _numOfIteratorItems int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.CallAndExpandIterator(Hash, "getAllRecords", _numOfIteratorItems, name)) + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "getAllRecords", _numOfIteratorItems, name)) } diff --git a/cli/smartcontract/testdata/notifications/rpcbindings.out b/cli/smartcontract/testdata/notifications/rpcbindings.out index a95cc1ea0..74c872833 100644 --- a/cli/smartcontract/testdata/notifications/rpcbindings.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings.out @@ -110,25 +110,27 @@ type Actor interface { // Contract implements all contract methods. type Contract struct { actor Actor + hash util.Uint160 } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - return &Contract{actor} + var hash = Hash + return &Contract{actor, hash} } // Array creates a transaction invoking `array` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Array() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "array") + return c.actor.SendCall(c.hash, "array") } // ArrayTransaction creates a transaction invoking `array` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "array") + return c.actor.MakeCall(c.hash, "array") } // ArrayUnsigned creates a transaction invoking `array` method of the contract. @@ -136,21 +138,21 @@ func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "array", nil) + return c.actor.MakeUnsignedCall(c.hash, "array", nil) } // CrazyMap creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) CrazyMap() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "crazyMap") + return c.actor.SendCall(c.hash, "crazyMap") } // CrazyMapTransaction creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "crazyMap") + return c.actor.MakeCall(c.hash, "crazyMap") } // CrazyMapUnsigned creates a transaction invoking `crazyMap` method of the contract. @@ -158,21 +160,21 @@ func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) CrazyMapUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "crazyMap", nil) + return c.actor.MakeUnsignedCall(c.hash, "crazyMap", nil) } // Main creates a transaction invoking `main` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Main() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "main") + return c.actor.SendCall(c.hash, "main") } // MainTransaction creates a transaction invoking `main` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) MainTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "main") + return c.actor.MakeCall(c.hash, "main") } // MainUnsigned creates a transaction invoking `main` method of the contract. @@ -180,21 +182,21 @@ func (c *Contract) MainTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "main", nil) + return c.actor.MakeUnsignedCall(c.hash, "main", nil) } // Struct creates a transaction invoking `struct` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Struct() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "struct") + return c.actor.SendCall(c.hash, "struct") } // StructTransaction creates a transaction invoking `struct` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) StructTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "struct") + return c.actor.MakeCall(c.hash, "struct") } // StructUnsigned creates a transaction invoking `struct` method of the contract. @@ -202,7 +204,7 @@ func (c *Contract) StructTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) StructUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "struct", nil) + return c.actor.MakeUnsignedCall(c.hash, "struct", nil) } // itemToLedgerBlock converts stack item into *LedgerBlock. diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out index 818c91993..8a71c6b32 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_extended.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_extended.out @@ -116,25 +116,27 @@ type Actor interface { // Contract implements all contract methods. type Contract struct { actor Actor + hash util.Uint160 } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - return &Contract{actor} + var hash = Hash + return &Contract{actor, hash} } // Array creates a transaction invoking `array` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Array() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "array") + return c.actor.SendCall(c.hash, "array") } // ArrayTransaction creates a transaction invoking `array` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "array") + return c.actor.MakeCall(c.hash, "array") } // ArrayUnsigned creates a transaction invoking `array` method of the contract. @@ -142,21 +144,21 @@ func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "array", nil) + return c.actor.MakeUnsignedCall(c.hash, "array", nil) } // CrazyMap creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) CrazyMap() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "crazyMap") + return c.actor.SendCall(c.hash, "crazyMap") } // CrazyMapTransaction creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "crazyMap") + return c.actor.MakeCall(c.hash, "crazyMap") } // CrazyMapUnsigned creates a transaction invoking `crazyMap` method of the contract. @@ -164,21 +166,21 @@ func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) CrazyMapUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "crazyMap", nil) + return c.actor.MakeUnsignedCall(c.hash, "crazyMap", nil) } // Main creates a transaction invoking `main` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Main() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "main") + return c.actor.SendCall(c.hash, "main") } // MainTransaction creates a transaction invoking `main` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) MainTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "main") + return c.actor.MakeCall(c.hash, "main") } // MainUnsigned creates a transaction invoking `main` method of the contract. @@ -186,21 +188,21 @@ func (c *Contract) MainTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "main", nil) + return c.actor.MakeUnsignedCall(c.hash, "main", nil) } // Struct creates a transaction invoking `struct` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Struct() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "struct") + return c.actor.SendCall(c.hash, "struct") } // StructTransaction creates a transaction invoking `struct` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) StructTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "struct") + return c.actor.MakeCall(c.hash, "struct") } // StructUnsigned creates a transaction invoking `struct` method of the contract. @@ -208,7 +210,7 @@ func (c *Contract) StructTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) StructUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "struct", nil) + return c.actor.MakeUnsignedCall(c.hash, "struct", nil) } // itemToCrazyStruct converts stack item into *CrazyStruct. diff --git a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out index 883283d09..eb5c650b1 100755 --- a/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out +++ b/cli/smartcontract/testdata/notifications/rpcbindings_guessed.out @@ -116,25 +116,27 @@ type Actor interface { // Contract implements all contract methods. type Contract struct { actor Actor + hash util.Uint160 } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - return &Contract{actor} + var hash = Hash + return &Contract{actor, hash} } // Array creates a transaction invoking `array` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Array() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "array") + return c.actor.SendCall(c.hash, "array") } // ArrayTransaction creates a transaction invoking `array` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "array") + return c.actor.MakeCall(c.hash, "array") } // ArrayUnsigned creates a transaction invoking `array` method of the contract. @@ -142,21 +144,21 @@ func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "array", nil) + return c.actor.MakeUnsignedCall(c.hash, "array", nil) } // CrazyMap creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) CrazyMap() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "crazyMap") + return c.actor.SendCall(c.hash, "crazyMap") } // CrazyMapTransaction creates a transaction invoking `crazyMap` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "crazyMap") + return c.actor.MakeCall(c.hash, "crazyMap") } // CrazyMapUnsigned creates a transaction invoking `crazyMap` method of the contract. @@ -164,21 +166,21 @@ func (c *Contract) CrazyMapTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) CrazyMapUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "crazyMap", nil) + return c.actor.MakeUnsignedCall(c.hash, "crazyMap", nil) } // Main creates a transaction invoking `main` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Main() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "main") + return c.actor.SendCall(c.hash, "main") } // MainTransaction creates a transaction invoking `main` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) MainTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "main") + return c.actor.MakeCall(c.hash, "main") } // MainUnsigned creates a transaction invoking `main` method of the contract. @@ -186,21 +188,21 @@ func (c *Contract) MainTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) MainUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "main", nil) + return c.actor.MakeUnsignedCall(c.hash, "main", nil) } // Struct creates a transaction invoking `struct` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Struct() (util.Uint256, uint32, error) { - return c.actor.SendCall(Hash, "struct") + return c.actor.SendCall(c.hash, "struct") } // StructTransaction creates a transaction invoking `struct` method of the contract. // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) StructTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(Hash, "struct") + return c.actor.MakeCall(c.hash, "struct") } // StructUnsigned creates a transaction invoking `struct` method of the contract. @@ -208,7 +210,7 @@ func (c *Contract) StructTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) StructUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(Hash, "struct", nil) + return c.actor.MakeUnsignedCall(c.hash, "struct", nil) } // itemToLedgerBlock converts stack item into *LedgerBlock. diff --git a/cli/smartcontract/testdata/structs/rpcbindings.out b/cli/smartcontract/testdata/structs/rpcbindings.out index ba503be59..32acf3089 100644 --- a/cli/smartcontract/testdata/structs/rpcbindings.out +++ b/cli/smartcontract/testdata/structs/rpcbindings.out @@ -162,31 +162,33 @@ type Invoker interface { // ContractReader implements safe contract methods. type ContractReader struct { invoker Invoker + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{invoker} + var hash = Hash + return &ContractReader{invoker, hash} } // Block invokes `block` method of contract. func (c *ContractReader) Block(b *LedgerBlock) (*LedgerBlock, error) { - return itemToLedgerBlock(unwrap.Item(c.invoker.Call(Hash, "block", b))) + return itemToLedgerBlock(unwrap.Item(c.invoker.Call(c.hash, "block", b))) } // Contract invokes `contract` method of contract. func (c *ContractReader) Contract(mc *ManagementContract) (*ManagementContract, error) { - return itemToManagementContract(unwrap.Item(c.invoker.Call(Hash, "contract", mc))) + return itemToManagementContract(unwrap.Item(c.invoker.Call(c.hash, "contract", mc))) } // Struct invokes `struct` method of contract. func (c *ContractReader) Struct(s *StructsInternal) (*StructsInternal, error) { - return itemToStructsInternal(unwrap.Item(c.invoker.Call(Hash, "struct", s))) + return itemToStructsInternal(unwrap.Item(c.invoker.Call(c.hash, "struct", s))) } // Transaction invokes `transaction` method of contract. func (c *ContractReader) Transaction(t *LedgerTransaction) (*LedgerTransaction, error) { - return itemToLedgerTransaction(unwrap.Item(c.invoker.Call(Hash, "transaction", t))) + return itemToLedgerTransaction(unwrap.Item(c.invoker.Call(c.hash, "transaction", t))) } // itemToLedgerBlock converts stack item into *LedgerBlock. diff --git a/cli/smartcontract/testdata/structs/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/structs/rpcbindings_dynamic_hash.out new file mode 100755 index 000000000..69558da30 --- /dev/null +++ b/cli/smartcontract/testdata/structs/rpcbindings_dynamic_hash.out @@ -0,0 +1,1622 @@ +// Package structs contains RPC wrappers for Types contract. +package structs + +import ( + "crypto/elliptic" + "errors" + "fmt" + "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/unwrap" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// LedgerBlock is a contract-specific ledger.Block type used by its methods. +type LedgerBlock struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int +} + +// LedgerBlockSR is a contract-specific ledger.BlockSR type used by its methods. +type LedgerBlockSR struct { + Hash util.Uint256 + Version *big.Int + PrevHash util.Uint256 + MerkleRoot util.Uint256 + Timestamp *big.Int + Nonce *big.Int + Index *big.Int + NextConsensus util.Uint160 + TransactionsLength *big.Int + PrevStateRoot util.Uint256 +} + +// LedgerTransaction is a contract-specific ledger.Transaction type used by its methods. +type LedgerTransaction struct { + Hash util.Uint256 + Version *big.Int + Nonce *big.Int + Sender util.Uint160 + SysFee *big.Int + NetFee *big.Int + ValidUntilBlock *big.Int + Script []byte +} + +// LedgerTransactionSigner is a contract-specific ledger.TransactionSigner type used by its methods. +type LedgerTransactionSigner struct { + Account util.Uint160 + Scopes *big.Int + AllowedContracts []util.Uint160 + AllowedGroups keys.PublicKeys + Rules []*LedgerWitnessRule +} + +// LedgerWitnessCondition is a contract-specific ledger.WitnessCondition type used by its methods. +type LedgerWitnessCondition struct { + Type *big.Int + Value any +} + +// LedgerWitnessRule is a contract-specific ledger.WitnessRule type used by its methods. +type LedgerWitnessRule struct { + Action *big.Int + Condition *LedgerWitnessCondition +} + +// ManagementABI is a contract-specific management.ABI type used by its methods. +type ManagementABI struct { + Methods []*ManagementMethod + Events []*ManagementEvent +} + +// ManagementContract is a contract-specific management.Contract type used by its methods. +type ManagementContract struct { + ID *big.Int + UpdateCounter *big.Int + Hash util.Uint160 + NEF []byte + Manifest *ManagementManifest +} + +// ManagementEvent is a contract-specific management.Event type used by its methods. +type ManagementEvent struct { + Name string + Params []*ManagementParameter +} + +// ManagementGroup is a contract-specific management.Group type used by its methods. +type ManagementGroup struct { + PublicKey *keys.PublicKey + Signature []byte +} + +// ManagementManifest is a contract-specific management.Manifest type used by its methods. +type ManagementManifest struct { + Name string + Groups []*ManagementGroup + Features map[string]string + SupportedStandards []string + ABI *ManagementABI + Permissions []*ManagementPermission + Trusts []util.Uint160 + Extra any +} + +// ManagementMethod is a contract-specific management.Method type used by its methods. +type ManagementMethod struct { + Name string + Params []*ManagementParameter + ReturnType *big.Int + Offset *big.Int + Safe bool +} + +// ManagementParameter is a contract-specific management.Parameter type used by its methods. +type ManagementParameter struct { + Name string + Type *big.Int +} + +// ManagementPermission is a contract-specific management.Permission type used by its methods. +type ManagementPermission struct { + Contract util.Uint160 + Methods []string +} + +// StructsInternal is a contract-specific structs.Internal type used by its methods. +type StructsInternal struct { + Bool bool + Int *big.Int + Bytes []byte + String string + H160 util.Uint160 + H256 util.Uint256 + PK *keys.PublicKey + PubKey *keys.PublicKey + Sign []byte + ArrOfBytes [][]byte + ArrOfH160 []util.Uint160 + Map map[*big.Int]keys.PublicKeys + Struct *StructsInternal +} + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// Block invokes `block` method of contract. +func (c *ContractReader) Block(b *LedgerBlock) (*LedgerBlock, error) { + return itemToLedgerBlock(unwrap.Item(c.invoker.Call(c.hash, "block", b))) +} + +// Contract invokes `contract` method of contract. +func (c *ContractReader) Contract(mc *ManagementContract) (*ManagementContract, error) { + return itemToManagementContract(unwrap.Item(c.invoker.Call(c.hash, "contract", mc))) +} + +// Struct invokes `struct` method of contract. +func (c *ContractReader) Struct(s *StructsInternal) (*StructsInternal, error) { + return itemToStructsInternal(unwrap.Item(c.invoker.Call(c.hash, "struct", s))) +} + +// Transaction invokes `transaction` method of contract. +func (c *ContractReader) Transaction(t *LedgerTransaction) (*LedgerTransaction, error) { + return itemToLedgerTransaction(unwrap.Item(c.invoker.Call(c.hash, "transaction", t))) +} + +// itemToLedgerBlock converts stack item into *LedgerBlock. +func itemToLedgerBlock(item stackitem.Item, err error) (*LedgerBlock, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlock) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlock from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlock) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 9 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + return nil +} + +// itemToLedgerBlockSR converts stack item into *LedgerBlockSR. +func itemToLedgerBlockSR(item stackitem.Item, err error) (*LedgerBlockSR, error) { + if err != nil { + return nil, err + } + var res = new(LedgerBlockSR) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerBlockSR from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerBlockSR) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 10 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.PrevHash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevHash: %w", err) + } + + index++ + res.MerkleRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field MerkleRoot: %w", err) + } + + index++ + res.Timestamp, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Timestamp: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Index, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Index: %w", err) + } + + index++ + res.NextConsensus, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field NextConsensus: %w", err) + } + + index++ + res.TransactionsLength, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field TransactionsLength: %w", err) + } + + index++ + res.PrevStateRoot, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PrevStateRoot: %w", err) + } + + return nil +} + +// itemToLedgerTransaction converts stack item into *LedgerTransaction. +func itemToLedgerTransaction(item stackitem.Item, err error) (*LedgerTransaction, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransaction) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransaction from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransaction) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.Version, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Version: %w", err) + } + + index++ + res.Nonce, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Nonce: %w", err) + } + + index++ + res.Sender, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Sender: %w", err) + } + + index++ + res.SysFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field SysFee: %w", err) + } + + index++ + res.NetFee, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field NetFee: %w", err) + } + + index++ + res.ValidUntilBlock, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ValidUntilBlock: %w", err) + } + + index++ + res.Script, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Script: %w", err) + } + + return nil +} + +// itemToLedgerTransactionSigner converts stack item into *LedgerTransactionSigner. +func itemToLedgerTransactionSigner(item stackitem.Item, err error) (*LedgerTransactionSigner, error) { + if err != nil { + return nil, err + } + var res = new(LedgerTransactionSigner) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerTransactionSigner from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerTransactionSigner) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Account, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Account: %w", err) + } + + index++ + res.Scopes, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Scopes: %w", err) + } + + index++ + res.AllowedContracts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedContracts: %w", err) + } + + index++ + res.AllowedGroups, err = func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field AllowedGroups: %w", err) + } + + index++ + res.Rules, err = func (item stackitem.Item) ([]*LedgerWitnessRule, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*LedgerWitnessRule, len(arr)) + for i := range res { + res[i], err = itemToLedgerWitnessRule(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Rules: %w", err) + } + + return nil +} + +// itemToLedgerWitnessCondition converts stack item into *LedgerWitnessCondition. +func itemToLedgerWitnessCondition(item stackitem.Item, err error) (*LedgerWitnessCondition, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessCondition) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessCondition from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessCondition) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + index++ + res.Value, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Value: %w", err) + } + + return nil +} + +// itemToLedgerWitnessRule converts stack item into *LedgerWitnessRule. +func itemToLedgerWitnessRule(item stackitem.Item, err error) (*LedgerWitnessRule, error) { + if err != nil { + return nil, err + } + var res = new(LedgerWitnessRule) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of LedgerWitnessRule from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *LedgerWitnessRule) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Action, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Action: %w", err) + } + + index++ + res.Condition, err = itemToLedgerWitnessCondition(arr[index], nil) + if err != nil { + return fmt.Errorf("field Condition: %w", err) + } + + return nil +} + +// itemToManagementABI converts stack item into *ManagementABI. +func itemToManagementABI(item stackitem.Item, err error) (*ManagementABI, error) { + if err != nil { + return nil, err + } + var res = new(ManagementABI) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementABI from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementABI) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Methods, err = func (item stackitem.Item) ([]*ManagementMethod, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementMethod, len(arr)) + for i := range res { + res[i], err = itemToManagementMethod(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + index++ + res.Events, err = func (item stackitem.Item) ([]*ManagementEvent, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementEvent, len(arr)) + for i := range res { + res[i], err = itemToManagementEvent(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Events: %w", err) + } + + return nil +} + +// itemToManagementContract converts stack item into *ManagementContract. +func itemToManagementContract(item stackitem.Item, err error) (*ManagementContract, error) { + if err != nil { + return nil, err + } + var res = new(ManagementContract) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementContract from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementContract) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.ID, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ID: %w", err) + } + + index++ + res.UpdateCounter, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field UpdateCounter: %w", err) + } + + index++ + res.Hash, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Hash: %w", err) + } + + index++ + res.NEF, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field NEF: %w", err) + } + + index++ + res.Manifest, err = itemToManagementManifest(arr[index], nil) + if err != nil { + return fmt.Errorf("field Manifest: %w", err) + } + + return nil +} + +// itemToManagementEvent converts stack item into *ManagementEvent. +func itemToManagementEvent(item stackitem.Item, err error) (*ManagementEvent, error) { + if err != nil { + return nil, err + } + var res = new(ManagementEvent) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementEvent from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementEvent) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + return nil +} + +// itemToManagementGroup converts stack item into *ManagementGroup. +func itemToManagementGroup(item stackitem.Item, err error) (*ManagementGroup, error) { + if err != nil { + return nil, err + } + var res = new(ManagementGroup) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementGroup from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementGroup) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.PublicKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PublicKey: %w", err) + } + + index++ + res.Signature, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Signature: %w", err) + } + + return nil +} + +// itemToManagementManifest converts stack item into *ManagementManifest. +func itemToManagementManifest(item stackitem.Item, err error) (*ManagementManifest, error) { + if err != nil { + return nil, err + } + var res = new(ManagementManifest) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementManifest from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementManifest) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 8 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Groups, err = func (item stackitem.Item) ([]*ManagementGroup, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementGroup, len(arr)) + for i := range res { + res[i], err = itemToManagementGroup(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Groups: %w", err) + } + + index++ + res.Features, err = func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Features: %w", err) + } + + index++ + res.SupportedStandards, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field SupportedStandards: %w", err) + } + + index++ + res.ABI, err = itemToManagementABI(arr[index], nil) + if err != nil { + return fmt.Errorf("field ABI: %w", err) + } + + index++ + res.Permissions, err = func (item stackitem.Item) ([]*ManagementPermission, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementPermission, len(arr)) + for i := range res { + res[i], err = itemToManagementPermission(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Permissions: %w", err) + } + + index++ + res.Trusts, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Trusts: %w", err) + } + + index++ + res.Extra, err = arr[index].Value(), error(nil) + if err != nil { + return fmt.Errorf("field Extra: %w", err) + } + + return nil +} + +// itemToManagementMethod converts stack item into *ManagementMethod. +func itemToManagementMethod(item stackitem.Item, err error) (*ManagementMethod, error) { + if err != nil { + return nil, err + } + var res = new(ManagementMethod) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementMethod from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementMethod) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 5 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Params, err = func (item stackitem.Item) ([]*ManagementParameter, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]*ManagementParameter, len(arr)) + for i := range res { + res[i], err = itemToManagementParameter(arr[i], nil) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Params: %w", err) + } + + index++ + res.ReturnType, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field ReturnType: %w", err) + } + + index++ + res.Offset, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Offset: %w", err) + } + + index++ + res.Safe, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Safe: %w", err) + } + + return nil +} + +// itemToManagementParameter converts stack item into *ManagementParameter. +func itemToManagementParameter(item stackitem.Item, err error) (*ManagementParameter, error) { + if err != nil { + return nil, err + } + var res = new(ManagementParameter) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementParameter from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementParameter) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Name, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Name: %w", err) + } + + index++ + res.Type, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Type: %w", err) + } + + return nil +} + +// itemToManagementPermission converts stack item into *ManagementPermission. +func itemToManagementPermission(item stackitem.Item, err error) (*ManagementPermission, error) { + if err != nil { + return nil, err + } + var res = new(ManagementPermission) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of ManagementPermission from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *ManagementPermission) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 2 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Contract, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Contract: %w", err) + } + + index++ + res.Methods, err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Methods: %w", err) + } + + return nil +} + +// itemToStructsInternal converts stack item into *StructsInternal. +func itemToStructsInternal(item stackitem.Item, err error) (*StructsInternal, error) { + if err != nil { + return nil, err + } + var res = new(StructsInternal) + err = res.FromStackItem(item) + return res, err +} + +// FromStackItem retrieves fields of StructsInternal from the given +// [stackitem.Item] or returns an error if it's not possible to do to so. +func (res *StructsInternal) FromStackItem(item stackitem.Item) error { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return errors.New("not an array") + } + if len(arr) != 13 { + return errors.New("wrong number of structure elements") + } + + var ( + index = -1 + err error + ) + index++ + res.Bool, err = arr[index].TryBool() + if err != nil { + return fmt.Errorf("field Bool: %w", err) + } + + index++ + res.Int, err = arr[index].TryInteger() + if err != nil { + return fmt.Errorf("field Int: %w", err) + } + + index++ + res.Bytes, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Bytes: %w", err) + } + + index++ + res.String, err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field String: %w", err) + } + + index++ + res.H160, err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field H160: %w", err) + } + + index++ + res.H256, err = func (item stackitem.Item) (util.Uint256, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint256{}, err + } + u, err := util.Uint256DecodeBytesBE(b) + if err != nil { + return util.Uint256{}, err + } + return u, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field H256: %w", err) + } + + index++ + res.PK, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PK: %w", err) + } + + index++ + res.PubKey, err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field PubKey: %w", err) + } + + index++ + res.Sign, err = arr[index].TryBytes() + if err != nil { + return fmt.Errorf("field Sign: %w", err) + } + + index++ + res.ArrOfBytes, err = func (item stackitem.Item) ([][]byte, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([][]byte, len(arr)) + for i := range res { + res[i], err = arr[i].TryBytes() + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field ArrOfBytes: %w", err) + } + + index++ + res.ArrOfH160, err = func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field ArrOfH160: %w", err) + } + + index++ + res.Map, err = func (item stackitem.Item) (map[*big.Int]keys.PublicKeys, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[*big.Int]keys.PublicKeys) + for i := range m { + k, err := m[i].Key.TryInteger() + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (keys.PublicKeys, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make(keys.PublicKeys, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (*keys.PublicKey, error) { + b, err := item.TryBytes() + if err != nil { + return nil, err + } + k, err := keys.NewPublicKeyFromBytes(b, elliptic.P256()) + if err != nil { + return nil, err + } + return k, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[index]) + if err != nil { + return fmt.Errorf("field Map: %w", err) + } + + index++ + res.Struct, err = itemToStructsInternal(arr[index], nil) + if err != nil { + return fmt.Errorf("field Struct: %w", err) + } + + return nil +} diff --git a/cli/smartcontract/testdata/types/rpcbindings.out b/cli/smartcontract/testdata/types/rpcbindings.out index 49f6ac7e5..ee61838d1 100644 --- a/cli/smartcontract/testdata/types/rpcbindings.out +++ b/cli/smartcontract/testdata/types/rpcbindings.out @@ -24,11 +24,13 @@ type Invoker interface { // ContractReader implements safe contract methods. type ContractReader struct { invoker Invoker + hash util.Uint160 } // NewReader creates an instance of ContractReader using Hash and the given Invoker. func NewReader(invoker Invoker) *ContractReader { - return &ContractReader{invoker} + var hash = Hash + return &ContractReader{invoker, hash} } // AAAStrings invokes `aAAStrings` method of contract. @@ -86,7 +88,7 @@ func (c *ContractReader) AAAStrings(s [][][]string) ([][][]string, error) { } return res, nil } (item) - } (unwrap.Item(c.invoker.Call(Hash, "aAAStrings", s))) + } (unwrap.Item(c.invoker.Call(c.hash, "aAAStrings", s))) } // Any invokes `any` method of contract. @@ -96,7 +98,7 @@ func (c *ContractReader) Any(a any) (any, error) { return nil, err } return item.Value(), error(nil) - } (unwrap.Item(c.invoker.Call(Hash, "any", a))) + } (unwrap.Item(c.invoker.Call(c.hash, "any", a))) } // AnyMaps invokes `anyMaps` method of contract. @@ -124,27 +126,27 @@ func (c *ContractReader) AnyMaps(m map[*big.Int]any) (map[*big.Int]any, error) { } return res, nil } (item) - } (unwrap.Item(c.invoker.Call(Hash, "anyMaps", m))) + } (unwrap.Item(c.invoker.Call(c.hash, "anyMaps", m))) } // Bool invokes `bool` method of contract. func (c *ContractReader) Bool(b bool) (bool, error) { - return unwrap.Bool(c.invoker.Call(Hash, "bool", b)) + return unwrap.Bool(c.invoker.Call(c.hash, "bool", b)) } // Bools invokes `bools` method of contract. func (c *ContractReader) Bools(b []bool) ([]bool, error) { - return unwrap.ArrayOfBools(c.invoker.Call(Hash, "bools", b)) + return unwrap.ArrayOfBools(c.invoker.Call(c.hash, "bools", b)) } // Bytes invokes `bytes` method of contract. func (c *ContractReader) Bytes(b []byte) ([]byte, error) { - return unwrap.Bytes(c.invoker.Call(Hash, "bytes", b)) + return unwrap.Bytes(c.invoker.Call(c.hash, "bytes", b)) } // Bytess invokes `bytess` method of contract. func (c *ContractReader) Bytess(b [][]byte) ([][]byte, error) { - return unwrap.ArrayOfBytes(c.invoker.Call(Hash, "bytess", b)) + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "bytess", b)) } // CrazyMaps invokes `crazyMaps` method of contract. @@ -235,37 +237,37 @@ func (c *ContractReader) CrazyMaps(m map[*big.Int][]map[string][]util.Uint160) ( } return res, nil } (item) - } (unwrap.Item(c.invoker.Call(Hash, "crazyMaps", m))) + } (unwrap.Item(c.invoker.Call(c.hash, "crazyMaps", m))) } // Hash160 invokes `hash160` method of contract. func (c *ContractReader) Hash160(h util.Uint160) (util.Uint160, error) { - return unwrap.Uint160(c.invoker.Call(Hash, "hash160", h)) + return unwrap.Uint160(c.invoker.Call(c.hash, "hash160", h)) } // Hash160s invokes `hash160s` method of contract. func (c *ContractReader) Hash160s(h []util.Uint160) ([]util.Uint160, error) { - return unwrap.ArrayOfUint160(c.invoker.Call(Hash, "hash160s", h)) + return unwrap.ArrayOfUint160(c.invoker.Call(c.hash, "hash160s", h)) } // Hash256 invokes `hash256` method of contract. func (c *ContractReader) Hash256(h util.Uint256) (util.Uint256, error) { - return unwrap.Uint256(c.invoker.Call(Hash, "hash256", h)) + return unwrap.Uint256(c.invoker.Call(c.hash, "hash256", h)) } // Hash256s invokes `hash256s` method of contract. func (c *ContractReader) Hash256s(h []util.Uint256) ([]util.Uint256, error) { - return unwrap.ArrayOfUint256(c.invoker.Call(Hash, "hash256s", h)) + return unwrap.ArrayOfUint256(c.invoker.Call(c.hash, "hash256s", h)) } // Int invokes `int` method of contract. func (c *ContractReader) Int(i *big.Int) (*big.Int, error) { - return unwrap.BigInt(c.invoker.Call(Hash, "int", i)) + return unwrap.BigInt(c.invoker.Call(c.hash, "int", i)) } // Ints invokes `ints` method of contract. func (c *ContractReader) Ints(i []*big.Int) ([]*big.Int, error) { - return unwrap.ArrayOfBigInts(c.invoker.Call(Hash, "ints", i)) + return unwrap.ArrayOfBigInts(c.invoker.Call(c.hash, "ints", i)) } // Maps invokes `maps` method of contract. @@ -311,35 +313,35 @@ func (c *ContractReader) Maps(m map[string]string) (map[string]string, error) { } return res, nil } (item) - } (unwrap.Item(c.invoker.Call(Hash, "maps", m))) + } (unwrap.Item(c.invoker.Call(c.hash, "maps", m))) } // PublicKey invokes `publicKey` method of contract. func (c *ContractReader) PublicKey(k *keys.PublicKey) (*keys.PublicKey, error) { - return unwrap.PublicKey(c.invoker.Call(Hash, "publicKey", k)) + return unwrap.PublicKey(c.invoker.Call(c.hash, "publicKey", k)) } // PublicKeys invokes `publicKeys` method of contract. func (c *ContractReader) PublicKeys(k keys.PublicKeys) (keys.PublicKeys, error) { - return unwrap.ArrayOfPublicKeys(c.invoker.Call(Hash, "publicKeys", k)) + return unwrap.ArrayOfPublicKeys(c.invoker.Call(c.hash, "publicKeys", k)) } // Signature invokes `signature` method of contract. func (c *ContractReader) Signature(s []byte) ([]byte, error) { - return unwrap.Bytes(c.invoker.Call(Hash, "signature", s)) + return unwrap.Bytes(c.invoker.Call(c.hash, "signature", s)) } // Signatures invokes `signatures` method of contract. func (c *ContractReader) Signatures(s [][]byte) ([][]byte, error) { - return unwrap.ArrayOfBytes(c.invoker.Call(Hash, "signatures", s)) + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "signatures", s)) } // String invokes `string` method of contract. func (c *ContractReader) String(s string) (string, error) { - return unwrap.UTF8String(c.invoker.Call(Hash, "string", s)) + return unwrap.UTF8String(c.invoker.Call(c.hash, "string", s)) } // Strings invokes `strings` method of contract. func (c *ContractReader) Strings(s []string) ([]string, error) { - return unwrap.ArrayOfUTF8Strings(c.invoker.Call(Hash, "strings", s)) + return unwrap.ArrayOfUTF8Strings(c.invoker.Call(c.hash, "strings", s)) } diff --git a/cli/smartcontract/testdata/types/rpcbindings_dynamic_hash.out b/cli/smartcontract/testdata/types/rpcbindings_dynamic_hash.out new file mode 100755 index 000000000..1075e3260 --- /dev/null +++ b/cli/smartcontract/testdata/types/rpcbindings_dynamic_hash.out @@ -0,0 +1,343 @@ +// Package types contains RPC wrappers for Types contract. +package types + +import ( + "errors" + "fmt" + "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/unwrap" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "math/big" + "unicode/utf8" +) + +// Invoker is used by ContractReader to call various safe methods. +type Invoker interface { + Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) +} + +// ContractReader implements safe contract methods. +type ContractReader struct { + invoker Invoker + hash util.Uint160 +} + +// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. +func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { + return &ContractReader{invoker, hash} +} + +// AAAStrings invokes `aAAStrings` method of contract. +func (c *ContractReader) AAAStrings(s [][][]string) ([][][]string, error) { + return func (item stackitem.Item, err error) ([][][]string, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) ([][][]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([][][]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) ([][]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([][]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) ([]string, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]string, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "aAAStrings", s))) +} + +// Any invokes `any` method of contract. +func (c *ContractReader) Any(a any) (any, error) { + return func (item stackitem.Item, err error) (any, error) { + if err != nil { + return nil, err + } + return item.Value(), error(nil) + } (unwrap.Item(c.invoker.Call(c.hash, "any", a))) +} + +// AnyMaps invokes `anyMaps` method of contract. +func (c *ContractReader) AnyMaps(m map[*big.Int]any) (map[*big.Int]any, error) { + return func (item stackitem.Item, err error) (map[*big.Int]any, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) (map[*big.Int]any, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[*big.Int]any) + for i := range m { + k, err := m[i].Key.TryInteger() + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := m[i].Value.Value(), error(nil) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "anyMaps", m))) +} + +// Bool invokes `bool` method of contract. +func (c *ContractReader) Bool(b bool) (bool, error) { + return unwrap.Bool(c.invoker.Call(c.hash, "bool", b)) +} + +// Bools invokes `bools` method of contract. +func (c *ContractReader) Bools(b []bool) ([]bool, error) { + return unwrap.ArrayOfBools(c.invoker.Call(c.hash, "bools", b)) +} + +// Bytes invokes `bytes` method of contract. +func (c *ContractReader) Bytes(b []byte) ([]byte, error) { + return unwrap.Bytes(c.invoker.Call(c.hash, "bytes", b)) +} + +// Bytess invokes `bytess` method of contract. +func (c *ContractReader) Bytess(b [][]byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "bytess", b)) +} + +// CrazyMaps invokes `crazyMaps` method of contract. +func (c *ContractReader) CrazyMaps(m map[*big.Int][]map[string][]util.Uint160) (map[*big.Int][]map[string][]util.Uint160, error) { + return func (item stackitem.Item, err error) (map[*big.Int][]map[string][]util.Uint160, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) (map[*big.Int][]map[string][]util.Uint160, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[*big.Int][]map[string][]util.Uint160) + for i := range m { + k, err := m[i].Key.TryInteger() + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) ([]map[string][]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]map[string][]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (map[string][]util.Uint160, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string][]util.Uint160) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) ([]util.Uint160, error) { + arr, ok := item.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("not an array") + } + res := make([]util.Uint160, len(arr)) + for i := range res { + res[i], err = func (item stackitem.Item) (util.Uint160, error) { + b, err := item.TryBytes() + if err != nil { + return util.Uint160{}, err + } + u, err := util.Uint160DecodeBytesBE(b) + if err != nil { + return util.Uint160{}, err + } + return u, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (arr[i]) + if err != nil { + return nil, fmt.Errorf("item %d: %w", i, err) + } + } + return res, nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "crazyMaps", m))) +} + +// Hash160 invokes `hash160` method of contract. +func (c *ContractReader) Hash160(h util.Uint160) (util.Uint160, error) { + return unwrap.Uint160(c.invoker.Call(c.hash, "hash160", h)) +} + +// Hash160s invokes `hash160s` method of contract. +func (c *ContractReader) Hash160s(h []util.Uint160) ([]util.Uint160, error) { + return unwrap.ArrayOfUint160(c.invoker.Call(c.hash, "hash160s", h)) +} + +// Hash256 invokes `hash256` method of contract. +func (c *ContractReader) Hash256(h util.Uint256) (util.Uint256, error) { + return unwrap.Uint256(c.invoker.Call(c.hash, "hash256", h)) +} + +// Hash256s invokes `hash256s` method of contract. +func (c *ContractReader) Hash256s(h []util.Uint256) ([]util.Uint256, error) { + return unwrap.ArrayOfUint256(c.invoker.Call(c.hash, "hash256s", h)) +} + +// Int invokes `int` method of contract. +func (c *ContractReader) Int(i *big.Int) (*big.Int, error) { + return unwrap.BigInt(c.invoker.Call(c.hash, "int", i)) +} + +// Ints invokes `ints` method of contract. +func (c *ContractReader) Ints(i []*big.Int) ([]*big.Int, error) { + return unwrap.ArrayOfBigInts(c.invoker.Call(c.hash, "ints", i)) +} + +// Maps invokes `maps` method of contract. +func (c *ContractReader) Maps(m map[string]string) (map[string]string, error) { + return func (item stackitem.Item, err error) (map[string]string, error) { + if err != nil { + return nil, err + } + return func (item stackitem.Item) (map[string]string, error) { + m, ok := item.Value().([]stackitem.MapElement) + if !ok { + return nil, fmt.Errorf("%s is not a map", item.Type().String()) + } + res := make(map[string]string) + for i := range m { + k, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Key) + if err != nil { + return nil, fmt.Errorf("key %d: %w", i, err) + } + v, err := func (item stackitem.Item) (string, error) { + b, err := item.TryBytes() + if err != nil { + return "", err + } + if !utf8.Valid(b) { + return "", errors.New("not a UTF-8 string") + } + return string(b), nil + } (m[i].Value) + if err != nil { + return nil, fmt.Errorf("value %d: %w", i, err) + } + res[k] = v + } + return res, nil + } (item) + } (unwrap.Item(c.invoker.Call(c.hash, "maps", m))) +} + +// PublicKey invokes `publicKey` method of contract. +func (c *ContractReader) PublicKey(k *keys.PublicKey) (*keys.PublicKey, error) { + return unwrap.PublicKey(c.invoker.Call(c.hash, "publicKey", k)) +} + +// PublicKeys invokes `publicKeys` method of contract. +func (c *ContractReader) PublicKeys(k keys.PublicKeys) (keys.PublicKeys, error) { + return unwrap.ArrayOfPublicKeys(c.invoker.Call(c.hash, "publicKeys", k)) +} + +// Signature invokes `signature` method of contract. +func (c *ContractReader) Signature(s []byte) ([]byte, error) { + return unwrap.Bytes(c.invoker.Call(c.hash, "signature", s)) +} + +// Signatures invokes `signatures` method of contract. +func (c *ContractReader) Signatures(s [][]byte) ([][]byte, error) { + return unwrap.ArrayOfBytes(c.invoker.Call(c.hash, "signatures", s)) +} + +// String invokes `string` method of contract. +func (c *ContractReader) String(s string) (string, error) { + return unwrap.UTF8String(c.invoker.Call(c.hash, "string", s)) +} + +// Strings invokes `strings` method of contract. +func (c *ContractReader) Strings(s []string) ([]string, error) { + return unwrap.ArrayOfUTF8Strings(c.invoker.Call(c.hash, "strings", s)) +} diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index 3a01b990c..7aa5904f0 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -32,15 +32,17 @@ type Actor interface { // Contract implements all contract methods. type Contract struct { actor Actor + hash util.Uint160 } // New creates an instance of Contract using Hash and the given Actor. func New(actor Actor) *Contract { - return &Contract{actor} + var hash = Hash + return &Contract{actor, hash} } func scriptForVerify() ([]byte, error) { - return smartcontract.CreateCallWithAssertScript(Hash, "verify") + return smartcontract.CreateCallWithAssertScript(c.hash, "verify") } // Verify creates a transaction invoking `verify` method of the contract. diff --git a/pkg/smartcontract/binding/generate.go b/pkg/smartcontract/binding/generate.go index bd7d42cbc..7e6716908 100644 --- a/pkg/smartcontract/binding/generate.go +++ b/pkg/smartcontract/binding/generate.go @@ -48,8 +48,10 @@ const Hash = "{{ .Hash }}" type ( // Config contains parameter for the generated binding. Config struct { - Package string `yaml:"package,omitempty"` - Manifest *manifest.Manifest `yaml:"-"` + Package string `yaml:"package,omitempty"` + Manifest *manifest.Manifest `yaml:"-"` + // Hash denotes the contract hash and is allowed to be empty for RPC bindings + // generation (if not provided by the user). Hash util.Uint160 `yaml:"hash,omitempty"` Overrides map[string]Override `yaml:"overrides,omitempty"` CallFlags map[string]callflag.CallFlag `yaml:"callflags,omitempty"` @@ -169,9 +171,11 @@ func scTypeToGo(name string, typ smartcontract.ParamType, cfg *Config) (string, // and type conversion function. It assumes manifest to be present in the // configuration and assumes it to be correct (passing IsValid check). func TemplateFromManifest(cfg Config, scTypeConverter func(string, smartcontract.ParamType, *Config) (string, string)) ContractTmpl { - hStr := "" - for _, b := range cfg.Hash.BytesBE() { - hStr += fmt.Sprintf("\\x%02x", b) + var hStr string + if !cfg.Hash.Equals(util.Uint160{}) { + for _, b := range cfg.Hash.BytesBE() { + hStr += fmt.Sprintf("\\x%02x", b) + } } ctr := ContractTmpl{ diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index caf6f4397..d1e835f31 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/binding" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest/standard" + "github.com/nspcc-dev/neo-go/pkg/util" ) // The set of constants containing parts of RPC binding template. Each block of code @@ -39,10 +40,10 @@ func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}} } return {{addIndent (etTypeConverter .ExtendedReturn "item") "\t"}} } ( {{- end -}} {{if .ItemTo -}} itemTo{{ .ItemTo }}( {{- end -}} - unwrap.{{.Unwrapper}}(c.invoker.Call(Hash, "{{ .NameABI }}" + unwrap.{{.Unwrapper}}(c.invoker.Call(c.hash, "{{ .NameABI }}" {{- range $arg := .Arguments -}}, {{.Name}}{{end -}} )) {{- if or .ItemTo (eq .Unwrapper "Item") -}} ) {{- end}} {{- else -}} (*result.Invoke, error) { - c.invoker.Call(Hash, "{{ .NameABI }}" + c.invoker.Call(c.hash, "{{ .NameABI }}" {{- range $arg := .Arguments -}}, {{.Name}}{{end}}) {{- end}} } @@ -53,7 +54,7 @@ func (c *ContractReader) {{.Name}}({{range $index, $arg := .Arguments -}} // number of result items from the iterator right in the VM and return them to // you. It's only limited by VM stack and GAS available for RPC invocations. func (c *ContractReader) {{.Name}}Expanded({{range $index, $arg := .Arguments}}{{.Name}} {{.Type}}, {{end}}_numOfIteratorItems int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.CallAndExpandIterator(Hash, "{{.NameABI}}", _numOfIteratorItems{{range $arg := .Arguments}}, {{.Name}}{{end}})) + return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "{{.NameABI}}", _numOfIteratorItems{{range $arg := .Arguments}}, {{.Name}}{{end}})) } {{ end }}{{ end }}` methodDefinition = `{{ define "METHOD" }}{{ if eq .ReturnType "bool"}} @@ -61,7 +62,7 @@ func scriptFor{{.Name}}({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} {{- .Name}} {{.Type}} {{- end}}) ([]byte, error) { - return smartcontract.CreateCallWithAssertScript(Hash, "{{ .NameABI }}"{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}) + return smartcontract.CreateCallWithAssertScript(c.hash, "{{ .NameABI }}"{{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}) } {{ end }} // {{.Name}} {{.Comment}} @@ -71,7 +72,7 @@ func (c *Contract) {{.Name}}({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} {{- .Name}} {{.Type}} {{- end}}) (util.Uint256, uint32, error) { - {{if ne .ReturnType "bool"}}return c.actor.SendCall(Hash, "{{ .NameABI }}" + {{if ne .ReturnType "bool"}}return c.actor.SendCall(c.hash, "{{ .NameABI }}" {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) if err != nil { return util.Uint256{}, 0, err @@ -86,7 +87,7 @@ func (c *Contract) {{.Name}}Transaction({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} {{- .Name}} {{.Type}} {{- end}}) (*transaction.Transaction, error) { - {{if ne .ReturnType "bool"}}return c.actor.MakeCall(Hash, "{{ .NameABI }}" + {{if ne .ReturnType "bool"}}return c.actor.MakeCall(c.hash, "{{ .NameABI }}" {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) if err != nil { return nil, err @@ -102,7 +103,7 @@ func (c *Contract) {{.Name}}Unsigned({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} {{- .Name}} {{.Type}} {{- end}}) (*transaction.Transaction, error) { - {{if ne .ReturnType "bool"}}return c.actor.MakeUnsignedCall(Hash, "{{ .NameABI }}", nil + {{if ne .ReturnType "bool"}}return c.actor.MakeUnsignedCall(c.hash, "{{ .NameABI }}", nil {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) if err != nil { return nil, err @@ -117,10 +118,11 @@ package {{.PackageName}} import ( {{range $m := .Imports}} "{{ $m }}" {{end}}) - +{{if len .Hash}} // Hash contains contract hash. var Hash = {{ .Hash }} -{{ range $name, $typ := .NamedTypes }} +{{end -}} +{{- range $name, $typ := .NamedTypes }} // {{toTypeName $name}} is a contract-specific {{$name}} type used by its methods. type {{toTypeName $name}} struct { {{- range $m := $typ.Fields}} @@ -175,6 +177,7 @@ type ContractReader struct { {{if .IsNep17}}nep17.TokenReader {{end -}} invoker Invoker + hash util.Uint160 } {{end -}} {{- if .HasWriter}} @@ -189,37 +192,44 @@ type Contract struct { {{if .IsNep17}}nep17.TokenWriter {{end -}} actor Actor + hash util.Uint160 } {{end -}} {{- if .HasReader}} -// NewReader creates an instance of ContractReader using Hash and the given Invoker. -func NewReader(invoker Invoker) *ContractReader { +// NewReader creates an instance of ContractReader using {{if len .Hash -}}Hash{{- else -}}provided contract hash{{- end}} and the given Invoker. +func NewReader(invoker Invoker{{- if not (len .Hash) -}}, hash util.Uint160{{- end -}}) *ContractReader { + {{if len .Hash -}} + var hash = Hash + {{end -}} return &ContractReader{ - {{- if .IsNep11D}}*nep11.NewDivisibleReader(invoker, Hash), {{end}} - {{- if .IsNep11ND}}*nep11.NewNonDivisibleReader(invoker, Hash), {{end}} - {{- if .IsNep17}}*nep17.NewReader(invoker, Hash), {{end -}} - invoker} + {{- if .IsNep11D}}*nep11.NewDivisibleReader(invoker, hash), {{end}} + {{- if .IsNep11ND}}*nep11.NewNonDivisibleReader(invoker, hash), {{end}} + {{- if .IsNep17}}*nep17.NewReader(invoker, hash), {{end -}} + invoker, hash} } {{end -}} {{- if .HasWriter}} -// New creates an instance of Contract using Hash and the given Actor. -func New(actor Actor) *Contract { - {{if .IsNep11D}}var nep11dt = nep11.NewDivisible(actor, Hash) +// New creates an instance of Contract using {{if len .Hash -}}Hash{{- else -}}provided contract hash{{- end}} and the given Actor. +func New(actor Actor{{- if not (len .Hash) -}}, hash util.Uint160{{- end -}}) *Contract { + {{if len .Hash -}} + var hash = Hash {{end -}} - {{if .IsNep11ND}}var nep11ndt = nep11.NewNonDivisible(actor, Hash) + {{if .IsNep11D}}var nep11dt = nep11.NewDivisible(actor, hash) {{end -}} - {{if .IsNep17}}var nep17t = nep17.New(actor, Hash) + {{if .IsNep11ND}}var nep11ndt = nep11.NewNonDivisible(actor, hash) + {{end -}} + {{if .IsNep17}}var nep17t = nep17.New(actor, hash) {{end -}} return &Contract{ {{- if .HasReader}}ContractReader{ {{- if .IsNep11D}}nep11dt.DivisibleReader, {{end -}} {{- if .IsNep11ND}}nep11ndt.NonDivisibleReader, {{end -}} {{- if .IsNep17}}nep17t.TokenReader, {{end -}} - actor}, {{end -}} + actor, hash}, {{end -}} {{- if .IsNep11D}}nep11dt.DivisibleWriter, {{end -}} {{- if .IsNep11ND}}nep11ndt.BaseWriter, {{end -}} {{- if .IsNep17}}nep17t.TokenWriter, {{end -}} - actor} + actor, hash} } {{end -}} {{- range $m := .SafeMethods }}{{template "SAFEMETHOD" $m }}{{ end -}} @@ -660,7 +670,9 @@ func scTemplateToRPC(cfg binding.Config, ctr ContractTmpl, imports map[string]st for i := range ctr.Imports { imports[ctr.Imports[i]] = struct{}{} } - ctr.Hash = fmt.Sprintf("%#v", cfg.Hash) + if !cfg.Hash.Equals(util.Uint160{}) { + ctr.Hash = fmt.Sprintf("%#v", cfg.Hash) + } for i := 0; i < len(ctr.Methods); i++ { abim := cfg.Manifest.ABI.GetMethod(ctr.Methods[i].NameABI, len(ctr.Methods[i].Arguments)) if abim.Safe { From 67ce9de181024fa89f8c140c3003a33774c6abc4 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 5 Jun 2023 14:58:17 +0300 Subject: [PATCH 101/125] go.mod: upgrade bolt to v1.3.7 Refs. nspcc-dev/neofs-node#999, it fixes a number of other Windows-related issues as well. Signed-off-by: Roman Khimov --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 10305632c..03aa9cbdc 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 github.com/twmb/murmur3 v1.1.5 github.com/urfave/cli v1.22.5 - go.etcd.io/bbolt v1.3.6 + go.etcd.io/bbolt v1.3.7 go.uber.org/atomic v1.10.0 go.uber.org/zap v1.24.0 golang.org/x/crypto v0.4.0 diff --git a/go.sum b/go.sum index a49806751..3c05214ff 100644 --- a/go.sum +++ b/go.sum @@ -309,8 +309,8 @@ github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -459,7 +459,6 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From c7836ed6e71d48eb797f4de421068bc4914e5a8f Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 5 Jun 2023 17:47:17 +0300 Subject: [PATCH 102/125] rpcbinding: convert `scriptFor*` from function to method Should be a part of #3012, otherwise generated bindings are failed to be compiled. Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/nameservice/nns.go | 2 +- cli/smartcontract/testdata/verifyrpc/verify.go | 2 +- pkg/smartcontract/rpcbinding/binding.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index da5f0311a..1578cf184 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -194,7 +194,7 @@ func (c *Contract) SetPriceUnsigned(priceList []any) (*transaction.Transaction, return c.actor.MakeUnsignedCall(c.hash, "setPrice", nil, priceList) } -func scriptForRegister(name string, owner util.Uint160) ([]byte, error) { +func (c *Contract) scriptForRegister(name string, owner util.Uint160) ([]byte, error) { return smartcontract.CreateCallWithAssertScript(c.hash, "register", name, owner) } diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index 7aa5904f0..938630a39 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -41,7 +41,7 @@ func New(actor Actor) *Contract { return &Contract{actor, hash} } -func scriptForVerify() ([]byte, error) { +func (c *Contract) scriptForVerify() ([]byte, error) { return smartcontract.CreateCallWithAssertScript(c.hash, "verify") } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index d1e835f31..376dadd0d 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -58,7 +58,7 @@ func (c *ContractReader) {{.Name}}Expanded({{range $index, $arg := .Arguments}}{ } {{ end }}{{ end }}` methodDefinition = `{{ define "METHOD" }}{{ if eq .ReturnType "bool"}} -func scriptFor{{.Name}}({{range $index, $arg := .Arguments -}} +func (c *Contract) scriptFor{{.Name}}({{range $index, $arg := .Arguments -}} {{- if ne $index 0}}, {{end}} {{- .Name}} {{.Type}} {{- end}}) ([]byte, error) { From 802a2b3879c8a884769e13e781ec3bbcd4b3931d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 5 Jun 2023 17:47:17 +0300 Subject: [PATCH 103/125] rpcbinding: call `scriptFor*` as method Should be a part of #3035, otherwise generated bindings are failed to be compiled. Signed-off-by: Anna Shaleva --- cli/smartcontract/testdata/nameservice/nns.go | 6 +++--- cli/smartcontract/testdata/verifyrpc/verify.go | 6 +++--- pkg/smartcontract/rpcbinding/binding.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cli/smartcontract/testdata/nameservice/nns.go b/cli/smartcontract/testdata/nameservice/nns.go index 1578cf184..97bd878a3 100644 --- a/cli/smartcontract/testdata/nameservice/nns.go +++ b/cli/smartcontract/testdata/nameservice/nns.go @@ -202,7 +202,7 @@ func (c *Contract) scriptForRegister(name string, owner util.Uint160) ([]byte, e // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Register(name string, owner util.Uint160) (util.Uint256, uint32, error) { - script, err := scriptForRegister(name, owner) + script, err := c.scriptForRegister(name, owner) if err != nil { return util.Uint256{}, 0, err } @@ -213,7 +213,7 @@ func (c *Contract) Register(name string, owner util.Uint160) (util.Uint256, uint // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) RegisterTransaction(name string, owner util.Uint160) (*transaction.Transaction, error) { - script, err := scriptForRegister(name, owner) + script, err := c.scriptForRegister(name, owner) if err != nil { return nil, err } @@ -225,7 +225,7 @@ func (c *Contract) RegisterTransaction(name string, owner util.Uint160) (*transa // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) RegisterUnsigned(name string, owner util.Uint160) (*transaction.Transaction, error) { - script, err := scriptForRegister(name, owner) + script, err := c.scriptForRegister(name, owner) if err != nil { return nil, err } diff --git a/cli/smartcontract/testdata/verifyrpc/verify.go b/cli/smartcontract/testdata/verifyrpc/verify.go index 938630a39..6a755aec0 100644 --- a/cli/smartcontract/testdata/verifyrpc/verify.go +++ b/cli/smartcontract/testdata/verifyrpc/verify.go @@ -49,7 +49,7 @@ func (c *Contract) scriptForVerify() ([]byte, error) { // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. func (c *Contract) Verify() (util.Uint256, uint32, error) { - script, err := scriptForVerify() + script, err := c.scriptForVerify() if err != nil { return util.Uint256{}, 0, err } @@ -60,7 +60,7 @@ func (c *Contract) Verify() (util.Uint256, uint32, error) { // This transaction is signed, but not sent to the network, instead it's // returned to the caller. func (c *Contract) VerifyTransaction() (*transaction.Transaction, error) { - script, err := scriptForVerify() + script, err := c.scriptForVerify() if err != nil { return nil, err } @@ -72,7 +72,7 @@ func (c *Contract) VerifyTransaction() (*transaction.Transaction, error) { // Any fields of it that do not affect fees can be changed (ValidUntilBlock, // Nonce), fee values (NetworkFee, SystemFee) can be increased as well. func (c *Contract) VerifyUnsigned() (*transaction.Transaction, error) { - script, err := scriptForVerify() + script, err := c.scriptForVerify() if err != nil { return nil, err } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 376dadd0d..697682b63 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -73,7 +73,7 @@ func (c *Contract) {{.Name}}({{range $index, $arg := .Arguments -}} {{- .Name}} {{.Type}} {{- end}}) (util.Uint256, uint32, error) { {{if ne .ReturnType "bool"}}return c.actor.SendCall(c.hash, "{{ .NameABI }}" - {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) + {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := c.scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) if err != nil { return util.Uint256{}, 0, err } @@ -88,7 +88,7 @@ func (c *Contract) {{.Name}}Transaction({{range $index, $arg := .Arguments -}} {{- .Name}} {{.Type}} {{- end}}) (*transaction.Transaction, error) { {{if ne .ReturnType "bool"}}return c.actor.MakeCall(c.hash, "{{ .NameABI }}" - {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) + {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := c.scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) if err != nil { return nil, err } @@ -104,7 +104,7 @@ func (c *Contract) {{.Name}}Unsigned({{range $index, $arg := .Arguments -}} {{- .Name}} {{.Type}} {{- end}}) (*transaction.Transaction, error) { {{if ne .ReturnType "bool"}}return c.actor.MakeUnsignedCall(c.hash, "{{ .NameABI }}", nil - {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) + {{- range $index, $arg := .Arguments -}}, {{.Name}}{{end}}){{else}}script, err := c.scriptFor{{.Name}}({{- range $index, $arg := .Arguments -}}{{- if ne $index 0}}, {{end}}{{.Name}}{{end}}) if err != nil { return nil, err } From 4b2fc32462576cdb7bbb4f9b319f95550b39250a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 6 Jun 2023 11:22:08 +0300 Subject: [PATCH 104/125] oracle: update NeoFS SDK to 1.0.0-rc.9 Signed-off-by: Anna Shaleva --- go.mod | 6 ++--- go.sum | 13 +++++----- pkg/services/oracle/neofs/neofs.go | 40 +++++++++++------------------- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index 03aa9cbdc..2077e04f8 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a - github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8 + github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.9 github.com/nspcc-dev/rfc6979 v0.2.0 github.com/pierrec/lz4 v2.6.1+incompatible github.com/pmezard/go-difflib v1.0.0 @@ -49,7 +49,7 @@ require ( github.com/nspcc-dev/hrw v1.0.9 // indirect github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 // indirect github.com/nspcc-dev/neofs-crypto v0.4.0 // indirect - github.com/nspcc-dev/tzhash v1.6.1 // indirect + github.com/nspcc-dev/tzhash v1.7.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.37.0 // indirect @@ -62,7 +62,7 @@ require ( golang.org/x/mod v0.6.0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.5.0 // indirect + golang.org/x/sys v0.8.0 // indirect google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect google.golang.org/grpc v1.48.0 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index 3c05214ff..924752114 100644 --- a/go.sum +++ b/go.sum @@ -223,12 +223,12 @@ github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkb github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8 h1:bsg3o7Oiae2xHYAs1M5yg8GDOs46x/IW5jCh/4dt8uo= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.8/go.mod h1:kq/KoRhj/Ye8b7ctykiXej42Kq09lUg2E5FXGCbLOWs= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.9 h1:uIQlWUUo5n/e8rLFGm14zIValcpXU1HWuwaoXUAHt5Q= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.9/go.mod h1:fTsdTU/M9rvv/f9jlp7vHOm3DRp+NSfjfTv9NohrKTE= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= -github.com/nspcc-dev/tzhash v1.6.1 h1:8dUrWFpjkmoHF+7GxuGUmarj9LLHWFcuyF3CTrqq9JE= -github.com/nspcc-dev/tzhash v1.6.1/go.mod h1:BoflzCVp+DO/f1mvbcsJQWoFzidIFBhWFZMglbUW648= +github.com/nspcc-dev/tzhash v1.7.0 h1:/+aL33NC7y5OIGnY2kYgjZt8mg7LVGFMdj/KAJLndnk= +github.com/nspcc-dev/tzhash v1.7.0/go.mod h1:Dnx9LUlOLr5paL2Rtc96x0PPs8D9eIkUtowt1n+KQus= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -468,8 +468,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= @@ -635,7 +635,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/services/oracle/neofs/neofs.go b/pkg/services/oracle/neofs/neofs.go index 771e92404..044fb2904 100644 --- a/pkg/services/oracle/neofs/neofs.go +++ b/pkg/services/oracle/neofs/neofs.go @@ -53,11 +53,15 @@ func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string, re return nil, err } - var c = new(client.Client) - var prmi client.PrmInit - prmi.ResolveNeoFSFailures() + var ( + prmi client.PrmInit + c *client.Client + ) prmi.SetDefaultSigner(neofsecdsa.Signer(priv.PrivateKey)) - c.Init(prmi) + c, err = client.New(prmi) + if err != nil { + return nil, fmt.Errorf("failed to create client: %w", err) + } var prmd client.PrmDial prmd.SetServerURI(addr) @@ -109,11 +113,7 @@ func parseNeoFSURL(u *url.URL) (*oid.Address, []string, error) { } func getPayload(ctx context.Context, c *client.Client, addr *oid.Address, resReader ResultReader) ([]byte, error) { - var getPrm client.PrmObjectGet - getPrm.FromContainer(addr.Container()) - getPrm.ByID(addr.Object()) - - objR, err := c.ObjectGetInit(ctx, getPrm) + objR, err := c.ObjectGetInit(ctx, addr.Container(), addr.Object(), client.PrmObjectGet{}) if err != nil { return nil, err } @@ -121,7 +121,7 @@ func getPayload(ctx context.Context, c *client.Client, addr *oid.Address, resRea if err != nil { return nil, err } - _, err = objR.Close() // Using ResolveNeoFSFailures. + err = objR.Close() if err != nil { return nil, err } @@ -137,13 +137,8 @@ func getRange(ctx context.Context, c *client.Client, addr *oid.Address, resReade if err != nil { return nil, err } - var rangePrm client.PrmObjectRange - rangePrm.FromContainer(addr.Container()) - rangePrm.ByID(addr.Object()) - rangePrm.SetLength(r.GetLength()) - rangePrm.SetOffset(r.GetOffset()) - rangeR, err := c.ObjectRangeInit(ctx, rangePrm) + rangeR, err := c.ObjectRangeInit(ctx, addr.Container(), addr.Object(), r.GetOffset(), r.GetLength(), client.PrmObjectRange{}) if err != nil { return nil, err } @@ -151,7 +146,7 @@ func getRange(ctx context.Context, c *client.Client, addr *oid.Address, resReade if err != nil { return nil, err } - _, err = rangeR.Close() // Using ResolveNeoFSFailures. + err = rangeR.Close() if err != nil { return nil, err } @@ -160,11 +155,7 @@ func getRange(ctx context.Context, c *client.Client, addr *oid.Address, resReade } func getObjHeader(ctx context.Context, c *client.Client, addr *oid.Address) (*object.Object, error) { - var headPrm client.PrmObjectHead - headPrm.FromContainer(addr.Container()) - headPrm.ByID(addr.Object()) - - res, err := c.ObjectHead(ctx, headPrm) + res, err := c.ObjectHead(ctx, addr.Container(), addr.Object(), client.PrmObjectHead{}) if err != nil { return nil, err } @@ -200,15 +191,12 @@ func getHash(ctx context.Context, c *client.Client, addr *oid.Address, ps ...str return nil, err } var hashPrm client.PrmObjectHash - hashPrm.FromContainer(addr.Container()) - hashPrm.ByID(addr.Object()) hashPrm.SetRangeList(r.GetOffset(), r.GetLength()) - res, err := c.ObjectHash(ctx, hashPrm) + hashes, err := c.ObjectHash(ctx, addr.Container(), addr.Object(), hashPrm) if err != nil { return nil, err } - hashes := res.Checksums() // Using ResolveNeoFSFailures. if len(hashes) == 0 { return nil, fmt.Errorf("%w: empty response", ErrInvalidRange) } From 0d470edf2158e80f1a45e8a3d9c99c6d11ece5c6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 6 Jun 2023 12:19:23 +0300 Subject: [PATCH 105/125] oracle: make use of ReadCloser returned from NeoFS's getters Close #3032. Signed-off-by: Anna Shaleva --- pkg/services/oracle/neofs/neofs.go | 92 ++++++++++++++---------------- pkg/services/oracle/request.go | 25 +++----- pkg/services/oracle/response.go | 21 +++++-- 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/pkg/services/oracle/neofs/neofs.go b/pkg/services/oracle/neofs/neofs.go index 044fb2904..d7a701534 100644 --- a/pkg/services/oracle/neofs/neofs.go +++ b/pkg/services/oracle/neofs/neofs.go @@ -1,6 +1,7 @@ package neofs import ( + "bytes" "context" "errors" "fmt" @@ -18,10 +19,6 @@ import ( oid "github.com/nspcc-dev/neofs-sdk-go/object/id" ) -// ResultReader is a function that reads required amount of data and -// checks it. -type ResultReader func(io.Reader) ([]byte, error) - const ( // URIScheme is the name of neofs URI scheme. URIScheme = "neofs" @@ -47,7 +44,7 @@ var ( // Get returns a neofs object from the provided url. // URI scheme is "neofs://". // If Command is not provided, full object is requested. -func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string, resReader ResultReader) ([]byte, error) { +func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string) (io.ReadCloser, error) { objectAddr, ps, err := parseNeoFSURL(u) if err != nil { return nil, err @@ -63,27 +60,44 @@ func Get(ctx context.Context, priv *keys.PrivateKey, u *url.URL, addr string, re return nil, fmt.Errorf("failed to create client: %w", err) } - var prmd client.PrmDial + var ( + res = clientCloseWrapper{c: c} + prmd client.PrmDial + ) prmd.SetServerURI(addr) prmd.SetContext(ctx) err = c.Dial(prmd) //nolint:contextcheck // contextcheck: Function `Dial->Balance->SendUnary->Init->setNeoFSAPIServer` should pass the context parameter if err != nil { - return nil, err + return res, err } - defer c.Close() switch { case len(ps) == 0 || ps[0] == "": // Get request - return getPayload(ctx, c, objectAddr, resReader) + res.ReadCloser, err = getPayload(ctx, c, objectAddr) case ps[0] == rangeCmd: - return getRange(ctx, c, objectAddr, resReader, ps[1:]...) + res.ReadCloser, err = getRange(ctx, c, objectAddr, ps[1:]...) case ps[0] == headerCmd: - return getHeader(ctx, c, objectAddr) + res.ReadCloser, err = getHeader(ctx, c, objectAddr) case ps[0] == hashCmd: - return getHash(ctx, c, objectAddr, ps[1:]...) + res.ReadCloser, err = getHash(ctx, c, objectAddr, ps[1:]...) default: - return nil, ErrInvalidCommand + err = ErrInvalidCommand } + return res, err +} + +type clientCloseWrapper struct { + io.ReadCloser + c *client.Client +} + +func (w clientCloseWrapper) Close() error { + var res error + if w.ReadCloser != nil { + res = w.ReadCloser.Close() + } + w.c.Close() + return res } // parseNeoFSURL returns parsed neofs address. @@ -112,24 +126,11 @@ func parseNeoFSURL(u *url.URL) (*oid.Address, []string, error) { return objAddr, ps[2:], nil } -func getPayload(ctx context.Context, c *client.Client, addr *oid.Address, resReader ResultReader) ([]byte, error) { - objR, err := c.ObjectGetInit(ctx, addr.Container(), addr.Object(), client.PrmObjectGet{}) - if err != nil { - return nil, err - } - resp, err := resReader(objR) - if err != nil { - return nil, err - } - err = objR.Close() - if err != nil { - return nil, err - } - - return resp, nil +func getPayload(ctx context.Context, c *client.Client, addr *oid.Address) (io.ReadCloser, error) { + return c.ObjectGetInit(ctx, addr.Container(), addr.Object(), client.PrmObjectGet{}) } -func getRange(ctx context.Context, c *client.Client, addr *oid.Address, resReader ResultReader, ps ...string) ([]byte, error) { +func getRange(ctx context.Context, c *client.Client, addr *oid.Address, ps ...string) (io.ReadCloser, error) { if len(ps) == 0 { return nil, ErrInvalidRange } @@ -138,20 +139,7 @@ func getRange(ctx context.Context, c *client.Client, addr *oid.Address, resReade return nil, err } - rangeR, err := c.ObjectRangeInit(ctx, addr.Container(), addr.Object(), r.GetOffset(), r.GetLength(), client.PrmObjectRange{}) - if err != nil { - return nil, err - } - resp, err := resReader(rangeR) - if err != nil { - return nil, err - } - err = rangeR.Close() - if err != nil { - return nil, err - } - - return resp, nil + return c.ObjectRangeInit(ctx, addr.Container(), addr.Object(), r.GetOffset(), r.GetLength(), client.PrmObjectRange{}) } func getObjHeader(ctx context.Context, c *client.Client, addr *oid.Address) (*object.Object, error) { @@ -166,15 +154,19 @@ func getObjHeader(ctx context.Context, c *client.Client, addr *oid.Address) (*ob return obj, nil } -func getHeader(ctx context.Context, c *client.Client, addr *oid.Address) ([]byte, error) { +func getHeader(ctx context.Context, c *client.Client, addr *oid.Address) (io.ReadCloser, error) { obj, err := getObjHeader(ctx, c, addr) if err != nil { return nil, err } - return obj.MarshalHeaderJSON() + res, err := obj.MarshalHeaderJSON() + if err != nil { + return nil, err + } + return io.NopCloser(bytes.NewReader(res)), nil } -func getHash(ctx context.Context, c *client.Client, addr *oid.Address, ps ...string) ([]byte, error) { +func getHash(ctx context.Context, c *client.Client, addr *oid.Address, ps ...string) (io.ReadCloser, error) { if len(ps) == 0 || ps[0] == "" { // hash of the full payload obj, err := getObjHeader(ctx, c, addr) if err != nil { @@ -184,7 +176,7 @@ func getHash(ctx context.Context, c *client.Client, addr *oid.Address, ps ...str if !flag { return nil, errors.New("missing checksum in the reply") } - return sum.Value(), nil + return io.NopCloser(bytes.NewReader(sum.Value())), nil } r, err := parseRange(ps[0]) if err != nil { @@ -204,7 +196,11 @@ func getHash(ctx context.Context, c *client.Client, addr *oid.Address, ps ...str if err != nil { return nil, fmt.Errorf("decode Uint256: %w", err) } - return u256.MarshalJSON() + res, err := u256.MarshalJSON() + if err != nil { + return nil, err + } + return io.NopCloser(bytes.NewReader(res)), nil } func parseRange(s string) (*object.Range, error) { diff --git a/pkg/services/oracle/request.go b/pkg/services/oracle/request.go index a8bd75490..6267f55d0 100644 --- a/pkg/services/oracle/request.go +++ b/pkg/services/oracle/request.go @@ -146,16 +146,7 @@ func (o *Oracle) processRequest(priv *keys.PrivateKey, req request) error { break } - resp.Result, err = readResponse(r.Body) - if err != nil { - if errors.Is(err, ErrResponseTooLarge) { - resp.Code = transaction.ResponseTooLarge - } else { - resp.Code = transaction.Error - } - o.Log.Warn("failed to read data for oracle request", zap.String("url", req.Req.URL), zap.Error(err)) - break - } + resp.Result, resp.Code = o.readResponse(r.Body, req.Req.URL) case http.StatusForbidden: resp.Code = transaction.Forbidden case http.StatusNotFound: @@ -169,15 +160,17 @@ func (o *Oracle) processRequest(priv *keys.PrivateKey, req request) error { ctx, cancel := context.WithTimeout(context.Background(), o.MainCfg.NeoFS.Timeout) defer cancel() index := (int(req.ID) + incTx.attempts) % len(o.MainCfg.NeoFS.Nodes) - resp.Result, err = neofs.Get(ctx, priv, u, o.MainCfg.NeoFS.Nodes[index], readResponse) + rc, err := neofs.Get(ctx, priv, u, o.MainCfg.NeoFS.Nodes[index]) if err != nil { - if errors.Is(err, ErrResponseTooLarge) { - resp.Code = transaction.ResponseTooLarge - } else { - resp.Code = transaction.Error + resp.Code = transaction.Error + o.Log.Warn("failed to perform oracle request", zap.String("url", req.Req.URL), zap.Error(err)) + if rc != nil { + rc.Close() // intentionally skip the closing error, make it unified with Oracle `https` protocol. } - o.Log.Warn("oracle request failed", zap.String("url", req.Req.URL), zap.Error(err)) + break } + resp.Result, resp.Code = o.readResponse(rc, req.Req.URL) + rc.Close() // intentionally skip the closing error, make it unified with Oracle `https` protocol. default: resp.Code = transaction.ProtocolNotSupported o.Log.Warn("unknown oracle request scheme", zap.String("url", req.Req.URL)) diff --git a/pkg/services/oracle/response.go b/pkg/services/oracle/response.go index 6b1563e84..06062941e 100644 --- a/pkg/services/oracle/response.go +++ b/pkg/services/oracle/response.go @@ -68,17 +68,30 @@ func (o *Oracle) AddResponse(pub *keys.PublicKey, reqID uint64, txSig []byte) { // ErrResponseTooLarge is returned when a response exceeds the max allowed size. var ErrResponseTooLarge = errors.New("too big response") -func readResponse(rc gio.Reader) ([]byte, error) { +func (o *Oracle) readResponse(rc gio.Reader, url string) ([]byte, transaction.OracleResponseCode) { const limit = transaction.MaxOracleResultSize buf := make([]byte, limit+1) n, err := gio.ReadFull(rc, buf) if errors.Is(err, gio.ErrUnexpectedEOF) && n <= limit { - return checkUTF8(buf[:n]) + res, err := checkUTF8(buf[:n]) + return o.handleResponseError(res, err, url) } if err == nil || n > limit { - return nil, ErrResponseTooLarge + return o.handleResponseError(nil, ErrResponseTooLarge, url) } - return nil, err + + return o.handleResponseError(nil, err, url) +} + +func (o *Oracle) handleResponseError(data []byte, err error, url string) ([]byte, transaction.OracleResponseCode) { + if err != nil { + o.Log.Warn("failed to read data for oracle request", zap.String("url", url), zap.Error(err)) + if errors.Is(err, ErrResponseTooLarge) { + return nil, transaction.ResponseTooLarge + } + return nil, transaction.Error + } + return data, transaction.Success } func checkUTF8(v []byte) ([]byte, error) { From 71bcb8bade4175af42b92e967a77608a4592110c Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 14 Jun 2023 16:42:11 +0300 Subject: [PATCH 106/125] native: allow to use EQUAL opcode for BLS12-381 points comparison That's the way how C# node handles equality checks for stackitem.Interop types for these points. Ref. https://github.com/nspcc-dev/neo-go/issues/3002#issuecomment-1591220501. Along the way, add GT case for CryptoLib's bls12381Equal method. It should be there since #2940. Signed-off-by: Anna Shaleva --- pkg/core/native/crypto.go | 112 +++++--------- pkg/core/native/crypto_blspoints.go | 104 +++++++++++++ pkg/core/native/native_test/cryptolib_test.go | 140 +++++++++++++----- pkg/vm/stackitem/item.go | 14 +- pkg/vm/vm_test.go | 14 ++ 5 files changed, 275 insertions(+), 109 deletions(-) create mode 100644 pkg/core/native/crypto_blspoints.go diff --git a/pkg/core/native/crypto.go b/pkg/core/native/crypto.go index 2d8afc524..f92554867 100644 --- a/pkg/core/native/crypto.go +++ b/pkg/core/native/crypto.go @@ -178,32 +178,11 @@ func curveFromStackitem(si stackitem.Item) (elliptic.Curve, error) { } func (c *Crypto) bls12381Serialize(_ *interop.Context, args []stackitem.Item) stackitem.Item { - val := args[0].(*stackitem.Interop).Value() - var res []byte - switch p := val.(type) { - case *bls12381.G1Affine: - compressed := p.Bytes() - res = compressed[:] - case *bls12381.G1Jac: - g1Affine := new(bls12381.G1Affine) - g1Affine.FromJacobian(p) - compressed := g1Affine.Bytes() - res = compressed[:] - case *bls12381.G2Affine: - compressed := p.Bytes() - res = compressed[:] - case *bls12381.G2Jac: - g2Affine := new(bls12381.G2Affine) - g2Affine.FromJacobian(p) - compressed := g2Affine.Bytes() - res = compressed[:] - case *bls12381.GT: - compressed := p.Bytes() - res = compressed[:] - default: - panic(errors.New("unknown bls12381 point type")) + val, ok := args[0].(*stackitem.Interop).Value().(blsPoint) + if !ok { + panic(errors.New("not a bls12381 point")) } - return stackitem.NewByteArray(res) + return stackitem.NewByteArray(val.Bytes()) } func (c *Crypto) bls12381Deserialize(_ *interop.Context, args []stackitem.Item) stackitem.Item { @@ -235,51 +214,32 @@ func (c *Crypto) bls12381Deserialize(_ *interop.Context, args []stackitem.Item) } res = gt } - return stackitem.NewInterop(res) + return stackitem.NewInterop(blsPoint{point: res}) } func (c *Crypto) bls12381Equal(_ *interop.Context, args []stackitem.Item) stackitem.Item { - a := args[0].(*stackitem.Interop).Value() - b := args[1].(*stackitem.Interop).Value() - var res bool - switch x := a.(type) { - case *bls12381.G1Affine: - y, ok := b.(*bls12381.G1Affine) - if !ok { - panic(errors.New("y is not bls12381 G1Affine point")) - } - res = x.Equal(y) - case *bls12381.G1Jac: - y, ok := b.(*bls12381.G1Jac) - if !ok { - panic(errors.New("y is not bls12381 G1Jac point")) - } - res = x.Equal(y) - case *bls12381.G2Affine: - y, ok := b.(*bls12381.G2Affine) - if !ok { - panic(errors.New("y is not bls12381 G2Affine point")) - } - res = x.Equal(y) - case *bls12381.G2Jac: - y, ok := b.(*bls12381.G2Jac) - if !ok { - panic(errors.New("y is not bls12381 G2Jac point")) - } - res = x.Equal(y) - default: - panic(fmt.Errorf("unexpected x bls12381 point type: %T", x)) + a, okA := args[0].(*stackitem.Interop).Value().(blsPoint) + b, okB := args[1].(*stackitem.Interop).Value().(blsPoint) + if !(okA && okB) { + panic("some of the arguments are not a bls12381 point") + } + res, err := a.EqualsCheckType(b) + if err != nil { + panic(err) } return stackitem.NewBool(res) } func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackitem.Item { - a := args[0].(*stackitem.Interop).Value() - b := args[1].(*stackitem.Interop).Value() + a, okA := args[0].(*stackitem.Interop).Value().(blsPoint) + b, okB := args[1].(*stackitem.Interop).Value().(blsPoint) + if !(okA && okB) { + panic("some of the arguments are not a bls12381 point") + } var res interface{} - switch x := a.(type) { + switch x := a.point.(type) { case *bls12381.G1Affine: - switch y := b.(type) { + switch y := b.point.(type) { case *bls12381.G1Affine: xJac := new(bls12381.G1Jac) xJac.FromAffine(x) @@ -296,7 +256,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite case *bls12381.G1Jac: resJac := new(bls12381.G1Jac) resJac.Set(x) - switch y := b.(type) { + switch y := b.point.(type) { case *bls12381.G1Affine: resJac.AddMixed(y) case *bls12381.G1Jac: @@ -306,7 +266,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite } res = resJac case *bls12381.G2Affine: - switch y := b.(type) { + switch y := b.point.(type) { case *bls12381.G2Affine: xJac := new(bls12381.G2Jac) xJac.FromAffine(x) @@ -323,7 +283,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite case *bls12381.G2Jac: resJac := new(bls12381.G2Jac) resJac.Set(x) - switch y := b.(type) { + switch y := b.point.(type) { case *bls12381.G2Affine: resJac.AddMixed(y) case *bls12381.G2Jac: @@ -335,7 +295,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite case *bls12381.GT: resGT := new(bls12381.GT) resGT.Set(x) - switch y := b.(type) { + switch y := b.point.(type) { case *bls12381.GT: // It's multiplication, see https://github.com/neo-project/Neo.Cryptography.BLS12_381/issues/4. resGT.Mul(x, y) @@ -346,7 +306,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite default: panic(fmt.Errorf("unexpected bls12381 point type: %T", x)) } - return stackitem.NewInterop(res) + return stackitem.NewInterop(blsPoint{point: res}) } func scalarFromBytes(bytes []byte, neg bool) (*fr.Element, error) { @@ -368,7 +328,10 @@ func scalarFromBytes(bytes []byte, neg bool) (*fr.Element, error) { } func (c *Crypto) bls12381Mul(_ *interop.Context, args []stackitem.Item) stackitem.Item { - a := args[0].(*stackitem.Interop).Value() + a, okA := args[0].(*stackitem.Interop).Value().(blsPoint) + if !okA { + panic("multiplier is not a bls12381 point") + } mulBytes, err := args[1].TryBytes() if err != nil { panic(fmt.Errorf("invalid multiplier: %w", err)) @@ -385,7 +348,7 @@ func (c *Crypto) bls12381Mul(_ *interop.Context, args []stackitem.Item) stackite alpha.BigInt(alphaBi) var res interface{} - switch x := a.(type) { + switch x := a.point.(type) { case *bls12381.G1Affine: // The result is in Jacobian form in the reference implementation. g1Jac := new(bls12381.G1Jac) @@ -423,17 +386,20 @@ func (c *Crypto) bls12381Mul(_ *interop.Context, args []stackitem.Item) stackite default: panic(fmt.Errorf("unexpected bls12381 point type: %T", x)) } - return stackitem.NewInterop(res) + return stackitem.NewInterop(blsPoint{point: res}) } func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stackitem.Item { - a := args[0].(*stackitem.Interop).Value() - b := args[1].(*stackitem.Interop).Value() + a, okA := args[0].(*stackitem.Interop).Value().(blsPoint) + b, okB := args[1].(*stackitem.Interop).Value().(blsPoint) + if !(okA && okB) { + panic("some of the arguments are not a bls12381 point") + } var ( x *bls12381.G1Affine y *bls12381.G2Affine ) - switch p := a.(type) { + switch p := a.point.(type) { case *bls12381.G1Affine: x = p case *bls12381.G1Jac: @@ -442,7 +408,7 @@ func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stac default: panic(fmt.Errorf("unexpected bls12381 point type (g1): %T", x)) } - switch p := b.(type) { + switch p := b.point.(type) { case *bls12381.G2Affine: y = p case *bls12381.G2Jac: @@ -455,7 +421,7 @@ func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stac if err != nil { panic(fmt.Errorf("failed to perform pairing operation")) } - return stackitem.NewInterop(interface{}(>)) + return stackitem.NewInterop(blsPoint{>}) } // Metadata implements the Contract interface. diff --git a/pkg/core/native/crypto_blspoints.go b/pkg/core/native/crypto_blspoints.go new file mode 100644 index 000000000..f1ef4ceb9 --- /dev/null +++ b/pkg/core/native/crypto_blspoints.go @@ -0,0 +1,104 @@ +package native + +import ( + "errors" + "fmt" + + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +// blsPoint is a wrapper around bls12381 point types that must be used as +// stackitem.Interop values and implement stackitem.Equatable interface. +type blsPoint struct { + point any +} + +var _ = stackitem.Equatable(blsPoint{}) + +// Equals implements stackitem.Equatable interface. +func (p blsPoint) Equals(other stackitem.Equatable) bool { + res, err := p.EqualsCheckType(other) + return err == nil && res +} + +// EqualsCheckType checks whether other is of the same type as p and returns an error if not. +// It also returns whether other and p are equal. +func (p blsPoint) EqualsCheckType(other stackitem.Equatable) (bool, error) { + b, ok := other.(blsPoint) + if !ok { + return false, errors.New("not a bls12-381 point") + } + var ( + res bool + err error + ) + switch x := p.point.(type) { + case *bls12381.G1Affine: + y, ok := b.point.(*bls12381.G1Affine) + if !ok { + err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G1Affine", y) + break + } + res = x.Equal(y) + case *bls12381.G1Jac: + y, ok := b.point.(*bls12381.G1Jac) + if !ok { + err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G1Jac", y) + break + } + res = x.Equal(y) + case *bls12381.G2Affine: + y, ok := b.point.(*bls12381.G2Affine) + if !ok { + err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G2Affine", y) + break + } + res = x.Equal(y) + case *bls12381.G2Jac: + y, ok := b.point.(*bls12381.G2Jac) + if !ok { + err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G2Jac", y) + break + } + res = x.Equal(y) + case *bls12381.GT: + y, ok := b.point.(*bls12381.GT) + if !ok { + err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs GT", y) + break + } + res = x.Equal(y) + default: + err = fmt.Errorf("equal: unexpected x bls12381 point type: %T", x) + } + + return res, err +} + +// Bytes returns serialized representation of the provided point in compressed form. +func (p blsPoint) Bytes() []byte { + switch p := p.point.(type) { + case *bls12381.G1Affine: + compressed := p.Bytes() + return compressed[:] + case *bls12381.G1Jac: + g1Affine := new(bls12381.G1Affine) + g1Affine.FromJacobian(p) + compressed := g1Affine.Bytes() + return compressed[:] + case *bls12381.G2Affine: + compressed := p.Bytes() + return compressed[:] + case *bls12381.G2Jac: + g2Affine := new(bls12381.G2Affine) + g2Affine.FromJacobian(p) + compressed := g2Affine.Bytes() + return compressed[:] + case *bls12381.GT: + compressed := p.Bytes() + return compressed[:] + default: + panic(errors.New("unknown bls12381 point type")) + } +} diff --git a/pkg/core/native/native_test/cryptolib_test.go b/pkg/core/native/native_test/cryptolib_test.go index bccda21a2..69bed9325 100644 --- a/pkg/core/native/native_test/cryptolib_test.go +++ b/pkg/core/native/native_test/cryptolib_test.go @@ -6,7 +6,6 @@ import ( "strings" "testing" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/io" @@ -38,6 +37,10 @@ func newCryptolibClient(t *testing.T) *neotest.ContractInvoker { return newNativeClient(t, nativenames.CryptoLib) } +type serializable interface { + Bytes() []byte +} + func TestCryptolib_TestG1_Compat(t *testing.T) { c := newCryptolibClient(t) cryptoInvoker := c.WithSigners(c.Committee) @@ -48,9 +51,9 @@ func TestCryptolib_TestG1_Compat(t *testing.T) { require.Equal(t, 1, stack.Len()) itm := stack.Pop().Item() require.Equal(t, stackitem.InteropT, itm.Type()) - actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.G1Affine) + actual, ok := itm.(*stackitem.Interop).Value().(serializable) require.True(t, ok) - arr := actual.Bytes() // the result in compressed form. + arr := actual.Bytes() // the G1Affine result in compressed form. // Expected value is taken from the reference test. require.Equal(t, "97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", hex.EncodeToString(arr[:])) @@ -66,9 +69,9 @@ func TestCryptolib_TestG2_Compat(t *testing.T) { require.Equal(t, 1, stack.Len()) itm := stack.Pop().Item() require.Equal(t, stackitem.InteropT, itm.Type()) - actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.G2Affine) + actual, ok := itm.(*stackitem.Interop).Value().(serializable) require.True(t, ok) - arr := actual.Bytes() // the result in compressed form. + arr := actual.Bytes() // the result G2Affine in compressed form. // Expected value is taken from the reference test. require.Equal(t, "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8", hex.EncodeToString(arr[:])) @@ -102,10 +105,10 @@ func TestCryptolib_TestBls12381Add_Compat(t *testing.T) { require.Equal(t, 1, stack.Len()) itm := stack.Pop().Item() require.Equal(t, stackitem.InteropT, itm.Type()) - actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + actual, ok := itm.(*stackitem.Interop).Value().(serializable) require.True(t, ok) arr := actual.Bytes() - // Expected value is taken from the reference test. + // Expected GT value is taken from the reference test. require.Equal(t, strings.ToLower("079AB7B345EB23C944C957A36A6B74C37537163D4CBF73BAD9751DE1DD9C68EF72CB21447E259880F72A871C3EDA1B0C017F1C95CF79B22B459599EA57E613E00CB75E35DE1F837814A93B443C54241015AC9761F8FB20A44512FF5CFC04AC7F0F6B8B52B2B5D0661CBF232820A257B8C5594309C01C2A45E64C6A7142301E4FB36E6E16B5A85BD2E437599D103C3ACE06D8046C6B3424C4CD2D72CE98D279F2290A28A87E8664CB0040580D0C485F34DF45267F8C215DCBCD862787AB555C7E113286DEE21C9C63A458898BEB35914DC8DAAAC453441E7114B21AF7B5F47D559879D477CF2A9CBD5B40C86BECD071280900410BB2751D0A6AF0FE175DCF9D864ECAAC463C6218745B543F9E06289922434EE446030923A3E4C4473B4E3B1914081ABD33A78D31EB8D4C1BB3BAAB0529BB7BAF1103D848B4CEAD1A8E0AA7A7B260FBE79C67DBE41CA4D65BA8A54A72B61692A61CE5F4D7A093B2C46AA4BCA6C4A66CF873D405EBC9C35D8AA639763720177B23BEFFAF522D5E41D3C5310EA3331409CEBEF9EF393AA00F2AC64673675521E8FC8FDDAF90976E607E62A740AC59C3DDDF95A6DE4FBA15BEB30C43D4E3F803A3734DBEB064BF4BC4A03F945A4921E49D04AB8D45FD753A28B8FA082616B4B17BBCB685E455FF3BF8F60C3BD32A0C185EF728CF41A1B7B700B7E445F0B372BC29E370BC227D443C70AE9DBCF73FEE8ACEDBD317A286A53266562D817269C004FB0F149DD925D2C590A960936763E519C2B62E14C7759F96672CD852194325904197B0B19C6B528AB33566946AF39B"), hex.EncodeToString(arr[:])) } @@ -132,10 +135,10 @@ func TestCryptolib_TestBls12381Mul_Compat(t *testing.T) { require.Equal(t, 1, stack.Len()) itm := stack.Pop().Item() require.Equal(t, stackitem.InteropT, itm.Type()) - actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + actual, ok := itm.(*stackitem.Interop).Value().(serializable) require.True(t, ok) arr := actual.Bytes() - // Expected value is taken from the reference test. + // Expected GT value is taken from the reference test. require.Equal(t, strings.ToLower(expected), hex.EncodeToString(arr[:])) } check(t, false, "18B2DB6B3286BAEA116CCAD8F5554D170A69B329A6DE5B24C50B8834965242001A1C58089FD872B211ACD3263897FA660B117248D69D8AC745283A3E6A4CCEC607F6CF7CEDEE919575D4B7C8AE14C36001F76BE5FCA50ADC296EF8DF4926FA7F0B55A75F255FE61FC2DA7CFFE56ADC8775AAAB54C50D0C4952AD919D90FB0EB221C41ABB9F2352A11BE2D7F176ABE41E0E30AFB34FC2CE16136DE66900D92068F30011E9882C0A56E7E7B30F08442BE9E58D093E1888151136259D059FB539210D635BC491D5244A16CA28FDCF10546EC0F7104D3A419DDC081BA30ECB0CD2289010C2D385946229B7A9735ADC82736914FE61AD26C6C38B787775DE3B939105DE055F8D7004358272A0823F6F1787A7ABB6C3C59C8C9CBD1674AC900512632818CDD273F0D38833C07467EAF77743B70C924D43975D3821D47110A358757F926FCF970660FBDD74EF15D93B81E3AA290C78F59CBC6ED0C1E0DCBADFD11A73EB7137850D29EFEB6FA321330D0CF70F5C7F6B004BCF86AC99125F8FECF83157930BEC2AF89F8B378C6D7F63B0A07B3651F5207A84F62CEE929D574DA154EBE795D519B661086F069C9F061BA3B53DC4910EA1614C87B114E2F9EF328AC94E93D00440B412D5AE5A3C396D52D26C0CDF2156EBD3D3F60EA500C42120A7CE1F7EF80F15323118956B17C09E80E96ED4E1572461D604CDE2533330C684F86680406B1D3EE830CBAFE6D29C9A0A2F41E03E26095B713EB7E782144DB1EC6B53047FCB606B7B665B3DD1F52E95FCF2AE59C4AB159C3F98468C0A43C36C022B548189B6") @@ -156,10 +159,10 @@ func TestCryptolib_TestBls12381Pairing_Compat(t *testing.T) { require.Equal(t, 1, stack.Len()) itm := stack.Pop().Item() require.Equal(t, stackitem.InteropT, itm.Type()) - actual, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) + actual, ok := itm.(*stackitem.Interop).Value().(serializable) require.True(t, ok) arr := actual.Bytes() - // Expected value is taken from the reference test. + // Expected GT value is taken from the reference test. require.Equal(t, strings.ToLower("0F41E58663BF08CF068672CBD01A7EC73BACA4D72CA93544DEFF686BFD6DF543D48EAA24AFE47E1EFDE449383B67663104C581234D086A9902249B64728FFD21A189E87935A954051C7CDBA7B3872629A4FAFC05066245CB9108F0242D0FE3EF03350F55A7AEFCD3C31B4FCB6CE5771CC6A0E9786AB5973320C806AD360829107BA810C5A09FFDD9BE2291A0C25A99A211B8B424CD48BF38FCEF68083B0B0EC5C81A93B330EE1A677D0D15FF7B984E8978EF48881E32FAC91B93B47333E2BA5706FBA23EB7C5AF0D9F80940CA771B6FFD5857BAAF222EB95A7D2809D61BFE02E1BFD1B68FF02F0B8102AE1C2D5D5AB1A19F26337D205FB469CD6BD15C3D5A04DC88784FBB3D0B2DBDEA54D43B2B73F2CBB12D58386A8703E0F948226E47EE89D018107154F25A764BD3C79937A45B84546DA634B8F6BE14A8061E55CCEBA478B23F7DACAA35C8CA78BEAE9624045B4B601B2F522473D171391125BA84DC4007CFBF2F8DA752F7C74185203FCCA589AC719C34DFFBBAAD8431DAD1C1FB597AAA5193502B86EDB8857C273FA075A50512937E0794E1E65A7617C90D8BD66065B1FFFE51D7A579973B1315021EC3C19934F1368BB445C7C2D209703F239689CE34C0378A68E72A6B3B216DA0E22A5031B54DDFF57309396B38C881C4C849EC23E87089A1C5B46E5110B86750EC6A532348868A84045483C92B7AF5AF689452EAFABF1A8943E50439F1D59882A98EAA0170F1250EBD871FC0A92A7B2D83168D0D727272D441BEFA15C503DD8E90CE98DB3E7B6D194F60839C508A84305AACA1789B6"), hex.EncodeToString(arr[:])) } @@ -313,30 +316,10 @@ func TestCryptolib_TestBls12381Mul_CompatCustom(t *testing.T) { require.Equal(t, 1, stack.Len()) itm := stack.Pop().Item() require.Equal(t, stackitem.InteropT, itm.Type()) - var actual []byte - switch resTyp { - case gtP: - gt, ok := itm.(*stackitem.Interop).Value().(*bls12381.GT) - require.True(t, ok) - arr := gt.Bytes() - actual = arr[:] - case g1JacP: - g1Jac, ok := itm.(*stackitem.Interop).Value().(*bls12381.G1Jac) - require.True(t, ok) - g1Affine := new(bls12381.G1Affine) - g1Affine.FromJacobian(g1Jac) - arr := g1Affine.Bytes() - actual = arr[:] - case g2JacP: - g2Jac, ok := itm.(*stackitem.Interop).Value().(*bls12381.G2Jac) - require.True(t, ok) - g2Affine := new(bls12381.G2Affine) - g2Affine.FromJacobian(g2Jac) - arr := g2Affine.Bytes() - actual = arr[:] - default: - t.Fatal("unexpected result type", resTyp) - } + p, ok := itm.(*stackitem.Interop).Value().(serializable) + require.True(t, ok) + arr := p.Bytes() + actual := arr[:] require.Equal(t, strings.ToLower(expected), hex.EncodeToString(actual)) } @@ -350,3 +333,90 @@ func TestCryptolib_TestBls12381Mul_CompatCustom(t *testing.T) { }) } } + +func TestCryptolib_Bls12381PointsEQUAL_DUP(t *testing.T) { + c := newCryptolibClient(t) + + check := func(t *testing.T, point string) { + bytes, err := hex.DecodeString(point) + require.NoError(t, err) + script := io.NewBufBinWriter() + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, bytes) + emit.Opcodes(script.BinWriter, opcode.DUP, opcode.EQUAL) + + c.InvokeScriptCheckHALT(t, script.Bytes(), c.Signers, stackitem.NewBool(true)) + } + t.Run("GT", func(t *testing.T) { + check(t, "14fd52fe9bfd08bbe23fcdf1d3bc5390c62e75a8786a72f8a343123a30a7c5f8d18508a21a2bf902f4db2c068913bc1c130e7ce13260d601c89ee717acfd3d4e1d80f409dd2a5c38b176f0b64d3d0a224c502717270dfecf2b825ac24608215c0d7fcfdf3c1552ada42b7e0521bc2e7389436660c352ecbf2eedf30b77b6b501df302399e6240473af47abe56fc974780c214542fcc0cf10e3001fa5e82d398f6ba1ddd1ccdf133bfd75e033eae50aec66bd5e884b8c74d4c1c6ac7c01278ac5164a54600cb2e24fec168f82542fbf98234dbb9ddf06503dc3c497da88b73db584ba19e685b1b398b51f40160e6c8f0917b4a68dedcc04674e5f5739cf0d845ba801263f712ed4ddda59c1d9909148e3f28124ae770682c9b19233bf0bcfa00d05bfe708d381b066b83a883ba8251ce2ea6772cbde51e1322d82b2c8a026a2153f4822e20cb69b8b05003ee74e09cb481728d688caa8a671f90b55488e272f48c7c5ae32526d3635a5343eb02640358d9ac445c76a5d8f52f653bbaee04ba5ce03c68b88c25be6fd3611cc21c9968e4f87e541beeccc5170b8696a439bb666ad8a6608ab30ebc7dfe56eaf0dd9ab8439171a6e4e0d608e6e6c8ac5ddcf8d6d2a950d06051e6b6c4d3feb6dc8dac2acadd345cadfb890454a2101a112f7471f0e001701f60f3d4352c4d388c0f198854908c0e939719709c1b3f82d2a25cc7156a3838bc141e041c259849326fbd0839f15cea6a78b89349dcd1c03695a74e72d3657af4ee2cf267337bc96363ef4a1c5d5d7a673cc3a3c1a1350043f99537d62") + }) + t.Run("G1", func(t *testing.T) { + check(t, "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8") + }) + t.Run("G2", func(t *testing.T) { + check(t, "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365") + }) +} + +func TestCryptolib_Bls12381PointsEQUAL(t *testing.T) { + c := newCryptolibClient(t) + + check := func(t *testing.T, point1, point2 string, expected bool) { + bytes1, err := hex.DecodeString(point1) + require.NoError(t, err) + bytes2, err := hex.DecodeString(point2) + require.NoError(t, err) + script := io.NewBufBinWriter() + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, bytes1) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, bytes2) + emit.Opcodes(script.BinWriter, opcode.EQUAL) + + c.InvokeScriptCheckHALT(t, script.Bytes(), c.Signers, stackitem.NewBool(expected)) + } + t.Run("GT true", func(t *testing.T) { + check(t, "14fd52fe9bfd08bbe23fcdf1d3bc5390c62e75a8786a72f8a343123a30a7c5f8d18508a21a2bf902f4db2c068913bc1c130e7ce13260d601c89ee717acfd3d4e1d80f409dd2a5c38b176f0b64d3d0a224c502717270dfecf2b825ac24608215c0d7fcfdf3c1552ada42b7e0521bc2e7389436660c352ecbf2eedf30b77b6b501df302399e6240473af47abe56fc974780c214542fcc0cf10e3001fa5e82d398f6ba1ddd1ccdf133bfd75e033eae50aec66bd5e884b8c74d4c1c6ac7c01278ac5164a54600cb2e24fec168f82542fbf98234dbb9ddf06503dc3c497da88b73db584ba19e685b1b398b51f40160e6c8f0917b4a68dedcc04674e5f5739cf0d845ba801263f712ed4ddda59c1d9909148e3f28124ae770682c9b19233bf0bcfa00d05bfe708d381b066b83a883ba8251ce2ea6772cbde51e1322d82b2c8a026a2153f4822e20cb69b8b05003ee74e09cb481728d688caa8a671f90b55488e272f48c7c5ae32526d3635a5343eb02640358d9ac445c76a5d8f52f653bbaee04ba5ce03c68b88c25be6fd3611cc21c9968e4f87e541beeccc5170b8696a439bb666ad8a6608ab30ebc7dfe56eaf0dd9ab8439171a6e4e0d608e6e6c8ac5ddcf8d6d2a950d06051e6b6c4d3feb6dc8dac2acadd345cadfb890454a2101a112f7471f0e001701f60f3d4352c4d388c0f198854908c0e939719709c1b3f82d2a25cc7156a3838bc141e041c259849326fbd0839f15cea6a78b89349dcd1c03695a74e72d3657af4ee2cf267337bc96363ef4a1c5d5d7a673cc3a3c1a1350043f99537d62", + "14fd52fe9bfd08bbe23fcdf1d3bc5390c62e75a8786a72f8a343123a30a7c5f8d18508a21a2bf902f4db2c068913bc1c130e7ce13260d601c89ee717acfd3d4e1d80f409dd2a5c38b176f0b64d3d0a224c502717270dfecf2b825ac24608215c0d7fcfdf3c1552ada42b7e0521bc2e7389436660c352ecbf2eedf30b77b6b501df302399e6240473af47abe56fc974780c214542fcc0cf10e3001fa5e82d398f6ba1ddd1ccdf133bfd75e033eae50aec66bd5e884b8c74d4c1c6ac7c01278ac5164a54600cb2e24fec168f82542fbf98234dbb9ddf06503dc3c497da88b73db584ba19e685b1b398b51f40160e6c8f0917b4a68dedcc04674e5f5739cf0d845ba801263f712ed4ddda59c1d9909148e3f28124ae770682c9b19233bf0bcfa00d05bfe708d381b066b83a883ba8251ce2ea6772cbde51e1322d82b2c8a026a2153f4822e20cb69b8b05003ee74e09cb481728d688caa8a671f90b55488e272f48c7c5ae32526d3635a5343eb02640358d9ac445c76a5d8f52f653bbaee04ba5ce03c68b88c25be6fd3611cc21c9968e4f87e541beeccc5170b8696a439bb666ad8a6608ab30ebc7dfe56eaf0dd9ab8439171a6e4e0d608e6e6c8ac5ddcf8d6d2a950d06051e6b6c4d3feb6dc8dac2acadd345cadfb890454a2101a112f7471f0e001701f60f3d4352c4d388c0f198854908c0e939719709c1b3f82d2a25cc7156a3838bc141e041c259849326fbd0839f15cea6a78b89349dcd1c03695a74e72d3657af4ee2cf267337bc96363ef4a1c5d5d7a673cc3a3c1a1350043f99537d62", + true) + }) + t.Run("GT false", func(t *testing.T) { + check(t, "14fd52fe9bfd08bbe23fcdf1d3bc5390c62e75a8786a72f8a343123a30a7c5f8d18508a21a2bf902f4db2c068913bc1c130e7ce13260d601c89ee717acfd3d4e1d80f409dd2a5c38b176f0b64d3d0a224c502717270dfecf2b825ac24608215c0d7fcfdf3c1552ada42b7e0521bc2e7389436660c352ecbf2eedf30b77b6b501df302399e6240473af47abe56fc974780c214542fcc0cf10e3001fa5e82d398f6ba1ddd1ccdf133bfd75e033eae50aec66bd5e884b8c74d4c1c6ac7c01278ac5164a54600cb2e24fec168f82542fbf98234dbb9ddf06503dc3c497da88b73db584ba19e685b1b398b51f40160e6c8f0917b4a68dedcc04674e5f5739cf0d845ba801263f712ed4ddda59c1d9909148e3f28124ae770682c9b19233bf0bcfa00d05bfe708d381b066b83a883ba8251ce2ea6772cbde51e1322d82b2c8a026a2153f4822e20cb69b8b05003ee74e09cb481728d688caa8a671f90b55488e272f48c7c5ae32526d3635a5343eb02640358d9ac445c76a5d8f52f653bbaee04ba5ce03c68b88c25be6fd3611cc21c9968e4f87e541beeccc5170b8696a439bb666ad8a6608ab30ebc7dfe56eaf0dd9ab8439171a6e4e0d608e6e6c8ac5ddcf8d6d2a950d06051e6b6c4d3feb6dc8dac2acadd345cadfb890454a2101a112f7471f0e001701f60f3d4352c4d388c0f198854908c0e939719709c1b3f82d2a25cc7156a3838bc141e041c259849326fbd0839f15cea6a78b89349dcd1c03695a74e72d3657af4ee2cf267337bc96363ef4a1c5d5d7a673cc3a3c1a1350043f99537d62", + hex.EncodeToString(gt), + false) + }) + t.Run("G1 true", func(t *testing.T) { + check(t, "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8", + "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8", + true) + }) + t.Run("G1 false", func(t *testing.T) { + check(t, "a1f9855f7670a63e4c80d64dfe6ddedc2ed2bfaebae27e4da82d71ba474987a39808e8921d3df97df6e5d4b979234de8", + hex.EncodeToString(g1), + false) + }) + t.Run("G2 true", func(t *testing.T) { + check(t, "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365", + "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365", + true) + }) + t.Run("G2 false", func(t *testing.T) { + check(t, "a41e586fdd58d39616fea921a855e65417a5732809afc35e28466e3acaeed3d53dd4b97ca398b2f29bf6bbcaca026a6609a42bdeaaeef42813ae225e35c23c61c293e6ecb6759048fb76ac648ba3bc49f0fcf62f73fca38cdc5e7fa5bf511365", + hex.EncodeToString(g2), + false) + }) +} + +func TestCryptolib_Bls12381Equal_GT(t *testing.T) { + c := newCryptolibClient(t) + + script := io.NewBufBinWriter() + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, gt) + emit.AppCall(script.BinWriter, c.Hash, "bls12381Deserialize", callflag.All, gt) + emit.Opcodes(script.BinWriter, opcode.PUSH2, opcode.PACK) + emit.AppCallNoArgs(script.BinWriter, c.Hash, "bls12381Equal", callflag.All) + + stack, err := c.TestInvokeScript(t, script.Bytes(), c.Signers) + require.NoError(t, err) + require.Equal(t, 1, stack.Len()) + itm := stack.Pop().Item() + require.Equal(t, stackitem.BooleanT, itm.Type()) + require.True(t, itm.Value().(bool)) +} diff --git a/pkg/vm/stackitem/item.go b/pkg/vm/stackitem/item.go index 7f86879b5..9e645589c 100644 --- a/pkg/vm/stackitem/item.go +++ b/pkg/vm/stackitem/item.go @@ -60,6 +60,13 @@ type Convertible interface { FromStackItem(Item) error } +// Equatable describes a special value of Interop that can be compared with +// value of some other Interop that implements Equatable. +type Equatable interface { + // Equals checks if two objects are equal. + Equals(other Equatable) bool +} + var ( // ErrInvalidConversion is returned upon an attempt to make an incorrect // conversion between item types. @@ -994,7 +1001,12 @@ func (i *Interop) Equals(s Item) bool { return false } val, ok := s.(*Interop) - return ok && i.value == val.value + if !ok { + return false + } + a, okA := i.value.(Equatable) + b, okB := val.value.(Equatable) + return (okA && okB && a.Equals(b)) || (!okA && !okB && i.value == val.value) } // Type implements the Item interface. diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 67af89618..d19b42e6e 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -820,11 +820,23 @@ func TestDepth(t *testing.T) { assert.Equal(t, int64(3), vm.estack.Pop().BigInt().Int64()) } +type simpleEquatable struct { + ok bool +} + +var _ = stackitem.Equatable(simpleEquatable{}) + +func (e simpleEquatable) Equals(other stackitem.Equatable) bool { + _, ok := other.(simpleEquatable) + return ok && e.ok +} + func TestEQUALTrue(t *testing.T) { prog := makeProgram(opcode.DUP, opcode.EQUAL) t.Run("Array", getTestFuncForVM(prog, true, []stackitem.Item{})) t.Run("Map", getTestFuncForVM(prog, true, stackitem.NewMap())) t.Run("Buffer", getTestFuncForVM(prog, true, stackitem.NewBuffer([]byte{1, 2}))) + t.Run("Equatable", getTestFuncForVM(prog, true, stackitem.NewInterop(simpleEquatable{ok: true}))) } func TestEQUAL(t *testing.T) { @@ -837,6 +849,8 @@ func TestEQUAL(t *testing.T) { t.Run("Map", getTestFuncForVM(prog, false, stackitem.NewMap(), stackitem.NewMap())) t.Run("Array", getTestFuncForVM(prog, false, []stackitem.Item{}, []stackitem.Item{})) t.Run("Buffer", getTestFuncForVM(prog, false, stackitem.NewBuffer([]byte{42}), stackitem.NewBuffer([]byte{42}))) + t.Run("EquatableFalse", getTestFuncForVM(prog, false, stackitem.NewInterop(simpleEquatable{false}), stackitem.NewInterop(simpleEquatable{}))) + t.Run("EquatableTrue", getTestFuncForVM(prog, true, stackitem.NewInterop(simpleEquatable{true}), stackitem.NewInterop(simpleEquatable{}))) } func TestEQUALByteArrayWithLimit(t *testing.T) { From ea13fbe94aeaa858fd7b36045185c86ff4edb75d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 14 Jun 2023 19:53:57 +0300 Subject: [PATCH 107/125] core: improve errors logging for bls12381-related operations Signed-off-by: Anna Shaleva --- pkg/core/native/crypto.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/core/native/crypto.go b/pkg/core/native/crypto.go index f92554867..d736f2beb 100644 --- a/pkg/core/native/crypto.go +++ b/pkg/core/native/crypto.go @@ -251,7 +251,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite yJac.AddMixed(x) res = yJac default: - panic("inconsistent point types") + panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) } case *bls12381.G1Jac: resJac := new(bls12381.G1Jac) @@ -262,7 +262,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite case *bls12381.G1Jac: resJac.AddAssign(y) default: - panic("inconsistent") + panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) } res = resJac case *bls12381.G2Affine: @@ -278,7 +278,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite yJac.AddMixed(x) res = yJac default: - panic("inconsistent") + panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) } case *bls12381.G2Jac: resJac := new(bls12381.G2Jac) @@ -289,7 +289,7 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite case *bls12381.G2Jac: resJac.AddAssign(y) default: - panic("invalid") + panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) } res = resJac case *bls12381.GT: @@ -300,11 +300,11 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite // It's multiplication, see https://github.com/neo-project/Neo.Cryptography.BLS12_381/issues/4. resGT.Mul(x, y) default: - panic("invalid") + panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) } res = resGT default: - panic(fmt.Errorf("unexpected bls12381 point type: %T", x)) + panic(fmt.Errorf("add: unexpected bls12381 point type: %T", x)) } return stackitem.NewInterop(blsPoint{point: res}) } @@ -384,7 +384,7 @@ func (c *Crypto) bls12381Mul(_ *interop.Context, args []stackitem.Item) stackite res = gt default: - panic(fmt.Errorf("unexpected bls12381 point type: %T", x)) + panic(fmt.Errorf("mul: unexpected bls12381 point type: %T", x)) } return stackitem.NewInterop(blsPoint{point: res}) } @@ -406,7 +406,7 @@ func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stac x = new(bls12381.G1Affine) x.FromJacobian(p) default: - panic(fmt.Errorf("unexpected bls12381 point type (g1): %T", x)) + panic(fmt.Errorf("pairing: unexpected bls12381 point type (g1): %T", x)) } switch p := b.point.(type) { case *bls12381.G2Affine: @@ -415,11 +415,11 @@ func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stac y = new(bls12381.G2Affine) y.FromJacobian(p) default: - panic(fmt.Errorf("unexpected bls12381 point type (g2): %T", x)) + panic(fmt.Errorf("pairing: unexpected bls12381 point type (g2): %T", x)) } gt, err := bls12381.Pair([]bls12381.G1Affine{*x}, []bls12381.G2Affine{*y}) if err != nil { - panic(fmt.Errorf("failed to perform pairing operation")) + panic(fmt.Errorf("failed to perform pairing operation: %w", err)) } return stackitem.NewInterop(blsPoint{>}) } From 31e20768108b07f3afeebe27af8d510a014aa29d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 15 Jun 2023 18:57:59 +0300 Subject: [PATCH 108/125] native: move BLS12-381-related operations to a separate file No functional changes, just refactoring. Signed-off-by: Anna Shaleva --- pkg/core/native/crypto.go | 177 +++----------------------- pkg/core/native/crypto_blspoints.go | 189 ++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 159 deletions(-) diff --git a/pkg/core/native/crypto.go b/pkg/core/native/crypto.go index d736f2beb..b4da10fa2 100644 --- a/pkg/core/native/crypto.go +++ b/pkg/core/native/crypto.go @@ -7,7 +7,6 @@ import ( "fmt" "math/big" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/nspcc-dev/neo-go/pkg/core/dao" @@ -190,31 +189,12 @@ func (c *Crypto) bls12381Deserialize(_ *interop.Context, args []stackitem.Item) if err != nil { panic(fmt.Errorf("invalid serialized bls12381 point: %w", err)) } - var res interface{} - switch l := len(buf); l { - case bls12381.SizeOfG1AffineCompressed: - g1Affine := new(bls12381.G1Affine) - _, err = g1Affine.SetBytes(buf) - if err != nil { - panic(fmt.Errorf("failed to decode bls12381 G1Affine point: %w", err)) - } - res = g1Affine - case bls12381.SizeOfG2AffineCompressed: - g2Affine := new(bls12381.G2Affine) - _, err = g2Affine.SetBytes(buf) - if err != nil { - panic(fmt.Errorf("failed to decode bls12381 G2Affine point: %w", err)) - } - res = g2Affine - case bls12381.SizeOfGT: - gt := new(bls12381.GT) - err := gt.SetBytes(buf) - if err != nil { - panic(fmt.Errorf("failed to decode GT point: %w", err)) - } - res = gt + p := new(blsPoint) + err = p.FromBytes(buf) + if err != nil { + panic(err) } - return stackitem.NewInterop(blsPoint{point: res}) + return stackitem.NewInterop(*p) } func (c *Crypto) bls12381Equal(_ *interop.Context, args []stackitem.Item) stackitem.Item { @@ -236,77 +216,12 @@ func (c *Crypto) bls12381Add(_ *interop.Context, args []stackitem.Item) stackite if !(okA && okB) { panic("some of the arguments are not a bls12381 point") } - var res interface{} - switch x := a.point.(type) { - case *bls12381.G1Affine: - switch y := b.point.(type) { - case *bls12381.G1Affine: - xJac := new(bls12381.G1Jac) - xJac.FromAffine(x) - xJac.AddMixed(y) - res = xJac - case *bls12381.G1Jac: - yJac := new(bls12381.G1Jac) - yJac.Set(y) - yJac.AddMixed(x) - res = yJac - default: - panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) - } - case *bls12381.G1Jac: - resJac := new(bls12381.G1Jac) - resJac.Set(x) - switch y := b.point.(type) { - case *bls12381.G1Affine: - resJac.AddMixed(y) - case *bls12381.G1Jac: - resJac.AddAssign(y) - default: - panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) - } - res = resJac - case *bls12381.G2Affine: - switch y := b.point.(type) { - case *bls12381.G2Affine: - xJac := new(bls12381.G2Jac) - xJac.FromAffine(x) - xJac.AddMixed(y) - res = xJac - case *bls12381.G2Jac: - yJac := new(bls12381.G2Jac) - yJac.Set(y) - yJac.AddMixed(x) - res = yJac - default: - panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) - } - case *bls12381.G2Jac: - resJac := new(bls12381.G2Jac) - resJac.Set(x) - switch y := b.point.(type) { - case *bls12381.G2Affine: - resJac.AddMixed(y) - case *bls12381.G2Jac: - resJac.AddAssign(y) - default: - panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) - } - res = resJac - case *bls12381.GT: - resGT := new(bls12381.GT) - resGT.Set(x) - switch y := b.point.(type) { - case *bls12381.GT: - // It's multiplication, see https://github.com/neo-project/Neo.Cryptography.BLS12_381/issues/4. - resGT.Mul(x, y) - default: - panic(fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y)) - } - res = resGT - default: - panic(fmt.Errorf("add: unexpected bls12381 point type: %T", x)) + + p, err := blsPointAdd(a, b) + if err != nil { + panic(err) } - return stackitem.NewInterop(blsPoint{point: res}) + return stackitem.NewInterop(p) } func scalarFromBytes(bytes []byte, neg bool) (*fr.Element, error) { @@ -347,46 +262,11 @@ func (c *Crypto) bls12381Mul(_ *interop.Context, args []stackitem.Item) stackite alphaBi := new(big.Int) alpha.BigInt(alphaBi) - var res interface{} - switch x := a.point.(type) { - case *bls12381.G1Affine: - // The result is in Jacobian form in the reference implementation. - g1Jac := new(bls12381.G1Jac) - g1Jac.FromAffine(x) - g1Jac.ScalarMultiplication(g1Jac, alphaBi) - res = g1Jac - case *bls12381.G1Jac: - g1Jac := new(bls12381.G1Jac) - g1Jac.ScalarMultiplication(x, alphaBi) - res = g1Jac - case *bls12381.G2Affine: - // The result is in Jacobian form in the reference implementation. - g2Jac := new(bls12381.G2Jac) - g2Jac.FromAffine(x) - g2Jac.ScalarMultiplication(g2Jac, alphaBi) - res = g2Jac - case *bls12381.G2Jac: - g2Jac := new(bls12381.G2Jac) - g2Jac.ScalarMultiplication(x, alphaBi) - res = g2Jac - case *bls12381.GT: - gt := new(bls12381.GT) - - // C# implementation differs a bit from go's. They use double-and-add algorithm, see - // https://github.com/neo-project/Neo.Cryptography.BLS12_381/blob/844bc3a4f7d8ba2c545ace90ca124f8ada4c8d29/src/Neo.Cryptography.BLS12_381/Gt.cs#L102 - // and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Double-and-add, - // Pay attention that C#'s Gt.Double() squares (not doubles!) the initial GT point. - // Thus.C#'s scalar multiplication operation over Gt and Scalar is effectively an exponent. - // Go's exponent algorithm differs a bit from the C#'s double-and-add in that go's one - // uses 2-bits windowed method for multiplication. However, the resulting GT point is - // absolutely the same between two implementations. - gt.Exp(*x, alphaBi) - - res = gt - default: - panic(fmt.Errorf("mul: unexpected bls12381 point type: %T", x)) + p, err := blsPointMul(a, alphaBi) + if err != nil { + panic(err) } - return stackitem.NewInterop(blsPoint{point: res}) + return stackitem.NewInterop(p) } func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stackitem.Item { @@ -395,33 +275,12 @@ func (c *Crypto) bls12381Pairing(_ *interop.Context, args []stackitem.Item) stac if !(okA && okB) { panic("some of the arguments are not a bls12381 point") } - var ( - x *bls12381.G1Affine - y *bls12381.G2Affine - ) - switch p := a.point.(type) { - case *bls12381.G1Affine: - x = p - case *bls12381.G1Jac: - x = new(bls12381.G1Affine) - x.FromJacobian(p) - default: - panic(fmt.Errorf("pairing: unexpected bls12381 point type (g1): %T", x)) - } - switch p := b.point.(type) { - case *bls12381.G2Affine: - y = p - case *bls12381.G2Jac: - y = new(bls12381.G2Affine) - y.FromJacobian(p) - default: - panic(fmt.Errorf("pairing: unexpected bls12381 point type (g2): %T", x)) - } - gt, err := bls12381.Pair([]bls12381.G1Affine{*x}, []bls12381.G2Affine{*y}) + + p, err := blsPointPairing(a, b) if err != nil { - panic(fmt.Errorf("failed to perform pairing operation: %w", err)) + panic(err) } - return stackitem.NewInterop(blsPoint{>}) + return stackitem.NewInterop(p) } // Metadata implements the Contract interface. diff --git a/pkg/core/native/crypto_blspoints.go b/pkg/core/native/crypto_blspoints.go index f1ef4ceb9..317d9b795 100644 --- a/pkg/core/native/crypto_blspoints.go +++ b/pkg/core/native/crypto_blspoints.go @@ -3,6 +3,7 @@ package native import ( "errors" "fmt" + "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -102,3 +103,191 @@ func (p blsPoint) Bytes() []byte { panic(errors.New("unknown bls12381 point type")) } } + +// FromBytes deserializes BLS12-381 point from the given byte slice in compressed form. +func (p *blsPoint) FromBytes(buf []byte) error { + switch l := len(buf); l { + case bls12381.SizeOfG1AffineCompressed: + g1Affine := new(bls12381.G1Affine) + _, err := g1Affine.SetBytes(buf) + if err != nil { + return fmt.Errorf("failed to decode bls12381 G1Affine point: %w", err) + } + p.point = g1Affine + case bls12381.SizeOfG2AffineCompressed: + g2Affine := new(bls12381.G2Affine) + _, err := g2Affine.SetBytes(buf) + if err != nil { + return fmt.Errorf("failed to decode bls12381 G2Affine point: %w", err) + } + p.point = g2Affine + case bls12381.SizeOfGT: + gt := new(bls12381.GT) + err := gt.SetBytes(buf) + if err != nil { + return fmt.Errorf("failed to decode GT point: %w", err) + } + p.point = gt + } + + return nil +} + +// blsPointAdd performs addition of two BLS12-381 points. +func blsPointAdd(a, b blsPoint) (blsPoint, error) { + var ( + res any + err error + ) + switch x := a.point.(type) { + case *bls12381.G1Affine: + switch y := b.point.(type) { + case *bls12381.G1Affine: + xJac := new(bls12381.G1Jac) + xJac.FromAffine(x) + xJac.AddMixed(y) + res = xJac + case *bls12381.G1Jac: + yJac := new(bls12381.G1Jac) + yJac.Set(y) + yJac.AddMixed(x) + res = yJac + default: + err = fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y) + } + case *bls12381.G1Jac: + resJac := new(bls12381.G1Jac) + resJac.Set(x) + switch y := b.point.(type) { + case *bls12381.G1Affine: + resJac.AddMixed(y) + case *bls12381.G1Jac: + resJac.AddAssign(y) + default: + err = fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y) + } + res = resJac + case *bls12381.G2Affine: + switch y := b.point.(type) { + case *bls12381.G2Affine: + xJac := new(bls12381.G2Jac) + xJac.FromAffine(x) + xJac.AddMixed(y) + res = xJac + case *bls12381.G2Jac: + yJac := new(bls12381.G2Jac) + yJac.Set(y) + yJac.AddMixed(x) + res = yJac + default: + err = fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y) + } + case *bls12381.G2Jac: + resJac := new(bls12381.G2Jac) + resJac.Set(x) + switch y := b.point.(type) { + case *bls12381.G2Affine: + resJac.AddMixed(y) + case *bls12381.G2Jac: + resJac.AddAssign(y) + default: + err = fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y) + } + res = resJac + case *bls12381.GT: + resGT := new(bls12381.GT) + resGT.Set(x) + switch y := b.point.(type) { + case *bls12381.GT: + // It's multiplication, see https://github.com/neo-project/Neo.Cryptography.BLS12_381/issues/4. + resGT.Mul(x, y) + default: + err = fmt.Errorf("add: inconsistent bls12381 point types: %T and %T", x, y) + } + res = resGT + default: + err = fmt.Errorf("add: unexpected bls12381 point type: %T", x) + } + + return blsPoint{point: res}, err +} + +// blsPointAdd performs scalar multiplication of two BLS12-381 points. +func blsPointMul(a blsPoint, alphaBi *big.Int) (blsPoint, error) { + var ( + res any + err error + ) + switch x := a.point.(type) { + case *bls12381.G1Affine: + // The result is in Jacobian form in the reference implementation. + g1Jac := new(bls12381.G1Jac) + g1Jac.FromAffine(x) + g1Jac.ScalarMultiplication(g1Jac, alphaBi) + res = g1Jac + case *bls12381.G1Jac: + g1Jac := new(bls12381.G1Jac) + g1Jac.ScalarMultiplication(x, alphaBi) + res = g1Jac + case *bls12381.G2Affine: + // The result is in Jacobian form in the reference implementation. + g2Jac := new(bls12381.G2Jac) + g2Jac.FromAffine(x) + g2Jac.ScalarMultiplication(g2Jac, alphaBi) + res = g2Jac + case *bls12381.G2Jac: + g2Jac := new(bls12381.G2Jac) + g2Jac.ScalarMultiplication(x, alphaBi) + res = g2Jac + case *bls12381.GT: + gt := new(bls12381.GT) + + // C# implementation differs a bit from go's. They use double-and-add algorithm, see + // https://github.com/neo-project/Neo.Cryptography.BLS12_381/blob/844bc3a4f7d8ba2c545ace90ca124f8ada4c8d29/src/Neo.Cryptography.BLS12_381/Gt.cs#L102 + // and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Double-and-add, + // Pay attention that C#'s Gt.Double() squares (not doubles!) the initial GT point. + // Thus.C#'s scalar multiplication operation over Gt and Scalar is effectively an exponent. + // Go's exponent algorithm differs a bit from the C#'s double-and-add in that go's one + // uses 2-bits windowed method for multiplication. However, the resulting GT point is + // absolutely the same between two implementations. + gt.Exp(*x, alphaBi) + + res = gt + default: + err = fmt.Errorf("mul: unexpected bls12381 point type: %T", x) + } + + return blsPoint{point: res}, err +} + +func blsPointPairing(a, b blsPoint) (blsPoint, error) { + var ( + x *bls12381.G1Affine + y *bls12381.G2Affine + ) + switch p := a.point.(type) { + case *bls12381.G1Affine: + x = p + case *bls12381.G1Jac: + x = new(bls12381.G1Affine) + x.FromJacobian(p) + default: + return blsPoint{}, fmt.Errorf("pairing: unexpected bls12381 point type (g1): %T", x) + } + switch p := b.point.(type) { + case *bls12381.G2Affine: + y = p + case *bls12381.G2Jac: + y = new(bls12381.G2Affine) + y.FromJacobian(p) + default: + return blsPoint{}, fmt.Errorf("pairing: unexpected bls12381 point type (g2): %T", x) + } + + gt, err := bls12381.Pair([]bls12381.G1Affine{*x}, []bls12381.G2Affine{*y}) + if err != nil { + return blsPoint{}, fmt.Errorf("failed to perform pairing operation: %w", err) + } + + return blsPoint{>}, nil +} From 20b19d4599b5e9b4d8ea2786522c45a3283c54c5 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 29 Jun 2023 11:18:30 +0300 Subject: [PATCH 109/125] interop/contract: fix state rollbacks for nested contexts Our wrapping optimization relied on the caller context having a TRY block, but each context (including internal calls!) has an exception handling stack of its own, which means that for an invocation stack of entry A.someMethodFromEntry() # this one has a TRY A.internalMethodViaCALL() # this one doesn't B.someMethod() we get `HasTryBlock() == false` for `A.internalMethodViaCALL()` context, which leads to missing wrapper and missing rollbacks if B is to THROW. What this patch does instead is it checks for any context within contract boundaries. Fixes #3045. Signed-off-by: Roman Khimov --- pkg/core/interop/contract/call.go | 2 +- pkg/core/interop/contract/call_test.go | 3 +++ pkg/vm/context.go | 10 ---------- pkg/vm/vm.go | 22 ++++++++++++++++++++++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/pkg/core/interop/contract/call.go b/pkg/core/interop/contract/call.go index 170e596a4..e1b8b72be 100644 --- a/pkg/core/interop/contract/call.go +++ b/pkg/core/interop/contract/call.go @@ -117,7 +117,7 @@ func callExFromNative(ic *interop.Context, caller util.Uint160, cs *state.Contra ic.Invocations[cs.Hash]++ f = ic.VM.Context().GetCallFlags() & f - wrapped := ic.VM.Context().HasTryBlock() && // If the method is not wrapped into try-catch block, then changes should be discarded anyway if exception occurs. + wrapped := ic.VM.ContractHasTryBlock() && // If the method is not wrapped into try-catch block, then changes should be discarded anyway if exception occurs. f&(callflag.All^callflag.ReadOnly) != 0 // If the method is safe, then it's read-only and doesn't perform storage changes or emit notifications. baseNtfCount := len(ic.Notifications) baseDAO := ic.DAO diff --git a/pkg/core/interop/contract/call_test.go b/pkg/core/interop/contract/call_test.go index 6bcf575a7..e51671562 100644 --- a/pkg/core/interop/contract/call_test.go +++ b/pkg/core/interop/contract/call_test.go @@ -304,6 +304,9 @@ func TestSnapshotIsolation_Exceptions(t *testing.T) { for i := 0; i < nNtfB1; i++ { runtime.Notify("NotificationFromB before panic", i) } + internalCaller(keyA, valueA, nNtfA) + } + func internalCaller(keyA, valueA []byte, nNtfA int) { contract.Call(interop.Hash160{` + hashAStr + `}, "doAndPanic", contract.All, keyA, valueA, nNtfA) } func CheckStorageChanges() bool { diff --git a/pkg/vm/context.go b/pkg/vm/context.go index 78c0f43ac..e777fdbeb 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -315,16 +315,6 @@ func (v *VM) PushContextScriptHash(n int) error { return nil } -func (c *Context) HasTryBlock() bool { - for i := 0; i < c.tryStack.Len(); i++ { - eCtx := c.tryStack.Peek(i).Value().(*exceptionHandlingContext) - if eCtx.State == eTry { - return true - } - } - return false -} - // MarshalJSON implements the JSON marshalling interface. func (c *Context) MarshalJSON() ([]byte, error) { var aux = contextAux{ diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 5541e25b8..8c1af0df8 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -1804,6 +1804,28 @@ func throwUnhandledException(item stackitem.Item) { panic(msg) } +// ContractHasTryBlock checks if the currently executing contract has a TRY +// block in one of its contexts. +func (v *VM) ContractHasTryBlock() bool { + var topctx *Context // Currently executing context. + for i := 0; i < len(v.istack); i++ { + ictx := v.istack[len(v.istack)-1-i] // It's a stack, going backwards like handleException(). + if topctx == nil { + topctx = ictx + } + if ictx.sc != topctx.sc { + return false // Different contract -> no one cares. + } + for j := 0; j < ictx.tryStack.Len(); j++ { + eCtx := ictx.tryStack.Peek(j).Value().(*exceptionHandlingContext) + if eCtx.State == eTry { + return true + } + } + } + return false +} + // CheckMultisigPar checks if the sigs contains sufficient valid signatures. func CheckMultisigPar(v *VM, curve elliptic.Curve, h []byte, pkeys [][]byte, sigs [][]byte) bool { if len(sigs) == 1 { From a30f098f7381dd04cb470a34ed992dcef51113a1 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 29 Jun 2023 11:41:04 +0300 Subject: [PATCH 110/125] server: allow to create incremental dumps Anything not starting from 0 is incremental by definition. Signed-off-by: Roman Khimov --- cli/server/server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/server/server.go b/cli/server/server.go index 8dd586e9a..b55982a4e 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -198,6 +198,9 @@ func dumpDB(ctx *cli.Context) error { if count == 0 { count = chainCount - start } + if start != 0 { + writer.WriteU32LE(start) + } writer.WriteU32LE(count) err = chaindump.Dump(chain, writer, start, count) if err != nil { From bfe8867e635efc6df42f528f5ae784e3ff53d31b Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 3 Jul 2023 13:24:11 +0300 Subject: [PATCH 111/125] cli: add test for incremental DB dump and restore Signed-off-by: Anna Shaleva --- cli/server/cli_dump_test.go | 49 +++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/cli/server/cli_dump_test.go b/cli/server/cli_dump_test.go index b743f9015..f7756add5 100644 --- a/cli/server/cli_dump_test.go +++ b/cli/server/cli_dump_test.go @@ -13,6 +13,9 @@ import ( "gopkg.in/yaml.v3" ) +// generated via `go run ./scripts/gendump/main.go --out ./cli/server/testdata/chain50x2.acc --blocks 50 --txs 2`. +const inDump = "./testdata/chain50x2.acc" + func TestDBRestoreDump(t *testing.T) { tmpDir := t.TempDir() @@ -32,8 +35,6 @@ func TestDBRestoreDump(t *testing.T) { cfgPath := filepath.Join(tmpDir, "protocol.unit_testnet.yml") require.NoError(t, os.WriteFile(cfgPath, out, os.ModePerm)) - // generated via `go run ./scripts/gendump/main.go --out ./cli/server/testdata/chain50x2.acc --blocks 50 --txs 2` - const inDump = "./testdata/chain50x2.acc" e := testcli.NewExecutor(t, false) stateDump := filepath.Join(tmpDir, "neogo.teststate") @@ -111,3 +112,47 @@ func TestDBRestoreDump(t *testing.T) { require.NoError(t, err) require.Equal(t, d1, d2, "dumps differ") } + +func TestDBDumpRestoreIncremental(t *testing.T) { + tmpDir := t.TempDir() + chainPath := filepath.Join(tmpDir, "neogotestchain") + nonincDump := filepath.Join(tmpDir, "nonincDump.acc") + incDump := filepath.Join(tmpDir, "incDump.acc") + + cfg, err := config.LoadFile(filepath.Join("..", "..", "config", "protocol.unit_testnet.yml")) + require.NoError(t, err, "could not load config") + cfg.ApplicationConfiguration.DBConfiguration.Type = dbconfig.LevelDB + cfg.ApplicationConfiguration.DBConfiguration.LevelDBOptions.DataDirectoryPath = chainPath + out, err := yaml.Marshal(cfg) + require.NoError(t, err) + + cfgPath := filepath.Join(tmpDir, "protocol.unit_testnet.yml") + require.NoError(t, os.WriteFile(cfgPath, out, os.ModePerm)) + + e := testcli.NewExecutor(t, false) + + // Create DB from dump. + e.Run(t, "neo-go", "db", "restore", "--unittest", "--config-path", tmpDir, "--in", inDump) + + // Create two dumps: non-incremental and incremental. + dumpBaseArgs := []string{"neo-go", "db", "dump", "--unittest", + "--config-path", tmpDir} + + // Dump first 15 blocks to a non-incremental dump. + e.Run(t, append(dumpBaseArgs, "--out", nonincDump, "--count", "15")...) + + // Dump second 15 blocks to an incremental dump. + e.Run(t, append(dumpBaseArgs, "--out", incDump, "--start", "15", "--count", "15")...) + + // Clean the DB. + require.NoError(t, os.RemoveAll(chainPath)) + + // Restore chain from two dumps. + restoreBaseArgs := []string{"neo-go", "db", "restore", "--unittest", "--config-path", tmpDir} + + // Restore first 15 blocks from non-incremental dump. + e.Run(t, append(restoreBaseArgs, "--in", nonincDump)...) + + // Restore second 15 blocks from incremental dump. + e.Run(t, append(restoreBaseArgs, "--in", incDump, "-n", "--count", "15")...) +} From 6fa4bcdc1dfb1fd519e566a04f1c30ba0a49b21d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 4 Jul 2023 12:51:41 +0300 Subject: [PATCH 112/125] core: remove contract script check on deploy/update This check is good and was present here since #1729, but it was accidently removed from the reference implementation (see the discussion in https://github.com/neo-project/neo/issues/2848). The removal of this check from the C# node leaded to the T5 testnet state diff since 1670095 heigh which causes inability to process new blocks since 2272533 height (see #3049). This check was added back to the C# node in https://github.com/neo-project/neo/pull/2849, but it is planned to be the part of the upcoming 3.6.0 C# node release. We need to keep our testnet healthy, thus, strict contract script check will be temporary removed from the node code and is planned to be added back to be a part of the next 3.6.0-compatible release. Close #3049. Signed-off-by: Anna Shaleva --- pkg/core/native/management.go | 6 +----- pkg/core/native/native_test/management_test.go | 11 ----------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index f78d4080e..24f88e076 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -23,8 +23,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/util/bitfield" - "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -717,12 +715,10 @@ func (m *Management) emitNotification(ic *interop.Context, name string, hash uti func checkScriptAndMethods(script []byte, methods []manifest.Method) error { l := len(script) - offsets := bitfield.New(l) for i := range methods { if methods[i].Offset >= l { return fmt.Errorf("method %s/%d: offset is out of the script range", methods[i].Name, len(methods[i].Parameters)) } - offsets.Set(methods[i].Offset) } - return vm.IsScriptCorrect(script, offsets) + return nil } diff --git a/pkg/core/native/native_test/management_test.go b/pkg/core/native/native_test/management_test.go index e60f806b7..04ff15c86 100644 --- a/pkg/core/native/native_test/management_test.go +++ b/pkg/core/native/native_test/management_test.go @@ -143,17 +143,6 @@ func TestManagement_ContractDeploy(t *testing.T) { managementInvoker.InvokeFail(t, "method add/2: offset is out of the script range", "deploy", nefBytes, manifB) }) - t.Run("bad methods in manifest 2", func(t *testing.T) { - var badManifest = cs1.Manifest - badManifest.ABI.Methods = make([]manifest.Method, len(cs1.Manifest.ABI.Methods)) - copy(badManifest.ABI.Methods, cs1.Manifest.ABI.Methods) - badManifest.ABI.Methods[0].Offset = len(cs1.NEF.Script) - 2 // Ends with `CALLT(X,X);RET`. - - manifB, err := json.Marshal(badManifest) - require.NoError(t, err) - - managementInvoker.InvokeFail(t, "some methods point to wrong offsets (not to instruction boundary)", "deploy", nefBytes, manifB) - }) t.Run("duplicated methods in manifest 1", func(t *testing.T) { badManifest := cs1.Manifest badManifest.ABI.Methods = make([]manifest.Method, len(cs1.Manifest.ABI.Methods)) From ca80cfea2bb9597b067468ffdaa5eb0b579399ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 21:28:13 +0000 Subject: [PATCH 113/125] build(deps): bump google.golang.org/grpc from 1.48.0 to 1.53.0 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.48.0 to 1.53.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.48.0...v1.53.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 7 +++---- go.sum | 33 ++++++--------------------------- 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 2077e04f8..e23b8dcdc 100644 --- a/go.mod +++ b/go.mod @@ -37,13 +37,12 @@ require ( github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/frankban/quicktest v1.14.5 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/nspcc-dev/hrw v1.0.9 // indirect @@ -63,8 +62,8 @@ require ( golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.8.0 // indirect - google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect - google.golang.org/grpc v1.48.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 924752114..2c53ee921 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 h1:npHgfD4Tl2WJS3AJaMUi5ynGDPUBfkg3U3fCzDyXZ+4= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -49,8 +48,9 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -59,11 +59,6 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWs github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.9.1 h1:mru55qKdWl3E035hAoh1jj9d7hVnYY5pfb6tmovSmII= @@ -80,15 +75,12 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -143,7 +135,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -158,14 +149,12 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= @@ -272,7 +261,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -292,7 +280,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -316,7 +303,6 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= @@ -397,7 +383,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -459,9 +444,7 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -578,14 +561,14 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -598,10 +581,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -614,7 +595,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -628,7 +608,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 8fcfa2c11ad18076f27264af3014f56fd2f352aa Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Sat, 8 Jul 2023 13:10:55 +0300 Subject: [PATCH 114/125] docs: adjust release instructions Our assets will be automatically attached to the release after #3010. Signed-off-by: Anna Shaleva --- docs/release-instruction.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/release-instruction.md b/docs/release-instruction.md index 6cb72a126..fc7c0dc36 100644 --- a/docs/release-instruction.md +++ b/docs/release-instruction.md @@ -56,11 +56,13 @@ Press the "Publish release" button. New release created at the previous step triggers automatic builds (if not, start them manually from the Build GitHub workflow), so wait for them to -finish. Then download currently supported binaries (at the time of writing -that's `neo-go-darwin-arm64`, `neo-go-linux-amd64`, `neo-go-linux-arm64` and -`neo-go-windows-amd64`), unpack archives and add resulting binaries (named in -the same way as archives) to the previously created release via "Edit release" -button. +finish. Built binaries should be automatically attached to the release as an +asset, check it on the release page. If binaries weren't attached after building +workflow completion, then submit the bug, download currently supported binaries +(at the time of writing they are `neo-go-darwin-arm64`, `neo-go-linux-amd64`, +`neo-go-linux-arm64` and `neo-go-windows-amd64`) from the building job artifacts, +unpack archives and add resulting binaries (named in the same way as archives) +to the previously created release via "Edit release" button. ## Close GitHub milestone From 9f69522ff5e0ed934cae8ef27a3e418f96ac7436 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 12 Jul 2023 08:33:26 +0300 Subject: [PATCH 115/125] neorpc: adjust SignerWithWitness scopes parsing Ensure that Scopes can be properly parsed not only from the string representation, but also from a single byte. transaction.Signer is not affected (checked against the C# implementation), only RPC-related signer scopes are allowed to be unmarshalled from byte. Close #3059. Signed-off-by: Anna Shaleva --- pkg/core/transaction/witness_scope.go | 14 +++ pkg/core/transaction/witness_scope_test.go | 62 +++++++++++++ pkg/neorpc/types.go | 32 ++++++- pkg/services/rpcsrv/params/param_test.go | 102 ++++++++++++++++----- 4 files changed, 185 insertions(+), 25 deletions(-) diff --git a/pkg/core/transaction/witness_scope.go b/pkg/core/transaction/witness_scope.go index aa67eb33a..c1cf2b7d8 100644 --- a/pkg/core/transaction/witness_scope.go +++ b/pkg/core/transaction/witness_scope.go @@ -3,6 +3,7 @@ package transaction //go:generate stringer -type=WitnessScope -linecomment -output=witness_scope_string.go import ( "encoding/json" + "errors" "fmt" "strings" ) @@ -29,6 +30,19 @@ const ( Global WitnessScope = 0x80 ) +// ScopesFromByte converts byte to a set of WitnessScopes and performs validity +// check. +func ScopesFromByte(b byte) (WitnessScope, error) { + var res = WitnessScope(b) + if (res&Global != 0) && (res&(None|CalledByEntry|CustomContracts|CustomGroups|Rules) != 0) { + return 0, errors.New("Global scope can not be combined with other scopes") + } + if res&^(None|CalledByEntry|CustomContracts|CustomGroups|Rules|Global) != 0 { + return 0, fmt.Errorf("invalid scope %d", res) + } + return res, nil +} + // ScopesFromString converts string of comma-separated scopes to a set of scopes // (case-sensitive). String can combine several scopes, e.g. be any of: 'Global', // 'CalledByEntry,CustomGroups' etc. In case of an empty string an error will be diff --git a/pkg/core/transaction/witness_scope_test.go b/pkg/core/transaction/witness_scope_test.go index 42a672e68..aea706a08 100644 --- a/pkg/core/transaction/witness_scope_test.go +++ b/pkg/core/transaction/witness_scope_test.go @@ -1,6 +1,7 @@ package transaction import ( + "strconv" "testing" "github.com/stretchr/testify/require" @@ -51,3 +52,64 @@ func TestScopesFromString(t *testing.T) { require.NoError(t, err) require.Equal(t, CalledByEntry|CustomGroups|CustomContracts, s) } + +func TestScopesFromByte(t *testing.T) { + testCases := []struct { + in byte + expected WitnessScope + shouldFail bool + }{ + { + in: 0, + expected: None, + }, + { + in: 1, + expected: CalledByEntry, + }, + { + in: 16, + expected: CustomContracts, + }, + { + in: 32, + expected: CustomGroups, + }, + { + in: 64, + expected: Rules, + }, + { + in: 128, + expected: Global, + }, + { + in: 17, + expected: CalledByEntry | CustomContracts, + }, + { + in: 48, + expected: CustomContracts | CustomGroups, + }, + { + in: 128 + 1, // Global can't be combined with others. + shouldFail: true, + }, + { + in: 2, // No such scope. + shouldFail: true, + }, + } + + for _, tc := range testCases { + t.Run(strconv.Itoa(int(tc.in)), func(t *testing.T) { + actual, err := ScopesFromByte(tc.in) + if tc.shouldFail { + require.Error(t, err, tc.in) + } else { + require.NoError(t, err, tc.in) + require.Equal(t, tc.expected, actual, tc.in) + } + }) + } +} diff --git a/pkg/neorpc/types.go b/pkg/neorpc/types.go index 40db91878..bbe7b690a 100644 --- a/pkg/neorpc/types.go +++ b/pkg/neorpc/types.go @@ -82,7 +82,7 @@ type ( // DisallowUnknownFields JSON marshaller setting. type signerWithWitnessAux struct { Account string `json:"account"` - Scopes transaction.WitnessScope `json:"scopes"` + Scopes json.RawMessage `json:"scopes"` AllowedContracts []util.Uint160 `json:"allowedcontracts,omitempty"` AllowedGroups []*keys.PublicKey `json:"allowedgroups,omitempty"` Rules []transaction.WitnessRule `json:"rules,omitempty"` @@ -92,9 +92,13 @@ type signerWithWitnessAux struct { // MarshalJSON implements the json.Marshaler interface. func (s *SignerWithWitness) MarshalJSON() ([]byte, error) { + sc, err := s.Scopes.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("failed to marshal scopes: %w", err) + } signer := &signerWithWitnessAux{ Account: s.Account.StringLE(), - Scopes: s.Scopes, + Scopes: sc, AllowedContracts: s.AllowedContracts, AllowedGroups: s.AllowedGroups, Rules: s.Rules, @@ -118,9 +122,31 @@ func (s *SignerWithWitness) UnmarshalJSON(data []byte) error { if err != nil { return fmt.Errorf("not a signer: %w", err) } + var ( + jStr string + jByte byte + scopes transaction.WitnessScope + ) + if len(aux.Scopes) != 0 { + if err := json.Unmarshal(aux.Scopes, &jStr); err == nil { + scopes, err = transaction.ScopesFromString(jStr) + if err != nil { + return fmt.Errorf("failed to retrieve scopes from string: %w", err) + } + } else { + err := json.Unmarshal(aux.Scopes, &jByte) + if err != nil { + return fmt.Errorf("failed to unmarshal scopes from byte: %w", err) + } + scopes, err = transaction.ScopesFromByte(jByte) + if err != nil { + return fmt.Errorf("failed to retrieve scopes from byte: %w", err) + } + } + } s.Signer = transaction.Signer{ Account: acc, - Scopes: aux.Scopes, + Scopes: scopes, AllowedContracts: aux.AllowedContracts, AllowedGroups: aux.AllowedGroups, Rules: aux.Rules, diff --git a/pkg/services/rpcsrv/params/param_test.go b/pkg/services/rpcsrv/params/param_test.go index af7c0bbc1..dfe0d2f3f 100644 --- a/pkg/services/rpcsrv/params/param_test.go +++ b/pkg/services/rpcsrv/params/param_test.go @@ -243,38 +243,96 @@ func TestGetWitness(t *testing.T) { require.NoError(t, err) testCases := []struct { - raw string - expected neorpc.SignerWithWitness + raw string + expected neorpc.SignerWithWitness + shouldFail bool }{ - {`{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569"}`, neorpc.SignerWithWitness{ - Signer: transaction.Signer{ - Account: accountHash, - Scopes: transaction.None, - }}, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569"}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: accountHash, + Scopes: transaction.None, + }, + }, }, - {`{"account": "NYxb4fSZVKAz8YsgaPK2WkT3KcAE9b3Vag", "scopes": "Global"}`, neorpc.SignerWithWitness{ - Signer: transaction.Signer{ - Account: addrHash, - Scopes: transaction.Global, - }}, + { + raw: `{"account": "NYxb4fSZVKAz8YsgaPK2WkT3KcAE9b3Vag", "scopes": "Global"}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: addrHash, + Scopes: transaction.Global, + }, + }, }, - {`{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": "Global"}`, neorpc.SignerWithWitness{ - Signer: transaction.Signer{ - Account: accountHash, - Scopes: transaction.Global, - }}, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": "Global"}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: accountHash, + Scopes: transaction.Global, + }, + }, + }, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": 128}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: accountHash, + Scopes: transaction.Global, + }, + }, + }, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": 0}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: accountHash, + Scopes: transaction.None, + }, + }, + }, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": 1}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: accountHash, + Scopes: transaction.CalledByEntry, + }, + }, + }, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": 17}`, + expected: neorpc.SignerWithWitness{ + Signer: transaction.Signer{ + Account: accountHash, + Scopes: transaction.CalledByEntry | transaction.CustomContracts, + }, + }, + }, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": 178}`, + shouldFail: true, + }, + { + raw: `{"account": "0xcadb3dc2faa3ef14a13b619c9a43124755aa2569", "scopes": 2}`, + shouldFail: true, }, } for _, tc := range testCases { p := Param{RawMessage: json.RawMessage(tc.raw)} actual, err := p.GetSignerWithWitness() - require.NoError(t, err) - require.Equal(t, tc.expected, actual) + if tc.shouldFail { + require.Error(t, err, tc.raw) + } else { + require.NoError(t, err, tc.raw) + require.Equal(t, tc.expected, actual) - actual, err = p.GetSignerWithWitness() // valid second invocation. - require.NoError(t, err) - require.Equal(t, tc.expected, actual) + actual, err = p.GetSignerWithWitness() // valid second invocation. + require.NoError(t, err, tc.raw) + require.Equal(t, tc.expected, actual) + } } } From 165525b7e9f5864ae8784fcc60ce0147de145f58 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 12 Jul 2023 08:39:15 +0300 Subject: [PATCH 116/125] neorpc: adjust the way SignerWithWitness is marshalled Marshal account with `0x` prefix and add a test. Signed-off-by: Anna Shaleva --- pkg/neorpc/types.go | 2 +- pkg/neorpc/types_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 pkg/neorpc/types_test.go diff --git a/pkg/neorpc/types.go b/pkg/neorpc/types.go index bbe7b690a..8a2a24dd2 100644 --- a/pkg/neorpc/types.go +++ b/pkg/neorpc/types.go @@ -97,7 +97,7 @@ func (s *SignerWithWitness) MarshalJSON() ([]byte, error) { return nil, fmt.Errorf("failed to marshal scopes: %w", err) } signer := &signerWithWitnessAux{ - Account: s.Account.StringLE(), + Account: `0x` + s.Account.StringLE(), Scopes: sc, AllowedContracts: s.AllowedContracts, AllowedGroups: s.AllowedGroups, diff --git a/pkg/neorpc/types_test.go b/pkg/neorpc/types_test.go new file mode 100644 index 000000000..f0c99ea23 --- /dev/null +++ b/pkg/neorpc/types_test.go @@ -0,0 +1,40 @@ +package neorpc + +import ( + "encoding/json" + "testing" + + "github.com/nspcc-dev/neo-go/internal/testserdes" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +func TestSignerWithWitnessMarshalUnmarshalJSON(t *testing.T) { + s := &SignerWithWitness{ + Signer: transaction.Signer{ + Account: util.Uint160{1, 2, 3}, + Scopes: transaction.CalledByEntry | transaction.CustomContracts, + AllowedContracts: []util.Uint160{{1, 2, 3, 4}}, + }, + Witness: transaction.Witness{ + InvocationScript: []byte{1, 2, 3}, + VerificationScript: []byte{4, 5, 6}, + }, + } + testserdes.MarshalUnmarshalJSON(t, s, &SignerWithWitness{}) + + // Check marshalling separately to ensure Scopes are marshalled OK. + expected := `{"account":"0xcadb3dc2faa3ef14a13b619c9a43124755aa2569","scopes":"CalledByEntry, CustomContracts"}` + acc, err := util.Uint160DecodeStringLE("cadb3dc2faa3ef14a13b619c9a43124755aa2569") + require.NoError(t, err) + s = &SignerWithWitness{ + Signer: transaction.Signer{ + Account: acc, + Scopes: transaction.CalledByEntry | transaction.CustomContracts, + }, + } + actual, err := json.Marshal(s) + require.NoError(t, err) + require.Equal(t, expected, string(actual)) +} From 8253025c90c2948f0595d3f4b8537e7d48f16ff3 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 12 Jul 2023 12:31:40 +0300 Subject: [PATCH 117/125] core: do not use formatted error if not needed Signed-off-by: Anna Shaleva --- pkg/core/transaction/witness_scope.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/transaction/witness_scope.go b/pkg/core/transaction/witness_scope.go index c1cf2b7d8..5c60e983b 100644 --- a/pkg/core/transaction/witness_scope.go +++ b/pkg/core/transaction/witness_scope.go @@ -68,7 +68,7 @@ func ScopesFromString(s string) (WitnessScope, error) { return result, fmt.Errorf("invalid witness scope: %v", scopeStr) } if isGlobal && !(scope == Global) { - return result, fmt.Errorf("Global scope can not be combined with other scopes") + return result, errors.New("Global scope can not be combined with other scopes") } result |= scope if scope == Global { From 966111f4a8312a0620097c4a00e3df20a86c2664 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 20 Jul 2023 10:55:11 +0300 Subject: [PATCH 118/125] network: forbid Notary contract to be a sender of main transaction This prevents the possible attack on notary request sender when malicious partie is allowed to send notary request with main transaction being someone else's fallback. Signed-off-by: Anna Shaleva --- pkg/network/server.go | 3 +++ pkg/network/server_test.go | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/network/server.go b/pkg/network/server.go index 5a8f7027d..8f97665cd 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -1201,6 +1201,9 @@ func (s *Server) verifyNotaryRequest(_ *transaction.Transaction, data any) error if r.FallbackTransaction.Sender() != notaryHash { return fmt.Errorf("P2PNotary contract should be a sender of the fallback transaction, got %s", address.Uint160ToString(r.FallbackTransaction.Sender())) } + if r.MainTransaction.Sender() == notaryHash { + return errors.New("P2PNotary contract is not allowed to be the sender of the main transaction") + } depositExpiration := s.chain.GetNotaryDepositExpiration(payer) if r.FallbackTransaction.ValidUntilBlock >= depositExpiration { return fmt.Errorf("fallback transaction is valid after deposit is unlocked: ValidUntilBlock is %d, deposit lock for %s expires at %d", r.FallbackTransaction.ValidUntilBlock, address.Uint160ToString(payer), depositExpiration) diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index 71849a82f..1f862d105 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -1036,7 +1036,10 @@ func TestVerifyNotaryRequest(t *testing.T) { require.NoError(t, err) newNotaryRequest := func() *payload.P2PNotaryRequest { return &payload.P2PNotaryRequest{ - MainTransaction: &transaction.Transaction{Script: []byte{0, 1, 2}}, + MainTransaction: &transaction.Transaction{ + Script: []byte{0, 1, 2}, + Signers: []transaction.Signer{{Account: random.Uint160()}}, + }, FallbackTransaction: &transaction.Transaction{ ValidUntilBlock: 321, Signers: []transaction.Signer{{Account: bc.NotaryContractScriptHash}, {Account: random.Uint160()}}, @@ -1057,6 +1060,13 @@ func TestVerifyNotaryRequest(t *testing.T) { require.Error(t, s.verifyNotaryRequest(nil, r)) }) + t.Run("bad main sender", func(t *testing.T) { + bc.VerifyWitnessF = func() (int64, error) { return 0, nil } + r := newNotaryRequest() + r.MainTransaction.Signers[0] = transaction.Signer{Account: bc.NotaryContractScriptHash} + require.Error(t, s.verifyNotaryRequest(nil, r)) + }) + t.Run("expired deposit", func(t *testing.T) { r := newNotaryRequest() bc.NotaryDepositExpiration = r.FallbackTransaction.ValidUntilBlock From c926d53869f7e38bd71aad35d1d2f053fc36daf3 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 21 Jul 2023 13:18:08 +0300 Subject: [PATCH 119/125] smartcontract: allow to pass nil as parameter to (*Invoker).Call Signed-off-by: Anna Shaleva --- pkg/smartcontract/parameter.go | 2 ++ pkg/smartcontract/parameter_test.go | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/pkg/smartcontract/parameter.go b/pkg/smartcontract/parameter.go index afe48dba6..758b86bd1 100644 --- a/pkg/smartcontract/parameter.go +++ b/pkg/smartcontract/parameter.go @@ -360,6 +360,8 @@ func NewParameterFromValue(value any) (Parameter, error) { } result.Type = ArrayType result.Value = arr + case nil: + result.Type = AnyType default: return result, fmt.Errorf("unsupported parameter %T", value) } diff --git a/pkg/smartcontract/parameter_test.go b/pkg/smartcontract/parameter_test.go index 1150e9cbc..c93179a2a 100644 --- a/pkg/smartcontract/parameter_test.go +++ b/pkg/smartcontract/parameter_test.go @@ -690,6 +690,11 @@ func TestParameterFromValue(t *testing.T) { expType: PublicKeyType, expVal: pk2.PublicKey().Bytes(), }, + { + value: nil, + expType: AnyType, + expVal: nil, + }, { value: [][]byte{{1, 2, 3}, {3, 2, 1}}, expType: ArrayType, From 0a2be8996402a4fda0cdeae174c5288f48534633 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 14 Jul 2023 10:51:17 +0300 Subject: [PATCH 120/125] core: remove unused blockchain API `(*Blockchain).HasTransaction` is one of the oldest methods in our codebase, and currently it's completely unused. I also doubt that this method works as expected because it returns `true` if transaction in the mempool. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index e6e659b7b..f23a6dead 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2174,15 +2174,6 @@ func (bc *Blockchain) GetHeader(hash util.Uint256) (*block.Header, error) { return &block.Header, nil } -// HasTransaction returns true if the blockchain contains he given -// transaction hash. -func (bc *Blockchain) HasTransaction(hash util.Uint256) bool { - if bc.memPool.ContainsKey(hash) { - return true - } - return errors.Is(bc.dao.HasTransaction(hash), dao.ErrAlreadyExists) -} - // HasBlock returns true if the blockchain contains the given // block hash. func (bc *Blockchain) HasBlock(hash util.Uint256) bool { From 0d17273476c5363a0b8c7ff76854ad6571cdccc2 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 14 Jul 2023 11:40:44 +0300 Subject: [PATCH 121/125] core: fix formatted error on transaction verification Witnesses are not yet created by the moment we return this error, thus, it was always 0 as an actual number of witnesses in ErrInvalidWitnessNum. Signed-off-by: Anna Shaleva --- pkg/core/transaction/transaction.go | 2 +- pkg/vm/testdata/neo-vm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 3c201d042..eba0c237d 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -193,7 +193,7 @@ func (t *Transaction) decodeBinaryNoSize(br *io.BinReader, buf []byte) { br.Err = errors.New("too many witnesses") return } else if int(nscripts) != len(t.Signers) { - br.Err = fmt.Errorf("%w: %d vs %d", ErrInvalidWitnessNum, len(t.Signers), len(t.Scripts)) + br.Err = fmt.Errorf("%w: %d vs %d", ErrInvalidWitnessNum, len(t.Signers), nscripts) return } t.Scripts = make([]Witness, nscripts) diff --git a/pkg/vm/testdata/neo-vm b/pkg/vm/testdata/neo-vm index 02f2c68e7..7e5996844 160000 --- a/pkg/vm/testdata/neo-vm +++ b/pkg/vm/testdata/neo-vm @@ -1 +1 @@ -Subproject commit 02f2c68e7ba2694aff88c143631e7acf158d378a +Subproject commit 7e5996844a90b514739f879bc9f873f9a34c9a67 From ee4b8f883bd04e5c0d615828e59506927aca5baf Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 14 Jul 2023 11:57:18 +0300 Subject: [PATCH 122/125] core: check signers of on-chained conflict during new tx verification During new transaction verification if there's an on-chain conflicting transaction, we should check the signers of this conflicting transaction. If the signers intersect with signers of the incoming transaction, then the conflict is treated as valid and verification for new incoming transaction should fail. Otherwise, the conflict is treated as the malicious attack attempt and will not be taken into account; verification for the new incoming transaction should continue. This commint implements the scheme described at https://github.com/neo-project/neo/pull/2818#issuecomment-1632972055, thanks to @shargon for digging. Signed-off-by: Anna Shaleva --- pkg/core/blockchain.go | 10 +- pkg/core/blockchain_neotest_test.go | 286 ++++++++++++++++++++++++++-- pkg/core/dao/dao.go | 84 ++++++-- pkg/core/dao/dao_test.go | 78 ++++++-- pkg/core/mempool/mem_pool.go | 32 +++- 5 files changed, 429 insertions(+), 61 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index f23a6dead..b5ca036dd 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -45,7 +45,7 @@ import ( // Tuning parameters. const ( - version = "0.2.8" + version = "0.2.9" defaultInitialGAS = 52000000_00000000 defaultGCPeriod = 10000 @@ -2477,7 +2477,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool. return fmt.Errorf("%w: net fee is %v, need %v", ErrTxSmallNetworkFee, t.NetworkFee, needNetworkFee) } // check that current tx wasn't included in the conflicts attributes of some other transaction which is already in the chain - if err := bc.dao.HasTransaction(t.Hash()); err != nil { + if err := bc.dao.HasTransaction(t.Hash(), t.Signers); err != nil { switch { case errors.Is(err, dao.ErrAlreadyExists): return fmt.Errorf("blockchain: %w", ErrAlreadyExists) @@ -2578,7 +2578,9 @@ func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transact return fmt.Errorf("%w: Conflicts attribute was found, but P2PSigExtensions are disabled", ErrInvalidAttribute) } conflicts := tx.Attributes[i].Value.(*transaction.Conflicts) - if err := bc.dao.HasTransaction(conflicts.Hash); errors.Is(err, dao.ErrAlreadyExists) { + // Only fully-qualified dao.ErrAlreadyExists error bothers us here, thus, we + // can safely omit the payer argument to HasTransaction call to improve performance a bit. + if err := bc.dao.HasTransaction(conflicts.Hash, nil); errors.Is(err, dao.ErrAlreadyExists) { return fmt.Errorf("%w: conflicting transaction %s is already on chain", ErrInvalidAttribute, conflicts.Hash.StringLE()) } case transaction.NotaryAssistedT: @@ -2611,7 +2613,7 @@ func (bc *Blockchain) IsTxStillRelevant(t *transaction.Transaction, txpool *memp return false } if txpool == nil { - if bc.dao.HasTransaction(t.Hash()) != nil { + if bc.dao.HasTransaction(t.Hash(), t.Signers) != nil { return false } } else if txpool.HasConflicts(t, bc) { diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index 69463f5c6..c00f4b0e9 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -1634,28 +1634,272 @@ func TestBlockchain_VerifyTx(t *testing.T) { }) t.Run("enabled", func(t *testing.T) { t.Run("dummy on-chain conflict", func(t *testing.T) { - tx := newTestTx(t, h, testScript) - require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) - conflicting := transaction.New([]byte{byte(opcode.RET)}, 1000_0000) - conflicting.ValidUntilBlock = bc.BlockHeight() + 1 - conflicting.Signers = []transaction.Signer{ - { - Account: validator.ScriptHash(), - Scopes: transaction.CalledByEntry, - }, - } - conflicting.Attributes = []transaction.Attribute{ - { - Type: transaction.ConflictsT, - Value: &transaction.Conflicts{ - Hash: tx.Hash(), + t.Run("on-chain conflict signed by malicious party", func(t *testing.T) { + tx := newTestTx(t, h, testScript) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) + conflicting := transaction.New([]byte{byte(opcode.RET)}, 1000_0000) + conflicting.ValidUntilBlock = bc.BlockHeight() + 1 + conflicting.Signers = []transaction.Signer{ + { + Account: validator.ScriptHash(), + Scopes: transaction.CalledByEntry, }, - }, - } - conflicting.NetworkFee = 1000_0000 - require.NoError(t, validator.SignTx(netmode.UnitTestNet, conflicting)) - e.AddNewBlock(t, conflicting) - require.ErrorIs(t, bc.VerifyTx(tx), core.ErrHasConflicts) + } + conflicting.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: tx.Hash(), + }, + }, + } + conflicting.NetworkFee = 1000_0000 + require.NoError(t, validator.SignTx(netmode.UnitTestNet, conflicting)) + e.AddNewBlock(t, conflicting) + // We expect `tx` to pass verification, because on-chained `conflicting` doesn't have + // `tx`'s payer in the signers list, thus, `conflicting` should be considered as + // malicious conflict. + require.NoError(t, bc.VerifyTx(tx)) + }) + t.Run("multiple on-chain conflicts signed by malicious parties", func(t *testing.T) { + m1 := e.NewAccount(t) + m2 := e.NewAccount(t) + m3 := e.NewAccount(t) + good := e.NewAccount(t) + + // txGood doesn't conflict with anyone and signed by good signer. + txGood := newTestTx(t, good.ScriptHash(), testScript) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txGood)) + + // txM1 conflicts with txGood and signed by two malicious signers. + txM1 := newTestTx(t, m1.ScriptHash(), testScript) + txM1.Signers = append(txM1.Signers, transaction.Signer{Account: m2.ScriptHash()}) + txM1.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM1.NetworkFee = 1_000_0000 + require.NoError(t, m1.SignTx(netmode.UnitTestNet, txM1)) + require.NoError(t, m2.SignTx(netmode.UnitTestNet, txM1)) + e.AddNewBlock(t, txM1) + + // txM2 conflicts with txGood and signed by one malicious signer. + txM2 := newTestTx(t, m3.ScriptHash(), testScript) + txM2.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM2.NetworkFee = 1_000_0000 + require.NoError(t, m3.SignTx(netmode.UnitTestNet, txM2)) + e.AddNewBlock(t, txM2) + + // We expect `tx` to pass verification, because on-chained `conflicting` doesn't have + // `tx`'s payer in the signers list, thus, `conflicting` should be considered as + // malicious conflict. + require.NoError(t, bc.VerifyTx(txGood)) + + // After that txGood can be added to the chain normally. + e.AddNewBlock(t, txGood) + + // And after that ErrAlreadyExist is expected on verification. + require.ErrorIs(t, bc.VerifyTx(txGood), core.ErrAlreadyExists) + }) + + t.Run("multiple on-chain conflicts signed by [valid+malicious] parties", func(t *testing.T) { + m1 := e.NewAccount(t) + m2 := e.NewAccount(t) + m3 := e.NewAccount(t) + good := e.NewAccount(t) + + // txGood doesn't conflict with anyone and signed by good signer. + txGood := newTestTx(t, good.ScriptHash(), testScript) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txGood)) + + // txM1 conflicts with txGood and signed by one malicious and one good signers. + txM1 := newTestTx(t, m1.ScriptHash(), testScript) + txM1.Signers = append(txM1.Signers, transaction.Signer{Account: good.ScriptHash()}) + txM1.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM1.NetworkFee = 1_000_0000 + require.NoError(t, m1.SignTx(netmode.UnitTestNet, txM1)) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txM1)) + e.AddNewBlock(t, txM1) + + // txM2 conflicts with txGood and signed by two malicious signers. + txM2 := newTestTx(t, m2.ScriptHash(), testScript) + txM2.Signers = append(txM2.Signers, transaction.Signer{Account: m3.ScriptHash()}) + txM2.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM2.NetworkFee = 1_000_0000 + require.NoError(t, m2.SignTx(netmode.UnitTestNet, txM2)) + require.NoError(t, m3.SignTx(netmode.UnitTestNet, txM2)) + e.AddNewBlock(t, txM2) + + // We expect `tx` to fail verification, because one of the on-chained `conflicting` + // transactions has common signers with `tx`, thus, `conflicting` should be + // considered as a valid conflict. + require.ErrorIs(t, bc.VerifyTx(txGood), core.ErrHasConflicts) + }) + + t.Run("multiple on-chain conflicts signed by [malicious+valid] parties", func(t *testing.T) { + m1 := e.NewAccount(t) + m2 := e.NewAccount(t) + m3 := e.NewAccount(t) + good := e.NewAccount(t) + + // txGood doesn't conflict with anyone and signed by good signer. + txGood := newTestTx(t, good.ScriptHash(), testScript) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txGood)) + + // txM2 conflicts with txGood and signed by two malicious signers. + txM2 := newTestTx(t, m2.ScriptHash(), testScript) + txM2.Signers = append(txM2.Signers, transaction.Signer{Account: m3.ScriptHash()}) + txM2.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM2.NetworkFee = 1_000_0000 + require.NoError(t, m2.SignTx(netmode.UnitTestNet, txM2)) + require.NoError(t, m3.SignTx(netmode.UnitTestNet, txM2)) + e.AddNewBlock(t, txM2) + + // txM1 conflicts with txGood and signed by one malicious and one good signers. + txM1 := newTestTx(t, m1.ScriptHash(), testScript) + txM1.Signers = append(txM1.Signers, transaction.Signer{Account: good.ScriptHash()}) + txM1.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM1.NetworkFee = 1_000_0000 + require.NoError(t, m1.SignTx(netmode.UnitTestNet, txM1)) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txM1)) + e.AddNewBlock(t, txM1) + + // We expect `tx` to fail verification, because one of the on-chained `conflicting` + // transactions has common signers with `tx`, thus, `conflicting` should be + // considered as a valid conflict. + require.ErrorIs(t, bc.VerifyTx(txGood), core.ErrHasConflicts) + }) + + t.Run("multiple on-chain conflicts signed by [valid + malicious + valid] parties", func(t *testing.T) { + m1 := e.NewAccount(t) + m2 := e.NewAccount(t) + m3 := e.NewAccount(t) + good := e.NewAccount(t) + + // txGood doesn't conflict with anyone and signed by good signer. + txGood := newTestTx(t, good.ScriptHash(), testScript) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txGood)) + + // txM1 conflicts with txGood and signed by one malicious and one good signers. + txM1 := newTestTx(t, m1.ScriptHash(), testScript) + txM1.Signers = append(txM1.Signers, transaction.Signer{Account: good.ScriptHash()}) + txM1.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM1.NetworkFee = 1_000_0000 + require.NoError(t, m1.SignTx(netmode.UnitTestNet, txM1)) + require.NoError(t, good.SignTx(netmode.UnitTestNet, txM1)) + e.AddNewBlock(t, txM1) + + // txM2 conflicts with txGood and signed by two malicious signers. + txM2 := newTestTx(t, m2.ScriptHash(), testScript) + txM2.Signers = append(txM2.Signers, transaction.Signer{Account: m3.ScriptHash()}) + txM2.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM2.NetworkFee = 1_000_0000 + require.NoError(t, m2.SignTx(netmode.UnitTestNet, txM2)) + require.NoError(t, m3.SignTx(netmode.UnitTestNet, txM2)) + e.AddNewBlock(t, txM2) + + // txM3 conflicts with txGood and signed by one good and one malicious signers. + txM3 := newTestTx(t, good.ScriptHash(), testScript) + txM3.Signers = append(txM3.Signers, transaction.Signer{Account: m1.ScriptHash()}) + txM3.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: txGood.Hash(), + }, + }, + } + txM3.NetworkFee = 1_000_0000 + require.NoError(t, good.SignTx(netmode.UnitTestNet, txM3)) + require.NoError(t, m1.SignTx(netmode.UnitTestNet, txM3)) + e.AddNewBlock(t, txM3) + + // We expect `tx` to fail verification, because one of the on-chained `conflicting` + // transactions has common signers with `tx`, thus, `conflicting` should be + // considered as a valid conflict. + require.ErrorIs(t, bc.VerifyTx(txGood), core.ErrHasConflicts) + }) + + t.Run("on-chain conflict signed by single valid sender", func(t *testing.T) { + tx := newTestTx(t, h, testScript) + tx.Signers = []transaction.Signer{{Account: validator.ScriptHash()}} + require.NoError(t, validator.SignTx(netmode.UnitTestNet, tx)) + conflicting := transaction.New([]byte{byte(opcode.RET)}, 1000_0000) + conflicting.ValidUntilBlock = bc.BlockHeight() + 1 + conflicting.Signers = []transaction.Signer{ + { + Account: validator.ScriptHash(), + Scopes: transaction.CalledByEntry, + }, + } + conflicting.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{ + Hash: tx.Hash(), + }, + }, + } + conflicting.NetworkFee = 1000_0000 + require.NoError(t, validator.SignTx(netmode.UnitTestNet, conflicting)) + e.AddNewBlock(t, conflicting) + // We expect `tx` to fail verification, because on-chained `conflicting` has + // `tx`'s payer as a signer. + require.ErrorIs(t, bc.VerifyTx(tx), core.ErrHasConflicts) + }) }) t.Run("attribute on-chain conflict", func(t *testing.T) { tx := neoValidatorsInvoker.Invoke(t, stackitem.NewBool(true), "transfer", neoOwner, neoOwner, 1, nil) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index ae3862eee..b6092e1fc 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -684,8 +684,11 @@ func (dao *Simple) StoreHeaderHashes(hashes []util.Uint256, height uint32) error // HasTransaction returns nil if the given store does not contain the given // Transaction hash. It returns an error in case the transaction is in chain -// or in the list of conflicting transactions. -func (dao *Simple) HasTransaction(hash util.Uint256) error { +// or in the list of conflicting transactions. If non-zero signers are specified, +// then additional check against the conflicting transaction signers intersection +// is held. Do not omit signers in case if it's important to check the validity +// of a supposedly conflicting on-chain transaction. +func (dao *Simple) HasTransaction(hash util.Uint256, signers []transaction.Signer) error { key := dao.makeExecutableKey(hash) bytes, err := dao.Store.Get(key) if err != nil { @@ -695,10 +698,33 @@ func (dao *Simple) HasTransaction(hash util.Uint256) error { if len(bytes) < 6 { return nil } - if bytes[5] == transaction.DummyVersion { + if bytes[5] != transaction.DummyVersion { + return ErrAlreadyExists + } + if len(signers) == 0 { return ErrHasConflicts } - return ErrAlreadyExists + + sMap := make(map[util.Uint160]struct{}, len(signers)) + for _, s := range signers { + sMap[s.Account] = struct{}{} + } + br := io.NewBinReaderFromBuf(bytes[6:]) + for { + var u util.Uint160 + u.DecodeBinary(br) + if br.Err != nil { + if errors.Is(br.Err, iocore.EOF) { + break + } + return fmt.Errorf("failed to decode conflict record: %w", err) + } + if _, ok := sMap[u]; ok { + return ErrHasConflicts + } + } + + return nil } // StoreAsBlock stores given block as DataBlock. It can reuse given buffer for @@ -805,18 +831,50 @@ func (dao *Simple) StoreAsTransaction(tx *transaction.Transaction, index uint32, } dao.Store.Put(key, buf.Bytes()) if dao.Version.P2PSigExtensions { - var value []byte - for _, attr := range tx.GetAttributes(transaction.ConflictsT) { + var ( + valuePrefix []byte + newSigners []byte + ) + attrs := tx.GetAttributes(transaction.ConflictsT) + for _, attr := range attrs { hash := attr.Value.(*transaction.Conflicts).Hash copy(key[1:], hash.BytesBE()) - if value == nil { - buf.Reset() - buf.WriteB(storage.ExecTransaction) - buf.WriteU32LE(index) - buf.BinWriter.WriteB(transaction.DummyVersion) - value = buf.Bytes() + + old, err := dao.Store.Get(key) + if err != nil && !errors.Is(err, storage.ErrKeyNotFound) { + return fmt.Errorf("failed to retrieve previous conflict record for %s: %w", hash.StringLE(), err) + } + if err == nil { + if len(old) <= 6 { // storage.ExecTransaction + U32LE index + transaction.DummyVersion + return fmt.Errorf("invalid conflict record format of length %d", len(old)) + } + } + buf.Reset() + buf.WriteBytes(old) + if len(old) == 0 { + if len(valuePrefix) != 0 { + buf.WriteBytes(valuePrefix) + } else { + buf.WriteB(storage.ExecTransaction) + buf.WriteU32LE(index) + buf.WriteB(transaction.DummyVersion) + } + } + newSignersOffset := buf.Len() + if len(newSigners) == 0 { + for _, s := range tx.Signers { + s.Account.EncodeBinary(buf.BinWriter) + } + } else { + buf.WriteBytes(newSigners) + } + val := buf.Bytes() + dao.Store.Put(key, val) + + if len(attrs) > 1 && len(valuePrefix) == 0 { + valuePrefix = slice.Copy(val[:6]) + newSigners = slice.Copy(val[newSignersOffset:]) } - dao.Store.Put(key, value) } } return nil diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index c9eea92b8..1e8b647cd 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -186,8 +186,8 @@ func TestStoreAsTransaction(t *testing.T) { } err := dao.StoreAsTransaction(tx, 0, aer) require.NoError(t, err) - err = dao.HasTransaction(hash) - require.NotNil(t, err) + err = dao.HasTransaction(hash, nil) + require.ErrorIs(t, err, ErrAlreadyExists) gotAppExecResult, err := dao.GetAppExecResults(hash, trigger.All) require.NoError(t, err) require.Equal(t, 1, len(gotAppExecResult)) @@ -197,34 +197,84 @@ func TestStoreAsTransaction(t *testing.T) { t.Run("P2PSigExtensions on", func(t *testing.T) { dao := NewSimple(storage.NewMemoryStore(), false, true) conflictsH := util.Uint256{1, 2, 3} - tx := transaction.New([]byte{byte(opcode.PUSH1)}, 1) - tx.Signers = append(tx.Signers, transaction.Signer{}) - tx.Scripts = append(tx.Scripts, transaction.Witness{}) - tx.Attributes = []transaction.Attribute{ + signer1 := util.Uint160{1, 2, 3} + signer2 := util.Uint160{4, 5, 6} + signer3 := util.Uint160{7, 8, 9} + signerMalicious := util.Uint160{10, 11, 12} + tx1 := transaction.New([]byte{byte(opcode.PUSH1)}, 1) + tx1.Signers = append(tx1.Signers, transaction.Signer{Account: signer1}, transaction.Signer{Account: signer2}) + tx1.Scripts = append(tx1.Scripts, transaction.Witness{}, transaction.Witness{}) + tx1.Attributes = []transaction.Attribute{ { Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: conflictsH}, }, } - hash := tx.Hash() - aer := &state.AppExecResult{ - Container: hash, + hash1 := tx1.Hash() + tx2 := transaction.New([]byte{byte(opcode.PUSH1)}, 1) + tx2.Signers = append(tx2.Signers, transaction.Signer{Account: signer3}) + tx2.Scripts = append(tx2.Scripts, transaction.Witness{}) + tx2.Attributes = []transaction.Attribute{ + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{Hash: conflictsH}, + }, + } + hash2 := tx2.Hash() + aer1 := &state.AppExecResult{ + Container: hash1, Execution: state.Execution{ Trigger: trigger.Application, Events: []state.NotificationEvent{}, Stack: []stackitem.Item{}, }, } - err := dao.StoreAsTransaction(tx, 0, aer) + err := dao.StoreAsTransaction(tx1, 0, aer1) require.NoError(t, err) - err = dao.HasTransaction(hash) + aer2 := &state.AppExecResult{ + Container: hash2, + Execution: state.Execution{ + Trigger: trigger.Application, + Events: []state.NotificationEvent{}, + Stack: []stackitem.Item{}, + }, + } + err = dao.StoreAsTransaction(tx2, 0, aer2) + require.NoError(t, err) + err = dao.HasTransaction(hash1, nil) require.ErrorIs(t, err, ErrAlreadyExists) - err = dao.HasTransaction(conflictsH) + err = dao.HasTransaction(hash2, nil) + require.ErrorIs(t, err, ErrAlreadyExists) + + // Conflicts: unimportant payer. + err = dao.HasTransaction(conflictsH, nil) require.ErrorIs(t, err, ErrHasConflicts) - gotAppExecResult, err := dao.GetAppExecResults(hash, trigger.All) + + // Conflicts: payer is important, conflict isn't malicious, test signer #1. + err = dao.HasTransaction(conflictsH, []transaction.Signer{{Account: signer1}}) + require.ErrorIs(t, err, ErrHasConflicts) + + // Conflicts: payer is important, conflict isn't malicious, test signer #2. + err = dao.HasTransaction(conflictsH, []transaction.Signer{{Account: signer2}}) + require.ErrorIs(t, err, ErrHasConflicts) + + // Conflicts: payer is important, conflict isn't malicious, test signer #3. + err = dao.HasTransaction(conflictsH, []transaction.Signer{{Account: signer3}}) + require.ErrorIs(t, err, ErrHasConflicts) + + // Conflicts: payer is important, conflict is malicious. + err = dao.HasTransaction(conflictsH, []transaction.Signer{{Account: signerMalicious}}) + require.NoError(t, err) + + gotAppExecResult, err := dao.GetAppExecResults(hash1, trigger.All) require.NoError(t, err) require.Equal(t, 1, len(gotAppExecResult)) - require.Equal(t, *aer, gotAppExecResult[0]) + require.Equal(t, *aer1, gotAppExecResult[0]) + + gotAppExecResult, err = dao.GetAppExecResults(hash2, trigger.All) + require.NoError(t, err) + require.Equal(t, 1, len(gotAppExecResult)) + require.Equal(t, *aer2, gotAppExecResult[0]) }) } diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index 10512f946..2fbce047b 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -536,17 +536,31 @@ func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) ([]*tran } } // Step 2: check if mempooled transactions were in `tx`'s attributes. - for _, attr := range tx.GetAttributes(transaction.ConflictsT) { - hash := attr.Value.(*transaction.Conflicts).Hash - existingTx, ok := mp.verifiedMap[hash] - if !ok { - continue + conflictsAttrs := tx.GetAttributes(transaction.ConflictsT) + if len(conflictsAttrs) != 0 { + txSigners := make(map[util.Uint160]struct{}, len(tx.Signers)) + for _, s := range tx.Signers { + txSigners[s.Account] = struct{}{} } - if !tx.HasSigner(existingTx.Signers[mp.payerIndex].Account) { - return nil, fmt.Errorf("%w: not signed by the sender of conflicting transaction %s", ErrConflictsAttribute, existingTx.Hash().StringBE()) + for _, attr := range conflictsAttrs { + hash := attr.Value.(*transaction.Conflicts).Hash + existingTx, ok := mp.verifiedMap[hash] + if !ok { + continue + } + var signerOK bool + for _, s := range existingTx.Signers { + if _, ok := txSigners[s.Account]; ok { + signerOK = true + break + } + } + if !signerOK { + return nil, fmt.Errorf("%w: not signed by a signer of conflicting transaction %s", ErrConflictsAttribute, existingTx.Hash().StringBE()) + } + conflictingFee += existingTx.NetworkFee + conflictsToBeRemoved = append(conflictsToBeRemoved, existingTx) } - conflictingFee += existingTx.NetworkFee - conflictsToBeRemoved = append(conflictsToBeRemoved, existingTx) } if conflictingFee != 0 && tx.NetworkFee <= conflictingFee { return nil, fmt.Errorf("%w: conflicting transactions have bigger or equal network fee: %d vs %d", ErrConflictsAttribute, tx.NetworkFee, conflictingFee) From e57967b11ceb03e438871bee5d820a7f95cda1ca Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 27 Jul 2023 16:28:19 +0300 Subject: [PATCH 123/125] rpcclient: adjust `unwrapContract` helper There may be no such contract, then Null stackitem is expected on stack. Signed-off-by: Anna Shaleva --- pkg/rpcclient/management/management.go | 9 ++++++++- pkg/rpcclient/management/management_test.go | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pkg/rpcclient/management/management.go b/pkg/rpcclient/management/management.go index c6d2e77ef..4862cd8b6 100644 --- a/pkg/rpcclient/management/management.go +++ b/pkg/rpcclient/management/management.go @@ -105,16 +105,23 @@ func (c *ContractReader) GetContract(hash util.Uint160) (*state.Contract, error) return unwrapContract(c.invoker.Call(Hash, "getContract", hash)) } -// GetContractByID allows to get contract data from its ID. +// GetContractByID allows to get contract data from its ID. In case of missing +// contract it returns nil state.Contract and nil error. func (c *ContractReader) GetContractByID(id int32) (*state.Contract, error) { return unwrapContract(c.invoker.Call(Hash, "getContractById", id)) } +// unwrapContract tries to retrieve state.Contract from the provided result.Invoke. +// If the resulting stack contains stackitem.Null, then nil state and nil error +// will be returned. func unwrapContract(r *result.Invoke, err error) (*state.Contract, error) { itm, err := unwrap.Item(r, err) if err != nil { return nil, err } + if itm.Equals(stackitem.Null{}) { + return nil, nil + } res := new(state.Contract) err = res.FromStackItem(itm) if err != nil { diff --git a/pkg/rpcclient/management/management_test.go b/pkg/rpcclient/management/management_test.go index f30531972..51f6d3390 100644 --- a/pkg/rpcclient/management/management_test.go +++ b/pkg/rpcclient/management/management_test.go @@ -100,6 +100,17 @@ func TestReader(t *testing.T) { require.NoError(t, err) require.False(t, hm) + ta.res = &result.Invoke{ + State: "HALT", + Stack: []stackitem.Item{ + stackitem.Null{}, + }, + } + + cs, err := man.GetContract(util.Uint160{1, 2, 3}) + require.NoError(t, err) + require.Nil(t, cs) + ta.res = &result.Invoke{ State: "HALT", Stack: []stackitem.Item{ @@ -127,7 +138,7 @@ func TestReader(t *testing.T) { }), }, } - cs, err := man.GetContract(util.Uint160{1, 2, 3}) + cs, err = man.GetContract(util.Uint160{1, 2, 3}) require.NoError(t, err) require.Equal(t, int32(1), cs.ID) require.Equal(t, uint16(0), cs.UpdateCounter) From 4be692193eb9d0387af57004f78804c1b41d674c Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 27 Jul 2023 18:12:02 +0300 Subject: [PATCH 124/125] vm: allow parsing scientific JSON numbers 52-bit precision is not enough for our 256-bit VM, but this value matches the reference implementation, see the https://github.com/neo-project/neo/issues/2879. MaxIntegerPrec will be increased (or even removed) as soon as the ref. issue is resolved. Signed-off-by: Anna Shaleva --- pkg/vm/stackitem/json.go | 42 ++++++++++++++++++++++++++--------- pkg/vm/stackitem/json_test.go | 30 +++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/pkg/vm/stackitem/json.go b/pkg/vm/stackitem/json.go index d7b93f623..508d91fbd 100644 --- a/pkg/vm/stackitem/json.go +++ b/pkg/vm/stackitem/json.go @@ -26,6 +26,11 @@ const MaxAllowedInteger = 2<<53 - 1 // MaxJSONDepth is the maximum allowed nesting level of an encoded/decoded JSON. const MaxJSONDepth = 10 +// MaxIntegerPrec is the maximum precision allowed for big.Integer parsing. +// It equals to the reference value and doesn't allow to precisely parse big +// numbers, see the https://github.com/neo-project/neo/issues/2879. +const MaxIntegerPrec = 53 + // ErrInvalidValue is returned when an item value doesn't fit some constraints // during serialization or deserialization. var ErrInvalidValue = errors.New("invalid value") @@ -213,18 +218,35 @@ func (d *decoder) decode() (Item, error) { return NewByteArray([]byte(t)), nil case json.Number: ts := t.String() - dot := strings.IndexByte(ts, '.') - if dot != -1 { - // As a special case numbers like 123.000 are allowed (SetString rejects them). - // And yes, that's the way C# code works also. - for _, r := range ts[dot+1:] { - if r != '0' { - return nil, fmt.Errorf("%w (real value for int)", ErrInvalidValue) - } + var ( + num *big.Int + ok bool + ) + isScientific := strings.Contains(ts, "e+") || strings.Contains(ts, "E+") + if isScientific { + // As a special case numbers like 2.8e+22 are allowed (SetString rejects them). + // That's the way how C# code works. + f, _, err := big.ParseFloat(ts, 10, MaxIntegerPrec, big.ToNearestEven) + if err != nil { + return nil, fmt.Errorf("%w (malformed exp value for int)", ErrInvalidValue) } - ts = ts[:dot] + num = new(big.Int) + _, acc := f.Int(num) + ok = acc == big.Exact + } else { + dot := strings.IndexByte(ts, '.') + if dot != -1 { + // As a special case numbers like 123.000 are allowed (SetString rejects them). + // And yes, that's the way C# code works also. + for _, r := range ts[dot+1:] { + if r != '0' { + return nil, fmt.Errorf("%w (real value for int)", ErrInvalidValue) + } + } + ts = ts[:dot] + } + num, ok = new(big.Int).SetString(ts, 10) } - num, ok := new(big.Int).SetString(ts, 10) if !ok { return nil, fmt.Errorf("%w (integer)", ErrInvalidValue) } diff --git a/pkg/vm/stackitem/json_test.go b/pkg/vm/stackitem/json_test.go index 59cc1d1a0..679da1b3b 100644 --- a/pkg/vm/stackitem/json_test.go +++ b/pkg/vm/stackitem/json_test.go @@ -8,7 +8,11 @@ import ( "github.com/stretchr/testify/require" ) -func getTestDecodeFunc(js string, expected ...any) func(t *testing.T) { +func getTestDecodeFunc(js string, expected ...interface{}) func(t *testing.T) { + return getTestDecodeEncodeFunc(js, true, expected...) +} + +func getTestDecodeEncodeFunc(js string, needEncode bool, expected ...interface{}) func(t *testing.T) { return func(t *testing.T) { actual, err := FromJSON([]byte(js), 20) if expected[0] == nil { @@ -18,7 +22,7 @@ func getTestDecodeFunc(js string, expected ...any) func(t *testing.T) { require.NoError(t, err) require.Equal(t, Make(expected[0]), actual) - if len(expected) == 1 { + if needEncode && len(expected) == 1 { encoded, err := ToJSON(actual) require.NoError(t, err) require.Equal(t, js, string(encoded)) @@ -27,6 +31,8 @@ func getTestDecodeFunc(js string, expected ...any) func(t *testing.T) { } func TestFromToJSON(t *testing.T) { + bigInt, ok := new(big.Int).SetString("28000000000000000000000", 10) + require.True(t, ok) t.Run("ByteString", func(t *testing.T) { t.Run("Empty", getTestDecodeFunc(`""`, []byte{})) t.Run("Base64", getTestDecodeFunc(`"test"`, "test")) @@ -35,6 +41,8 @@ func TestFromToJSON(t *testing.T) { t.Run("BigInteger", func(t *testing.T) { t.Run("ZeroFloat", getTestDecodeFunc(`12.000`, 12, nil)) t.Run("NonZeroFloat", getTestDecodeFunc(`12.01`, nil)) + t.Run("ExpInteger", getTestDecodeEncodeFunc(`2.8e+22`, false, bigInt)) + t.Run("ExpFloat", getTestDecodeEncodeFunc(`1.2345e+3`, false, nil)) // float value, parsing should fail for it. t.Run("Negative", getTestDecodeFunc(`-4`, -4)) t.Run("Positive", getTestDecodeFunc(`123`, 123)) }) @@ -122,6 +130,24 @@ func TestFromToJSON(t *testing.T) { }) } +// TestFromJSON_CompatBigInt ensures that maximum BigInt parsing precision matches +// the C# one, ref. https://github.com/neo-project/neo/issues/2879. +func TestFromJSON_CompatBigInt(t *testing.T) { + tcs := map[string]string{ + `9.05e+28`: "90499999999999993918259200000", + `1.871e+21`: "1871000000000000000000", + `3.0366e+32`: "303660000000000004445016810323968", + `1e+30`: "1000000000000000019884624838656", + } + for in, expected := range tcs { + t.Run(in, func(t *testing.T) { + actual, err := FromJSON([]byte(in), 5) + require.NoError(t, err) + require.Equal(t, expected, actual.Value().(*big.Int).String()) + }) + } +} + func testToJSON(t *testing.T, expectedErr error, item Item) { data, err := ToJSON(item) if expectedErr != nil { From 01a5816f04fb04b9f5832815963e60b3d0189947 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 1 Aug 2023 15:46:01 +0300 Subject: [PATCH 125/125] rpcsrv: properly set content-type and CORS for all headers Not only for successful ones. Close #3075. Signed-off-by: Anna Shaleva --- pkg/services/rpcsrv/server.go | 8 ++++---- pkg/services/rpcsrv/server_test.go | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index b57d227a5..5fcbf656c 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -2861,16 +2861,16 @@ func (s *Server) writeHTTPServerResponse(r *params.Request, w http.ResponseWrite resp.RunForErrors(func(jsonErr *neorpc.Error) { s.logRequestError(r, jsonErr) }) + w.Header().Set("Content-Type", "application/json; charset=utf-8") + if s.config.EnableCORSWorkaround { + setCORSOriginHeaders(w.Header()) + } if r.In != nil { resp := resp.(abstract) if resp.Error != nil { w.WriteHeader(getHTTPCodeForError(resp.Error)) } } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - if s.config.EnableCORSWorkaround { - setCORSOriginHeaders(w.Header()) - } encoder := json.NewEncoder(w) err := encoder.Encode(resp) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 76e0ea92b..e59055b8a 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -3350,3 +3350,21 @@ func TestFailedPreconditionShutdown(t *testing.T) { require.Eventually(t, stopped.Load, 5*time.Second, 100*time.Millisecond, "Shutdown should return") } + +func TestErrorResponseContentType(t *testing.T) { + chain, rpcSrv, httpSrv := initClearServerWithServices(t, true, false, false) + defer chain.Close() + defer rpcSrv.Shutdown() + + const ( + expectedContentType = "application/json; charset=utf-8" + req = `{"jsonrpc":"2.0", "method":"unknown","params":[]}` + ) + + cl := http.Client{Timeout: time.Second} + resp, err := cl.Post(httpSrv.URL, "application/json", strings.NewReader(req)) + require.NoErrorf(t, err, "could not make a POST request") + resp.Body.Close() + contentType := resp.Header.Get("Content-Type") + require.Equal(t, expectedContentType, contentType) +}