diff --git a/.forgejo/workflows/codegen.yml b/.forgejo/workflows/codegen.yml
deleted file mode 100644
index 3aa9594..0000000
--- a/.forgejo/workflows/codegen.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-name: Code generation
-on: [pull_request]
-
-jobs:
- wrappers:
- name: Generate wrappers
- runs-on: ubuntu-22.04
- steps:
- - uses: actions/checkout@v3
- - name: Set up Go
- uses: actions/setup-go@v3
- with:
- go-version: '1.23'
- - name: Generate wrappers
- run: make generate-wrappers
- # The command seems to be non-deterministic.
- # However, with >20 runs I haven't been able to reproduce the issue.
- # This `git diff` is here to print diff in case we catch the behaviour again.
- - name: Print diff
- run: git diff HEAD
- - name: Check that nothing has changed
- run: git diff-index --exit-code HEAD
diff --git a/.forgejo/workflows/dco.yml b/.forgejo/workflows/dco.yml
deleted file mode 100644
index 2374802..0000000
--- a/.forgejo/workflows/dco.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: DCO action
-on: [pull_request]
-
-jobs:
- dco:
- name: DCO
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0
-
- - name: Setup Go
- uses: actions/setup-go@v3
- with:
- go-version: '1.23'
-
- - name: Run commit format checker
- uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3
- with:
- from: 'origin/${{ github.event.pull_request.base.ref }}'
diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml
deleted file mode 100644
index 5a5f1f2..0000000
--- a/.forgejo/workflows/tests.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: Tests
-on: [pull_request]
-
-jobs:
- tests:
- name: Tests
- runs-on: ubuntu-latest
- strategy:
- matrix:
- go_versions: [ '1.22', '1.23' ]
- fail-fast: false
- steps:
- - uses: actions/checkout@v3
-
- - name: Set up Go
- uses: actions/setup-go@v3
- with:
- go-version: '${{ matrix.go_versions }}'
-
- - name: Run tests
- run: make test
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..85fa6d9
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @carpawell @fyrchik @cthulhu-rider
diff --git a/.forgejo/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
similarity index 100%
rename from .forgejo/ISSUE_TEMPLATE/bug_report.md
rename to .github/ISSUE_TEMPLATE/bug_report.md
diff --git a/.forgejo/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
similarity index 100%
rename from .forgejo/ISSUE_TEMPLATE/config.yml
rename to .github/ISSUE_TEMPLATE/config.yml
diff --git a/.forgejo/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
similarity index 100%
rename from .forgejo/ISSUE_TEMPLATE/feature_request.md
rename to .github/ISSUE_TEMPLATE/feature_request.md
diff --git a/.forgejo/logo.svg b/.github/logo.svg
similarity index 100%
rename from .forgejo/logo.svg
rename to .github/logo.svg
diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml
new file mode 100644
index 0000000..40ed8fc
--- /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 }}
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
new file mode 100644
index 0000000..d1856c1
--- /dev/null
+++ b/.github/workflows/go.yml
@@ -0,0 +1,20 @@
+name: Go
+
+on:
+ pull_request:
+ branches: [ master ]
+
+jobs:
+
+ tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: 1.17
+
+ - name: Test
+ run: go test -v ./...
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f9b995..ef924ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,54 +1,13 @@
# Changelog
Changelog for FrostFS Contract
-
## [Unreleased]
### Added
-- Field `state` to a namespace to indicate its' lifecycle stage (#154).
-- Method `UpdateNamespace` to adjust namespace state (#154).
-- Method `DeleteNamespace` to remove existing namespace (#168).
-
### Changed
### Removed
-### Updated
-### Fixed
-
-## [0.21.0]
-
-### Added
-- Mention domain name in error messages in the nns contract (#92)
-- Emit DeleteRecord event on record deletion in the nns contract (#114)
-
-### Changed
-- Allow to register TLD automatically (#114)
-- Use frostfsid claims as a permission to create TLD (#115)
-- Ensure subject keys are unique (#118, #129)
-
-### Fixed
-- Terminate session in `ReadIteratorItems()` (#85)
-- Declare `nns.getAllRecords` as safe (#131)
-
-## [0.20.0]
-
-### Added
-- Add `ListFullSubjects` method to the frostfsid RPC client (#107)
-- Add `ListChainNames` method to the policy contract (#105)
-- Add `DeleteRecord` method to the nns contract (#114)
-- Emit notification on record changes in nns contract (#109)
-
-### Updated
-- neo-go to v0.106.3
-
-## [0.18.0] - 2023-09-14 - Academy of Sciences Glacier
-
-### Added
-- Documentation for contract storage schema (#21)
-### Changed
-- `container.Delete()` now accepts public key along with token (#27)
-- Allow to check whether container was deleted with `container.DeletionInfo()` (#38)
-### Removed
- `subnet` contract (#20)
+
### Updated
### Fixed
### Updating from v0.17.0
diff --git a/CODEOWNERS b/CODEOWNERS
deleted file mode 100644
index 2f44ab8..0000000
--- a/CODEOWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-.forgejo/.* @potyarkin
-Makefile @potyarkin
-frostfsid/client/.* @dkirillov
-.* @TrueCloudLab/storage-core-developers @TrueCloudLab/storage-core-committers @TrueCloudLab/storage-service-developers @TrueCloudLab/storage-service-committers
-tests/.* @fyrchik
diff --git a/Makefile b/Makefile
index e6e6a51..b80cddc 100644
--- a/Makefile
+++ b/Makefile
@@ -22,13 +22,12 @@ all: sidechain mainnet
sidechain: alphabet morph nns
alphabet_sc = alphabet
-morph_sc = balance container frostfsid netmap proxy policy
+morph_sc = audit balance container frostfsid netmap proxy reputation
mainnet_sc = frostfs processing
nns_sc = nns
-all_sc = $(alphabet_sc) $(morph_sc) $(mainnet_sc) $(nns_sc)
define sc_template
-$(2)$(1)/$(1)_contract.nef: $(2)$(1)/$(1)_contract.go $(2)$(1)/config.yml
+$(2)$(1)/$(1)_contract.nef: $(2)$(1)/$(1)_contract.go
$(NEOGO) contract compile -i $(2)$(1) -c $(if $(2),$(2),$(1)/)config.yml -m $(2)$(1)/config.json -o $(2)$(1)/$(1)_contract.nef
$(if $(2),$(2)$(1)/$(1)_contract.go: alphabet/alphabet.go alphabet/alphabet.tpl
@@ -50,32 +49,9 @@ neo-go:
@go list -f '{{.Path}}/...@{{.Version}}' -m github.com/nspcc-dev/neo-go \
| xargs go install -v
-generate-wrapper.%:
- @mkdir -p ./rpcclient/$*
- @# Note, that bindings file is currently missing: is can be emitted by compiler,
- @# but this leads to a large amount of code duplication. It can be written by hand,
- @# in case we need to override the type of some variables.
- @# --config $*/$*.bindings.yml
- @# Unfortunately, primitive integer types are not yet supported.
- $(NEOGO) contract generate-rpcwrapper --manifest=$*/config.json --out ./rpcclient/$*/client.go
-
-generate-wrappers: build $(foreach sc,$(all_sc),generate-wrapper.$(sc))
-
test:
@go test ./tests/...
-# Run all code formatters
-fmts: fumpt imports
-
-# Reformat imports
-imports:
- @echo "⇒ Processing goimports check"
- @goimports -w $(all_sc) tests/
-
-fumpt:
- @echo "⇒ Processing gofumpt check"
- @gofumpt -l -w $(all_sc) tests/
-
clean:
find . -name '*.nef' -exec rm -rf {} \;
find . -name 'config.json' -exec rm -rf {} \;
diff --git a/README.md b/README.md
index d0bc70f..004861f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
FrostFS related smart contracts.
diff --git a/VERSION b/VERSION
index e124b61..a86d3df 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v0.21.4
+v0.18.0
diff --git a/alphabet/alphabet_contract.go b/alphabet/alphabet_contract.go
index af7540b..72aebe8 100644
--- a/alphabet/alphabet_contract.go
+++ b/alphabet/alphabet_contract.go
@@ -18,32 +18,38 @@ const (
indexKey = "index"
totalKey = "threshold"
nameKey = "name"
+
+ notaryDisabledKey = "notary"
)
// OnNEP17Payment is a callback for NEP-17 compatible native GAS and NEO
// contracts.
-func OnNEP17Payment(from interop.Hash160, amount int, data any) {
+func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
caller := runtime.GetCallingScriptHash()
if !common.BytesEqual(caller, []byte(gas.Hash)) && !common.BytesEqual(caller, []byte(neo.Hash)) {
common.AbortWithMessage("alphabet contract accepts GAS and NEO only")
}
}
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
ctx := storage.GetContext()
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
return
}
args := data.(struct {
- addrNetmap interop.Hash160
- addrProxy interop.Hash160
- name string
- index int
- total int
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrNetmap interop.Hash160
+ addrProxy interop.Hash160
+ name string
+ index int
+ total int
})
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrProxy) != interop.Hash160Len {
@@ -61,12 +67,13 @@ func _deploy(data any, isUpdate bool) {
// Update method updates contract source code and manifest. It can be invoked
// only by committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
if !common.HasUpdateAccess() {
panic("only committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("alphabet contract updated")
}
diff --git a/alphabet/doc.go b/alphabet/doc.go
index 9176aaf..2571e6b 100644
--- a/alphabet/doc.go
+++ b/alphabet/doc.go
@@ -17,15 +17,5 @@ for each alphabet contract.
# Contract notifications
Alphabet contract does not produce notifications to process.
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |--------------------|------------|-------------------------------------------------|
- | `netmapScriptHash` | Hash160 | netmap contract hash |
- | `proxyScriptHash` | Hash160 | proxy contract hash |
- | `name` | string | assigned glagolitic letter |
- | `index` | int | the index of deployed alphabet contract |
- | `threshold` | int | the total number of deployed alphabet contracts |
*/
package alphabet
diff --git a/audit/audit_contract.go b/audit/audit_contract.go
new file mode 100644
index 0000000..638a76d
--- /dev/null
+++ b/audit/audit_contract.go
@@ -0,0 +1,228 @@
+package audit
+
+import (
+ "git.frostfs.info/TrueCloudLab/frostfs-contract/common"
+ "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/native/crypto"
+ "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/storage"
+)
+
+type (
+ auditHeader struct {
+ epoch int
+ cid []byte
+ from interop.PublicKey
+ }
+)
+
+// Audit key is a combination of the epoch, the container ID and the public key of the node that
+// has executed the audit. Together, it shouldn't be more than 64 bytes. We can't shrink
+// epoch and container ID since we iterate over these values. But we can shrink
+// public key by using first bytes of the hashed value.
+
+// V2 format
+const maxKeySize = 24 // 24 + 32 (container ID length) + 8 (epoch length) = 64
+
+func (a auditHeader) ID() []byte {
+ var buf interface{} = a.epoch
+
+ hashedKey := crypto.Sha256(a.from)
+ shortedKey := hashedKey[:maxKeySize]
+
+ return append(buf.([]byte), append(a.cid, shortedKey...)...)
+}
+
+const (
+ netmapContractKey = "netmapScriptHash"
+
+ notaryDisabledKey = "notary"
+)
+
+func _deploy(data interface{}, isUpdate bool) {
+ ctx := storage.GetContext()
+
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
+ if isUpdate {
+ args := data.([]interface{})
+ common.CheckVersion(args[len(args)-1].(int))
+ return
+ }
+
+ args := data.(struct {
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrNetmap interop.Hash160
+ })
+
+ if len(args.addrNetmap) != interop.Hash160Len {
+ panic("incorrect length of contract script hash")
+ }
+
+ storage.Put(ctx, netmapContractKey, args.addrNetmap)
+
+ runtime.Log("audit contract initialized")
+}
+
+// Update method updates contract source code and manifest. It can be invoked
+// only by committee.
+func Update(script []byte, manifest []byte, data interface{}) {
+ if !common.HasUpdateAccess() {
+ panic("only committee can update contract")
+ }
+
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
+ runtime.Log("audit contract updated")
+}
+
+// Put method stores a stable marshalled `DataAuditResult` structure. It can be
+// invoked only by Inner Ring nodes.
+//
+// Inner Ring nodes perform audit of containers and produce `DataAuditResult`
+// structures. They are stored in audit contract and used for settlements
+// in later epochs.
+func Put(rawAuditResult []byte) {
+ ctx := storage.GetContext()
+
+ innerRing := common.InnerRingNodes()
+
+ hdr := newAuditHeader(rawAuditResult)
+ presented := false
+
+ for i := range innerRing {
+ ir := innerRing[i]
+ if common.BytesEqual(ir, hdr.from) {
+ presented = true
+
+ break
+ }
+ }
+
+ if !runtime.CheckWitness(hdr.from) || !presented {
+ panic("put access denied")
+ }
+
+ storage.Put(ctx, hdr.ID(), rawAuditResult)
+
+ runtime.Log("audit: result has been saved")
+}
+
+// Get method returns a stable marshaled DataAuditResult structure.
+//
+// The ID of the DataAuditResult can be obtained from listing methods.
+func Get(id []byte) []byte {
+ ctx := storage.GetReadOnlyContext()
+ return storage.Get(ctx, id).([]byte)
+}
+
+// List method returns a list of all available DataAuditResult IDs from
+// the contract storage.
+func List() [][]byte {
+ ctx := storage.GetReadOnlyContext()
+ it := storage.Find(ctx, []byte{}, storage.KeysOnly)
+
+ return list(it)
+}
+
+// ListByEpoch method returns a list of DataAuditResult IDs generated during
+// the specified epoch.
+func ListByEpoch(epoch int) [][]byte {
+ ctx := storage.GetReadOnlyContext()
+ var buf interface{} = epoch
+ it := storage.Find(ctx, buf.([]byte), storage.KeysOnly)
+
+ return list(it)
+}
+
+// ListByCID method returns a list of DataAuditResult IDs generated during
+// the specified epoch for the specified container.
+func ListByCID(epoch int, cid []byte) [][]byte {
+ ctx := storage.GetReadOnlyContext()
+
+ var buf interface{} = epoch
+
+ prefix := append(buf.([]byte), cid...)
+ it := storage.Find(ctx, prefix, storage.KeysOnly)
+
+ return list(it)
+}
+
+// ListByNode method returns a list of DataAuditResult IDs generated in
+// the specified epoch for the specified container by the specified Inner Ring node.
+func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte {
+ ctx := storage.GetReadOnlyContext()
+ hdr := auditHeader{
+ epoch: epoch,
+ cid: cid,
+ from: key,
+ }
+
+ it := storage.Find(ctx, hdr.ID(), storage.KeysOnly)
+
+ return list(it)
+}
+
+func list(it iterator.Iterator) [][]byte {
+ var result [][]byte
+
+ ignore := [][]byte{
+ []byte(netmapContractKey),
+ }
+
+loop:
+ for iterator.Next(it) {
+ key := iterator.Value(it).([]byte) // iterator MUST BE `storage.KeysOnly`
+ for _, ignoreKey := range ignore {
+ if common.BytesEqual(key, ignoreKey) {
+ continue loop
+ }
+ }
+
+ result = append(result, key)
+ }
+
+ return result
+}
+
+// Version returns the version of the contract.
+func Version() int {
+ return common.Version
+}
+
+// readNext reads the length from the first byte, and then reads data (max 127 bytes).
+func readNext(input []byte) ([]byte, int) {
+ var buf interface{} = input[0]
+ ln := buf.(int)
+
+ return input[1 : 1+ln], 1 + ln
+}
+
+func newAuditHeader(input []byte) auditHeader {
+ // V2 format
+ offset := int(input[1])
+ offset = 2 + offset + 1 // version prefix + version len + epoch prefix
+
+ var buf interface{} = input[offset : offset+8] // [ 8 integer bytes ]
+ epoch := buf.(int)
+
+ offset = offset + 8
+
+ // cid is a nested structure with raw bytes
+ // [ cid struct prefix (wireType + len = 2 bytes), cid value wireType (1 byte), ... ]
+ cid, cidOffset := readNext(input[offset+2+1:])
+
+ // key is a raw byte
+ // [ public key wireType (1 byte), ... ]
+ key, _ := readNext(input[offset+2+1+cidOffset+1:])
+
+ return auditHeader{
+ epoch,
+ cid,
+ key,
+ }
+}
diff --git a/audit/config.yml b/audit/config.yml
new file mode 100644
index 0000000..5033360
--- /dev/null
+++ b/audit/config.yml
@@ -0,0 +1,4 @@
+name: "Audit"
+safemethods: ["get", "list", "listByEpoch", "listByCID", "listByNode", "version"]
+permissions:
+ - methods: ["update"]
diff --git a/audit/doc.go b/audit/doc.go
new file mode 100644
index 0000000..97acfee
--- /dev/null
+++ b/audit/doc.go
@@ -0,0 +1,22 @@
+/*
+Audit contract is a contract deployed in FrostFS sidechain.
+
+Inner Ring nodes perform audit of the registered containers during every epoch.
+If a container contains StorageGroup objects, an Inner Ring node initializes
+a series of audit checks. Based on the results of these checks, the Inner Ring
+node creates a DataAuditResult structure for the container. The content of this
+structure makes it possible to determine which storage nodes have been examined and
+see the status of these checks. Regarding this information, the container owner is
+charged for data storage.
+
+Audit contract is used as a reliable and verifiable storage for all
+DataAuditResult structures. At the end of data audit routine, Inner Ring
+nodes send a stable marshaled version of the DataAuditResult structure to the
+contract. When Alphabet nodes of the Inner Ring perform settlement operations,
+they make a list and get these AuditResultStructures from the audit contract.
+
+# Contract notifications
+
+Audit contract does not produce notifications to process.
+*/
+package audit
diff --git a/balance/balance_contract.go b/balance/balance_contract.go
index 803c819..3859c6e 100644
--- a/balance/balance_contract.go
+++ b/balance/balance_contract.go
@@ -3,6 +3,7 @@ package balance
import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
"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/native/management"
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
@@ -31,13 +32,6 @@ type (
// account wasn't burnt.
Parent []byte
}
-
- // account is a stored view of Account with fixed int size
- account struct {
- Balance []byte
- Until []byte
- Parent []byte
- }
)
const (
@@ -47,6 +41,7 @@ const (
netmapContractKey = "netmapScriptHash"
containerContractKey = "containerScriptHash"
+ notaryDisabledKey = "notary"
)
var token Token
@@ -63,18 +58,22 @@ func init() {
token = createToken()
}
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
ctx := storage.GetContext()
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
return
}
args := data.(struct {
- addrNetmap interop.Hash160
- addrContainer interop.Hash160
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrNetmap interop.Hash160
+ addrContainer interop.Hash160
})
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrContainer) != interop.Hash160Len {
@@ -89,12 +88,13 @@ func _deploy(data any, isUpdate bool) {
// Update method updates contract source code and manifest. It can be invoked
// only by committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
if !common.HasUpdateAccess() {
panic("only committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("balance contract updated")
}
@@ -128,7 +128,7 @@ func BalanceOf(account interop.Hash160) int {
//
// It produces Transfer and TransferX notifications. TransferX notification
// will have empty details field.
-func Transfer(from, to interop.Hash160, amount int, data any) bool {
+func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
ctx := storage.GetContext()
return token.transfer(ctx, from, to, amount, false, nil)
}
@@ -175,7 +175,7 @@ func Lock(txDetails []byte, from, to interop.Hash160, amount, until int) {
Parent: from,
}
- setAccount(ctx, to, lockAccount)
+ common.SetSerialized(ctx, to, lockAccount)
result := token.transfer(ctx, from, to, amount, true, details)
if !result {
@@ -312,14 +312,14 @@ func (t Token) transfer(ctx storage.Context, from, to interop.Hash160, amount in
storage.Delete(ctx, from)
} else {
amountFrom.Balance = amountFrom.Balance - amount // neo-go#953
- setAccount(ctx, from, amountFrom)
+ common.SetSerialized(ctx, from, amountFrom)
}
}
if len(to) == 20 {
amountTo := getAccount(ctx, to)
amountTo.Balance = amountTo.Balance + amount // neo-go#953
- setAccount(ctx, to, amountTo)
+ common.SetSerialized(ctx, to, amountTo)
}
runtime.Notify("Transfer", from, to, amount)
@@ -330,7 +330,9 @@ func (t Token) transfer(ctx storage.Context, from, to interop.Hash160, amount in
// canTransfer returns the amount it can transfer.
func (t Token) canTransfer(ctx storage.Context, from, to interop.Hash160, amount int, innerRing bool) (Account, bool) {
- emptyAcc := Account{}
+ var (
+ emptyAcc = Account{}
+ )
if !innerRing {
if len(to) != interop.Hash160Len || !isUsableAddress(from) {
@@ -368,24 +370,11 @@ func isUsableAddress(addr interop.Hash160) bool {
return false
}
-func getAccount(ctx storage.Context, key any) Account {
+func getAccount(ctx storage.Context, key interface{}) Account {
data := storage.Get(ctx, key)
if data != nil {
- acc := std.Deserialize(data.([]byte)).(account)
- return Account{
- Balance: common.FromFixedWidth64(acc.Balance),
- Until: common.FromFixedWidth64(acc.Until),
- Parent: acc.Parent,
- }
+ return std.Deserialize(data.([]byte)).(Account)
}
return Account{}
}
-
-func setAccount(ctx storage.Context, key any, acc Account) {
- common.SetSerialized(ctx, key, account{
- Balance: common.ToFixedWidth64(acc.Balance),
- Until: common.ToFixedWidth64(acc.Until),
- Parent: acc.Parent,
- })
-}
diff --git a/balance/config.yml b/balance/config.yml
index ba2a7a6..35fad6d 100644
--- a/balance/config.yml
+++ b/balance/config.yml
@@ -1,11 +1,6 @@
name: "Balance"
supportedstandards: ["NEP-17"]
-safemethods:
- - "balanceOf"
- - "decimals"
- - "symbol"
- - "totalSupply"
- - "version"
+safemethods: ["balanceOf", "decimals", "symbol", "totalSupply", "version"]
permissions:
- methods: ["update"]
events:
diff --git a/balance/doc.go b/balance/doc.go
index 437d546..3879048 100644
--- a/balance/doc.go
+++ b/balance/doc.go
@@ -74,13 +74,5 @@ when FrostFS contract has transferred GAS assets back to the user.
type: Hash160
- name: amount
type: Integer
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |-----------------------|------------|----------------------------------|
- | `netmapScriptHash` | Hash160 | netmap contract hash |
- | `containerScriptHash` | Hash160 | container contract hash |
- | circulationKey | int | the token circulation key value |
*/
package balance
diff --git a/common/address.go b/common/address.go
deleted file mode 100644
index a5a713a..0000000
--- a/common/address.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package common
-
-import "github.com/nspcc-dev/neo-go/pkg/interop"
-
-const (
- NEO3PrefixLen = 1
- ChecksumLen = 4
-
- AddressLen = NEO3PrefixLen + interop.Hash160Len + ChecksumLen
-)
diff --git a/common/common.go b/common/common.go
index a52f749..a8cf9c2 100644
--- a/common/common.go
+++ b/common/common.go
@@ -1,11 +1,26 @@
package common
import (
+ "github.com/nspcc-dev/neo-go/pkg/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/interop/util"
)
+const (
+ panicMsgForNotaryDisabledEnv = "contract not applicable for notary-disabled environment"
+)
+
// BytesEqual compares two slices of bytes by wrapping them into strings,
// which is necessary with new util.Equals interop behaviour, see neo-go#1176.
func BytesEqual(a []byte, b []byte) bool {
return util.Equals(string(a), string(b))
}
+
+// RmAndCheckNotaryDisabledKey remove notary disabled key from storage and
+// panic in notary disabled environment
+func RmAndCheckNotaryDisabledKey(data interface{}, key interface{}) {
+ //TODO(@acid-ant): #9 remove notaryDisabled from args in future version
+ storage.Delete(storage.GetContext(), key)
+ if data.([]interface{})[0].(bool) {
+ panic(panicMsgForNotaryDisabledEnv)
+ }
+}
diff --git a/common/ir.go b/common/ir.go
index a639bf1..fbc813a 100644
--- a/common/ir.go
+++ b/common/ir.go
@@ -25,20 +25,20 @@ func AlphabetNodes() []interop.PublicKey {
}
// AlphabetAddress returns multi address of alphabet public keys.
-func AlphabetAddress() interop.Hash160 {
+func AlphabetAddress() []byte {
alphabet := neo.GetCommittee()
return Multiaddress(alphabet, false)
}
// CommitteeAddress returns multi address of committee.
-func CommitteeAddress() interop.Hash160 {
+func CommitteeAddress() []byte {
committee := neo.GetCommittee()
return Multiaddress(committee, true)
}
// Multiaddress returns default multisignature account address for N keys.
// If committee set to true, it is `M = N/2+1` committee account.
-func Multiaddress(n []interop.PublicKey, committee bool) interop.Hash160 {
+func Multiaddress(n []interop.PublicKey, committee bool) []byte {
threshold := len(n)*2/3 + 1
if committee {
threshold = len(n)/2 + 1
diff --git a/common/storage.go b/common/storage.go
index 8a184f3..3b9e494 100644
--- a/common/storage.go
+++ b/common/storage.go
@@ -1,28 +1,12 @@
package common
import (
- "github.com/nspcc-dev/neo-go/pkg/interop/convert"
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
)
// SetSerialized serializes data and puts it into contract storage.
-func SetSerialized(ctx storage.Context, key any, value interface{}) {
+func SetSerialized(ctx storage.Context, key interface{}, value interface{}) {
data := std.Serialize(value)
storage.Put(ctx, key, data)
}
-
-// ToFixedWidth64 converts x to bytes such that numbers <= math.MaxUint64
-// have constant with of 9.
-func ToFixedWidth64(x int) []byte {
- data := convert.ToBytes(x)
- if x < 0 || len(data) >= 9 {
- return data
- }
- return append(data, make([]byte, 9-len(data))...)
-}
-
-// FromFixedWidth64 is a reverse function for ToFixedWidth64.
-func FromFixedWidth64(x []byte) int {
- return convert.ToInteger(x)
-}
diff --git a/common/transfer.go b/common/transfer.go
index 14a0129..b3eebdc 100644
--- a/common/transfer.go
+++ b/common/transfer.go
@@ -31,7 +31,7 @@ func LockTransferDetails(txDetails []byte) []byte {
}
func UnlockTransferDetails(epoch int) []byte {
- var buf any = epoch
+ var buf interface{} = epoch
return append(unlockPrefix, buf.([]byte)...)
}
diff --git a/common/version.go b/common/version.go
index b72ea06..09dd6c9 100644
--- a/common/version.go
+++ b/common/version.go
@@ -4,15 +4,15 @@ import "github.com/nspcc-dev/neo-go/pkg/interop/native/std"
const (
major = 0
- minor = 21
- patch = 4
+ minor = 18
+ patch = 0
// Versions from which an update should be performed.
// These should be used in a group (so prevMinor can be equal to minor if there are
// any migration routines.
prevMajor = 0
- prevMinor = 19
- prevPatch = 4
+ prevMinor = 16
+ prevPatch = 0
Version = major*1_000_000 + minor*1_000 + patch
@@ -32,20 +32,15 @@ func CheckVersion(from int) {
if from < PrevVersion {
panic(ErrVersionMismatch + ": expected >=" + std.Itoa(PrevVersion, 10))
}
- if Version <= from {
+ if from == Version {
panic(ErrAlreadyUpdated + ": " + std.Itoa(Version, 10))
}
}
// AppendVersion appends current contract version to the list of deploy arguments.
-func AppendVersion(data any) []interface{} {
+func AppendVersion(data interface{}) []interface{} {
if data == nil {
- return []any{Version}
+ return []interface{}{Version}
}
- return append(data.([]any), Version)
-}
-
-// GetVersion returns version as int by major, minor, patch.
-func GetVersion(major, minor, patch int) int {
- return major*1_000_000 + minor*1_000 + patch
+ return append(data.([]interface{}), Version)
}
diff --git a/commonclient/invoker.go b/commonclient/invoker.go
deleted file mode 100644
index 5b3d392..0000000
--- a/commonclient/invoker.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package commonclient
-
-import (
- "github.com/google/uuid"
- "github.com/nspcc-dev/neo-go/pkg/neorpc/result"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
-)
-
-// Invoker is a subset of methods provided by struct invoker.Invoker. The subset contains only those
-// methods that are used by ActorWrapper and clients of the contracts.
-type Invoker interface {
- Run([]byte) (*result.Invoke, error)
- Call(contract util.Uint160, method string, params ...any) (*result.Invoke, error)
- TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error)
- TerminateSession(sessionID uuid.UUID) error
-}
-
-// Ensure the interface is compatible with the invoker.Invoker struct.
-var _ Invoker = (*invoker.Invoker)(nil)
diff --git a/commonclient/iterator.go b/commonclient/iterator.go
deleted file mode 100644
index a46eab8..0000000
--- a/commonclient/iterator.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package commonclient
-
-import (
- "fmt"
-
- "github.com/google/uuid"
- "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"
-)
-
-// ReadIteratorItems calls method that returns iterator and traverses the iterator until all items are read into array.
-func ReadIteratorItems(inv Invoker, batchSize int, contract util.Uint160, method string, params ...any) ([]stackitem.Item, error) {
- if batchSize <= 0 {
- panic("batch size must be positive")
- }
-
- script, err := smartcontract.CreateCallAndPrefetchIteratorScript(contract, method, batchSize, params...)
- if err != nil {
- return nil, fmt.Errorf("couldn't create unwrap script: %w", err)
- }
-
- arr, sessionID, iter, err := unwrap.ArrayAndSessionIterator(inv.Run(script))
- if err != nil {
- return nil, fmt.Errorf("unwrap session iterator: %w", err)
- }
- if (sessionID == uuid.UUID{}) {
- return arr, nil
- }
-
- defer func() {
- _ = inv.TerminateSession(sessionID)
- }()
-
- var shouldStop bool
- res := arr
- for !shouldStop {
- items, err := inv.TraverseIterator(sessionID, &iter, batchSize)
- if err != nil {
- return nil, err
- }
-
- res = append(res, items...)
- shouldStop = len(items) < batchSize
- }
-
- return res, nil
-}
diff --git a/commonclient/transaction.go b/commonclient/transaction.go
deleted file mode 100644
index 15a33aa..0000000
--- a/commonclient/transaction.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package commonclient
-
-import (
- "errors"
-
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
- "github.com/nspcc-dev/neo-go/pkg/io"
- "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"
-)
-
-// Transaction allows to invoke several contract method at once.
-type Transaction struct {
- writer *io.BufBinWriter
- buffer *io.BufBinWriter
- contract util.Uint160
-}
-
-var ErrTransactionTooLarge = errors.New("transaction/script size limit exceeded")
-
-// NewTransaction creates new transaction to accumulate contract invocations.
-func NewTransaction(contractHash util.Uint160) *Transaction {
- return &Transaction{
- writer: io.NewBufBinWriter(),
- buffer: io.NewBufBinWriter(),
- contract: contractHash,
- }
-}
-
-// WrapCall accept methods and arguments to invoke.
-// Should be used with method on clients like Client.MethodNameCall.
-func (t Transaction) WrapCall(method string, args []any) error {
- t.buffer.Reset()
- emit.AppCall(t.buffer.BinWriter, t.contract, method, callflag.All, args...)
-
- if t.writer.Len()+t.buffer.Len() > transaction.MaxScriptLength {
- return ErrTransactionTooLarge
- }
-
- t.writer.WriteBytes(t.buffer.Bytes())
-
- return t.writer.Err
-}
-
-// WrapCallErr accept methods, arguments and error to handle and invoke.
-// Should be used with method on clients like *CallErr.
-func (t Transaction) WrapCallErr(method string, args []any, err error) error {
- if err != nil {
- return err
- }
-
- return t.WrapCall(method, args)
-}
-
-// Bytes returns the resulting buffer and makes future writes return an error.
-func (t Transaction) Bytes() ([]byte, error) {
- if t.writer.Len() > transaction.MaxScriptLength {
- return nil, ErrTransactionTooLarge
- }
-
- return t.writer.Bytes(), nil
-}
diff --git a/commonclient/waiter.go b/commonclient/waiter.go
deleted file mode 100644
index 2a86043..0000000
--- a/commonclient/waiter.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package commonclient
-
-import (
- "context"
- "fmt"
- "strings"
-
- "github.com/nspcc-dev/neo-go/pkg/core/state"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
-)
-
-const alreadyExistsError = "already exists"
-
-// ContextWaiter is an interface that supports transaction awaiting with a context limit.
-type ContextWaiter interface {
- waiter.Waiter
- WaitCtx(ctx context.Context, h util.Uint256, vub uint32, err error) (*state.AppExecResult, error)
-}
-
-type WaiterOptions struct {
- // IgnoreAlreadyExistsError controls behavior for "already exists" error:
- // - If set to true, it indicates that "already exists" error is not a problem, we should
- // wait for transaction as usual (this is the behavior of neo-go [waiter.PollingBased]).
- // - If set to false, it indicates that "already exists" should be reported as an error.
- IgnoreAlreadyExistsError bool
-
- // VerifyExecResults controls whether waiter should ensure that transaction successfully
- // enters blockchain block.
- VerifyExecResults bool
-}
-
-// Waiter is a decorator on top of the standard [waiter.Waiter].
-// It provides additional behavior (controlled by [WaiterOptions]) on top of the standard
-// functionality of awaiting transactions.
-type Waiter struct {
- waiter waiter.Waiter
- options WaiterOptions
-}
-
-var _ waiter.Waiter = (*Waiter)(nil)
-
-// NewWaiter decorates the specified waiter in a new [Waiter] instance.
-func NewWaiter(waiter waiter.Waiter, options WaiterOptions) *Waiter {
- return &Waiter{
- waiter: waiter,
- options: options,
- }
-}
-
-// Wait allows to wait until transaction will be accepted to the chain.
-func (w *Waiter) Wait(h util.Uint256, vub uint32, err error) (*state.AppExecResult, error) {
- if !w.options.IgnoreAlreadyExistsError && errIsAlreadyExists(err) {
- return nil, err
- }
- result, err := w.waiter.Wait(h, vub, err)
- return w.examineExecResult(result, err)
-}
-
-// WaitCtx allows to wait until transaction is accepted to the chain.
-// Waiting is limited by the specified context.
-func (w *Waiter) WaitCtx(ctx context.Context, h util.Uint256, vub uint32, err error) (*state.AppExecResult, error) {
- if err != nil {
- shouldIgnore := errIsAlreadyExists(err) && w.options.IgnoreAlreadyExistsError
- if !shouldIgnore {
- return nil, err
- }
- }
- result, err := w.waiter.WaitAny(ctx, vub, h)
- return w.examineExecResult(result, err)
-}
-
-// WaitAny waits until at least one of the specified transactions will be accepted
-// to the chain.
-func (w *Waiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Uint256) (*state.AppExecResult, error) {
- result, err := w.waiter.WaitAny(ctx, vub, hashes...)
- return w.examineExecResult(result, err)
-}
-
-func (w *Waiter) examineExecResult(result *state.AppExecResult, err error) (*state.AppExecResult, error) {
- if !w.options.VerifyExecResults || err != nil {
- return result, err
- }
-
- if result.Execution.VMState != vmstate.Fault {
- // Transaction didn't fail, so we just return result "as is"
- return result, nil
- }
-
- // Transaction failed, we extract VM exception from it and report as an error
- if result.FaultException != "" {
- return result, fmt.Errorf("%s", result.FaultException)
- }
- return result, fmt.Errorf("transaction failed, stack=%v", result.Stack)
-}
-
-func errIsAlreadyExists(err error) bool {
- if err == nil {
- return false
- }
- return strings.Contains(strings.ToLower(err.Error()), alreadyExistsError)
-}
diff --git a/commonclient/waiter_test.go b/commonclient/waiter_test.go
deleted file mode 100644
index a614900..0000000
--- a/commonclient/waiter_test.go
+++ /dev/null
@@ -1,209 +0,0 @@
-package commonclient
-
-import (
- "context"
- "fmt"
- "testing"
-
- "github.com/nspcc-dev/neo-go/pkg/core/state"
- "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
-)
-
-type mockWaiter struct {
- mock.Mock
-}
-
-func (w *mockWaiter) successfulResult(txHash util.Uint256) *state.AppExecResult {
- return &state.AppExecResult{
- Container: txHash,
- Execution: state.Execution{
- Trigger: trigger.Application,
- VMState: vmstate.Halt,
- GasConsumed: 100500,
- Stack: nil,
- Events: nil,
- FaultException: "",
- },
- }
-}
-
-func (w *mockWaiter) failedResult(txHash util.Uint256, exception string) *state.AppExecResult {
- return &state.AppExecResult{
- Container: txHash,
- Execution: state.Execution{
- Trigger: trigger.Application,
- VMState: vmstate.Fault,
- GasConsumed: 100500,
- Stack: nil,
- Events: nil,
- FaultException: exception,
- },
- }
-}
-
-func (m *mockWaiter) Wait(h util.Uint256, vub uint32, err error) (*state.AppExecResult, error) {
- args := m.Called(h, vub, err)
- result := args.Get(0)
- if result == nil {
- return nil, args.Error(1)
- }
- return result.(*state.AppExecResult), args.Error(1)
-}
-
-func (m *mockWaiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Uint256) (*state.AppExecResult, error) {
- args := m.Called(ctx, vub, hashes)
- result := args.Get(0)
- if result == nil {
- return nil, args.Error(1)
- }
- return result.(*state.AppExecResult), args.Error(1)
-}
-
-func TestWaiter(t *testing.T) {
- txHash := util.Uint256{}
- txHashes := []util.Uint256{txHash}
-
- vub := uint32(100)
-
- t.Run("wait ignores already exists error", func(t *testing.T) {
- sendErr := fmt.Errorf("transaction already exists")
- mw := &mockWaiter{}
- mw.On("Wait", txHash, vub, mock.Anything).Return(mw.successfulResult(txHash), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{IgnoreAlreadyExistsError: true})
- _, err := waiter.Wait(txHash, vub, sendErr)
-
- require.NoError(t, err)
- })
-
- t.Run("wait reports already exists error", func(t *testing.T) {
- sendErr := fmt.Errorf("transaction already exists")
- mw := &mockWaiter{}
- mw.On("Wait", txHash, vub, mock.Anything).Return(mw.successfulResult(txHash), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{IgnoreAlreadyExistsError: false})
- _, err := waiter.Wait(txHash, vub, sendErr)
-
- require.Error(t, err)
- })
-
- t.Run("wait reports wait error when transaction error is ignored", func(t *testing.T) {
- waitErr := fmt.Errorf("mock error")
- mw := &mockWaiter{}
- mw.On("Wait", txHash, vub, nil).Return(nil, waitErr)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: false})
- _, err := waiter.Wait(txHash, vub, nil)
-
- require.ErrorIs(t, err, waitErr)
- })
-
- t.Run("wait reports wait error when transaction error is verified", func(t *testing.T) {
- waitErr := fmt.Errorf("mock error")
- mw := &mockWaiter{}
- mw.On("Wait", txHash, vub, nil).Return(nil, waitErr)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: true})
- _, err := waiter.Wait(txHash, vub, nil)
-
- require.ErrorIs(t, err, waitErr)
- })
-
- t.Run("wait ignores error from transaction", func(t *testing.T) {
- txError := "mock error"
- mw := &mockWaiter{}
- mw.On("Wait", txHash, vub, nil).Return(mw.failedResult(txHash, txError), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: false})
- _, err := waiter.Wait(txHash, vub, nil)
-
- require.NoError(t, err)
- })
-
- t.Run("wait examines error from transaction", func(t *testing.T) {
- txError := "mock error"
- mw := &mockWaiter{}
- mw.On("Wait", txHash, vub, nil).Return(mw.failedResult(txHash, txError), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: true})
- _, err := waiter.Wait(txHash, vub, nil)
-
- require.ErrorContains(t, err, txError)
- })
-
- t.Run("waitctx ignores already exists error", func(t *testing.T) {
- sendErr := fmt.Errorf("transaction already exists")
- mw := &mockWaiter{}
- mw.On("WaitAny", mock.Anything, vub, txHashes).Return(mw.successfulResult(txHash), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{IgnoreAlreadyExistsError: true})
- _, err := waiter.WaitCtx(context.Background(), txHash, vub, sendErr)
-
- require.NoError(t, err)
- mw.AssertNotCalled(t, "Wait", mock.Anything, mock.Anything, mock.Anything)
- })
-
- t.Run("waitctx reports already exists error", func(t *testing.T) {
- sendErr := fmt.Errorf("transaction already exists")
- mw := &mockWaiter{}
- mw.On("WaitAny", mock.Anything, vub, txHashes).Return(mw.successfulResult(txHash), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{IgnoreAlreadyExistsError: false})
- _, err := waiter.WaitCtx(context.Background(), txHash, vub, sendErr)
-
- require.Error(t, err)
- mw.AssertNotCalled(t, "Wait", mock.Anything, mock.Anything, mock.Anything)
- })
-
- t.Run("waitctx reports wait error when transaction error is ignored", func(t *testing.T) {
- waitErr := fmt.Errorf("mock error")
- mw := &mockWaiter{}
- mw.On("WaitAny", mock.Anything, vub, txHashes).Return(nil, waitErr)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: false})
- _, err := waiter.WaitCtx(context.Background(), txHash, vub, nil)
-
- require.ErrorIs(t, err, waitErr)
- mw.AssertNotCalled(t, "Wait", mock.Anything, mock.Anything, mock.Anything)
- })
-
- t.Run("waitctx reports wait error when transaction error is verified", func(t *testing.T) {
- waitErr := fmt.Errorf("mock error")
- mw := &mockWaiter{}
- mw.On("WaitAny", mock.Anything, vub, txHashes).Return(nil, waitErr)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: true})
- _, err := waiter.WaitCtx(context.Background(), txHash, vub, nil)
-
- require.ErrorIs(t, err, waitErr)
- mw.AssertNotCalled(t, "Wait", mock.Anything, mock.Anything, mock.Anything)
- })
-
- t.Run("waitctx ignores error from transaction", func(t *testing.T) {
- txError := "mock error"
- mw := &mockWaiter{}
- mw.On("WaitAny", mock.Anything, vub, txHashes).Return(mw.failedResult(txHash, txError), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: false})
- _, err := waiter.WaitCtx(context.Background(), txHash, vub, nil)
-
- require.NoError(t, err)
- mw.AssertNotCalled(t, "Wait", mock.Anything, mock.Anything, mock.Anything)
- })
-
- t.Run("waitctx examines error from transaction", func(t *testing.T) {
- txError := "mock error"
- mw := &mockWaiter{}
- mw.On("WaitAny", mock.Anything, vub, txHashes).Return(mw.failedResult(txHash, txError), nil)
-
- waiter := NewWaiter(mw, WaiterOptions{VerifyExecResults: true})
- _, err := waiter.WaitCtx(context.Background(), txHash, vub, nil)
-
- require.ErrorContains(t, err, txError)
- mw.AssertNotCalled(t, "Wait", mock.Anything, mock.Anything, mock.Anything)
- })
-}
diff --git a/container/config.yml b/container/config.yml
index df98605..2bf9d97 100644
--- a/container/config.yml
+++ b/container/config.yml
@@ -1,36 +1,47 @@
name: "Container"
-safemethods:
- - "count"
- - "containersOf"
- - "deletionInfo"
- - "eACL"
- - "get"
- - "getContainerSize"
- - "iterateContainerSizes"
- - "list"
- - "listContainerSizes"
- - "owner"
- - "version"
+safemethods: ["count", "containersOf", "get", "owner", "list", "eACL", "getContainerSize", "listContainerSizes", "iterateContainerSizes", "version"]
permissions:
- - methods:
- - "addRecord"
- - "deleteRecords"
- - "register"
- - "transferX"
- - "update"
- - "setAdmin"
-
+ - methods: ["update", "addKey", "transferX",
+ "register", "addRecord", "deleteRecords"]
events:
+ - name: containerPut
+ parameters:
+ - name: container
+ type: ByteArray
+ - name: signature
+ type: Signature
+ - name: publicKey
+ type: PublicKey
+ - name: token
+ type: ByteArray
- name: PutSuccess
parameters:
- name: containerID
type: Hash256
- name: publicKey
type: PublicKey
+ - name: containerDelete
+ parameters:
+ - name: containerID
+ type: ByteArray
+ - name: signature
+ type: Signature
+ - name: token
+ type: ByteArray
- name: DeleteSuccess
parameters:
- name: containerID
- type: Hash256
+ type: ByteArray
+ - name: setEACL
+ parameters:
+ - name: eACL
+ type: ByteArray
+ - name: signature
+ type: Signature
+ - name: publicKey
+ type: PublicKey
+ - name: token
+ type: ByteArray
- name: SetEACLSuccess
parameters:
- name: containerID
diff --git a/container/container_contract.go b/container/container_contract.go
index a4f0ebf..9a600d1 100644
--- a/container/container_contract.go
+++ b/container/container_contract.go
@@ -50,6 +50,7 @@ const (
nnsContractKey = "nnsScriptHash"
nnsRootKey = "nnsRoot"
nnsHasAliasKey = "nnsHasAlias"
+ notaryDisabledKey = "notary"
// RegistrationFeeKey is a key in netmap config which contains fee for container registration.
RegistrationFeeKey = "ContainerFee"
@@ -63,7 +64,6 @@ const (
estimateKeyPrefix = "cnr"
containerKeyPrefix = 'x'
ownerKeyPrefix = 'o'
- graveKeyPrefix = 'g'
estimatePostfixSize = 10
// CleanupDelta contains the number of the last epochs for which container estimations are present.
CleanupDelta = 3
@@ -82,27 +82,53 @@ const (
defaultTTL = 3600 // 1 hour
)
-var eACLPrefix = []byte("eACL")
+var (
+ eACLPrefix = []byte("eACL")
+)
// OnNEP11Payment is needed for registration with contract as the owner to work.
-func OnNEP11Payment(a interop.Hash160, b int, c []byte, d any) {
+func OnNEP11Payment(a interop.Hash160, b int, c []byte, d interface{}) {
}
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
ctx := storage.GetContext()
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
+
+ it := storage.Find(ctx, []byte{}, storage.None)
+ for iterator.Next(it) {
+ item := iterator.Value(it).(struct {
+ key []byte
+ value []byte
+ })
+
+ // Migrate container.
+ if len(item.key) == containerIDSize {
+ storage.Delete(ctx, item.key)
+ storage.Put(ctx, append([]byte{containerKeyPrefix}, item.key...), item.value)
+ }
+
+ // Migrate owner-cid map.
+ if len(item.key) == 25 /* owner id size */ +containerIDSize {
+ storage.Delete(ctx, item.key)
+ storage.Put(ctx, append([]byte{ownerKeyPrefix}, item.key...), item.value)
+ }
+ }
return
}
args := data.(struct {
- addrNetmap interop.Hash160
- addrBalance interop.Hash160
- addrID interop.Hash160
- addrNNS interop.Hash160
- nnsRoot string
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrNetmap interop.Hash160
+ addrBalance interop.Hash160
+ addrID interop.Hash160
+ addrNNS interop.Hash160
+ nnsRoot string
})
if len(args.addrNetmap) != interop.Hash160Len ||
@@ -131,7 +157,7 @@ func registerNiceNameTLD(addrNNS interop.Hash160, nnsRoot string) {
}
res := contract.Call(addrNNS, "register", contract.All,
- nnsRoot, runtime.GetExecutingScriptHash(), "ops@frostfs.info",
+ nnsRoot, runtime.GetExecutingScriptHash(), "ops@nspcc.ru",
defaultRefresh, defaultRetry, defaultExpire, defaultTTL).(bool)
if !res {
panic("can't register NNS TLD")
@@ -140,17 +166,18 @@ func registerNiceNameTLD(addrNNS interop.Hash160, nnsRoot string) {
// Update method updates contract source code and manifest. It can be invoked
// by committee only.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
if !common.HasUpdateAccess() {
panic("only committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("container contract updated")
}
// Put method creates a new container if it has been invoked by Alphabet nodes
-// of the Inner Ring.
+// of the Inner Ring. Otherwise, it produces containerPut notification.
//
// Container should be a stable marshaled Container structure from API.
// Signature is a RFC6979 signature of the Container.
@@ -165,12 +192,12 @@ func Put(container []byte, signature interop.Signature, publicKey interop.Public
// Note that zone must exist.
func PutNamed(container []byte, signature interop.Signature,
publicKey interop.PublicKey, token []byte,
- name, zone string,
-) {
+ name, zone string) {
ctx := storage.GetContext()
ownerID := ownerFromBinaryContainer(container)
containerID := crypto.Sha256(container)
+ frostfsIDContractAddr := storage.Get(ctx, frostfsIDContractKey).(interop.Hash160)
cnr := Container{
value: container,
sig: signature,
@@ -230,7 +257,7 @@ func PutNamed(container []byte, signature interop.Signature,
if name != "" {
if needRegister {
res := contract.Call(nnsContractAddr, "register", contract.All,
- domain, runtime.GetExecutingScriptHash(), "ops@frostfs.info",
+ domain, runtime.GetExecutingScriptHash(), "ops@nspcc.ru",
defaultRefresh, defaultRetry, defaultExpire, defaultTTL).(bool)
if !res {
panic("can't register the domain " + domain)
@@ -243,6 +270,10 @@ func PutNamed(container []byte, signature interop.Signature,
storage.Put(ctx, key, domain)
}
+ if len(token) == 0 { // if container created directly without session
+ contract.Call(frostfsIDContractAddr, "addKey", contract.All, ownerID, [][]byte{publicKey})
+ }
+
runtime.Log("added new container")
runtime.Notify("PutSuccess", containerID, publicKey)
}
@@ -272,14 +303,15 @@ func checkNiceNameAvailable(nnsContractAddr interop.Hash160, domain string) bool
}
// Delete method removes a container from the contract storage if it has been
-// invoked by Alphabet nodes of the Inner Ring.
+// invoked by Alphabet nodes of the Inner Ring. Otherwise, it produces
+// containerDelete notification.
//
// Signature is a RFC6979 signature of the container ID.
// Token is optional and should be a stable marshaled SessionToken structure from
// API.
//
// If the container doesn't exist, it panics with NotFoundError.
-func Delete(containerID interop.Hash256, signature interop.Signature, publicKey interop.PublicKey, token []byte) {
+func Delete(containerID []byte, signature interop.Signature, token []byte) {
ctx := storage.GetContext()
ownerID := getOwnerByID(ctx, containerID)
@@ -298,7 +330,7 @@ func Delete(containerID interop.Hash256, signature interop.Signature, publicKey
// and inability to delete a container. We should also check if we own the record in case.
nnsContractAddr := storage.Get(ctx, nnsContractKey).(interop.Hash160)
res := contract.Call(nnsContractAddr, "getRecords", contract.ReadStates|contract.AllowCall, domain, 16 /* TXT */)
- if res != nil && std.Base58Encode(containerID) == string(res.([]any)[0].(string)) {
+ if res != nil && std.Base58Encode(containerID) == string(res.([]interface{})[0].(string)) {
contract.Call(nnsContractAddr, "deleteRecords", contract.All, domain, 16 /* TXT */)
}
}
@@ -307,35 +339,6 @@ func Delete(containerID interop.Hash256, signature interop.Signature, publicKey
runtime.Notify("DeleteSuccess", containerID)
}
-type DelInfo struct {
- Owner []byte
- Epoch int
-}
-
-type delInfo struct {
- Owner []byte
- Epoch []byte
-}
-
-// DeletionInfo method returns container deletion info.
-// If the container had never existed, NotFoundError is throwed.
-// It can be used to check whether non-existing container was indeed deleted
-// or does not yet exist at some height.
-func DeletionInfo(containerID []byte) DelInfo {
- ctx := storage.GetReadOnlyContext()
- graveKey := append([]byte{graveKeyPrefix}, containerID...)
- data := storage.Get(ctx, graveKey).([]byte)
- if data == nil {
- panic(NotFoundError)
- }
-
- d := std.Deserialize(data).(delInfo)
- return DelInfo{
- Owner: d.Owner,
- Epoch: common.FromFixedWidth64(d.Epoch),
- }
-}
-
// Get method returns a structure that contains a stable marshaled Container structure,
// the signature, the public key of the container creator and a stable marshaled SessionToken
// structure if it was provided.
@@ -404,7 +407,8 @@ func List(owner []byte) [][]byte {
}
// SetEACL method sets a new extended ACL table related to the contract
-// if it was invoked by Alphabet nodes of the Inner Ring.
+// if it was invoked by Alphabet nodes of the Inner Ring. Otherwise, it produces
+// setEACL notification.
//
// EACL should be a stable marshaled EACLTable structure from API.
// Signature is a RFC6979 signature of the Container.
@@ -515,7 +519,7 @@ func GetContainerSize(id []byte) containerSizes {
func ListContainerSizes(epoch int) [][]byte {
ctx := storage.GetReadOnlyContext()
- var buf any = epoch
+ var buf interface{} = epoch
key := []byte(estimateKeyPrefix)
key = append(key, buf.([]byte)...)
@@ -547,7 +551,7 @@ func ListContainerSizes(epoch int) [][]byte {
func IterateContainerSizes(epoch int) iterator.Iterator {
ctx := storage.GetReadOnlyContext()
- var buf any = epoch
+ var buf interface{} = epoch
key := []byte(estimateKeyPrefix)
key = append(key, buf.([]byte)...)
@@ -565,21 +569,6 @@ func NewEpoch(epochNum int) {
cleanupContainers(ctx, epochNum)
}
-// SetAdmin sets admin for root container domain.
-func SetAdmin(admin interop.Hash160) {
- ctx := storage.GetReadOnlyContext()
-
- if !runtime.CheckWitness(common.CommitteeAddress()) {
- panic("only committee can set admin")
- }
-
- addrNNS := storage.Get(ctx, nnsContractKey).(interop.Hash160)
- rootContainerDomain := storage.Get(ctx, nnsRootKey).(string)
-
- contract.Call(addrNNS, "setAdmin", contract.All,
- rootContainerDomain, admin)
-}
-
// StartContainerEstimation method produces StartEstimation notification.
// It can be invoked only by Alphabet nodes of the Inner Ring.
func StartContainerEstimation(epoch int) {
@@ -610,9 +599,6 @@ func addContainer(ctx storage.Context, id, owner []byte, container Container) {
idKey := append([]byte{containerKeyPrefix}, id...)
common.SetSerialized(ctx, idKey, container)
-
- graveKey := append([]byte{graveKeyPrefix}, id...)
- storage.Delete(ctx, graveKey)
}
func removeContainer(ctx storage.Context, id []byte, owner []byte) {
@@ -621,14 +607,6 @@ func removeContainer(ctx storage.Context, id []byte, owner []byte) {
storage.Delete(ctx, containerListKey)
storage.Delete(ctx, append([]byte{containerKeyPrefix}, id...))
-
- graveKey := append([]byte{graveKeyPrefix}, id...)
- netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
- epoch := contract.Call(netmapContractAddr, "epoch", contract.ReadOnly).(int)
- common.SetSerialized(ctx, graveKey, delInfo{
- Owner: owner,
- Epoch: common.ToFixedWidth64(epoch),
- })
}
func getAllContainers(ctx storage.Context) [][]byte {
@@ -680,7 +658,7 @@ func ownerFromBinaryContainer(container []byte) []byte {
}
func estimationKey(epoch int, cid []byte, key interop.PublicKey) []byte {
- var buf any = epoch
+ var buf interface{} = epoch
hash := crypto.Ripemd160(key)
@@ -758,7 +736,7 @@ func cleanupContainers(ctx storage.Context, epoch int) {
// V2 format
nbytes := k[len(estimateKeyPrefix) : len(k)-containerIDSize-estimatePostfixSize]
- var n any = nbytes
+ var n interface{} = nbytes
if epoch-n.(int) > TotalCleanupDelta {
storage.Delete(ctx, k)
diff --git a/container/doc.go b/container/doc.go
index 20dcb6e..0636b0f 100644
--- a/container/doc.go
+++ b/container/doc.go
@@ -9,6 +9,47 @@ the same arguments.
# Contract notifications
+containerPut notification. This notification is produced when a user wants to
+create a new container. Alphabet nodes of the Inner Ring catch the notification and
+validate container data, signature and token if present.
+
+ containerPut:
+ - name: container
+ type: ByteArray
+ - name: signature
+ type: Signature
+ - name: publicKey
+ type: PublicKey
+ - name: token
+ type: ByteArray
+
+containerDelete notification. This notification is produced when a container owner
+wants to delete a container. Alphabet nodes of the Inner Ring catch the notification
+and validate container ownership, signature and token if present.
+
+ containerDelete:
+ - name: containerID
+ type: ByteArray
+ - name: signature
+ type: Signature
+ - name: token
+ type: ByteArray
+
+setEACL notification. This notification is produced when a container owner wants
+to update an extended ACL of a container. Alphabet nodes of the Inner Ring catch
+the notification and validate container ownership, signature and token if
+present.
+
+ setEACL:
+ - name: eACL
+ type: ByteArray
+ - name: signature
+ type: Signature
+ - name: publicKey
+ type: PublicKey
+ - name: token
+ type: ByteArray
+
StartEstimation notification. This notification is produced when Storage nodes
should exchange estimation values of container sizes among other Storage nodes.
@@ -23,20 +64,5 @@ it in Container contract.
StopEstimation:
- name: epoch
type: Integer
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |-----------------------------------------------------------------------------------------------------|
- | `netmapScriptHash` | Hash160 | netmap contract hash |
- | `balanceScriptHash` | Hash160 | balance contract hash |
- | `identityScriptHash` | Hash160 | frostfsID contract hash |
- | `nnsContractKey` | Hash160 | nns contract hash |
- | `nnsRoot` | string | default value for domain zone |
- | `cnr` + epoch + containerID + publicKeyHash[:10] | ByteArray | estimated container size |
- | `est` + containerID + publicKeyHash | ByteArray | serialized epochs array |
- | `o` + ownerID + containerID | ByteArray | container ID |
- | `x` + containerID | ByteArray | serialized container struct |
- | `nnsHasAlias` + containerID | string | domain name |
*/
package container
diff --git a/docs/globally-unique-domain-zone.md b/docs/globally-unique-domain-zone.md
deleted file mode 100644
index 25872cc..0000000
--- a/docs/globally-unique-domain-zone.md
+++ /dev/null
@@ -1,160 +0,0 @@
-# Globally unique domain zone
-
-**Make sure you understand the [basic concepts](../nns/README.md) of `NNS`.**
-
-`Globally Unique Domains Zone` (`GUDZ`) is an extension of `NNS` that ensures unique names across multiple domain zones. When this option is enabled, all newly created domains will automatically receive a corresponding alias in the designated global zone. Deleting a domain will also remove its alias from the global zone.
-
-It's important to note that this feature is not retroactive: domains created before this option is enabled will not receive a global alias. Likewise, if the option is later disabled, domains that already have a `GUDZ` alias will retain their records. To fully disable `GUDZ`, all domains must be recreated with the option turned off.
-
-To enable `GUDZ`, add a `cnametgt=$(global domain)` `TXT` record that specifies the global zone.
-
-**Example:**
-
-Domains:
-- `poland`
-- `sweden`
-- `animals.org`
-
-It is necessary to associate the domain zones `.poland` and `.sweden` into the global zone `.animals`.
-
-
-
-Create domains:
-
-```
-frostfs-adm morph nns register --name="poland" --email="email@email.email"
-frostfs-adm morph nns register --name="sweden" --email="email@email.email"
-frostfs-adm morph nns register --name="org" --email="email@email.email"
-frostfs-adm morph nns register --name="animals.org" --email="email@email.email"
-```
-
-Add the `cnametgt` records:
-
-```
-frostfs-adm morph nns add-record --name="poland" --data="cnametgt=animals.org" --type="txt"
-frostfs-adm morph nns add-record --name="sweden" --data="cnametgt=animals.org" --type="txt"
-```
-
-Create a domain with mapping to the global zone:
-
-```
-frostfs-adm morph nns register --name="bober.poland" --email="email@email.email"
-```
-
-Add any `TXT` record
-
-```
-frostfs-adm morph nns add-record --name="bober.poland" --data="CID" --type="txt"
-```
-
-Verify that the created domain has alias in the global zone
-
-```
-frostfs-adm morph nns tokens -v
-
-balance.frostfs
-animals.org
-group.frostfs
-container
-org
-container.frostfs
-proxy.frostfs
-policy.frostfs
-alphabet0.frostfs
-sweden
-frostfsid.frostfs
-bober.animals.org (CNAME: bober.poland)
-netmap.frostfs
-frostfs
-poland
-bober.poland
-```
-
-Create of a conflicting domain
-```
-frostfs-adm morph nns register --name="bober.sweden" --email="email@email.email"
-
-unable to register domain: script failed (FAULT state) due to an error: at instruction 1263 (THROW): unhandled exception: "global domain is already taken: bober.animals.org. Domain: bober.poland
-```
-
-**Disable GUDZ**
-Delete `cnametgt` records
-
-```
-frostfs-adm morph nns delete-records --type=txt --name=poland
-```
-Create `hamster.poland` and `hamster.sweden`
-```
-frostfs-adm morph nns register --name="hamster.poland" --email="email@email.email"
-frostfs-adm morph nns register --name="hamster.sweden" --email="email@email.email"
-```
-`hamster.poland` and `hamster.sweden` does not have alias
-```
-frostfs-adm morph nns tokens -v
-balance.frostfs
-animals.org
-group.frostfs
-container
-org
-container.frostfs
-proxy.frostfs
-policy.frostfs
-alphabet0.frostfs
-sweden
-frostfsid.frostfs
-bober.animals.org (CNAME: bober.poland)
-netmap.frostfs
-frostfs
-poland
-bober.poland
-hamster.poland
-```
-Delete global alias of `bober.poland`
-
-```
- frostfs-adm morph nns delete-records --name="bober.poland" --type="txt"
-```
-
-
-```
-frostfs-adm morph nns tokens -v
-balance.frostfs
-animals.org
-group.frostfs
-container
-org
-container.frostfs
-proxy.frostfs
-policy.frostfs
-alphabet0.frostfs
-sweden
-frostfsid.frostfs
-netmap.frostfs
-frostfs
-poland
-bober.poland
-hamster.poland
-```
-Delete `bober.poland`
-```
- frostfs-adm morph nns delete --name="bober.poland"
-```
-
-```
-frostfs-adm morph nns tokens -v
-balance.frostfs
-animals.org
-group.frostfs
-container
-org
-container.frostfs
-proxy.frostfs
-policy.frostfs
-alphabet0.frostfs
-sweden
-frostfsid.frostfs
-netmap.frostfs
-frostfs
-poland
-hamster.poland
-```
\ No newline at end of file
diff --git a/docs/img/GUDZ.drawio b/docs/img/GUDZ.drawio
deleted file mode 100644
index 13ddf92..0000000
--- a/docs/img/GUDZ.drawio
+++ /dev/null
@@ -1,139 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/img/GUDZ.png b/docs/img/GUDZ.png
deleted file mode 100644
index 6d1057d..0000000
Binary files a/docs/img/GUDZ.png and /dev/null differ
diff --git a/frostfs/config.yml b/frostfs/config.yml
index b7220bb..4718ca9 100644
--- a/frostfs/config.yml
+++ b/frostfs/config.yml
@@ -1,9 +1,5 @@
name: "FrostFS"
-safemethods:
- - "config"
- - "innerRingCandidates"
- - "listConfig"
- - "version"
+safemethods: ["alphabetAddress", "innerRingCandidates", "config", "listConfig", "version"]
permissions:
- methods: ["update", "transfer"]
events:
@@ -47,6 +43,12 @@ events:
type: ByteArray
- name: keys
type: Array
+ - name: AlphabetUpdate
+ parameters:
+ - name: id
+ type: ByteArray
+ - name: alphabet
+ type: Array
- name: SetConfig
parameters:
- name: id
diff --git a/frostfs/doc.go b/frostfs/doc.go
index ec22bd8..8a312be 100644
--- a/frostfs/doc.go
+++ b/frostfs/doc.go
@@ -80,13 +80,5 @@ FrostFS network configuration value.
type: ByteArray
- name: value
type: ByteArray
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |-----------------------------------------------------------------------------|
- | `processingScriptHash` | Hash160 | processing contract hash |
- | `candidates` + candidateKey | ByteArray | it flags inner ring candidate |
- | `config` + postfix | ByteArray | serialized config data |
*/
package frostfs
diff --git a/frostfs/frostfs_contract.go b/frostfs/frostfs_contract.go
index f43e4bf..f902d30 100644
--- a/frostfs/frostfs_contract.go
+++ b/frostfs/frostfs_contract.go
@@ -9,6 +9,7 @@ import (
"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/roles"
+ "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"
)
@@ -25,7 +26,9 @@ const (
CandidateFeeConfigKey = "InnerRingCandidateFee"
withdrawFeeConfigKey = "WithdrawFee"
- candidatesKey = "candidates"
+ alphabetKey = "alphabet"
+ candidatesKey = "candidates"
+ notaryDisabledKey = "notary"
processingContractKey = "processingScriptHash"
@@ -36,22 +39,28 @@ const (
ignoreDepositNotification = "\x57\x0b"
)
-var configPrefix = []byte("config")
+var (
+ configPrefix = []byte("config")
+)
// _deploy sets up initial alphabet node keys.
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
ctx := storage.GetContext()
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
return
}
args := data.(struct {
- addrProc interop.Hash160
- keys []interop.PublicKey
- config [][]byte
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrProc interop.Hash160
+ keys []interop.PublicKey
+ config [][]byte
})
if len(args.keys) == 0 {
@@ -69,6 +78,9 @@ func _deploy(data any, isUpdate bool) {
}
}
+ // initialize all storage slices
+ common.SetSerialized(ctx, alphabetKey, args.keys)
+
storage.Put(ctx, processingContractKey, args.addrProc)
ln := len(args.config)
@@ -88,7 +100,7 @@ func _deploy(data any, isUpdate bool) {
// Update method updates contract source code and manifest. It can be invoked
// only by sidechain committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
blockHeight := ledger.CurrentIndex()
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
alphabetCommittee := common.Multiaddress(alphabetKeys, true)
@@ -97,10 +109,18 @@ func Update(script []byte, manifest []byte, data any) {
panic(common.ErrAlphabetWitnessFailed)
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("frostfs contract updated")
}
+// AlphabetAddress returns 2\3n+1 multisignature address of alphabet nodes.
+// It is used in sidechain notary disabled environment.
+func AlphabetAddress() interop.Hash160 {
+ ctx := storage.GetReadOnlyContext()
+ return multiaddress(getAlphabetNodes(ctx))
+}
+
// InnerRingCandidates returns an array of structures that contain an Inner Ring
// candidate node key.
func InnerRingCandidates() []common.IRNode {
@@ -125,7 +145,8 @@ func InnerRingCandidateRemove(key interop.PublicKey) {
keyOwner := runtime.CheckWitness(key)
if !keyOwner {
- if !runtime.CheckWitness(common.AlphabetAddress()) {
+ multiaddr := AlphabetAddress()
+ if !runtime.CheckWitness(multiaddr) {
panic("this method must be invoked by candidate or alphabet")
}
}
@@ -170,7 +191,7 @@ func InnerRingCandidateAdd(key interop.PublicKey) {
// It takes no more than 9000.0 GAS. Native GAS has precision 8, and
// FrostFS balance contract has precision 12. Values bigger than 9000.0 can
// break JSON limits for integers when precision is converted.
-func OnNEP17Payment(from interop.Hash160, amount int, data any) {
+func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
rcv := data.(interop.Hash160)
if common.BytesEqual(rcv, []byte(ignoreDepositNotification)) {
return
@@ -301,7 +322,7 @@ func Unbind(user []byte, keys []interop.PublicKey) {
// Config returns configuration value of FrostFS configuration. If the key does
// not exists, returns nil.
-func Config(key []byte) any {
+func Config(key []byte) interface{} {
ctx := storage.GetReadOnlyContext()
return getConfig(ctx, key)
}
@@ -345,8 +366,18 @@ func Version() int {
return common.Version
}
+// getAlphabetNodes returns a deserialized slice of nodes from storage.
+func getAlphabetNodes(ctx storage.Context) []interop.PublicKey {
+ data := storage.Get(ctx, alphabetKey)
+ if data != nil {
+ return std.Deserialize(data.([]byte)).([]interop.PublicKey)
+ }
+
+ return []interop.PublicKey{}
+}
+
// getConfig returns the installed frostfs configuration value or nil if it is not set.
-func getConfig(ctx storage.Context, key any) interface{} {
+func getConfig(ctx storage.Context, key interface{}) interface{} {
postfix := key.([]byte)
storageKey := append(configPrefix, postfix...)
@@ -354,7 +385,7 @@ func getConfig(ctx storage.Context, key any) interface{} {
}
// setConfig sets a frostfs configuration value in the contract storage.
-func setConfig(ctx storage.Context, key, val any) {
+func setConfig(ctx storage.Context, key, val interface{}) {
postfix := key.([]byte)
storageKey := append(configPrefix, postfix...)
diff --git a/frostfsid/client/client.go b/frostfsid/client/client.go
deleted file mode 100644
index 8f95b00..0000000
--- a/frostfsid/client/client.go
+++ /dev/null
@@ -1,693 +0,0 @@
-package client
-
-import (
- "context"
- "fmt"
-
- "git.frostfs.info/TrueCloudLab/frostfs-contract/commonclient"
- "github.com/nspcc-dev/neo-go/pkg/core/state"
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
- "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
- "github.com/nspcc-dev/neo-go/pkg/io"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/notary"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
- "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"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
- "github.com/nspcc-dev/neo-go/pkg/wallet"
-)
-
-type (
- Client struct {
- act *actor.Actor
- waiter commonclient.ContextWaiter
- contract util.Uint160
- }
-
- Options struct {
- ProxyContract util.Uint160
- Waiter commonclient.WaiterOptions
- }
-)
-
-type (
- Subject struct {
- PrimaryKey *keys.PublicKey
- AdditionalKeys keys.PublicKeys
- Namespace string
- Name string
- KV map[string]string
- }
-
- SubjectExtended struct {
- PrimaryKey *keys.PublicKey
- AdditionalKeys keys.PublicKeys
- Namespace string
- Name string
- KV map[string]string
- Groups []*Group
- }
-
- Namespace struct {
- Name string
- State NamespaceState
- }
-
- NamespaceExtended struct {
- Name string
- State NamespaceState
- GroupsCount int64
- SubjectsCount int64
- }
-
- Group struct {
- ID int64
- Name string
- Namespace string
- KV map[string]string
- }
-
- GroupExtended struct {
- ID int64
- Name string
- Namespace string
- KV map[string]string
- SubjectsCount int64
- }
-
- NamespaceState string
-)
-
-const (
- IAMPathKey = "iam-path"
- IAMARNKey = "iam-arn"
- IAMCreatedTimeKey = "ctime"
- IAMModifiedTimeKey = "mtime"
-)
-
-const iteratorBatchSize = 100
-
-const (
- getAdminMethod = "getAdmin"
- setAdminMethod = "setAdmin"
- clearAdminMethod = "clearAdmin"
-
- versionMethod = "version"
-
- createSubjectMethod = "createSubject"
- getSubjectMethod = "getSubject"
- getSubjectExtendedMethod = "getSubjectExtended"
- getSubjectKVMethod = "getSubjectKV"
- listSubjectsMethod = "listSubjects"
- addSubjectKeyMethod = "addSubjectKey"
- removeSubjectKeyMethod = "removeSubjectKey"
- getSubjectByKeyMethod = "getSubjectByKey"
- getSubjectByNameMethod = "getSubjectByName"
- getSubjectKeyByNameMethod = "getSubjectKeyByName"
- setSubjectKVMethod = "setSubjectKV"
- setSubjectNameMethod = "setSubjectName"
- deleteSubjectKVMethod = "deleteSubjectKV"
- deleteSubjectMethod = "deleteSubject"
-
- createNamespaceMethod = "createNamespace"
- updateNamespaceMethod = "updateNamespace"
- deleteNamespaceMethod = "deleteNamespace"
- getNamespaceMethod = "getNamespace"
- getNamespaceExtendedMethod = "getNamespaceExtended"
- listNamespacesMethod = "listNamespaces"
- listNamespaceSubjectsMethod = "listNamespaceSubjects"
-
- createGroupMethod = "createGroup"
- getGroupMethod = "getGroup"
- getGroupExtendedMethod = "getGroupExtended"
- getGroupIDByNameMethod = "getGroupIDByName"
- getGroupByNameMethod = "getGroupByName"
- setGroupNameMethod = "setGroupName"
- setGroupKVMethod = "setGroupKV"
- deleteGroupKVMethod = "deleteGroupKV"
- listGroupsMethod = "listGroups"
- addSubjectToGroupMethod = "addSubjectToGroup"
- removeSubjectFromGroupMethod = "removeSubjectFromGroup"
- listGroupSubjectsMethod = "listGroupSubjects"
- deleteGroupMethod = "deleteGroup"
-)
-
-const (
- Active NamespaceState = "active"
- Frozen NamespaceState = "frozen"
- Purge NamespaceState = "purge"
-)
-
-// New creates a new Client. Options can be empty.
-func New(ra actor.RPCActor, acc *wallet.Account, contract util.Uint160, opt Options) (*Client, error) {
- signers := []actor.SignerAccount{{
- Signer: transaction.Signer{
- Account: acc.Contract.ScriptHash(),
- Scopes: transaction.CalledByEntry,
- },
- Account: acc,
- }}
-
- if !opt.ProxyContract.Equals(util.Uint160{}) {
- signers = append([]actor.SignerAccount{{
- Signer: transaction.Signer{
- Account: opt.ProxyContract,
- Scopes: transaction.CustomContracts,
- AllowedContracts: []util.Uint160{contract},
- },
- Account: notary.FakeContractAccount(opt.ProxyContract),
- }}, signers...)
- }
-
- act, err := actor.New(ra, signers)
- if err != nil {
- return nil, fmt.Errorf("init actor: %w", err)
- }
- wtr := commonclient.NewWaiter(act, opt.Waiter)
-
- return &Client{
- act: act,
- waiter: wtr,
- contract: contract,
- }, nil
-}
-
-// NewSimple creates a new Client using existing actor.Actor and default waiter options.
-func NewSimple(act *actor.Actor, contract util.Uint160) *Client {
- wtr := commonclient.NewWaiter(act, commonclient.WaiterOptions{})
- return &Client{
- act: act,
- waiter: wtr,
- contract: contract,
- }
-}
-
-// StartTx inits transaction.
-func (c Client) StartTx() *commonclient.Transaction {
- return commonclient.NewTransaction(c.contract)
-}
-
-// SendTx sends provided transaction to blockchain.
-func (c Client) SendTx(txn *commonclient.Transaction) (tx util.Uint256, vub uint32, err error) {
- txBytes, err := txn.Bytes()
- if err != nil {
- return util.Uint256{}, 0, err
- }
-
- return c.act.SendRun(txBytes)
-}
-
-// Version returns version of contract.
-func (c Client) Version() (int64, error) {
- return unwrap.Int64(c.act.Call(c.contract, versionMethod))
-}
-
-// SetAdmin sets address that can perform write operations on contract.
-// Must be invoked by committee.
-func (c Client) SetAdmin(owner util.Uint160) (tx util.Uint256, vub uint32, err error) {
- method, args := c.SetAdminCall(owner)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// SetAdminCall provides args for SetAdmin to use in commonclient.Transaction.
-func (c Client) SetAdminCall(owner util.Uint160) (method string, args []any) {
- return setAdminMethod, []any{owner}
-}
-
-// ClearAdmin removes address that can perform write operations on contract.
-// Must be invoked by committee.
-func (c Client) ClearAdmin() (tx util.Uint256, vub uint32, err error) {
- method, args := c.ClearAdminCall()
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// ClearAdminCall provides args for ClearAdmin to use in commonclient.Transaction.
-func (c Client) ClearAdminCall() (method string, args []any) {
- return clearAdminMethod, nil
-}
-
-// GetAdmin returns address that can perform write operations on contract.
-// Second return values is true iff admin is set.
-func (c Client) GetAdmin() (util.Uint160, bool, error) {
- item, err := unwrap.Item(c.act.Call(c.contract, getAdminMethod))
- if err != nil {
- return util.Uint160{}, false, err
- }
- if item.Value() == nil {
- return util.Uint160{}, false, nil
- }
- bs, err := item.TryBytes()
- if err != nil {
- return util.Uint160{}, true, err
- }
- u, err := util.Uint160DecodeBytesBE(bs)
- return u, true, err
-}
-
-// CreateSubject creates new subject using public key and namespace.
-// Must be invoked by contract owner.
-func (c Client) CreateSubject(ns string, key *keys.PublicKey) (tx util.Uint256, vub uint32, err error) {
- method, args := c.CreateSubjectCall(ns, key)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// CreateSubjectCall provides args for CreateSubject to use in commonclient.Transaction.
-func (c Client) CreateSubjectCall(ns string, key *keys.PublicKey) (method string, args []any) {
- return createSubjectMethod, []any{ns, key.Bytes()}
-}
-
-// GetSubject gets subject by address.
-func (c Client) GetSubject(addr util.Uint160) (*Subject, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getSubjectMethod, addr))
- if err != nil {
- return nil, err
- }
-
- return ParseSubject(items)
-}
-
-// GetSubjectExtended gets extended subject by address.
-func (c Client) GetSubjectExtended(addr util.Uint160) (*SubjectExtended, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getSubjectExtendedMethod, addr))
- if err != nil {
- return nil, err
- }
-
- return ParseSubjectExtended(items)
-}
-
-// GetSubjectKV invokes `getSubjectKV` method of contract.
-func (c Client) GetSubjectKV(addr util.Uint160, name string) (string, error) {
- return unwrap.UTF8String(c.act.Call(c.contract, getSubjectKVMethod, addr, name))
-}
-
-// ListSubjects gets all subjects.
-func (c Client) ListSubjects() ([]util.Uint160, error) {
- return UnwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listSubjectsMethod))
-}
-
-// ListFullSubjects gets list of subjects.
-func (c Client) ListFullSubjects(hashes []util.Uint160) ([]*Subject, error) {
- w := io.NewBufBinWriter()
-
- for _, hash := range hashes {
- emit.AppCall(w.BinWriter, c.contract, getSubjectMethod, callflag.All, hash)
- }
-
- invoker, err := c.act.Run(w.Bytes())
- if err != nil {
- return nil, err
- }
- if invoker.State != vmstate.Halt.String() {
- return nil, fmt.Errorf("invocation failed: %s", invoker.FaultException)
- }
- subjects := make([]*Subject, 0, len(invoker.Stack))
-
- for _, item := range invoker.Stack {
- arr, ok := item.Value().([]stackitem.Item)
- if !ok {
- return nil, fmt.Errorf("invalid subject")
- }
-
- subject, err := ParseSubject(arr)
- if err != nil {
- return nil, err
- }
- subjects = append(subjects, subject)
- }
-
- return subjects, nil
-}
-
-// AddSubjectKey adds extra public key to subject.
-// Must be invoked by contract owner.
-func (c Client) AddSubjectKey(addr util.Uint160, key *keys.PublicKey) (tx util.Uint256, vub uint32, err error) {
- method, args := c.AddSubjectKeyCall(addr, key)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// AddSubjectKeyCall provides args for AddSubjectKey to use in commonclient.Transaction.
-func (c Client) AddSubjectKeyCall(addr util.Uint160, key *keys.PublicKey) (method string, args []any) {
- return addSubjectKeyMethod, []any{addr, key.Bytes()}
-}
-
-// RemoveSubjectKey removes extra public key from subject.
-// Must be invoked by contract owner.
-func (c Client) RemoveSubjectKey(addr util.Uint160, key *keys.PublicKey) (tx util.Uint256, vub uint32, err error) {
- method, args := c.RemoveSubjectKeyCall(addr, key)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// RemoveSubjectKeyCall provides args for RemoveSubjectKey to use in commonclient.Transaction.
-func (c Client) RemoveSubjectKeyCall(addr util.Uint160, key *keys.PublicKey) (method string, args []any) {
- return removeSubjectKeyMethod, []any{addr, key.Bytes()}
-}
-
-// SetSubjectKV updates subject kv map.
-// Must be invoked by contract owner.
-// You can use some predefined key constants: IAMPathKey, IAMARNKey, IAMCreatedTimeKey, IAMModifiedTimeKey.
-func (c Client) SetSubjectKV(addr util.Uint160, key, val string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.SetSubjectKVCall(addr, key, val)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// SetSubjectKVCall provides args for SetSubjectKV to use in commonclient.Transaction.
-func (c Client) SetSubjectKVCall(addr util.Uint160, key, val string) (method string, args []any) {
- return setSubjectKVMethod, []any{addr, key, val}
-}
-
-// SetSubjectName updates subject name.
-// Must be invoked by contract owner.
-func (c Client) SetSubjectName(addr util.Uint160, name string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.SetSubjectNameCall(addr, name)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// SetSubjectNameCall provides args for SetSubjectName to use in commonclient.Transaction.
-func (c Client) SetSubjectNameCall(addr util.Uint160, name string) (method string, args []any) {
- return setSubjectNameMethod, []any{addr, name}
-}
-
-// DeleteSubjectKV removes subject kv map.
-// Must be invoked by contract owner.
-func (c Client) DeleteSubjectKV(addr util.Uint160, key string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.DeleteSubjectKVCall(addr, key)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// DeleteSubjectKVCall provides args for DeleteSubjectKV to use in commonclient.Transaction.
-func (c Client) DeleteSubjectKVCall(addr util.Uint160, key string) (method string, args []any) {
- return deleteSubjectKVMethod, []any{addr, key}
-}
-
-// GetSubjectByKey gets subject by its primary or additional keys.
-func (c Client) GetSubjectByKey(key *keys.PublicKey) (*Subject, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getSubjectByKeyMethod, key.Bytes()))
- if err != nil {
- return nil, err
- }
-
- return ParseSubject(items)
-}
-
-// GetSubjectByName gets subject by its name (namespace scope).
-func (c Client) GetSubjectByName(namespace, subjectName string) (*Subject, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getSubjectByNameMethod, namespace, subjectName))
- if err != nil {
- return nil, err
- }
-
- return ParseSubject(items)
-}
-
-// GetSubjectKeyByName gets subject public key by its name (namespace scope).
-func (c Client) GetSubjectKeyByName(namespace, subjectName string) (*keys.PublicKey, error) {
- return unwrap.PublicKey(c.act.Call(c.contract, getSubjectKeyByNameMethod, namespace, subjectName))
-}
-
-// DeleteSubject delete subject and removes it from related namespaces and groups.
-// Must be invoked by contract owner.
-func (c Client) DeleteSubject(addr util.Uint160) (tx util.Uint256, vub uint32, err error) {
- method, args := c.DeleteSubjectCall(addr)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// DeleteSubjectCall provides args for DeleteSubject to use in commonclient.Transaction.
-func (c Client) DeleteSubjectCall(addr util.Uint160) (method string, args []any) {
- return deleteSubjectMethod, []any{addr}
-}
-
-// CreateNamespace create new namespace.
-// Must be invoked by contract owner.
-func (c Client) CreateNamespace(namespace string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.CreateNamespaceCall(namespace)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// CreateNamespaceCall provides args for CreateNamespace to use in commonclient.Transaction.
-func (c Client) CreateNamespaceCall(namespace string) (method string, args []any) {
- return createNamespaceMethod, []any{namespace}
-}
-
-// GetNamespace gets namespace.
-func (c Client) GetNamespace(namespace string) (*Namespace, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getNamespaceMethod, namespace))
- if err != nil {
- return nil, err
- }
-
- return ParseNamespace(items)
-}
-
-// GetNamespaceExtended gets extended namespace.
-func (c Client) GetNamespaceExtended(namespace string) (*NamespaceExtended, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getNamespaceExtendedMethod, namespace))
- if err != nil {
- return nil, err
- }
-
- return ParseNamespaceExtended(items)
-}
-
-// UpdateNamespace updates namespace.
-// Must be invoked by contract owner.
-func (c Client) UpdateNamespace(namespace string, state NamespaceState) (tx util.Uint256, vub uint32, err error) {
- method, args := c.UpdateNamespaceCall(namespace, string(state))
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// UpdateNamespaceCall provides args for UpdateNamespace to use in commonclient.Transaction.
-func (c Client) UpdateNamespaceCall(namespace string, state string) (method string, args []any) {
- return updateNamespaceMethod, []any{namespace, state}
-}
-
-// DeleteNamespace idempotently removes the namespace.
-// Must be invoked by contract owner.
-func (c Client) DeleteNamespace(namespace string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.DeleteNamespaceCall(namespace)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// DeleteNamespaceCall provides args for DeleteNamespace to use in commonclient.Transaction.
-func (c Client) DeleteNamespaceCall(namespace string) (method string, args []any) {
- return deleteNamespaceMethod, []any{namespace}
-}
-
-// ListNamespaces gets all namespaces.
-func (c Client) ListNamespaces() ([]*Namespace, error) {
- items, err := commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listNamespacesMethod)
- if err != nil {
- return nil, err
- }
-
- return ParseNamespaces(items)
-}
-
-// ListNamespaceSubjects gets all subjects from namespace.
-func (c Client) ListNamespaceSubjects(namespace string) ([]util.Uint160, error) {
- return UnwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listNamespaceSubjectsMethod, namespace))
-}
-
-// CreateGroup creates a new group in specific namespace.
-// Must be invoked by contract owner.
-func (c Client) CreateGroup(namespace, group string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.CreateGroupCall(namespace, group)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// CreateGroupCall provides args for CreateGroup to use in commonclient.Transaction.
-func (c Client) CreateGroupCall(namespace, group string) (method string, args []any) {
- return createGroupMethod, []any{namespace, group}
-}
-
-// GetGroup gets group.
-func (c Client) GetGroup(namespace string, groupID int64) (*Group, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getGroupMethod, namespace, groupID))
- if err != nil {
- return nil, err
- }
-
- return ParseGroup(items)
-}
-
-// GetGroupExtended gets extended group.
-func (c Client) GetGroupExtended(namespace string, groupID int64) (*GroupExtended, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getGroupExtendedMethod, namespace, groupID))
- if err != nil {
- return nil, err
- }
-
- return ParseGroupExtended(items)
-}
-
-// SetGroupName updates subject name.
-// Must be invoked by contract owner.
-func (c Client) SetGroupName(namespace string, groupID int64, name string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.SetGroupNameCall(namespace, groupID, name)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// SetGroupNameCall provides args for SetGroupName to use in commonclient.Transaction.
-func (c Client) SetGroupNameCall(namespace string, groupID int64, name string) (method string, args []any) {
- return setGroupNameMethod, []any{namespace, groupID, name}
-}
-
-// SetGroupKV updates group kv map.
-// Must be invoked by contract owner.
-// You can use some predefined key constants: IAMPathKey, IAMARNKey, IAMCreatedTimeKey, IAMModifiedTimeKey.
-func (c Client) SetGroupKV(namespace string, groupID int64, key, val string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.SetGroupKVCall(namespace, groupID, key, val)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// SetGroupKVCall provides args for SetGroupKV to use in commonclient.Transaction.
-func (c Client) SetGroupKVCall(namespace string, groupID int64, key, val string) (method string, args []any) {
- return setGroupKVMethod, []any{namespace, groupID, key, val}
-}
-
-// DeleteGroupKV removes group kv map.
-// Must be invoked by contract owner.
-func (c Client) DeleteGroupKV(namespace string, groupID int64, key string) (tx util.Uint256, vub uint32, err error) {
- method, args := c.DeleteGroupKVCall(namespace, groupID, key)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// DeleteGroupKVCall provides args for DeleteGroupKV to use in commonclient.Transaction.
-func (c Client) DeleteGroupKVCall(namespace string, groupID int64, key string) (method string, args []any) {
- return deleteGroupKVMethod, []any{namespace, groupID, key}
-}
-
-// GetGroupIDByName gets group id its name (namespace scope).
-func (c Client) GetGroupIDByName(namespace, groupName string) (int64, error) {
- return unwrap.Int64(c.act.Call(c.contract, getGroupIDByNameMethod, namespace, groupName))
-}
-
-// GetGroupByName gets group by its name (namespace scope).
-func (c Client) GetGroupByName(namespace, groupName string) (*Group, error) {
- items, err := unwrap.Array(c.act.Call(c.contract, getGroupByNameMethod, namespace, groupName))
- if err != nil {
- return nil, err
- }
-
- return ParseGroup(items)
-}
-
-// ListGroups gets all groups in specific namespace.
-func (c Client) ListGroups(namespace string) ([]*Group, error) {
- items, err := commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listGroupsMethod, namespace)
- if err != nil {
- return nil, err
- }
-
- return ParseGroups(items)
-}
-
-// AddSubjectToGroup adds a new subject to group.
-// Must be invoked by contract owner.
-func (c Client) AddSubjectToGroup(addr util.Uint160, groupID int64) (tx util.Uint256, vub uint32, err error) {
- method, args := c.AddSubjectToGroupCall(addr, groupID)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// AddSubjectToGroupCall provides args for AddSubjectToGroup to use in commonclient.Transaction.
-func (c Client) AddSubjectToGroupCall(addr util.Uint160, groupID int64) (method string, args []any) {
- return addSubjectToGroupMethod, []any{addr, groupID}
-}
-
-// RemoveSubjectFromGroup removes subject from group.
-// Must be invoked by contract owner.
-func (c Client) RemoveSubjectFromGroup(addr util.Uint160, groupID int64) (tx util.Uint256, vub uint32, err error) {
- method, args := c.RemoveSubjectFromGroupCall(addr, groupID)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// RemoveSubjectFromGroupCall provides args for RemoveSubjectFromGroup to use in commonclient.Transaction.
-func (c Client) RemoveSubjectFromGroupCall(addr util.Uint160, groupID int64) (method string, args []any) {
- return removeSubjectFromGroupMethod, []any{addr, groupID}
-}
-
-// ListGroupSubjects gets all subjects in specific group.
-func (c Client) ListGroupSubjects(namespace string, groupID int64) ([]util.Uint160, error) {
- return UnwrapArrayOfUint160(commonclient.ReadIteratorItems(c.act, iteratorBatchSize, c.contract, listGroupSubjectsMethod, namespace, groupID))
-}
-
-// DeleteGroup deletes group.
-// Must be invoked by contract owner.
-func (c Client) DeleteGroup(namespace string, groupID int64) (tx util.Uint256, vub uint32, err error) {
- method, args := c.DeleteGroupCall(namespace, groupID)
- return c.act.SendCall(c.contract, method, args...)
-}
-
-// DeleteGroupCall provides args for DeleteGroup to use in commonclient.Transaction.
-func (c Client) DeleteGroupCall(namespace string, groupID int64) (method string, args []any) {
- return deleteGroupMethod, []any{namespace, groupID}
-}
-
-// ListNonEmptyNamespaces gets namespaces that contain at least one subject.
-func (c Client) ListNonEmptyNamespaces() ([]string, error) {
- namespaces, err := c.ListNamespaces()
- if err != nil {
- return nil, err
- }
-
- var res []string
-
- for _, namespace := range namespaces {
- nsExt, err := c.GetNamespaceExtended(namespace.Name)
- if err != nil {
- return nil, err
- }
-
- if nsExt.SubjectsCount > 0 {
- res = append(res, nsExt.Name)
- }
- }
-
- return res, nil
-}
-
-// Wait waits until the specified transaction is accepted to the chain.
-// Deprecated: use [Waiter] method instead.
-func (c Client) Wait(tx util.Uint256, vub uint32, err error) (*state.AppExecResult, error) {
- return c.Waiter().WaitCtx(context.TODO(), tx, vub, err)
-}
-
-// Waiter returns underlying waiter.
-func (c Client) Waiter() commonclient.ContextWaiter {
- return c.waiter
-}
-
-// ParseGroupID fetch groupID from stack after creating group method invocation.
-func (c Client) ParseGroupID(res *state.AppExecResult, err error) (int64, error) {
- if err != nil {
- return 0, err
- }
-
- return unwrap.Int64(makeResFromAppExec(res))
-}
-
-// ListNonEmptyGroups gets groups that contain at least one subject.
-func (c Client) ListNonEmptyGroups(namespace string) ([]string, error) {
- groups, err := c.ListGroups(namespace)
- if err != nil {
- return nil, err
- }
-
- var res []string
-
- for _, group := range groups {
- groupExt, err := c.GetGroupExtended(namespace, group.ID)
- if err != nil {
- return nil, err
- }
-
- if groupExt.SubjectsCount > 0 {
- res = append(res, groupExt.Name)
- }
- }
-
- return res, nil
-}
diff --git a/frostfsid/client/utils.go b/frostfsid/client/utils.go
deleted file mode 100644
index 4dc0c70..0000000
--- a/frostfsid/client/utils.go
+++ /dev/null
@@ -1,332 +0,0 @@
-package client
-
-import (
- "errors"
- "fmt"
-
- "github.com/nspcc-dev/neo-go/pkg/core/state"
- "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"
- "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
-)
-
-func UnwrapArrayOfUint160(items []stackitem.Item, err error) ([]util.Uint160, error) {
- if err != nil {
- return nil, err
- }
-
- return unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(items)))
-}
-
-func ParseSubject(structArr []stackitem.Item) (*Subject, error) {
- if len(structArr) < 5 {
- return nil, errors.New("invalid response subject struct")
- }
-
- var (
- err error
- subj Subject
- )
-
- subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0]))
- if err != nil {
- return nil, err
- }
-
- if !structArr[1].Equals(stackitem.Null{}) {
- subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1]))
- if err != nil {
- return nil, err
- }
- }
-
- if !structArr[2].Equals(stackitem.Null{}) {
- subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2]))
- if err != nil {
- return nil, err
- }
- }
-
- if !structArr[2].Equals(stackitem.Null{}) {
- subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3]))
- if err != nil {
- return nil, err
- }
- }
-
- subj.KV, err = ParseMap(structArr[4])
- if err != nil {
- return nil, err
- }
-
- return &subj, nil
-}
-
-func ParseSubjectExtended(structArr []stackitem.Item) (*SubjectExtended, error) {
- if len(structArr) < 6 {
- return nil, errors.New("invalid response subject extended struct")
- }
-
- var (
- err error
- subj SubjectExtended
- )
-
- subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0]))
- if err != nil {
- return nil, err
- }
-
- if !structArr[1].Equals(stackitem.Null{}) {
- subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1]))
- if err != nil {
- return nil, err
- }
- }
-
- nsBytes, err := structArr[2].TryBytes()
- if err != nil {
- return nil, err
- }
- subj.Namespace = string(nsBytes)
-
- nameBytes, err := structArr[3].TryBytes()
- if err != nil {
- return nil, err
- }
- subj.Name = string(nameBytes)
-
- subj.KV, err = ParseMap(structArr[4])
- if err != nil {
- return nil, err
- }
-
- if !structArr[5].Equals(stackitem.Null{}) {
- groupItems, ok := structArr[5].Value().([]stackitem.Item)
- if !ok {
- return nil, fmt.Errorf("invalid groups field")
- }
-
- subj.Groups, err = ParseGroups(groupItems)
- if err != nil {
- return nil, err
- }
- }
-
- return &subj, nil
-}
-
-func ParseMap(item stackitem.Item) (map[string]string, error) {
- if item.Equals(stackitem.Null{}) {
- return nil, nil
- }
-
- metaMap, err := unwrap.Map(makeValidRes(item))
- if err != nil {
- return nil, err
- }
-
- meta, ok := metaMap.Value().([]stackitem.MapElement)
- if !ok {
- return nil, errors.New("invalid map type")
- }
-
- res := make(map[string]string, len(meta))
- for _, element := range meta {
- key, err := element.Key.TryBytes()
- if err != nil {
- return nil, err
- }
- val, err := element.Value.TryBytes()
- if err != nil {
- return nil, err
- }
- res[string(key)] = string(val)
- }
-
- return res, nil
-}
-
-func ParseNamespace(structArr []stackitem.Item) (*Namespace, error) {
- if len(structArr) < 1 {
- return nil, errors.New("invalid response namespace struct")
- }
-
- return parseNamespace(structArr, 1)
-}
-
-func ParseNamespaceExtended(structArr []stackitem.Item) (*NamespaceExtended, error) {
- if len(structArr) < 3 {
- return nil, errors.New("invalid response namespace extended struct")
- }
-
- ns, err := parseNamespace(structArr, 3)
- if err != nil {
- return nil, err
- }
-
- groupCount, err := structArr[1].TryInteger()
- if err != nil {
- return nil, err
- }
-
- subjectCount, err := structArr[2].TryInteger()
- if err != nil {
- return nil, err
- }
-
- return &NamespaceExtended{
- Name: ns.Name,
- State: ns.State,
- GroupsCount: groupCount.Int64(),
- SubjectsCount: subjectCount.Int64(),
- }, nil
-}
-
-func parseNamespace(structArr []stackitem.Item, stateIndex int) (*Namespace, error) {
- name, err := structArr[0].TryBytes()
- if err != nil {
- return nil, err
- }
-
- nsState := Active
- if len(structArr) >= stateIndex+1 {
- nsStateBytes, err := structArr[stateIndex].TryBytes()
- if err != nil {
- return nil, err
- }
-
- if len(nsStateBytes) > 0 {
- nsState = NamespaceState(nsStateBytes)
- }
- }
-
- return &Namespace{
- Name: string(name),
- State: nsState,
- }, nil
-}
-
-func ParseNamespaces(items []stackitem.Item) ([]*Namespace, error) {
- var err error
- res := make([]*Namespace, len(items))
-
- for i := 0; i < len(items); i++ {
- arr, ok := items[i].Value().([]stackitem.Item)
- if !ok {
- return nil, fmt.Errorf("invalid namespace type")
- }
- res[i], err = ParseNamespace(arr)
- if err != nil {
- return nil, err
- }
- }
-
- return res, nil
-}
-
-func ParseGroup(structArr []stackitem.Item) (*Group, error) {
- if len(structArr) < 4 {
- return nil, errors.New("invalid response group struct")
- }
-
- groupID, err := structArr[0].TryInteger()
- if err != nil {
- return nil, err
- }
-
- name, err := structArr[1].TryBytes()
- if err != nil {
- return nil, err
- }
-
- namespace, err := structArr[2].TryBytes()
- if err != nil {
- return nil, err
- }
-
- kvs, err := ParseMap(structArr[3])
- if err != nil {
- return nil, err
- }
-
- return &Group{
- ID: groupID.Int64(),
- Name: string(name),
- Namespace: string(namespace),
- KV: kvs,
- }, nil
-}
-
-func ParseGroupExtended(structArr []stackitem.Item) (*GroupExtended, error) {
- if len(structArr) < 5 {
- return nil, errors.New("invalid response group extended struct")
- }
-
- groupID, err := structArr[0].TryInteger()
- if err != nil {
- return nil, err
- }
-
- name, err := structArr[1].TryBytes()
- if err != nil {
- return nil, err
- }
-
- namespace, err := structArr[2].TryBytes()
- if err != nil {
- return nil, err
- }
-
- kvs, err := ParseMap(structArr[3])
- if err != nil {
- return nil, err
- }
-
- subjectCount, err := structArr[4].TryInteger()
- if err != nil {
- return nil, err
- }
-
- return &GroupExtended{
- ID: groupID.Int64(),
- Name: string(name),
- Namespace: string(namespace),
- KV: kvs,
- SubjectsCount: subjectCount.Int64(),
- }, nil
-}
-
-func ParseGroups(items []stackitem.Item) ([]*Group, error) {
- var err error
- res := make([]*Group, len(items))
-
- for i := 0; i < len(items); i++ {
- arr, ok := items[i].Value().([]stackitem.Item)
- if !ok {
- return nil, fmt.Errorf("invalid group type")
- }
- res[i], err = ParseGroup(arr)
- if err != nil {
- return nil, err
- }
- }
-
- return res, nil
-}
-
-func makeValidRes(item stackitem.Item) (*result.Invoke, error) {
- return &result.Invoke{
- Stack: []stackitem.Item{item},
- State: vmstate.Halt.String(),
- }, nil
-}
-
-func makeResFromAppExec(res *state.AppExecResult) (*result.Invoke, error) {
- return &result.Invoke{
- Stack: res.Stack,
- State: res.VMState.String(),
- }, nil
-}
diff --git a/frostfsid/config.yml b/frostfsid/config.yml
index be3cfb3..a8daad2 100644
--- a/frostfsid/config.yml
+++ b/frostfsid/config.yml
@@ -1,144 +1,4 @@
name: "Identity"
-safemethods:
- - "getAdmin"
- - "getGroup"
- - "getGroupExtended"
- - "getGroupIDByName"
- - "getGroupByName"
- - "getNamespace"
- - "getNamespaceExtended"
- - "getSubjectKV"
- - "getSubject"
- - "getSubjectExtended"
- - "getSubjectByKey"
- - "getSubjectByName"
- - "getSubjectKeyByName"
- - "listGroups"
- - "listGroupSubjects"
- - "listNamespaces"
- - "listNamespaceSubjects"
- - "listSubjects"
- - "version"
+safemethods: ["key", "version"]
permissions:
- methods: ["update"]
-events:
- - name: CreateSubject
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: AddSubjectKey
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: subjectKey
- type: PublicKey
- - name: RemoveSubjectKey
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: subjectKey
- type: PublicKey
- - name: SetSubjectName
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: name
- type: String
- - name: SetSubjectKV
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: key
- type: String
- - name: value
- type: String
- - name: DeleteSubjectKV
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: key
- type: String
- - name: DeleteSubject
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: CreateNamespace
- parameters:
- - name: namespace
- type: String
- - name: UpdateNamespace
- parameters:
- - name: namespace
- type: String
- - name: state
- type: String
- - name: DeleteNamespace
- parameters:
- - name: namespace
- type: String
- - name: AddSubjectToNamespace
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: namespace
- type: String
- - name: RemoveSubjectFromNamespace
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: namespace
- type: String
- - name: CreateGroup
- parameters:
- - name: namespace
- type: String
- - name: group
- type: String
- - name: SetGroupName
- parameters:
- - name: namespace
- type: String
- - name: groupID
- type: Integer
- - name: name
- type: String
- - name: SetGroupKV
- parameters:
- - name: namespace
- type: String
- - name: groupID
- type: Integer
- - name: key
- type: String
- - name: value
- type: String
- - name: DeleteGroupKV
- parameters:
- - name: namespace
- type: String
- - name: groupID
- type: Integer
- - name: key
- type: String
- - name: AddSubjectToGroup
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: namespace
- type: String
- - name: groupID
- type: Integer
- - name: RemoveSubjectFromGroup
- parameters:
- - name: subjectAddress
- type: Hash160
- - name: namespace
- type: String
- - name: groupID
- type: Integer
- - name: DeleteGroup
- parameters:
- - name: namespace
- type: String
- - name: groupID
- type: Integer
diff --git a/frostfsid/doc.go b/frostfsid/doc.go
index a887f42..e15832d 100644
--- a/frostfsid/doc.go
+++ b/frostfsid/doc.go
@@ -1,28 +1,20 @@
-// Package frostfsid
/*
FrostFSID contract is a contract deployed in FrostFS sidechain.
+FrostFSID contract is used to store connection between an OwnerID and its public keys.
+OwnerID is a 25-byte N3 wallet address that can be produced from a public key.
+It is one-way conversion. In simple cases, FrostFS verifies ownership by checking
+signature and relation between a public key and an OwnerID.
+
+In more complex cases, a user can use public keys unrelated to the OwnerID to maintain
+secure access to the data. FrostFSID contract stores relation between an OwnerID and
+arbitrary public keys. Data owner can bind a public key with its account or unbind it
+by invoking Bind or Unbind methods of FrostFS contract in the mainchain. After that,
+Alphabet nodes produce multisigned AddKey and RemoveKey invocations of FrostFSID
+contract.
+
# Contract notifications
FrostFSID contract does not produce notifications to process.
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |------------------------------------------------------------------------------|--------------------------------|-----------------------------------------------|
- | `o` + [ owner address ] | []byte{1} | contract owners that can invoke write methods |
- | `s` + [ subject address ] | Serialized Subject structure | subject into |
- | `a` + [ pk address ] + [ subject address ] | []byte{1} | link extra public keys for subject |
- | `n` + [ RIPEMD160 of namespace ] | Serialized Namespace structure | namespace info |
- | `N` + [ RIPEMD160 of namespace ] + [ subject address ] | []byte{1} | subject that belongs to the namespace |
- | `l` + [ RIPEMD160 of namespace ] + [ RIPEMD160 of subject name ] | Subject public key | subject name to public key index |
- | `g` + [ RIPEMD160 of namespace ] + [ 8 byte group id ] | Serialized Group structure | group into |
- | `G` + [ RIPEMD160 of namespace ] + [ 8 byte group id ] + [ subject address ] | []byte{1} | subject that belongs to the group |
- | `c` | Int | group id counter |
- | `m` + [ RIPEMD160 of namespace ] + [ RIPEMD160 of subject name ] | Serialized group id int | group name to group id index |
- | `A` + [ subject address ] | bool | means that the wallet has been used |
- | `d` + [ subject address ] + [ pk address ] | []byte{1} | link subject to extra public keys |
-
-
*/
package frostfsid
diff --git a/frostfsid/frostfsid_contract.go b/frostfsid/frostfsid_contract.go
index 1167041..58d6fbc 100644
--- a/frostfsid/frostfsid_contract.go
+++ b/frostfsid/frostfsid_contract.go
@@ -4,1242 +4,159 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
"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/convert"
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
- "github.com/nspcc-dev/neo-go/pkg/interop/native/crypto"
"github.com/nspcc-dev/neo-go/pkg/interop/native/management"
- "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"
)
type (
- // Subject represents a subject entity.
- //
- // Fields:
- // - Namespace: a string representing the namespace of the subject.
- // - Name: a string representing the name of the subject.
- // The name must match the following regex pattern: ^[\w+=,.@-]{1,64}$
- // The Subject is stored in the storage as a hash(namespace) + hash(name).
- // AdditionalKeys are stored in records with subject's address prefix.
- Subject struct {
- PrimaryKey interop.PublicKey
- AdditionalKeys []interop.PublicKey
- Namespace string
- Name string
- KV map[string]string
- }
-
- SubjectExtended struct {
- PrimaryKey interop.PublicKey
- AdditionalKeys []interop.PublicKey
- Namespace string
- Name string
- KV map[string]string
- Groups []Group
- }
-
- // Namespace represents a namespace.
- //
- // Fields:
- // - Name: a string representing the name of the namespace.
- // The custom name must match the following regex pattern:
- // (^$)|(^[a-z0-9]{1,2}$)|(^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$)
- // An empty Name is considered the namespace.
- //
- // The Namespace is stored in the storage as a hash(name).
- Namespace struct {
- Name string
- State string
- }
-
- NamespaceExtended struct {
- Name string
- GroupsCount int
- SubjectsCount int
- State string
- }
-
- // Group represents a group entity.
- //
- // Fields:
- // - ID: an integer representing the unique identifier of the group.
- // The ID is generated upon creation and is the sequential number of the group within the namespace.
- // It cannot be changed once set.
- // - Name: a string representing the name of the group.
- // The name must match the following regex pattern: [\w+=,.@-]{1,128}$
- // - Namespace: a string representing the namespace of the group.
- // A group exists only within one namespace.
- //
- // The group is stored in the storage as a hash(namespace) + hash(name).
- Group struct {
- ID int
- Name string
- Namespace string
- KV map[string]string
- }
-
- GroupExtended struct {
- ID int
- Name string
- Namespace string
- KV map[string]string
- SubjectsCount int
+ UserInfo struct {
+ Keys [][]byte
}
)
const (
- adminKey = 'o'
- subjectKeysPrefix = 's'
- additionalKeysPrefix = 'a'
- namespaceKeysPrefix = 'n'
- namespaceSubjectsKeysPrefix = 'N'
- namespaceSubjectsNamesPrefix = 'l'
- groupKeysPrefix = 'g'
- groupSubjectsKeysPrefix = 'G'
- groupCounterKey = 'c'
- namespaceGroupsNamesPrefix = 'm'
- addressPrefix = 'A'
- subjectToAddKeyPrefix = 'd'
-
- nsActiveState = "active"
- nsFrozenState = "frozen"
- nsPurgeState = "purge"
+ ownerSize = 1 + interop.Hash160Len + 4
)
-var dummyValue = []byte{1}
+const (
+ netmapContractKey = "netmapScriptHash"
+ containerContractKey = "containerScriptHash"
+ notaryDisabledKey = "notary"
+ ownerKeysPrefix = 'o'
+)
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
ctx := storage.GetContext()
- args := data.(struct {
- admin interop.Hash160
- version int
- })
-
- if args.admin != nil {
- if len(args.admin) != interop.Hash160Len {
- panic("incorrect length of owner address")
- }
- storage.Put(ctx, adminKey, args.admin)
- }
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
if isUpdate {
- common.CheckVersion(args.version)
- if args.version < common.GetVersion(0, 21, 1) {
- it := storage.Find(ctx, subjectKeysPrefix, storage.ValuesOnly)
- for iterator.Next(it) {
- subjectRaw := iterator.Value(it)
- subject := std.Deserialize(subjectRaw.([]byte)).(Subject)
- address := addressKey(contract.CreateStandardAccount(subject.PrimaryKey))
- if storage.Get(ctx, address) != nil {
- panic("frostfsid contract contains duplicate keys")
- }
- storage.Put(ctx, address, true)
-
- for i := 0; i < len(subject.AdditionalKeys); i++ {
- address = addressKey(contract.CreateStandardAccount(subject.AdditionalKeys[i]))
- if storage.Get(ctx, address) != nil {
- panic("frostfsid contract contains duplicate keys")
- }
- storage.Put(ctx, address, true)
- }
- }
- }
- if args.version < common.GetVersion(0, 21, 2) {
- maxGroupID := 0
- it := storage.Find(ctx, groupKeysPrefix, storage.ValuesOnly)
- for iterator.Next(it) {
- groupRaw := iterator.Value(it)
- group := std.Deserialize(groupRaw.([]byte)).(Group)
- if group.ID > maxGroupID {
- maxGroupID = group.ID
- }
- }
-
- storage.Put(ctx, groupCounterKey, maxGroupID)
- }
-
- if args.version < common.GetVersion(0, 21, 3) {
- migrateNamespacesState(ctx)
- }
-
- if args.version < common.GetVersion(0, 21, 4) {
- it := storage.Find(ctx, subjectKeysPrefix, storage.ValuesOnly)
- for iterator.Next(it) {
- subject := std.Deserialize(iterator.Value(it).([]byte)).(Subject)
- subjAddr := contract.CreateStandardAccount(subject.PrimaryKey)
- for i := 0; i < len(subject.AdditionalKeys); i++ {
- storage.Put(ctx, subjectToAdditionalKeyKey(subjAddr, subject.AdditionalKeys[i]), dummyValue)
- }
- subject.AdditionalKeys = nil
- storage.Put(ctx, subjectKeyFromAddr(subjAddr), std.Serialize(subject))
- }
- }
-
+ args := data.([]interface{})
+ common.CheckVersion(args[len(args)-1].(int))
return
}
- storage.Put(ctx, groupCounterKey, 0)
- storage.Put(ctx, namespaceKey(""), std.Serialize(Namespace{State: nsActiveState}))
+ args := data.(struct {
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrNetmap interop.Hash160
+ addrContainer interop.Hash160
+ })
+
+ if len(args.addrNetmap) != interop.Hash160Len || len(args.addrContainer) != interop.Hash160Len {
+ panic("incorrect length of contract script hash")
+ }
+
+ storage.Put(ctx, netmapContractKey, args.addrNetmap)
+ storage.Put(ctx, containerContractKey, args.addrContainer)
runtime.Log("frostfsid contract initialized")
}
-// SetAdmin sets the admin address for the contract.
-func SetAdmin(addr interop.Hash160) {
- ctx := storage.GetContext()
- if !common.HasUpdateAccess() {
- panic("not witnessed")
- }
-
- storage.Put(ctx, adminKey, addr)
-}
-
-// ClearAdmin removes the admin address from the contract storage.
-func ClearAdmin() {
- ctx := storage.GetContext()
- if !common.HasUpdateAccess() {
- panic("not witnessed")
- }
-
- storage.Delete(ctx, adminKey)
-}
-
-// GetAdmin retrieves the admin address from the contract storage.
-func GetAdmin() interop.Hash160 {
- ctx := storage.GetReadOnlyContext()
- return storage.Get(ctx, adminKey).(interop.Hash160)
-}
-
// Update method updates contract source code and manifest. It can be invoked
// only by committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
if !common.HasUpdateAccess() {
panic("only committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("frostfsid contract updated")
}
+// AddKey binds a list of the provided public keys to the OwnerID. It can be invoked only by
+// Alphabet nodes.
+//
+// This method panics if the OwnerID is not an ownerSize byte or the public key is not 33 byte long.
+// If the key is already bound, the method ignores it.
+func AddKey(owner []byte, keys []interop.PublicKey) {
+ // V2 format
+ if len(owner) != ownerSize {
+ panic("incorrect owner")
+ }
+
+ for i := range keys {
+ if len(keys[i]) != interop.PublicKeyCompressedLen {
+ panic("incorrect public key")
+ }
+ }
+
+ ctx := storage.GetContext()
+
+ common.CheckAlphabetWitness()
+
+ ownerKey := append([]byte{ownerKeysPrefix}, owner...)
+ for i := range keys {
+ stKey := append(ownerKey, keys[i]...)
+ storage.Put(ctx, stKey, []byte{1})
+ }
+
+ runtime.Log("key bound to the owner")
+}
+
+// RemoveKey unbinds the provided public keys from the OwnerID. It can be invoked only by
+// Alphabet nodes.
+//
+// This method panics if the OwnerID is not an ownerSize byte or the public key is not 33 byte long.
+// If the key is already unbound, the method ignores it.
+func RemoveKey(owner []byte, keys []interop.PublicKey) {
+ // V2 format
+ if len(owner) != ownerSize {
+ panic("incorrect owner")
+ }
+
+ for i := range keys {
+ if len(keys[i]) != interop.PublicKeyCompressedLen {
+ panic("incorrect public key")
+ }
+ }
+
+ ctx := storage.GetContext()
+
+ multiaddr := common.AlphabetAddress()
+ if !runtime.CheckWitness(multiaddr) {
+ panic("invocation from non inner ring node")
+ }
+
+ ownerKey := append([]byte{ownerKeysPrefix}, owner...)
+ for i := range keys {
+ stKey := append(ownerKey, keys[i]...)
+ storage.Delete(ctx, stKey)
+ }
+}
+
+// Key method returns a list of 33-byte public keys bound with the OwnerID.
+//
+// This method panics if the owner is not ownerSize byte long.
+func Key(owner []byte) [][]byte {
+ // V2 format
+ if len(owner) != ownerSize {
+ panic("incorrect owner")
+ }
+
+ ctx := storage.GetReadOnlyContext()
+
+ ownerKey := append([]byte{ownerKeysPrefix}, owner...)
+ info := getUserInfo(ctx, ownerKey)
+
+ return info.Keys
+}
+
// Version returns the version of the contract.
func Version() int {
return common.Version
}
-// CreateSubject creates a new subject in the specified namespace with the provided public key.
-func CreateSubject(ns string, key interop.PublicKey) {
- ctx := storage.GetContext()
- checkNamespaceState(ns)
- checkContractOwner(ctx)
-
- if len(key) != interop.PublicKeyCompressedLen {
- panic("incorrect public key length")
- }
-
- addr := contract.CreateStandardAccount(key)
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data != nil {
- panic("subject already exists")
- }
-
- saPrefix := additionalKeyToSubjectPrefix(key)
- it := storage.Find(ctx, saPrefix, storage.KeysOnly)
+func getUserInfo(ctx storage.Context, key interface{}) UserInfo {
+ it := storage.Find(ctx, key, storage.KeysOnly|storage.RemovePrefix)
+ pubs := [][]byte{}
for iterator.Next(it) {
- panic("key is occupied")
+ pub := iterator.Value(it).([]byte)
+ pubs = append(pubs, pub)
}
- allAddressKey := addressKey(addr)
- if storage.Get(ctx, allAddressKey) != nil {
- panic("key is occupied by another additional key")
- }
-
- nsKey := namespaceKey(ns)
- data = storage.Get(ctx, nsKey).([]byte)
- if data == nil {
- panic("namespace not found")
- }
-
- subj := Subject{
- PrimaryKey: key,
- Namespace: ns,
- }
-
- storage.Put(ctx, sKey, std.Serialize(subj))
-
- nsSubjKey := namespaceSubjectKey(ns, addr)
- storage.Put(ctx, nsSubjKey, dummyValue)
- storage.Put(ctx, allAddressKey, true)
-
- runtime.Notify("CreateSubject", interop.Hash160(addr))
-}
-
-// AddSubjectKey adds an additional public key to a subject with the specified address.
-func AddSubjectKey(addr interop.Hash160, key interop.PublicKey) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
- if len(key) != interop.PublicKeyCompressedLen {
- panic("incorrect public key length")
- }
-
- addressKey := addressKey(contract.CreateStandardAccount(key))
- if storage.Get(ctx, addressKey) != nil {
- panic("key is occupied")
- }
-
- saKey := additionalKeyToSubjectKey(key, addr)
- data := storage.Get(ctx, saKey).([]byte)
- if data != nil {
- panic("key already added")
- }
-
- storage.Put(ctx, saKey, dummyValue)
-
- sKey := subjectKeyFromAddr(addr)
- data = storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("address not found")
- }
- subject := std.Deserialize(data).(Subject)
- checkNamespaceState(subject.Namespace)
-
- storage.Put(ctx, subjectToAdditionalKeyKey(addr, key), dummyValue)
- storage.Put(ctx, addressKey, true)
- runtime.Notify("AddSubjectKey", addr, key)
-}
-
-// RemoveSubjectKey removes an additional public key from the subject with the specified address.
-func RemoveSubjectKey(addr interop.Hash160, key interop.PublicKey) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
- if len(key) != interop.PublicKeyCompressedLen {
- panic("incorrect public key length")
- }
-
- saKey := additionalKeyToSubjectKey(key, addr)
- data := storage.Get(ctx, saKey).([]byte)
- if data == nil {
- panic("key already removed")
- }
-
- storage.Delete(ctx, saKey)
-
- sKey := subjectKeyFromAddr(addr)
- data = storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("address not found")
- }
-
- subjToAddKey := subjectToAdditionalKeyKey(addr, key)
- data = storage.Get(ctx, subjToAddKey).([]byte)
- if data == nil {
- panic("key already removed")
- }
- storage.Delete(ctx, subjToAddKey)
-
- storage.Delete(ctx, addressKey(contract.CreateStandardAccount(key)))
- runtime.Notify("RemoveSubjectKey", addr, key)
-}
-
-// SetSubjectName sets a new name for the subject with the specified address.
-func SetSubjectName(addr interop.Hash160, name string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
-
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("subject not found")
- }
-
- subject := std.Deserialize(data).(Subject)
- checkNamespaceState(subject.Namespace)
- oldName := subject.Name
- subject.Name = name
- storage.Put(ctx, sKey, std.Serialize(subject))
-
- updateNamespaceSubjectName(ctx, subject, oldName)
-
- runtime.Notify("SetSubjectName", addr, name)
-}
-
-// SetSubjectKV sets a key-value pair for the subject with the specified address.
-func SetSubjectKV(addr interop.Hash160, key, val string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
-
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("subject not found")
- }
-
- subject := std.Deserialize(data).(Subject)
- checkNamespaceState(subject.Namespace)
- if subject.KV == nil {
- subject.KV = map[string]string{}
- }
- subject.KV[key] = val
-
- storage.Put(ctx, sKey, std.Serialize(subject))
- runtime.Notify("SetSubjectKV", addr, key, val)
-}
-
-// DeleteSubjectKV deletes a key-value pair from the subject with the specified address.
-func DeleteSubjectKV(addr interop.Hash160, key string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
-
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("subject not found")
- }
-
- subject := std.Deserialize(data).(Subject)
- delete(subject.KV, key)
-
- storage.Put(ctx, sKey, std.Serialize(subject))
- runtime.Notify("DeleteSubjectKV", addr, key)
-}
-
-// DeleteSubject deletes the subject with the specified address.
-func DeleteSubject(addr interop.Hash160) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
-
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- return
- }
- subj := std.Deserialize(data).(Subject)
-
- subj.AdditionalKeys = getSubjectAdditionalKeys(ctx, addr)
- for i := 0; i < len(subj.AdditionalKeys); i++ {
- storage.Delete(ctx, additionalKeyToSubjectKey(subj.AdditionalKeys[i], addr))
- storage.Delete(ctx, subjectToAdditionalKeyKey(addr, subj.AdditionalKeys[i]))
- storage.Delete(ctx, addressKey(contract.CreateStandardAccount(subj.AdditionalKeys[i])))
- }
- storage.Delete(ctx, addressKey(addr))
- storage.Delete(ctx, sKey)
-
- removeSubjectFromNamespace(ctx, subj.Namespace, addr)
- deleteNamespaceSubjectName(ctx, subj.Namespace, subj.Name)
-
- runtime.Notify("DeleteSubject", addr)
-}
-
-// GetSubject retrieves the subject with the specified address.
-func GetSubject(addr interop.Hash160) Subject {
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
-
- ctx := storage.GetReadOnlyContext()
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- addr = getPrimaryAddr(ctx, addr)
- sKey = subjectKeyFromAddr(addr)
- data = storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("subject not found")
- }
- }
-
- subj := std.Deserialize(data).(Subject)
- subj.AdditionalKeys = getSubjectAdditionalKeys(ctx, addr)
- return subj
-}
-
-// GetSubjectExtended retrieves the extended information of the subject with the specified address.
-func GetSubjectExtended(addr interop.Hash160) SubjectExtended {
- subj := GetSubject(addr)
- ctx := storage.GetReadOnlyContext()
-
- var groups []Group
- nsHash := ripemd160Hash(subj.Namespace)
- it := storage.Find(ctx, groupPrefixFromHash(nsHash), storage.KeysOnly|storage.RemovePrefix)
- for iterator.Next(it) {
- groupHash := iterator.Value(it).([]byte)
- data := storage.Get(ctx, groupSubjectKeyFromHashes(nsHash, groupHash, addr)).([]byte)
- if data != nil {
- data = storage.Get(ctx, groupKeyFromHashes(nsHash, groupHash)).([]byte)
- if data == nil {
- panic("group not found")
- }
- groups = append(groups, std.Deserialize(data).(Group))
- }
- }
-
- subjExt := SubjectExtended{
- PrimaryKey: subj.PrimaryKey,
- AdditionalKeys: subj.AdditionalKeys,
- Namespace: subj.Namespace,
- Name: subj.Name,
- KV: subj.KV,
- Groups: groups,
- }
-
- return subjExt
-}
-
-// GetSubjectByKey retrieves the subject associated with the provided public key.
-func GetSubjectByKey(key interop.PublicKey) Subject {
- if len(key) != interop.PublicKeyCompressedLen {
- panic("incorrect key length")
- }
-
- ctx := storage.GetReadOnlyContext()
-
- sKey := subjectKey(key)
- data := storage.Get(ctx, sKey).([]byte)
- if data != nil {
- subj := std.Deserialize(data).(Subject)
- subj.AdditionalKeys = getSubjectAdditionalKeys(ctx, contract.CreateStandardAccount(key))
- return subj
- }
-
- addr := getPrimaryAddr(ctx, contract.CreateStandardAccount(key))
- sKey = subjectKeyFromAddr(addr)
- data = storage.Get(ctx, sKey).([]byte)
- if data != nil {
- subj := std.Deserialize(data).(Subject)
- subj.AdditionalKeys = getSubjectAdditionalKeys(ctx, addr)
- return subj
- }
-
- panic("subject not found")
-}
-
-func getPrimaryAddr(ctx storage.Context, addr interop.Hash160) interop.Hash160 {
- saPrefix := append([]byte{additionalKeysPrefix}, addr...)
- it := storage.Find(ctx, saPrefix, storage.KeysOnly|storage.RemovePrefix)
- if iterator.Next(it) {
- return iterator.Value(it).([]byte)
- }
- panic("subject not found")
-}
-
-func getSubjectAdditionalKeys(ctx storage.Context, addr interop.Hash160) []interop.PublicKey {
- var result []interop.PublicKey
- subjToAddKeyPrefix := subjectToAdditionalKeyPrefix(addr)
- it := storage.Find(ctx, subjToAddKeyPrefix, storage.KeysOnly|storage.RemovePrefix)
- if iterator.Next(it) {
- key := iterator.Value(it).([]byte)
- if len(key) < interop.PublicKeyCompressedLen {
- panic("invalid subject additional key")
- }
- result = append(result, interop.PublicKey(key[:interop.PublicKeyCompressedLen]))
- }
- return result
-}
-
-// GetSubjectByName retrieves the subject with the specified name within the given namespace.
-func GetSubjectByName(ns, name string) Subject {
- key := GetSubjectKeyByName(ns, name)
- addr := contract.CreateStandardAccount(key)
- return GetSubject(addr)
-}
-
-// GetSubjectKeyByName retrieves the public key of the subject with the specified namespace and name.
-func GetSubjectKeyByName(ns, name string) interop.PublicKey {
- if name == "" {
- panic("invalid or name")
- }
-
- ctx := storage.GetReadOnlyContext()
-
- nsSubjNameKey := namespaceSubjectNameKey(ns, name)
- subjKey := storage.Get(ctx, nsSubjNameKey).(interop.PublicKey)
- if subjKey == nil {
- panic("subject not found")
- }
-
- return subjKey
-}
-
-// GetSubjectKV GetSubjectKey returns the value associated with the key for the subject.
-func GetSubjectKV(addr interop.Hash160, name string) string {
- if len(addr) != interop.Hash160Len {
- panic("incorrect address length")
- }
-
- ctx := storage.GetReadOnlyContext()
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- return ""
- }
-
- sbj := std.Deserialize(data).(Subject)
-
- if sbj.KV == nil {
- return ""
- }
-
- for k, v := range sbj.KV {
- if k == name {
- return v
- }
- }
-
- return ""
-}
-
-func ListSubjects() iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- return storage.Find(ctx, []byte{subjectKeysPrefix}, storage.KeysOnly|storage.RemovePrefix)
-}
-
-// CreateNamespace creates a new namespace with the specified name.
-func CreateNamespace(ns string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- nsKey := namespaceKey(ns)
- data := storage.Get(ctx, nsKey).([]byte)
- if data != nil {
- panic("namespace already exists")
- }
-
- namespace := Namespace{
- Name: ns,
- State: nsActiveState,
- }
-
- storage.Put(ctx, nsKey, std.Serialize(namespace))
- runtime.Notify("CreateNamespace", ns)
-}
-
-// DeleteNamespace idempotently removes a namespace with the specified name.
-func DeleteNamespace(ns string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- nsKey := namespaceKey(ns)
- data := storage.Get(ctx, nsKey).([]byte)
- if data == nil {
- return
- }
-
- namespace := std.Deserialize(data).(Namespace)
- if namespace.State != nsPurgeState {
- panic("namespace should be in 'purge' state for deletion")
- }
-
- it := storage.Find(ctx, groupPrefix(ns), storage.KeysOnly)
- if iterator.Next(it) {
- panic("can't delete non-empty namespace: groups still present")
- }
-
- it = storage.Find(ctx, namespaceSubjectPrefix(ns), storage.KeysOnly)
- if iterator.Next(it) {
- panic("can't delete non-empty namespace: users still present")
- }
-
- storage.Delete(ctx, nsKey)
- runtime.Notify("DeleteNamespace", ns)
-}
-
-// UpdateNamespace updates existing namespace.
-func UpdateNamespace(ns string, state string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- nsKey := namespaceKey(ns)
- data := storage.Get(ctx, nsKey).([]byte)
- if data == nil {
- panic("namespace not found")
- }
-
- namespace := Namespace{
- Name: ns,
- State: state,
- }
-
- storage.Put(ctx, nsKey, std.Serialize(namespace))
- runtime.Notify("UpdateNamespace", ns, state)
-}
-
-// GetNamespace retrieves the namespace with the specified name.
-func GetNamespace(ns string) Namespace {
- ctx := storage.GetReadOnlyContext()
- nsKey := namespaceKey(ns)
- data := storage.Get(ctx, nsKey).([]byte)
- if data == nil {
- panic("namespace not found")
- }
-
- return std.Deserialize(data).(Namespace)
-}
-
-// GetNamespaceExtended retrieves extended information about the namespace.
-func GetNamespaceExtended(ns string) NamespaceExtended {
- ctx := storage.GetReadOnlyContext()
- nsKey := namespaceKey(ns)
- data := storage.Get(ctx, nsKey).([]byte)
- if data == nil {
- panic("namespace not found")
- }
- namespace := std.Deserialize(data).(Namespace)
-
- nsExtended := NamespaceExtended{
- Name: namespace.Name,
- State: namespace.State,
- }
-
- it := storage.Find(ctx, groupPrefix(ns), storage.KeysOnly)
- for iterator.Next(it) {
- nsExtended.GroupsCount += 1
- }
-
- it = storage.Find(ctx, namespaceSubjectPrefix(ns), storage.KeysOnly)
- for iterator.Next(it) {
- nsExtended.SubjectsCount += 1
- }
-
- return nsExtended
-}
-
-func ListNamespaces() iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- return storage.Find(ctx, []byte{namespaceKeysPrefix}, storage.ValuesOnly|storage.DeserializeValues)
-}
-
-func ListNamespaceSubjects(ns string) iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- return storage.Find(ctx, namespaceSubjectPrefix(ns), storage.KeysOnly|storage.RemovePrefix)
-}
-
-// CreateGroup creates a new group within the specified namespace.
-func CreateGroup(ns, group string) int {
- ctx := storage.GetContext()
- checkNamespaceState(ns)
- checkContractOwner(ctx)
-
- if group == "" {
- panic("invalid group name")
- }
-
- nsKey := namespaceKey(ns)
- data := storage.Get(ctx, nsKey).([]byte)
- if data == nil {
- panic("namespace not found")
- }
-
- groupCountID := storage.Get(ctx, groupCounterKey).(int)
- groupCountID++
- storage.Put(ctx, groupCounterKey, groupCountID)
-
- gr := Group{
- ID: groupCountID,
- Name: group,
- Namespace: ns,
- }
-
- setNamespaceGroupName(ctx, gr)
-
- gKey := groupKey(ns, groupCountID)
- storage.Put(ctx, gKey, std.Serialize(gr))
-
- runtime.Notify("CreateGroup", ns, group)
-
- return groupCountID
-}
-
-// GetGroup retrieves the group with the specified ID within the given namespace.
-func GetGroup(ns string, groupID int) Group {
- ctx := storage.GetReadOnlyContext()
- gKey := groupKey(ns, groupID)
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
-
- return std.Deserialize(data).(Group)
-}
-
-// GetGroupExtended retrieves extended information about the group, including the count of subjects in the group.
-func GetGroupExtended(ns string, groupID int) GroupExtended {
- ctx := storage.GetReadOnlyContext()
- gKey := groupKey(ns, groupID)
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
-
- gr := std.Deserialize(data).(Group)
-
- grExtended := GroupExtended{
- ID: gr.ID,
- Name: gr.Name,
- Namespace: gr.Namespace,
- KV: gr.KV,
- }
-
- it := storage.Find(ctx, groupSubjectPrefix(ns, groupID), storage.KeysOnly)
- for iterator.Next(it) {
- grExtended.SubjectsCount += 1
- }
-
- return grExtended
-}
-
-// GetGroupIDByName retrieves the ID of the group with the specified name within the given namespace.
-func GetGroupIDByName(ns, name string) int {
- if name == "" {
- panic("invalid name")
- }
-
- ctx := storage.GetReadOnlyContext()
-
- nsGroupNameKey := namespaceGroupNameKey(ns, name)
- groupIDRaw := storage.Get(ctx, nsGroupNameKey).([]byte)
- if groupIDRaw == nil {
- panic("group not found")
- }
-
- return std.Deserialize(groupIDRaw).(int)
-}
-
-// GetGroupByName retrieves the group with the specified name within the given namespace.
-func GetGroupByName(ns, name string) Group {
- groupID := GetGroupIDByName(ns, name)
- gKey := groupKey(ns, groupID)
-
- ctx := storage.GetReadOnlyContext()
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
-
- return std.Deserialize(data).(Group)
-}
-
-// SetGroupName sets a new name for the group with the specified ID within the given namespace.
-func SetGroupName(ns string, groupID int, name string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- gKey := groupKey(ns, groupID)
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
-
- gr := std.Deserialize(data).(Group)
- checkNamespaceState(gr.Namespace)
- oldName := gr.Name
- gr.Name = name
- storage.Put(ctx, gKey, std.Serialize(gr))
-
- updateNamespaceGroupName(ctx, gr, oldName)
-
- runtime.Notify("SetGroupName", ns, groupID, name)
-}
-
-// SetGroupKV sets a key-value pair for the group with the specified ID within the given namespace.
-func SetGroupKV(ns string, groupID int, key, val string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- gKey := groupKey(ns, groupID)
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
-
- gr := std.Deserialize(data).(Group)
- checkNamespaceState(gr.Namespace)
- if gr.KV == nil {
- gr.KV = map[string]string{}
- }
- gr.KV[key] = val
-
- storage.Put(ctx, gKey, std.Serialize(gr))
- runtime.Notify("SetGroupKV", ns, groupID, key, val)
-}
-
-// DeleteGroupKV deletes a key-value pair from the group with the specified ID within the given namespace.
-func DeleteGroupKV(ns string, groupID int, key string) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- gKey := groupKey(ns, groupID)
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
-
- gr := std.Deserialize(data).(Group)
- delete(gr.KV, key)
-
- storage.Put(ctx, gKey, std.Serialize(gr))
- runtime.Notify("DeleteGroupKV", ns, groupID, key)
-}
-
-func ListGroups(ns string) iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- return storage.Find(ctx, groupPrefix(ns), storage.ValuesOnly|storage.DeserializeValues)
-}
-
-// AddSubjectToGroup adds a subject to a group with the specified ID.
-func AddSubjectToGroup(addr interop.Hash160, groupID int) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("invalid address length")
- }
-
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("subject not found")
- }
- subject := std.Deserialize(data).(Subject)
- checkNamespaceState(subject.Namespace)
-
- gKey := groupKey(subject.Namespace, groupID)
- data = storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
- group := std.Deserialize(data).(Group)
-
- if group.Namespace != subject.Namespace {
- panic("subject and group must be in the same namespace")
- }
-
- gsKey := groupSubjectKey(subject.Namespace, groupID, addr)
- storage.Put(ctx, gsKey, dummyValue)
-
- runtime.Notify("AddSubjectToGroup", addr, subject.Namespace, groupID)
-}
-
-// RemoveSubjectFromGroup removes a subject from a group with the specified ID.
-func RemoveSubjectFromGroup(addr interop.Hash160, groupID int) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- if len(addr) != interop.Hash160Len {
- panic("invalid address length")
- }
-
- sKey := subjectKeyFromAddr(addr)
- data := storage.Get(ctx, sKey).([]byte)
- if data == nil {
- panic("subject not found")
- }
-
- subject := std.Deserialize(data).(Subject)
-
- gKey := groupKey(subject.Namespace, groupID)
- data = storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
- group := std.Deserialize(data).(Group)
-
- if group.Namespace != subject.Namespace {
- panic("subject and group must be in the same namespace")
- }
-
- gsKey := groupSubjectKey(subject.Namespace, groupID, addr)
- storage.Delete(ctx, gsKey)
-
- runtime.Notify("RemoveSubjectFromGroup", addr, subject.Namespace, groupID)
-}
-
-func ListGroupSubjects(ns string, groupID int) iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- return storage.Find(ctx, groupSubjectPrefix(ns, groupID), storage.KeysOnly|storage.RemovePrefix)
-}
-
-// DeleteGroup deletes the group with the specified ID within the given namespace.
-func DeleteGroup(ns string, groupID int) {
- ctx := storage.GetContext()
- checkContractOwner(ctx)
-
- gKey := groupKey(ns, groupID)
- data := storage.Get(ctx, gKey).([]byte)
- if data == nil {
- panic("group not found")
- }
- gr := std.Deserialize(data).(Group)
-
- storage.Delete(ctx, gKey)
-
- it := storage.Find(ctx, groupSubjectPrefix(ns, groupID), storage.KeysOnly)
- for iterator.Next(it) {
- gsKey := iterator.Value(it).([]byte)
- storage.Delete(ctx, gsKey)
- }
-
- deleteNamespaceGroupName(ctx, ns, gr.Name)
-
- runtime.Notify("DeleteGroup", ns, groupID)
-}
-
-func checkContractOwner(ctx storage.Context) {
- addr := storage.Get(ctx, adminKey)
- if addr != nil && runtime.CheckWitness(addr.(interop.Hash160)) {
- return
- }
- if common.HasUpdateAccess() {
- return
- }
- panic("not witnessed")
-}
-
-func removeSubjectFromNamespace(ctx storage.Context, ns string, addr interop.Hash160) {
- nsSubjKey := namespaceSubjectKey(ns, addr)
- storage.Delete(ctx, nsSubjKey)
-
- nsHash := ripemd160Hash(ns)
- it := storage.Find(ctx, groupPrefixFromHash(nsHash), storage.KeysOnly|storage.RemovePrefix)
- for iterator.Next(it) {
- groupHash := iterator.Value(it).([]byte)
- storage.Delete(ctx, groupSubjectKeyFromHashes(nsHash, groupHash, addr))
- }
-}
-
-func setNamespaceSubjectName(ctx storage.Context, subj Subject) {
- if subj.Name == "" {
- return
- }
-
- nsSubjNameKey := namespaceSubjectNameKey(subj.Namespace, subj.Name)
- subjKey := storage.Get(ctx, nsSubjNameKey).(interop.PublicKey)
- if subjKey == nil {
- storage.Put(ctx, nsSubjNameKey, subj.PrimaryKey)
- } else if !common.BytesEqual(subjKey, subj.PrimaryKey) {
- panic("subject name is not available in the current namespace")
- }
-}
-
-func deleteNamespaceSubjectName(ctx storage.Context, ns, subjName string) {
- if subjName == "" {
- return
- }
-
- nsSubjNameKey := namespaceSubjectNameKey(ns, subjName)
- storage.Delete(ctx, nsSubjNameKey)
-}
-
-func updateNamespaceSubjectName(ctx storage.Context, subj Subject, oldName string) {
- if subj.Name == oldName {
- return
- }
-
- deleteNamespaceSubjectName(ctx, subj.Namespace, oldName)
- setNamespaceSubjectName(ctx, subj)
-}
-
-func updateNamespaceGroupName(ctx storage.Context, gr Group, oldName string) {
- if gr.Name == oldName {
- return
- }
-
- deleteNamespaceGroupName(ctx, gr.Namespace, oldName)
- setNamespaceGroupName(ctx, gr)
-}
-
-func deleteNamespaceGroupName(ctx storage.Context, ns, grName string) {
- if grName == "" {
- return
- }
-
- nsGroupNameKey := namespaceGroupNameKey(ns, grName)
- storage.Delete(ctx, nsGroupNameKey)
-}
-
-func setNamespaceGroupName(ctx storage.Context, gr Group) {
- if gr.Name == "" {
- return
- }
-
- nsGroupNameKey := namespaceGroupNameKey(gr.Namespace, gr.Name)
- groupIDRaw := storage.Get(ctx, nsGroupNameKey).([]byte)
- if groupIDRaw == nil {
- storage.Put(ctx, nsGroupNameKey, std.Serialize(gr.ID))
- return
- }
-
- groupID := std.Deserialize(groupIDRaw).(int)
- if groupID != gr.ID {
- panic("group name is not available in the current namespace")
- }
-}
-
-func subjectKey(key interop.PublicKey) []byte {
- addr := contract.CreateStandardAccount(key)
- return subjectKeyFromAddr(addr)
-}
-
-func subjectKeyFromAddr(addr interop.Hash160) []byte {
- return append([]byte{subjectKeysPrefix}, addr...)
-}
-
-func additionalKeyToSubjectKey(additionalKey interop.PublicKey, primeAddr interop.Hash160) []byte {
- return append(additionalKeyToSubjectPrefix(additionalKey), primeAddr...)
-}
-
-func additionalKeyToSubjectPrefix(additionalKey interop.PublicKey) []byte {
- addr := contract.CreateStandardAccount(additionalKey)
- return append([]byte{additionalKeysPrefix}, addr...)
-}
-
-// subjectToAdditionalKeyKey returns 'd' + [20]byte subjectAddr + [33]byte additionalKey.
-func subjectToAdditionalKeyKey(subjectAddr interop.Hash160, additionalKey interop.PublicKey) []byte {
- return append(subjectToAdditionalKeyPrefix(subjectAddr), additionalKey...)
-}
-
-// subjectToAdditionalKeyPrefix returns 'd' + [20]byte subjectAddr.
-func subjectToAdditionalKeyPrefix(subjectAddr interop.Hash160) []byte {
- return append([]byte{subjectToAddKeyPrefix}, subjectAddr...)
-}
-
-func namespaceKey(ns string) []byte {
- return namespaceKeyFromHash(ripemd160Hash(ns))
-}
-
-func namespaceKeyFromHash(ns []byte) []byte {
- return append([]byte{namespaceKeysPrefix}, ns...)
-}
-
-func groupKey(ns string, groupID int) []byte {
- prefix := groupPrefix(ns)
- return append(prefix, idToBytes(groupID)...)
-}
-
-func groupKeyFromHashes(nsHash []byte, groupIDBytes []byte) []byte {
- prefix := groupPrefixFromHash(nsHash)
- return append(prefix, groupIDBytes...)
-}
-
-func groupPrefix(ns string) []byte {
- return groupPrefixFromHash(ripemd160Hash(ns))
-}
-
-func groupPrefixFromHash(nsHash []byte) []byte {
- return append([]byte{groupKeysPrefix}, nsHash...)
-}
-
-func ripemd160Hash(data string) []byte {
- return crypto.Ripemd160([]byte(data))
-}
-
-func namespaceSubjectKey(ns string, addr interop.Hash160) []byte {
- prefix := namespaceSubjectPrefix(ns)
- return append(prefix, addr...)
-}
-
-func namespaceSubjectPrefix(ns string) []byte {
- nsHash := ripemd160Hash(ns)
- return append([]byte{namespaceSubjectsKeysPrefix}, nsHash...)
-}
-
-func namespaceSubjectNameKey(ns, subjName string) []byte {
- nsHash := ripemd160Hash(ns)
- nameHash := ripemd160Hash(subjName)
- return append([]byte{namespaceSubjectsNamesPrefix}, append(nsHash, nameHash...)...)
-}
-
-func namespaceGroupNameKey(ns, groupName string) []byte {
- nsHash := ripemd160Hash(ns)
- nameHash := ripemd160Hash(groupName)
- return append([]byte{namespaceGroupsNamesPrefix}, append(nsHash, nameHash...)...)
-}
-
-func groupSubjectKey(ns string, groupID int, addr interop.Hash160) []byte {
- prefix := groupSubjectPrefix(ns, groupID)
- return append(prefix, addr...)
-}
-
-func groupSubjectKeyFromHashes(nsHash, groupHash []byte, addr interop.Hash160) []byte {
- prefix := groupSubjectPrefixFromHashes(nsHash, groupHash)
- return append(prefix, addr...)
-}
-
-func groupSubjectPrefix(ns string, groupID int) []byte {
- nsHash := ripemd160Hash(ns)
- return groupSubjectPrefixFromHashes(nsHash, idToBytes(groupID))
-}
-
-func groupSubjectPrefixFromHashes(nsHash, groupIDBytes []byte) []byte {
- return append([]byte{groupSubjectsKeysPrefix}, append(nsHash, groupIDBytes...)...)
-}
-
-// idToBytes converts i64 value to BE bytes. Panics if value is bigger than i64.
-func idToBytes(itemID int) []byte {
- b := convert.ToBytes(itemID)
- ln := len(b)
- if ln > 8 {
- panic("item ID exceeds 8 byte limit")
- }
- zeros := make([]byte, 8-ln)
- return append(b, zeros...)
-}
-
-func addressKey(address []byte) []byte {
- return append([]byte{addressPrefix}, address...)
-}
-
-func migrateNamespacesState(ctx storage.Context) {
- it := storage.Find(ctx, []byte{namespaceKeysPrefix}, storage.None)
-
- for iterator.Next(it) {
- kv := iterator.Value(it).(struct {
- Key []byte
- Value []byte
- })
-
- oldNs := std.Deserialize(kv.Value).(struct {
- Name string
- })
-
- newNs := Namespace{
- Name: oldNs.Name,
- State: nsActiveState,
- }
-
- namespaceData := std.Serialize(newNs)
- storage.Put(ctx, string(kv.Key), namespaceData)
- }
-}
-
-func checkNamespaceState(name string) {
- ns := GetNamespace(name)
- if ns.State == nsFrozenState || ns.State == nsPurgeState {
- panic("namespace is non-active")
- }
+ return UserInfo{Keys: pubs}
}
diff --git a/go.mod b/go.mod
index d144617..56e08fe 100644
--- a/go.mod
+++ b/go.mod
@@ -1,56 +1,10 @@
module git.frostfs.info/TrueCloudLab/frostfs-contract
-go 1.22
+go 1.14
require (
- github.com/google/uuid v1.6.0
github.com/mr-tron/base58 v1.2.0
- github.com/nspcc-dev/neo-go v0.106.3
- github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240727093519-1a48f1ce43ec
- github.com/stretchr/testify v1.9.0
- go.uber.org/zap v1.27.0
-)
-
-require (
- github.com/beorn7/perks v1.0.1 // indirect
- github.com/bits-and-blooms/bitset v1.8.0 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
- github.com/consensys/bavard v0.1.13 // indirect
- github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb // indirect
- github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
- github.com/golang/snappy v0.0.1 // indirect
- github.com/gorilla/websocket v1.5.1 // indirect
- github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
- github.com/holiman/uint256 v1.2.4 // indirect
- github.com/mmcloughlin/addchain v0.4.0 // indirect
- github.com/nspcc-dev/dbft v0.2.0 // indirect
- github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect
- github.com/nspcc-dev/rfc6979 v0.2.1 // indirect
- github.com/pierrec/lz4 v2.6.1+incompatible // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/client_golang v1.19.0 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.48.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
- github.com/rogpeppe/go-internal v1.11.0 // indirect
- github.com/russross/blackfriday/v2 v2.1.0 // indirect
- github.com/stretchr/objx v0.5.2 // indirect
- github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
- github.com/twmb/murmur3 v1.1.8 // indirect
- github.com/urfave/cli/v2 v2.27.2 // indirect
- github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
- go.etcd.io/bbolt v1.3.9 // indirect
- go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/crypto v0.21.0 // indirect
- golang.org/x/mod v0.16.0 // indirect
- golang.org/x/net v0.23.0 // indirect
- golang.org/x/sys v0.18.0 // indirect
- golang.org/x/term v0.18.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/tools v0.19.0 // indirect
- google.golang.org/protobuf v1.33.0 // indirect
- gopkg.in/yaml.v3 v3.0.1 // indirect
- rsc.io/tmplfunc v0.0.3 // indirect
+ github.com/nspcc-dev/neo-go v0.99.4
+ github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220927123257-24c107e3a262
+ github.com/stretchr/testify v1.7.0
)
diff --git a/go.sum b/go.sum
index 57d2589..9df8735 100644
--- a/go.sum
+++ b/go.sum
@@ -1,194 +1,730 @@
-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=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+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/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c=
-github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
-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/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
-github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
-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.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc=
-github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
-github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
-github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
+github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo=
+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=
+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=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
+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/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
-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/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 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
+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=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+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=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+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=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+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=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
-github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
-github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
-github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
-github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
-github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
-github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
-github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+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=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+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=
+github.com/hashicorp/golang-lru v0.5.4/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=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+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/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/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
-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/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=
+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=
+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/nspcc-dev/dbft v0.2.0 h1:sDwsQES600OSIMncV176t2SX5OvB14lzeOAyKFOkbMI=
-github.com/nspcc-dev/dbft v0.2.0/go.mod h1:oFE6paSC/yfFh9mcNU6MheMGOYXK9+sPiRk3YMoz49o=
-github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 h1:mD9hU3v+zJcnHAVmHnZKt3I++tvn30gBj2rP2PocZMk=
-github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2/go.mod h1:U5VfmPNM88P4RORFb6KSUVBdJBDhlqggJZYGXGPxOcc=
-github.com/nspcc-dev/hrw/v2 v2.0.1 h1:CxYUkBeJvNfMEn2lHhrV6FjY8pZPceSxXUtMVq0BUOU=
-github.com/nspcc-dev/hrw/v2 v2.0.1/go.mod h1:iZAs5hT2q47EGq6AZ0FjaUI6ggntOi7vrY4utfzk5VA=
-github.com/nspcc-dev/neo-go v0.106.3 h1:HEyhgkjQY+HfBzotMJ12xx2VuOUphkngZ4kEkjvXDtE=
-github.com/nspcc-dev/neo-go v0.106.3/go.mod h1:3vEwJ2ld12N7HRGCaH/l/7EwopplC/+8XdIdPDNmD/M=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240727093519-1a48f1ce43ec h1:vDrbVXF2+2uP0RlkZmem3QYATcXCu9BzzGGCNsNcK7Q=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240727093519-1a48f1ce43ec/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY=
-github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240305074711-35bc78d84dc4 h1:arN0Ypn+jawZpu1BND7TGRn44InAVIqKygndsx0y2no=
-github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240305074711-35bc78d84dc4/go.mod h1:7Tm1NKEoUVVIUlkVwFrPh7GG5+Lmta2m7EGr4oVpBd8=
-github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.12 h1:mdxtlSU2I4oVZ/7AXTLKyz8uUPbDWikZw4DM8gvrddA=
-github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.12/go.mod h1:JdsEM1qgNukrWqgOBDChcYp8oY4XUzidcKaxY4hNJvQ=
-github.com/nspcc-dev/rfc6979 v0.2.1 h1:8wWxkamHWFmO790GsewSoKUSJjVnL1fmdRpokU/RgRM=
-github.com/nspcc-dev/rfc6979 v0.2.1/go.mod h1:Tk7h5kyUWkhjyO3zUgFFhy1v2vQv3BvQEntakdtqrWc=
-github.com/nspcc-dev/tzhash v1.7.2 h1:iRXoa9TJqH/DQO7FFcqpq9BdruF9E7/xnFGlIghl5J4=
-github.com/nspcc-dev/tzhash v1.7.2/go.mod h1:oHiH0qwmTsZkeVs7pvCS5cVXUaLhXxSFvnmnZ++ijm4=
+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-20220902113116-58a5e763e647 h1:handGBjqVzRx7HD6152zsP8ZRxw083zCMbN0IlUaPQk=
+github.com/nspcc-dev/dbft v0.0.0-20220902113116-58a5e763e647/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.4 h1:8Y+SdRxksC72a4PNkcGCh/aaQinh9Gu+c5LilbcsXOI=
+github.com/nspcc-dev/neo-go v0.99.4/go.mod h1:mKTolfRUfKjFso5HPvGSQtUZc70n0VKBMs16eGuC5gA=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220927123257-24c107e3a262 h1:UTmSLZw5OpD/JPE1B5Vf98GF0zu2/Hsqq1lGLtStTUE=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220927123257-24c107e3a262/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=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
-github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
-github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
-github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
-github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
-github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
-github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
-github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
-github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+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=
+github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
+github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+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=
+github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
+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 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
+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=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+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/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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+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.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
-github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
-github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
-github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
-github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
-github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
-go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
-go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
-go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
-go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
-go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
-go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
-go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+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=
+github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c=
+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/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=
+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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
-golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
-golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
-golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
-golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
-golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+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/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=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+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 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
+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=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+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.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
-golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+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 h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+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=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+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 h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8=
+golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+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=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
-golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
-golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
+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 h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/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 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+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.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
-golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
+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=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+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=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+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 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
+golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
+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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
-google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
-google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+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/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=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
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=
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=
-rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
-rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+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=
diff --git a/netmap/config.yml b/netmap/config.yml
index ed88ebc..df985cd 100644
--- a/netmap/config.yml
+++ b/netmap/config.yml
@@ -1,13 +1,5 @@
name: "Netmap"
-safemethods:
- - "config"
- - "epoch"
- - "listConfig"
- - "netmap"
- - "netmapCandidates"
- - "snapshot"
- - "snapshotByEpoch"
- - "version"
+safemethods: ["epoch", "netmap", "netmapCandidates", "snapshot", "snapshotByEpoch", "config", "listConfig", "version"]
permissions:
- methods: ["update", "newEpoch"]
events:
diff --git a/netmap/doc.go b/netmap/doc.go
index 9df6c3c..c352699 100644
--- a/netmap/doc.go
+++ b/netmap/doc.go
@@ -29,17 +29,5 @@ in the network by invoking NewEpoch method.
NewEpoch
- name: epoch
type: Integer
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |-----------------------------|------------|-----------------------------------|
- | `snapshotCount` | int | snapshot count |
- | `snapshotEpoch` | int | snapshot epoch |
- | `snapshotBlock` | int | snapshot block |
- | `snapshot_` + snapshotNum | ByteArray | serialized '[]Node' array |
- | `snapshotCurrent` | int | current snapshot |
- | `balanceScriptHash` | Hash160 | balance contract hash |
- | `containerScriptHash` | Hash160 | container contract hash |
*/
package netmap
diff --git a/netmap/netmap_contract.go b/netmap/netmap_contract.go
index 1af6974..150c461 100644
--- a/netmap/netmap_contract.go
+++ b/netmap/netmap_contract.go
@@ -43,7 +43,8 @@ type Node struct {
}
const (
- innerRingKey = "innerring"
+ notaryDisabledKey = "notary"
+ innerRingKey = "innerring"
// DefaultSnapshotCount contains the number of previous snapshots stored by this contract.
// Must be less than 255.
@@ -66,15 +67,19 @@ var (
)
// _deploy function sets up initial list of inner ring public keys.
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
ctx := storage.GetContext()
- args := data.(struct {
- addrBalance interop.Hash160
- addrContainer interop.Hash160
- keys []interop.PublicKey
- config [][]byte
- version int
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
+ var args = data.(struct {
+ //TODO(@acid-ant): #9 remove notaryDisabled in future version
+ notaryDisabled bool
+ addrBalance interop.Hash160
+ addrContainer interop.Hash160
+ keys []interop.PublicKey
+ config [][]byte
+ version int
})
ln := len(args.config)
@@ -117,12 +122,13 @@ func _deploy(data any, isUpdate bool) {
// Update method updates contract source code and manifest. It can be invoked
// only by committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
if !common.HasUpdateAccess() {
panic("only committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("netmap contract updated")
}
@@ -426,7 +432,7 @@ func SnapshotByEpoch(epoch int) []Node {
// Config returns configuration value of FrostFS configuration. If key does
// not exists, returns nil.
-func Config(key []byte) any {
+func Config(key []byte) interface{} {
ctx := storage.GetReadOnlyContext()
return getConfig(ctx, key)
}
@@ -538,14 +544,14 @@ func getSnapshot(ctx storage.Context, key string) []Node {
return []Node{}
}
-func getConfig(ctx storage.Context, key any) interface{} {
+func getConfig(ctx storage.Context, key interface{}) interface{} {
postfix := key.([]byte)
storageKey := append(configPrefix, postfix...)
return storage.Get(ctx, storageKey)
}
-func setConfig(ctx storage.Context, key, val any) {
+func setConfig(ctx storage.Context, key, val interface{}) {
postfix := key.([]byte)
storageKey := append(configPrefix, postfix...)
diff --git a/nns/README.md b/nns/README.md
deleted file mode 100644
index 32a72bf..0000000
--- a/nns/README.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# NNS
-NNS - Neo Name Service is a service that allows manage a domain name as a digital asset (NFT). It has an interface similar to `DNS` but has significant differences in its internal structure.
-
-## Entities:
-
-- Domain
-- Record
-- Owner
-- Committee
-
-### Domain
-
-Domain is string that satisfies the following requirements:
-- Length from 2 to 255 characters.
-- Root domain must start with a letter.
-- All other fragments must start and end with a letter or digit.
-
-Domain has owner, a registration period, and may optionally have records.
-
-A fee established by the committee is charged upon domain registration. After registration, the owner can manage this asset (add/delete records, transfer ownership to another owner) until the end of the domain registration period.
-
-### Record
-
-A record is a pair of values ``.
-
-Supported record types:
-
-| Type | Description |
-|-------|-------------------------------------------|
-| A | Represents address record type |
-| AAA | Represents IPv6 address record type |
-| TXT | Represents text record type |
-| CNAME | Represents canonical name record type |
-| SOA | Represents start of authority record type |
-
-### Owner
-
-An owner is a wallet that has the right to manage this NFT (domain).
-
-### Committee
-
-The committee makes new tokens (domains), sets, and charges a fee for issuance.
-
-## Globally Unique Domain Zone
-
-For more information, see [here](../docs/globally-unique-domain-zone.md).
-
-## NNS and Frostfsid
-
-You can register a TLD domain without a committee signature using Frostfsid. To do this, create a new wallet
-```
-neo-go wallet init -w newwallet/wallet.json
-```
-
-Get wallet address:
-```
-neo-go wallet dump-keys -w newwallet/wallet.json
-[subject-address]
-[subject-key]
-```
-
-Create a subject in `FrostfsID`:
-```
-frostfs-adm morph frostfsid create-subject --subject-key="[subject-key]"
-```
-
-Grant permissions to the wallet:
-```
-frostfs-adm morph nns give-privilege --subject-address="[subject-address]"
-```
-
-Register domain:
-```
-neo-go contract invokefunction [NNS-hash] register "subdomain.domain" hash160:[subject-address] "email@frostfs.info" 10000 1000 1000 1000 -- [subject-address]:Global
-```
\ No newline at end of file
diff --git a/nns/config.yml b/nns/config.yml
index 54fc073..75a111d 100644
--- a/nns/config.yml
+++ b/nns/config.yml
@@ -2,35 +2,8 @@ name: "NameService"
supportedstandards: ["NEP-11"]
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply", "tokensOf", "ownerOf",
"tokens", "properties", "roots", "getPrice", "isAvailable", "getRecords",
- "getAllRecords",
"resolve", "version"]
events:
- - name: RegisterDomain
- parameters:
- - name: name
- type: String
- - name: AddRecord
- parameters:
- - name: name
- type: String
- - name: type
- type: Integer
- - name: DeleteRecord
- parameters:
- - name: name
- type: String
- - name: type
- type: Integer
- - name: DeleteRecords
- parameters:
- - name: name
- type: String
- - name: type
- type: Integer
- - name: DeleteDomain
- parameters:
- - name: name
- type: String
- name: Transfer
parameters:
- name: from
diff --git a/nns/doc.go b/nns/doc.go
deleted file mode 100644
index 787cca4..0000000
--- a/nns/doc.go
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |--------------------------------------|------------|-----------------------------------|
- | 0x0 | int | total supply of minted domains |
- | 0x1 + accountAddr | int | account's balance |
- | 0x2 + accountAddr + tokenKey | ByteArray | token ID |
- | 0x10 | int | price for domain registration |
- | 0x20 | int | set of roots |
- | 0x21 + tokenKey | ByteArray | serialized NameState struct |
- | 0x22 + tokenKey + Hash160(tokenName) | Hash160 | container contract hash |
- | 0x23 + tokenKey + Hash160(tokenName) | string | global domain flag |
-
-*/
-
-package nns
diff --git a/nns/frostfsid.go b/nns/frostfsid.go
deleted file mode 100644
index fcc2d87..0000000
--- a/nns/frostfsid.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package nns
-
-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/native/management"
- "github.com/nspcc-dev/neo-go/pkg/interop/native/std"
- "github.com/nspcc-dev/neo-go/pkg/interop/storage"
-)
-
-const FrostfsIDNNSName = "frostfsid.frostfs"
-
-const (
- FrostfsIDNNSTLDPermissionKey = "nns-allow-register-tld"
- FrostfsIDTLDRegistrationAllowed = "allow"
-)
-
-func checkFrostfsID(ctx storage.Context, addr interop.Hash160) bool {
- if len(addr) == 0 {
- return false
- }
-
- frostfsIDAddress := getRecordsByType(ctx, []byte(tokenIDFromName(FrostfsIDNNSName)), FrostfsIDNNSName, TXT)
- if len(frostfsIDAddress) < 2 {
- return false
- }
-
- decodedBytes := std.Base58Decode([]byte(frostfsIDAddress[1]))
-
- if len(decodedBytes) < 21 || management.GetContract(decodedBytes[1:21]) == nil {
- return false
- }
-
- if res := contract.Call(decodedBytes[1:21], "getSubjectKV", contract.ReadOnly, addr, FrostfsIDNNSTLDPermissionKey).(string); res == FrostfsIDTLDRegistrationAllowed {
- return true
- }
-
- return false
-}
diff --git a/nns/namestate.go b/nns/namestate.go
index ea186c8..72bbf94 100644
--- a/nns/namestate.go
+++ b/nns/namestate.go
@@ -7,14 +7,19 @@ import (
// NameState represents domain name state.
type NameState struct {
- Owner interop.Hash160
- Name string
- // Expiration field used to contain wall-clock time of a domain expiration.
- // It is preserved for backwards compatibility, but is unused by the contract and should be ignored.
+ Owner interop.Hash160
+ Name string
Expiration int64
Admin interop.Hash160
}
+// ensureNotExpired panics if domain name is expired.
+func (n NameState) ensureNotExpired() {
+ if int64(runtime.GetTime()) >= n.Expiration {
+ panic("name has expired")
+ }
+}
+
// checkAdmin panics if script container is not signed by the domain name admin.
func (n NameState) checkAdmin() {
if runtime.CheckWitness(n.Owner) {
diff --git a/nns/nns.yml b/nns/nns.yml
new file mode 100644
index 0000000..289793c
--- /dev/null
+++ b/nns/nns.yml
@@ -0,0 +1,20 @@
+name: "NameService"
+supportedstandards: ["NEP-11"]
+safemethods: ["balanceOf", "decimals", "symbol", "totalSupply", "tokensOf", "ownerOf",
+ "tokens", "properties", "roots", "getPrice", "isAvailable", "getRecord",
+ "resolve", "getAllRecords"]
+events:
+ - name: Transfer
+ parameters:
+ - name: from
+ type: Hash160
+ - name: to
+ type: Hash160
+ - name: amount
+ type: Integer
+ - name: tokenId
+ type: ByteArray
+permissions:
+ - hash: fffdc93764dbaddd97c48f252a53ea4643faa3fd
+ methods: ["update"]
+ - methods: ["onNEP11Payment"]
diff --git a/nns/nns_contract.go b/nns/nns_contract.go
index 9185e45..bf75fdf 100644
--- a/nns/nns_contract.go
+++ b/nns/nns_contract.go
@@ -41,14 +41,6 @@ const (
// prefixRecord contains map from (token key + hash160(token name) + record type)
// to record.
prefixRecord byte = 0x22
- // prefixGlobalDomain contains a flag indicating that this domain was created using GlobalDomain.
- // This is necessary to distinguish it from regular CNAME records.
- prefixGlobalDomain byte = 0x23
- // prefixCountSubDomains contains information about the number of domains in the zone.
- // If it is nil, it will definitely be calculated on the first removal.
- prefixCountSubDomains byte = 0x24
- // prefixAutoCreated contains a flag indicating whether the TLD domain was created automatically.
- prefixAutoCreated = 0x25
)
// Values constraints.
@@ -60,7 +52,7 @@ const (
// maxDomainNameFragmentLength is the maximum length of the domain name fragment.
maxDomainNameFragmentLength = 63
// minDomainNameLength is minimum domain length.
- minDomainNameLength = 2
+ minDomainNameLength = 3
// maxDomainNameLength is maximum domain length.
maxDomainNameLength = 255
// maxTXTRecordLength is the maximum length of the TXT domain record.
@@ -73,14 +65,6 @@ const (
defaultRegisterPrice = 10_0000_0000
// millisecondsInYear is amount of milliseconds per year.
millisecondsInYear = int64(365 * 24 * 3600 * 1000)
- // errInvalidDomainName is an error message for invalid domain name format.
- errInvalidDomainName = "invalid domain name format"
-)
-
-const (
- // Cnametgt is a special TXT record ensuring all created subdomains point to the global domain - the value of this variable.
- // It is guaranteed that two domains cannot point to the same global domain.
- Cnametgt = "cnametgt"
)
// RecordState is a type that registered entities are saved to.
@@ -92,20 +76,21 @@ type RecordState struct {
}
// Update updates NameService contract.
-func Update(nef []byte, manifest string, data any) {
+func Update(nef []byte, manifest string, data interface{}) {
checkCommittee()
// Calculating keys and serializing requires calling
// std and crypto contracts. This can be helpful on update
// thus we provide `AllowCall` to management.Update.
// management.Update(nef, []byte(manifest))
- management.UpdateWithData(nef, []byte(manifest), common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, nef, manifest, common.AppendVersion(data))
runtime.Log("nns contract updated")
}
// _deploy initializes defaults (total supply and registration price) on contract deploy.
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
return
}
@@ -144,11 +129,12 @@ func OwnerOf(tokenID []byte) interop.Hash160 {
}
// Properties returns a domain name and an expiration date of the specified domain.
-func Properties(tokenID []byte) map[string]any {
+func Properties(tokenID []byte) map[string]interface{} {
ctx := storage.GetReadOnlyContext()
ns := getNameState(ctx, tokenID)
- return map[string]any{
- "name": ns.Name,
+ return map[string]interface{}{
+ "name": ns.Name,
+ "expiration": ns.Expiration,
}
}
@@ -181,7 +167,7 @@ func TokensOf(owner interop.Hash160) iterator.Iterator {
}
// Transfer transfers the domain with the specified name to a new owner.
-func Transfer(to interop.Hash160, tokenID []byte, data any) bool {
+func Transfer(to interop.Hash160, tokenID []byte, data interface{}) bool {
if !isValid(to) {
panic(`invalid receiver`)
}
@@ -234,129 +220,69 @@ func GetPrice() int {
// IsAvailable checks whether the provided domain name is available.
func IsAvailable(name string) bool {
- fragments := splitAndCheck(name)
+ fragments := splitAndCheck(name, false)
+ if fragments == nil {
+ panic("invalid domain name format")
+ }
ctx := storage.GetReadOnlyContext()
l := len(fragments)
if storage.Get(ctx, append([]byte{prefixRoot}, []byte(fragments[l-1])...)) == nil {
+ if l != 1 {
+ panic("TLD not found")
+ }
return true
}
-
- checkParent(ctx, fragments)
- checkAvailableGlobalDomain(ctx, name)
- return storage.Get(ctx, append([]byte{prefixName}, getTokenKey([]byte(name))...)) == nil
+ return parentExpired(ctx, 0, fragments)
}
-// checkAvailableGlobalDomain - triggers a panic if the global domain name is occupied.
-func checkAvailableGlobalDomain(ctx storage.Context, domain string) {
- globalDomain := getGlobalDomain(ctx, domain)
- if globalDomain == "" {
- return
- }
-
- nsBytes := storage.Get(ctx, append([]byte{prefixName}, getTokenKey([]byte(globalDomain))...))
- if nsBytes != nil {
- panic("global domain is already taken: " + globalDomain + ". Domain: " + domain)
- }
-}
-
-// getGlobalDomain returns the global domain.
-func getGlobalDomain(ctx storage.Context, domain string) string {
- index := std.MemorySearch([]byte(domain), []byte("."))
-
- if index == -1 {
- return ""
- }
-
- name := domain[index+1:]
- if name == "" {
- return ""
- }
-
- return extractCnametgt(ctx, name, domain)
-}
-
-// extractCnametgt returns the value of the Cnametgt TXT record.
-func extractCnametgt(ctx storage.Context, name, domain string) string {
- fragments := splitAndCheck(domain)
-
- tokenID := []byte(tokenIDFromName(name))
- records := getRecordsByType(ctx, tokenID, name, TXT)
-
- if records == nil {
- return ""
- }
-
- globalDomain := ""
- for _, name := range records {
- fragments := std.StringSplit(name, "=")
- if len(fragments) != 2 {
- continue
- }
-
- if fragments[0] == Cnametgt {
- globalDomain = fragments[1]
- break
- }
- }
-
- if globalDomain == "" {
- return ""
- }
- return fragments[0] + "." + globalDomain
-}
-
-// checkParent returns parent domain or empty string if domain not found.
-func checkParent(ctx storage.Context, fragments []string) string {
+// parentExpired returns true if any domain from fragments doesn't exist or is expired.
+// first denotes the deepest subdomain to check.
+func parentExpired(ctx storage.Context, first int, fragments []string) bool {
+ now := int64(runtime.GetTime())
last := len(fragments) - 1
name := fragments[last]
- parent := ""
- for i := last; i > 0; i-- {
+ for i := last; i >= first; i-- {
if i != last {
name = fragments[i] + "." + name
}
nsBytes := storage.Get(ctx, append([]byte{prefixName}, getTokenKey([]byte(name))...))
if nsBytes == nil {
- continue
+ return true
+ }
+ ns := std.Deserialize(nsBytes.([]byte)).(NameState)
+ if now >= ns.Expiration {
+ return true
}
- parent = name
}
- return parent
+ return false
}
// Register registers a new domain with the specified owner and name if it's available.
func Register(name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
+ fragments := splitAndCheck(name, true)
+ if fragments == nil {
+ panic("invalid domain name format")
+ }
+
+ l := len(fragments)
+ tldKey := append([]byte{prefixRoot}, []byte(fragments[l-1])...)
ctx := storage.GetContext()
- return register(ctx, name, owner, email, refresh, retry, expire, ttl)
-}
-
-// Register registers a new domain with the specified owner and name if it's available.
-func register(ctx storage.Context, name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
- fragments := splitAndCheck(name)
- countZone := len(fragments)
- rootZone := []byte(fragments[countZone-1])
- tldKey := append([]byte{prefixRoot}, rootZone...)
-
tldBytes := storage.Get(ctx, tldKey)
- if countZone == 1 {
- checkCommitteeAndFrostfsID(ctx, owner)
+ if l == 1 {
+ checkCommittee()
if tldBytes != nil {
panic("TLD already exists")
}
storage.Put(ctx, tldKey, 0)
} else {
- parent := checkParent(ctx, fragments)
- if parent == "" {
- parent = fragments[len(fragments)-1]
-
- storage.Put(ctx, append([]byte{prefixAutoCreated}, rootZone...), true)
- register(ctx, parent, owner, email, refresh, retry, expire, ttl)
+ if tldBytes == nil {
+ panic("TLD not found")
}
-
- parentKey := getTokenKey([]byte(parent))
+ if parentExpired(ctx, 1, fragments) {
+ panic("one of the parent domains is not registered")
+ }
+ parentKey := getTokenKey([]byte(name[len(fragments[0])+1:]))
nsBytes := storage.Get(ctx, append([]byte{prefixName}, parentKey...))
- if nsBytes == nil {
- panic("parent does not exist:" + parent)
- }
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
ns.checkAdmin()
@@ -384,30 +310,46 @@ func register(ctx storage.Context, name string, owner interop.Hash160, email str
nsBytes := storage.Get(ctx, append([]byte{prefixName}, tokenKey...))
if nsBytes != nil {
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
+ if int64(runtime.GetTime()) < ns.Expiration {
+ return false
+ }
oldOwner = ns.Owner
updateBalance(ctx, []byte(name), oldOwner, -1)
} else {
updateTotalSupply(ctx, +1)
}
ns := NameState{
- Owner: owner,
- Name: name,
- Expiration: 0,
+ Owner: owner,
+ Name: name,
+ // NNS expiration is in milliseconds
+ Expiration: int64(runtime.GetTime() + expire*1000),
}
- checkAvailableGlobalDomain(ctx, name)
-
- updateSubdDomainCounter(ctx, rootZone, countZone)
putNameStateWithKey(ctx, tokenKey, ns)
putSoaRecord(ctx, name, email, refresh, retry, expire, ttl)
updateBalance(ctx, []byte(name), owner, +1)
postTransfer(oldOwner, owner, []byte(name), nil)
- runtime.Notify("RegisterDomain", name)
return true
}
+// Renew increases domain expiration date.
+func Renew(name string) int64 {
+ if len(name) > maxDomainNameLength {
+ panic("invalid domain name format")
+ }
+ runtime.BurnGas(GetPrice())
+ ctx := storage.GetContext()
+ ns := getNameState(ctx, []byte(name))
+ ns.checkAdmin()
+ ns.Expiration += millisecondsInYear
+ putNameState(ctx, ns)
+ return ns.Expiration
+}
+
// UpdateSOA updates soa record.
func UpdateSOA(name, email string, refresh, retry, expire, ttl int) {
- checkDomainNameLength(name)
+ if len(name) > maxDomainNameLength {
+ panic("invalid domain name format")
+ }
ctx := storage.GetContext()
ns := getNameState(ctx, []byte(name))
ns.checkAdmin()
@@ -416,7 +358,9 @@ func UpdateSOA(name, email string, refresh, retry, expire, ttl int) {
// SetAdmin updates domain admin.
func SetAdmin(name string, admin interop.Hash160) {
- checkDomainNameLength(name)
+ if len(name) > maxDomainNameLength {
+ panic("invalid domain name format")
+ }
if admin != nil && !runtime.CheckWitness(admin) {
panic("not witnessed by admin")
}
@@ -445,7 +389,7 @@ func checkBaseRecords(typ RecordType, data string) bool {
case A:
return checkIPv4(data)
case CNAME:
- return splitAndCheck(data) != nil
+ return splitAndCheck(data, true) != nil
case TXT:
return len(data) <= maxTXTRecordLength
case AAAA:
@@ -479,26 +423,13 @@ func GetRecords(name string, typ RecordType) []string {
// DeleteRecords removes domain records with the specified type.
func DeleteRecords(name string, typ RecordType) {
- ctx := storage.GetContext()
- deleteRecords(ctx, name, typ)
-}
-
-// DeleteRecords removes domain records with the specified type.
-func deleteRecords(ctx storage.Context, name string, typ RecordType) {
if typ == SOA {
panic("you cannot delete soa record")
}
tokenID := []byte(tokenIDFromName(name))
+ ctx := storage.GetContext()
ns := getNameState(ctx, tokenID)
ns.checkAdmin()
-
- globalDomainStorage := append([]byte{prefixGlobalDomain}, getTokenKey([]byte(name))...)
- globalDomainRaw := storage.Get(ctx, globalDomainStorage)
- globalDomain := globalDomainRaw.(string)
- if globalDomainRaw != nil && globalDomain != "" {
- deleteDomain(ctx, globalDomain)
- }
-
recordsKey := getRecordsKeyByType(tokenID, name, typ)
records := storage.Find(ctx, recordsKey, storage.KeysOnly)
for iterator.Next(records) {
@@ -506,126 +437,6 @@ func deleteRecords(ctx storage.Context, name string, typ RecordType) {
storage.Delete(ctx, r)
}
updateSoaSerial(ctx, tokenID)
- runtime.Notify("DeleteRecords", name, typ)
-}
-
-// DeleteRecord delete a record of the specified type by data in the provided domain.
-// Returns false if the record was not found.
-func DeleteRecord(name string, typ RecordType, data string) bool {
- tokenID := []byte(tokenIDFromName(name))
- if !checkBaseRecords(typ, data) {
- panic("invalid record data")
- }
- ctx := storage.GetContext()
- ns := getNameState(ctx, tokenID)
- ns.checkAdmin()
- return deleteRecord(ctx, tokenID, name, typ, data)
-}
-
-func deleteRecord(ctx storage.Context, tokenId []byte, name string, typ RecordType, data string) bool {
- recordsKey := getRecordsKeyByType(tokenId, name, typ)
-
- var previousKey any
- it := storage.Find(ctx, recordsKey, storage.KeysOnly)
- for iterator.Next(it) {
- key := iterator.Value(it).([]byte)
- ss := storage.Get(ctx, key).([]byte)
-
- ns := std.Deserialize(ss).(RecordState)
- if ns.Name == name && ns.Type == typ && ns.Data == data {
- previousKey = key
- continue
- }
-
- if previousKey != nil {
- data := storage.Get(ctx, key)
- storage.Put(ctx, previousKey, data)
- previousKey = key
- }
- }
-
- if previousKey == nil {
- return false
- }
-
- storage.Delete(ctx, previousKey)
- runtime.Notify("DeleteRecord", name, typ)
- return true
-}
-
-// DeleteDomain deletes the domain with the given name.
-func DeleteDomain(name string) {
- ctx := storage.GetContext()
- deleteDomain(ctx, name)
-}
-
-func countSubdomains(name string) int {
- countSubDomains := 0
- it := Tokens()
- for iterator.Next(it) {
- domain := iterator.Value(it)
- if std.MemorySearch([]byte(domain.(string)), []byte(name)) > 0 {
- countSubDomains = countSubDomains + 1
- }
- }
- return countSubDomains
-}
-
-func deleteDomain(ctx storage.Context, name string) {
- fragments := splitAndCheck(name)
- parent := []byte(fragments[len(fragments)-1])
- countSubDomainsKey := append([]byte{prefixCountSubDomains}, parent...)
- autoCreatedPrefix := append([]byte{prefixAutoCreated}, parent...)
-
- nsKey := append([]byte{prefixName}, getTokenKey([]byte(name))...)
- nsRaw := storage.Get(ctx, nsKey)
- if nsRaw == nil {
- panic("domain not found")
- }
-
- ns := std.Deserialize(nsRaw.([]byte)).(NameState)
- ns.checkAdmin()
-
- countSubDomain := 0
- countSubDomainRaw := storage.Get(ctx, countSubDomainsKey)
- if countSubDomainRaw != nil {
- countSubDomain = common.FromFixedWidth64(countSubDomainRaw.([]byte))
- } else {
- countSubDomain = countSubdomains(fragments[len(fragments)-1])
- }
-
- if countSubDomain > 1 && len(fragments) == 1 {
- panic("can't delete TLD domain that has subdomains")
- }
-
- countSubDomain = countSubDomain - 1
- storage.Put(ctx, countSubDomainsKey, common.ToFixedWidth64(countSubDomain))
-
- globalNSKey := append([]byte{prefixGlobalDomain}, getTokenKey([]byte(name))...)
- globalDomainRaw := storage.Get(ctx, globalNSKey)
- globalDomain := globalDomainRaw.(string)
- if globalDomainRaw != nil && globalDomain != "" {
- deleteDomain(ctx, globalDomain)
- }
-
- deleteRecords(ctx, name, CNAME)
- deleteRecords(ctx, name, TXT)
- deleteRecords(ctx, name, A)
- deleteRecords(ctx, name, AAAA)
- storage.Delete(ctx, nsKey)
- storage.Delete(ctx, append([]byte{prefixRoot}, []byte(name)...))
-
- isAutoCreated := storage.Get(ctx, autoCreatedPrefix)
- if countSubDomain == 1 && isAutoCreated != nil && isAutoCreated.(bool) {
- deleteDomain(ctx, fragments[len(fragments)-1])
- }
-
- if len(fragments) == 1 {
- storage.Delete(ctx, countSubDomainsKey)
- storage.Delete(ctx, autoCreatedPrefix)
- }
-
- runtime.Notify("DeleteDomain", name)
}
// Resolve resolves given name (not more then three redirects are allowed).
@@ -648,13 +459,13 @@ func updateBalance(ctx storage.Context, tokenId []byte, acc interop.Hash160, dif
balanceKey := append([]byte{prefixBalance}, acc...)
var balance int
if b := storage.Get(ctx, balanceKey); b != nil {
- balance = common.FromFixedWidth64(b.([]byte))
+ balance = b.(int)
}
balance += diff
if balance == 0 {
storage.Delete(ctx, balanceKey)
} else {
- storage.Put(ctx, balanceKey, common.ToFixedWidth64(balance))
+ storage.Put(ctx, balanceKey, balance)
}
tokenKey := getTokenKey(tokenId)
@@ -668,7 +479,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 any) {
+func postTransfer(from, to interop.Hash160, tokenID []byte, data interface{}) {
runtime.Notify("Transfer", from, to, 1, tokenID)
if management.GetContract(to) != nil {
contract.Call(to, "onNEP11Payment", contract.All, from, 1, tokenID, data)
@@ -678,14 +489,14 @@ func postTransfer(from, to interop.Hash160, tokenID []byte, data any) {
// getTotalSupply returns total supply from storage.
func getTotalSupply(ctx storage.Context) int {
val := storage.Get(ctx, []byte{prefixTotalSupply})
- return common.FromFixedWidth64(val.([]byte))
+ return val.(int)
}
// updateTotalSupply adds the specified diff to the total supply.
func updateTotalSupply(ctx storage.Context, diff int) {
tsKey := []byte{prefixTotalSupply}
ts := getTotalSupply(ctx)
- storage.Put(ctx, tsKey, common.ToFixedWidth64(ts+diff))
+ storage.Put(ctx, tsKey, ts+diff)
}
// getTokenKey computes hash160 from the given tokenID.
@@ -698,7 +509,9 @@ func getNameState(ctx storage.Context, tokenID []byte) NameState {
tokenKey := getTokenKey(tokenID)
ns := getNameStateWithKey(ctx, tokenKey)
fragments := std.StringSplit(string(tokenID), ".")
- checkParent(ctx, fragments)
+ if parentExpired(ctx, 1, fragments) {
+ panic("parent domain has expired")
+ }
return ns
}
@@ -709,7 +522,9 @@ func getNameStateWithKey(ctx storage.Context, tokenKey []byte) NameState {
if nsBytes == nil {
panic("token not found")
}
- return std.Deserialize(nsBytes.([]byte)).(NameState)
+ ns := std.Deserialize(nsBytes.([]byte)).(NameState)
+ ns.ensureNotExpired()
+ return ns
}
// putNameState stores domain name state.
@@ -766,33 +581,6 @@ func addRecord(ctx storage.Context, tokenId []byte, name string, typ RecordType,
}
}
- globalDomainKey := append([]byte{prefixGlobalDomain}, getTokenKey([]byte(name))...)
- globalDomainStorage := storage.Get(ctx, globalDomainKey)
- globalDomain := getGlobalDomain(ctx, name)
-
- if globalDomainStorage == nil && typ == TXT {
- if globalDomain != "" {
- checkAvailableGlobalDomain(ctx, name)
- nsOriginal := getNameState(ctx, []byte(tokenIDFromName(name)))
- ns := NameState{
- Name: globalDomain,
- Owner: nsOriginal.Owner,
- Expiration: 0,
- Admin: nsOriginal.Admin,
- }
-
- putNameStateWithKey(ctx, getTokenKey([]byte(globalDomain)), ns)
- storage.Put(ctx, globalDomainKey, globalDomain)
-
- var oldOwner interop.Hash160
- updateBalance(ctx, []byte(name), nsOriginal.Owner, +1)
- postTransfer(oldOwner, nsOriginal.Owner, []byte(name), nil)
- putCnameRecord(ctx, globalDomain, name)
- } else {
- storage.Put(ctx, globalDomainKey, "")
- }
- }
-
if typ == CNAME && id != 0 {
panic("you shouldn't have more than one CNAME record")
}
@@ -811,7 +599,6 @@ func storeRecord(ctx storage.Context, recordKey []byte, name string, typ RecordT
}
recBytes := std.Serialize(rs)
storage.Put(ctx, recordKey, recBytes)
- runtime.Notify("AddRecord", name, typ)
}
// putSoaRecord stores soa domain record.
@@ -832,24 +619,6 @@ func putSoaRecord(ctx storage.Context, name, email string, refresh, retry, expir
}
recBytes := std.Serialize(rs)
storage.Put(ctx, recordKey, recBytes)
- runtime.Notify("AddRecord", name, SOA)
-}
-
-// putCnameRecord stores CNAME domain record.
-func putCnameRecord(ctx storage.Context, name, data string) {
- var id byte
- tokenId := []byte(tokenIDFromName(name))
- recordKey := getIdRecordKey(tokenId, name, CNAME, id)
-
- rs := RecordState{
- Name: name,
- Type: CNAME,
- ID: id,
- Data: data,
- }
- recBytes := std.Serialize(rs)
- storage.Put(ctx, recordKey, recBytes)
- runtime.Notify("AddRecord", name, CNAME)
}
// updateSoaSerial stores soa domain record.
@@ -859,7 +628,7 @@ func updateSoaSerial(ctx storage.Context, tokenId []byte) {
recBytes := storage.Get(ctx, recordKey)
if recBytes == nil {
- return
+ panic("not found soa record")
}
rec := std.Deserialize(recBytes.([]byte)).(RecordState)
@@ -900,14 +669,6 @@ func isValid(address interop.Hash160) bool {
return address != nil && len(address) == interop.Hash160Len
}
-// checkCommitteeAndFrostfsID panics if the script container is not signed by the committee.
-// or if the owner does not have permission in FrostfsID.
-func checkCommitteeAndFrostfsID(ctx storage.Context, owner interop.Hash160) {
- if !checkFrostfsID(ctx, owner) {
- checkCommittee()
- }
-}
-
// checkCommittee panics if the script container is not signed by the committee.
func checkCommittee() {
committee := neo.GetCommittee()
@@ -956,29 +717,24 @@ func isAlNum(c uint8) bool {
}
// splitAndCheck splits domain name into parts and validates it.
-func splitAndCheck(name string) []string {
- checkDomainNameLength(name)
+func splitAndCheck(name string, allowMultipleFragments bool) []string {
+ l := len(name)
+ if l < minDomainNameLength || maxDomainNameLength < l {
+ return nil
+ }
fragments := std.StringSplit(name, ".")
- l := len(fragments)
+ l = len(fragments)
+ if l > 2 && !allowMultipleFragments {
+ return nil
+ }
for i := 0; i < l; i++ {
if !checkFragment(fragments[i], i == l-1) {
- panic(errInvalidDomainName + " '" + name + "': invalid fragment '" + fragments[i] + "'")
+ return nil
}
}
return fragments
}
-// checkDomainNameLength panics if domain name length is out of boundaries.
-func checkDomainNameLength(name string) {
- l := len(name)
- if l > maxDomainNameLength {
- panic(errInvalidDomainName + " '" + name + "': domain name too long: got = " + std.Itoa(l, 10) + ", max = " + std.Itoa(maxDomainNameLength, 10))
- }
- if l < minDomainNameLength {
- panic(errInvalidDomainName + " '" + name + "': domain name too short: got = " + std.Itoa(l, 10) + ", min = " + std.Itoa(minDomainNameLength, 10))
- }
-}
-
// checkIPv4 checks record on IPv4 compliance.
func checkIPv4(data string) bool {
l := len(data)
@@ -1091,17 +847,23 @@ func checkIPv6(data string) bool {
// tokenIDFromName returns token ID (domain.root) from the provided name.
func tokenIDFromName(name string) string {
- fragments := splitAndCheck(name)
+ fragments := splitAndCheck(name, true)
+ if fragments == nil {
+ panic("invalid domain name format")
+ }
ctx := storage.GetReadOnlyContext()
sum := 0
- l := len(fragments)
+ l := len(fragments) - 1
for i := 0; i < l; i++ {
tokenKey := getTokenKey([]byte(name[sum:]))
nameKey := append([]byte{prefixName}, tokenKey...)
nsBytes := storage.Get(ctx, nameKey)
if nsBytes != nil {
- return name[sum:]
+ ns := std.Deserialize(nsBytes.([]byte)).(NameState)
+ if int64(runtime.GetTime()) < ns.Expiration {
+ return name[sum:]
+ }
}
sum += len(fragments[i]) + 1
}
@@ -1147,16 +909,3 @@ func getAllRecords(ctx storage.Context, name string) iterator.Iterator {
recordsKey := getRecordsKey(tokenID, name)
return storage.Find(ctx, recordsKey, storage.ValuesOnly|storage.DeserializeValues)
}
-
-func updateSubdDomainCounter(ctx storage.Context, rootZone []byte, countZone int) {
- countSubDomain := 0
- delInfoRaw := storage.Get(ctx, append([]byte{prefixCountSubDomains}, rootZone...))
- if delInfoRaw != nil {
- countSubDomain = common.FromFixedWidth64(delInfoRaw.([]byte))
- }
-
- if delInfoRaw != nil || countZone == 1 {
- countSubDomain = countSubDomain + 1
- storage.Put(ctx, append([]byte{prefixCountSubDomains}, rootZone...), common.ToFixedWidth64(countSubDomain))
- }
-}
diff --git a/policy/config.yml b/policy/config.yml
deleted file mode 100644
index 921d853..0000000
--- a/policy/config.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-name: "APE"
-permissions:
- - methods: ["update"]
-safemethods:
- - "getAdmin"
- - "listChains"
- - "getChain"
- - "listChainsByPrefix"
- - "listTargets"
- - "listChainNames"
- - "iteratorChainsByPrefix"
- - "version"
\ No newline at end of file
diff --git a/policy/doc.go b/policy/doc.go
deleted file mode 100644
index d537585..0000000
--- a/policy/doc.go
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |------------------------------------------|--------|-----------------------------------|
- | 'c' + uint16(len(container)) + container | []byte | Namespace chain |
- | 'n' + uint16(len(namespace)) + namespace | []byte | Container chain |
- | 'm' + entity name (namespace/container) | []byte | Mapped name to an encoded number |
- | 'Counter' | uint64 | Integer counter used for mapping |
-
-*/
-
-package policy
diff --git a/policy/policy_contract.go b/policy/policy_contract.go
deleted file mode 100644
index 10f8cd7..0000000
--- a/policy/policy_contract.go
+++ /dev/null
@@ -1,317 +0,0 @@
-package policy
-
-import (
- "git.frostfs.info/TrueCloudLab/frostfs-contract/common"
- "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid"
- "git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
- "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/native/management"
- "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"
-)
-
-// Kind represents the object the chain is attached to.
-// Currently only namespace and container are supported.
-type Kind byte
-
-const (
- Namespace = 'n'
- Container = 'c'
- User = 'u'
- Group = 'g'
- IAM = 'i'
-)
-
-const (
- ownerKeyPrefix = 'o'
-)
-
-const (
- mappingKeyPrefix = 'm'
- counterKey = "Counter"
-)
-
-const (
- // ErrNotAuthorized is returned when the none of the transaction signers
- // belongs to the list of autorized keys.
- ErrNotAuthorized = "none of the signers is authorized to change the contract"
-)
-
-const (
- purgeNsState = "purge"
- frozenNsState = "frozen"
-)
-
-// _deploy function sets up initial list of inner ring public keys.
-func _deploy(data any, isUpdate bool) {
- if isUpdate {
- args := data.([]any)
- common.CheckVersion(args[len(args)-1].(int))
- return
- }
-
- args := data.(struct {
- Admin interop.Hash160
- })
- ctx := storage.GetContext()
- if args.Admin != nil {
- if len(args.Admin) != 20 {
- panic("invalid admin hash length")
- }
- storage.Put(ctx, []byte{ownerKeyPrefix}, args.Admin)
- }
- storage.Put(ctx, counterKey, 0)
-}
-
-func checkAuthorization(ctx storage.Context) {
- admin := getAdmin(ctx)
- if admin != nil && runtime.CheckWitness(admin) {
- return
- }
- if runtime.CheckWitness(common.AlphabetAddress()) {
- return
- }
-
- panic(ErrNotAuthorized)
-}
-
-// Version returns the version of the contract.
-func Version() int {
- return common.Version
-}
-
-// Update method updates contract source code and manifest. It can be invoked
-// by committee only.
-func Update(script []byte, manifest []byte, data any) {
- if !common.HasUpdateAccess() {
- panic("only committee can update contract")
- }
-
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
- runtime.Log("policy contract updated")
-}
-
-func SetAdmin(addr interop.Hash160) {
- common.CheckAlphabetWitness()
-
- ctx := storage.GetContext()
- storage.Put(ctx, []byte{ownerKeyPrefix}, addr)
-}
-
-func GetAdmin() interop.Hash160 {
- ctx := storage.GetReadOnlyContext()
- return getAdmin(ctx)
-}
-
-func getAdmin(ctx storage.Context) interop.Hash160 {
- return storage.Get(ctx, []byte{ownerKeyPrefix}).(interop.Hash160)
-}
-
-func storageKey(prefix Kind, counter int, name []byte) []byte {
- key := append([]byte{byte(prefix)}, common.ToFixedWidth64(counter)...)
- return append(key, name...)
-}
-
-func mapKey(kind Kind, name []byte) []byte {
- return append([]byte{mappingKeyPrefix, byte(kind)}, name...)
-}
-
-// mapToNumeric maps a name to a number. That allows to keep more space in
-// a storage key shortening long names. Short entity
-// names are also mapped to prevent collisions in the map.
-func mapToNumeric(ctx storage.Context, kind Kind, name []byte) (mapped int, mappingExists bool) {
- mKey := mapKey(kind, name)
- numericID := storage.Get(ctx, mKey)
- if numericID == nil {
- return 0, false
- }
- mapped = numericID.(int)
- mappingExists = true
- return
-}
-
-// mapToNumericCreateIfNotExists maps a name to a number. That allows to keep
-// more space in a storage key shortening long names. Short entity
-// names are also mapped to prevent collisions in the map.
-// If a mapping cannot be found, then the method creates and returns it.
-// mapToNumericCreateIfNotExists is NOT applicable for a read-only context.
-func mapToNumericCreateIfNotExists(ctx storage.Context, kind Kind, name []byte) int {
- mKey := mapKey(kind, name)
- numericID := storage.Get(ctx, mKey)
- if numericID == nil {
- counter := storage.Get(ctx, counterKey).(int)
- counter++
- storage.Put(ctx, counterKey, counter)
- storage.Put(ctx, mKey, counter)
- return counter
- }
- return numericID.(int)
-}
-
-func checkChainNamespace(entity Kind, name string) {
- if entity != Namespace {
- return
- }
- frostfsidAddr := getContractHash(nns.FrostfsIDNNSName)
- if frostfsidAddr == nil || management.GetContract(frostfsidAddr) == nil {
- panic("could not get frostfsid contract")
- }
- ns := contract.Call(frostfsidAddr, "getNamespace", contract.ReadOnly, name).(frostfsid.Namespace)
- if ns.State == purgeNsState || ns.State == frozenNsState {
- panic("namespace is non-active")
- }
-}
-
-// getContractHash returns nil when it can't resolve contract name,
-// so custom error message can be thrown.
-func getContractHash(name string) interop.Hash160 {
- nnsContract := management.GetContractByID(1)
- records := contract.Call(nnsContract.Hash, "getRecords", contract.ReadOnly, name, nns.TXT).([]string)
- for _, record := range records {
- contractHash := readContractHashFromNNSRecord(record)
- if contractHash != nil {
- return contractHash
- }
- }
- return nil
-}
-
-func readContractHashFromNNSRecord(nnsResponse string) interop.Hash160 {
- // 40 is size of hex encoded contract hash as string
- if len(nnsResponse) == 40 {
- return nil
- }
-
- decoded := std.Base58Decode([]byte(nnsResponse))
- if len(decoded) != common.AddressLen || management.GetContract(decoded[1:21]) == nil {
- return nil
- }
- return decoded[1:21]
-}
-
-func AddChain(entity Kind, entityName string, name []byte, chain []byte) {
- ctx := storage.GetContext()
- checkAuthorization(ctx)
- checkChainNamespace(entity, entityName)
-
- entityNameBytes := mapToNumericCreateIfNotExists(ctx, entity, []byte(entityName))
- key := storageKey(entity, entityNameBytes, name)
- storage.Put(ctx, key, chain)
-}
-
-func GetChain(entity Kind, entityName string, name []byte) []byte {
- ctx := storage.GetReadOnlyContext()
-
- entityNameBytes, exists := mapToNumeric(ctx, entity, []byte(entityName))
- if !exists {
- panic("not found")
- }
-
- key := storageKey(entity, entityNameBytes, name)
- data := storage.Get(ctx, key).([]byte)
- if data == nil {
- panic("not found")
- }
-
- return data
-}
-
-func RemoveChain(entity Kind, entityName string, name []byte) {
- ctx := storage.GetContext()
- checkAuthorization(ctx)
-
- entityNameNum, exists := mapToNumeric(ctx, entity, []byte(entityName))
- if !exists {
- return
- }
-
- key := storageKey(entity, entityNameNum, name)
- storage.Delete(ctx, key)
-
- // If no chains are left for the target, then remove the mapping.
- prefix := append([]byte{byte(entity)}, common.ToFixedWidth64(entityNameNum)...)
- it := storage.Find(ctx, prefix, storage.KeysOnly)
- if !iterator.Next(it) {
- storage.Delete(ctx, mapKey(entity, []byte(entityName)))
- }
-}
-
-func RemoveChainsByPrefix(entity Kind, entityName string, name []byte) {
- ctx := storage.GetContext()
- checkAuthorization(ctx)
-
- entityNameNum, exists := mapToNumeric(ctx, entity, []byte(entityName))
- if !exists {
- return
- }
-
- key := storageKey(entity, entityNameNum, name)
- it := storage.Find(ctx, key, storage.KeysOnly)
- for iterator.Next(it) {
- storage.Delete(ctx, iterator.Value(it).([]byte))
- }
-
- // If no chains are left for the target, then remove the mapping.
- prefix := append([]byte{byte(entity)}, common.ToFixedWidth64(entityNameNum)...)
- it = storage.Find(ctx, prefix, storage.KeysOnly)
- if !iterator.Next(it) {
- storage.Delete(ctx, mapKey(entity, []byte(entityName)))
- }
-}
-
-// ListChains lists all chains for the namespace by prefix.
-// container may be empty.
-func ListChains(namespace, container string, name []byte) [][]byte {
- result := ListChainsByPrefix(Namespace, namespace, name)
-
- if container != "" {
- result = append(result, ListChainsByPrefix(Container, container, name)...)
- }
-
- return result
-}
-
-// ListChainsByPrefix list all chains for the provided kind and entity by prefix.
-func ListChainsByPrefix(entity Kind, entityName string, prefix []byte) [][]byte {
- ctx := storage.GetReadOnlyContext()
-
- result := [][]byte{}
-
- entityNameBytes, exists := mapToNumeric(ctx, entity, []byte(entityName))
- if !exists {
- return result
- }
-
- keyPrefix := storageKey(entity, entityNameBytes, prefix)
- it := storage.Find(ctx, keyPrefix, storage.ValuesOnly)
- for iterator.Next(it) {
- result = append(result, iterator.Value(it).([]byte))
- }
-
- return result
-}
-
-func IteratorChainsByPrefix(entity Kind, entityName string, prefix []byte) iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- id, _ := mapToNumeric(ctx, entity, []byte(entityName))
- keyPrefix := storageKey(entity, id, prefix)
- return storage.Find(ctx, keyPrefix, storage.ValuesOnly)
-}
-
-// ListTargets iterates over targets for which rules are defined.
-func ListTargets(entity Kind) iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- mKey := mapKey(entity, []byte{})
- return storage.Find(ctx, mKey, storage.KeysOnly|storage.RemovePrefix)
-}
-
-// ListChainNames iterates over chain names for specific target.
-func ListChainNames(entity Kind, entityName string) iterator.Iterator {
- ctx := storage.GetReadOnlyContext()
- id, _ := mapToNumeric(ctx, entity, []byte(entityName))
- keyPrefix := storageKey(entity, id, []byte{})
- return storage.Find(ctx, keyPrefix, storage.KeysOnly|storage.RemovePrefix)
-}
diff --git a/processing/doc.go b/processing/doc.go
index fa2d4f0..f6a4979 100644
--- a/processing/doc.go
+++ b/processing/doc.go
@@ -18,11 +18,5 @@ execution.
# Contract notifications
Processing contract does not produce notifications to process.
-
-# Contract storage scheme
-
- | Key | Value | Description |
- |-----------------------------|------------|----------------------------------|
- | `frostfsScriptHash` | Hash160 | frostFS contract hash |
*/
package processing
diff --git a/processing/processing_contract.go b/processing/processing_contract.go
index 0ea4f2e..f96ffa6 100644
--- a/processing/processing_contract.go
+++ b/processing/processing_contract.go
@@ -3,34 +3,54 @@ package processing
import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
"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/native/gas"
"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/roles"
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
+ "github.com/nspcc-dev/neo-go/pkg/interop/storage"
+)
+
+const (
+ frostfsContractKey = "frostfsScriptHash"
+
+ multiaddrMethod = "alphabetAddress"
)
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
-func OnNEP17Payment(from interop.Hash160, amount int, data any) {
+func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
caller := runtime.GetCallingScriptHash()
if !common.BytesEqual(caller, []byte(gas.Hash)) {
common.AbortWithMessage("processing contract accepts GAS only")
}
}
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
return
}
+ args := data.(struct {
+ addrFrostFS interop.Hash160
+ })
+
+ ctx := storage.GetContext()
+
+ if len(args.addrFrostFS) != interop.Hash160Len {
+ panic("incorrect length of contract script hash")
+ }
+
+ storage.Put(ctx, frostfsContractKey, args.addrFrostFS)
+
runtime.Log("processing contract initialized")
}
// Update method updates contract source code and manifest. It can be invoked
// only by the sidechain committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
blockHeight := ledger.CurrentIndex()
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
alphabetCommittee := common.Multiaddress(alphabetKeys, true)
@@ -39,14 +59,19 @@ func Update(script []byte, manifest []byte, data any) {
panic("only side chain committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("processing contract updated")
}
// Verify method returns true if transaction contains valid multisignature of
// Alphabet nodes of the Inner Ring.
func Verify() bool {
- return runtime.CheckWitness(common.AlphabetAddress())
+ ctx := storage.GetContext()
+ frostfsContractAddr := storage.Get(ctx, frostfsContractKey).(interop.Hash160)
+ multiaddr := contract.Call(frostfsContractAddr, multiaddrMethod, contract.ReadOnly).(interop.Hash160)
+
+ return runtime.CheckWitness(multiaddr)
}
// Version returns the version of the contract.
diff --git a/proxy/doc.go b/proxy/doc.go
index 2a261cc..3201a92 100644
--- a/proxy/doc.go
+++ b/proxy/doc.go
@@ -17,9 +17,5 @@ verified, Proxy contract pays for the execution.
# Contract notifications
Proxy contract does not produce notifications to process.
-
-# Contract storage scheme
-
-Proxy contract does not use storage
*/
package proxy
diff --git a/proxy/proxy_contract.go b/proxy/proxy_contract.go
index 613bc17..3d22ad6 100644
--- a/proxy/proxy_contract.go
+++ b/proxy/proxy_contract.go
@@ -3,34 +3,24 @@ package proxy
import (
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
"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/native/gas"
"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"
)
-const accountKeyPrefix = 'a'
-
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
-func OnNEP17Payment(from interop.Hash160, amount int, data any) {
+func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
caller := runtime.GetCallingScriptHash()
if !common.BytesEqual(caller, []byte(gas.Hash)) {
common.AbortWithMessage("proxy contract accepts GAS only")
}
}
-// OnNEP11Payment is a callback for NEP-11 compatible NNS contract.
-func OnNEP11Payment(from interop.Hash160, amount int, token []byte, data any) {
- caller := runtime.GetCallingScriptHash()
- nnsHash := management.GetContractByID(1).Hash
- if !common.BytesEqual(caller, []byte(nnsHash)) {
- common.AbortWithMessage("proxy contract accepts NNS tokens only")
- }
-}
-
-func _deploy(data any, isUpdate bool) {
+func _deploy(data interface{}, isUpdate bool) {
if isUpdate {
- args := data.([]any)
+ args := data.([]interface{})
common.CheckVersion(args[len(args)-1].(int))
return
}
@@ -40,56 +30,31 @@ func _deploy(data any, isUpdate bool) {
// Update method updates contract source code and manifest. It can be invoked
// only by committee.
-func Update(script []byte, manifest []byte, data any) {
+func Update(script []byte, manifest []byte, data interface{}) {
if !common.HasUpdateAccess() {
panic("only committee can update contract")
}
- management.UpdateWithData(script, manifest, common.AppendVersion(data))
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
runtime.Log("proxy contract updated")
}
// Verify method returns true if transaction contains valid multisignature of
-// Alphabet nodes of the Inner Ring or any of the trusted accounts added via AddAccount.
+// Alphabet nodes of the Inner Ring.
func Verify() bool {
- if !runtime.GetScriptContainer().Sender.Equals(runtime.GetExecutingScriptHash()) {
- return false
+ alphabet := neo.GetCommittee()
+ sig := common.Multiaddress(alphabet, false)
+
+ if !runtime.CheckWitness(sig) {
+ sig = common.Multiaddress(alphabet, true)
+ return runtime.CheckWitness(sig)
}
- signers := runtime.CurrentSigners()
- ctx := storage.GetReadOnlyContext()
- for i := 1; /* skip sender */ i < len(signers); i++ {
- if storage.Get(ctx, append([]byte{accountKeyPrefix}, signers[i].Account...)) != nil {
- return true
- }
- }
-
- if runtime.CheckWitness(common.CommitteeAddress()) {
- return true
- }
-
- if runtime.CheckWitness(common.AlphabetAddress()) {
- return true
- }
-
- return false
+ return true
}
// Version returns the version of the contract.
func Version() int {
return common.Version
}
-
-func AddAccount(addr interop.Hash160) {
- common.CheckWitness(common.CommitteeAddress())
-
- ctx := storage.GetContext()
- storage.Put(ctx, append([]byte{accountKeyPrefix}, addr...), []byte{1})
-}
-
-func RemoveAccount(addr interop.Hash160) {
- common.CheckWitness(common.CommitteeAddress())
-
- ctx := storage.GetContext()
- storage.Delete(ctx, append([]byte{accountKeyPrefix}, addr...))
-}
diff --git a/reputation/config.yml b/reputation/config.yml
new file mode 100644
index 0000000..ffe98c6
--- /dev/null
+++ b/reputation/config.yml
@@ -0,0 +1,13 @@
+name: "Reputation"
+safemethods: ["get", "getByID", "listByEpoch"]
+permissions:
+ - methods: ["update"]
+events:
+ - name: reputationPut
+ parameters:
+ - name: epoch
+ type: Integer
+ - name: peerID
+ type: ByteArray
+ - name: value
+ type: ByteArray
diff --git a/reputation/doc.go b/reputation/doc.go
new file mode 100644
index 0000000..ad253af
--- /dev/null
+++ b/reputation/doc.go
@@ -0,0 +1,17 @@
+/*
+Reputation contract is a contract deployed in FrostFS sidechain.
+
+Inner Ring nodes produce data audit for each container during each epoch. In the end,
+nodes produce DataAuditResult structure that contains information about audit
+progress. Reputation contract provides storage for such structures and simple
+interface to iterate over available DataAuditResults on specified epoch.
+
+During settlement process, Alphabet nodes fetch all DataAuditResult structures
+from the epoch and execute balance transfers from data owners to Storage and
+Inner Ring nodes if data audit succeeds.
+
+# Contract notifications
+
+Reputation contract does not produce notifications to process.
+*/
+package reputation
diff --git a/reputation/reputation_contract.go b/reputation/reputation_contract.go
new file mode 100644
index 0000000..2055204
--- /dev/null
+++ b/reputation/reputation_contract.go
@@ -0,0 +1,125 @@
+package reputation
+
+import (
+ "git.frostfs.info/TrueCloudLab/frostfs-contract/common"
+ "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/convert"
+ "github.com/nspcc-dev/neo-go/pkg/interop/iterator"
+ "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/storage"
+)
+
+const (
+ notaryDisabledKey = "notary"
+ reputationValuePrefix = 'r'
+ reputationCountPrefix = 'c'
+)
+
+func _deploy(data interface{}, isUpdate bool) {
+ common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
+
+ if isUpdate {
+ args := data.([]interface{})
+ common.CheckVersion(args[len(args)-1].(int))
+ return
+ }
+
+ runtime.Log("reputation contract initialized")
+}
+
+// Update method updates contract source code and manifest. It can be invoked
+// only by committee.
+func Update(script []byte, manifest []byte, data interface{}) {
+ if !common.HasUpdateAccess() {
+ panic("only committee can update contract")
+ }
+
+ contract.Call(interop.Hash160(management.Hash), "update",
+ contract.All, script, manifest, common.AppendVersion(data))
+ runtime.Log("reputation contract updated")
+}
+
+// Put method saves DataAuditResult in contract storage. It can be invoked only by
+// Inner Ring nodes. It does not require multisignature invocations.
+//
+// Epoch is the epoch number when DataAuditResult structure was generated.
+// PeerID contains public keys of the Inner Ring node that has produced DataAuditResult.
+// Value contains a stable marshaled structure of DataAuditResult.
+func Put(epoch int, peerID []byte, value []byte) {
+ ctx := storage.GetContext()
+
+ multiaddr := common.AlphabetAddress()
+ if !runtime.CheckWitness(multiaddr) {
+ runtime.Notify("reputationPut", epoch, peerID, value)
+ return
+ }
+
+ id := storageID(epoch, peerID)
+ key := getReputationKey(reputationCountPrefix, id)
+ rawCnt := storage.Get(ctx, key)
+ cnt := 0
+ if rawCnt != nil {
+ cnt = rawCnt.(int)
+ }
+ cnt++
+ storage.Put(ctx, key, cnt)
+
+ key[0] = reputationValuePrefix
+ key = append(key, convert.ToBytes(cnt)...)
+ storage.Put(ctx, key, value)
+}
+
+// Get method returns a list of all stable marshaled DataAuditResult structures
+// produced by the specified Inner Ring node during the specified epoch.
+func Get(epoch int, peerID []byte) [][]byte {
+ id := storageID(epoch, peerID)
+ return GetByID(id)
+}
+
+// GetByID method returns a list of all stable marshaled DataAuditResult with
+// the specified id. Use ListByEpoch method to obtain the id.
+func GetByID(id []byte) [][]byte {
+ ctx := storage.GetReadOnlyContext()
+
+ var data [][]byte
+
+ it := storage.Find(ctx, getReputationKey(reputationValuePrefix, id), storage.ValuesOnly)
+ for iterator.Next(it) {
+ data = append(data, iterator.Value(it).([]byte))
+ }
+ return data
+}
+
+func getReputationKey(prefix byte, id []byte) []byte {
+ return append([]byte{prefix}, id...)
+}
+
+// ListByEpoch returns a list of IDs that may be used to get reputation data
+// with GetByID method.
+func ListByEpoch(epoch int) [][]byte {
+ ctx := storage.GetReadOnlyContext()
+ key := getReputationKey(reputationCountPrefix, convert.ToBytes(epoch))
+ it := storage.Find(ctx, key, storage.KeysOnly)
+
+ var result [][]byte
+
+ for iterator.Next(it) {
+ key := iterator.Value(it).([]byte) // iterator MUST BE `storage.KeysOnly`
+ result = append(result, key[1:])
+ }
+
+ return result
+}
+
+// Version returns the version of the contract.
+func Version() int {
+ return common.Version
+}
+
+func storageID(epoch int, peerID []byte) []byte {
+ var buf interface{} = epoch
+
+ return append(buf.([]byte), peerID...)
+}
diff --git a/rpcclient/alphabet/client.go b/rpcclient/alphabet/client.go
deleted file mode 100644
index 4b2e05e..0000000
--- a/rpcclient/alphabet/client.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package alphabet contains RPC wrappers for Alphabet contract.
-package alphabet
-
-import (
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
- "github.com/nspcc-dev/neo-go/pkg/neorpc/result"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "math/big"
-)
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// Gas invokes `gas` method of contract.
-func (c *ContractReader) Gas() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "gas"))
-}
-
-// Name invokes `name` method of contract.
-func (c *ContractReader) Name() (string, error) {
- return unwrap.UTF8String(c.invoker.Call(c.hash, "name"))
-}
-
-// Neo invokes `neo` method of contract.
-func (c *ContractReader) Neo() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "neo"))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// Emit creates a transaction invoking `emit` 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) Emit() (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "emit")
-}
-
-// EmitTransaction creates a transaction invoking `emit` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) EmitTransaction() (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "emit")
-}
-
-// EmitUnsigned creates a transaction invoking `emit` 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) EmitUnsigned() (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "emit", nil)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
-
-// Vote creates a transaction invoking `vote` 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) Vote(epoch *big.Int, candidates []any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "vote", epoch, candidates)
-}
-
-// VoteTransaction creates a transaction invoking `vote` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) VoteTransaction(epoch *big.Int, candidates []any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "vote", epoch, candidates)
-}
-
-// VoteUnsigned creates a transaction invoking `vote` 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) VoteUnsigned(epoch *big.Int, candidates []any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "vote", nil, epoch, candidates)
-}
diff --git a/rpcclient/balance/client.go b/rpcclient/balance/client.go
deleted file mode 100644
index 6b86502..0000000
--- a/rpcclient/balance/client.go
+++ /dev/null
@@ -1,549 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package balance contains RPC wrappers for Balance contract.
-package balance
-
-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/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"
-)
-
-// LockEvent represents "Lock" event emitted by the contract.
-type LockEvent struct {
- TxID []byte
- From util.Uint160
- To util.Uint160
- Amount *big.Int
- Until *big.Int
-}
-
-// TransferXEvent represents "TransferX" event emitted by the contract.
-type TransferXEvent struct {
- From util.Uint160
- To util.Uint160
- Amount *big.Int
- Details []byte
-}
-
-// MintEvent represents "Mint" event emitted by the contract.
-type MintEvent struct {
- To util.Uint160
- Amount *big.Int
-}
-
-// BurnEvent represents "Burn" event emitted by the contract.
-type BurnEvent struct {
- From util.Uint160
- Amount *big.Int
-}
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- nep17.Invoker
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- nep17.Actor
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- nep17.TokenReader
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- nep17.TokenWriter
- actor Actor
- 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{*nep17.NewReader(invoker, hash), invoker, hash}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- var nep17t = nep17.New(actor, hash)
- return &Contract{ContractReader{nep17t.TokenReader, actor, hash}, nep17t.TokenWriter, actor, hash}
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// Burn creates a transaction invoking `burn` 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) Burn(from util.Uint160, amount *big.Int, txDetails []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "burn", from, amount, txDetails)
-}
-
-// BurnTransaction creates a transaction invoking `burn` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) BurnTransaction(from util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "burn", from, amount, txDetails)
-}
-
-// BurnUnsigned creates a transaction invoking `burn` 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) BurnUnsigned(from util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "burn", nil, from, amount, txDetails)
-}
-
-// Lock creates a transaction invoking `lock` 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) Lock(txDetails []byte, from util.Uint160, to util.Uint160, amount *big.Int, until *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "lock", txDetails, from, to, amount, until)
-}
-
-// LockTransaction creates a transaction invoking `lock` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) LockTransaction(txDetails []byte, from util.Uint160, to util.Uint160, amount *big.Int, until *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "lock", txDetails, from, to, amount, until)
-}
-
-// LockUnsigned creates a transaction invoking `lock` 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) LockUnsigned(txDetails []byte, from util.Uint160, to util.Uint160, amount *big.Int, until *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "lock", nil, txDetails, from, to, amount, until)
-}
-
-// 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(to util.Uint160, amount *big.Int, txDetails []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "mint", to, amount, txDetails)
-}
-
-// 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(to util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "mint", to, amount, txDetails)
-}
-
-// MintUnsigned creates a transaction invoking `mint` 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) MintUnsigned(to util.Uint160, amount *big.Int, txDetails []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "mint", nil, to, amount, txDetails)
-}
-
-// NewEpoch creates a transaction invoking `newEpoch` 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) NewEpoch(epochNum *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "newEpoch", epochNum)
-}
-
-// NewEpochTransaction creates a transaction invoking `newEpoch` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) NewEpochTransaction(epochNum *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "newEpoch", epochNum)
-}
-
-// NewEpochUnsigned creates a transaction invoking `newEpoch` 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) NewEpochUnsigned(epochNum *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "newEpoch", nil, epochNum)
-}
-
-// TransferX creates a transaction invoking `transferX` 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) TransferX(from util.Uint160, to util.Uint160, amount *big.Int, details []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "transferX", from, to, amount, details)
-}
-
-// TransferXTransaction creates a transaction invoking `transferX` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) TransferXTransaction(from util.Uint160, to util.Uint160, amount *big.Int, details []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "transferX", from, to, amount, details)
-}
-
-// TransferXUnsigned creates a transaction invoking `transferX` 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) TransferXUnsigned(from util.Uint160, to util.Uint160, amount *big.Int, details []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "transferX", nil, from, to, amount, details)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
-
-// LockEventsFromApplicationLog retrieves a set of all emitted events
-// with "Lock" name from the provided [result.ApplicationLog].
-func LockEventsFromApplicationLog(log *result.ApplicationLog) ([]*LockEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*LockEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Lock" {
- continue
- }
- event := new(LockEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize LockEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to LockEvent or
-// returns an error if it's not possible to do to so.
-func (e *LockEvent) 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) != 5 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.TxID, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field TxID: %w", err)
- }
-
- 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.Until, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Until: %w", err)
- }
-
- return nil
-}
-
-// TransferXEventsFromApplicationLog retrieves a set of all emitted events
-// with "TransferX" name from the provided [result.ApplicationLog].
-func TransferXEventsFromApplicationLog(log *result.ApplicationLog) ([]*TransferXEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*TransferXEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "TransferX" {
- continue
- }
- event := new(TransferXEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize TransferXEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to TransferXEvent or
-// returns an error if it's not possible to do to so.
-func (e *TransferXEvent) 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.Details, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field Details: %w", err)
- }
-
- return nil
-}
-
-// MintEventsFromApplicationLog retrieves a set of all emitted events
-// with "Mint" name from the provided [result.ApplicationLog].
-func MintEventsFromApplicationLog(log *result.ApplicationLog) ([]*MintEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*MintEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Mint" {
- continue
- }
- event := new(MintEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize MintEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to MintEvent or
-// returns an error if it's not possible to do to so.
-func (e *MintEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- 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
-}
-
-// BurnEventsFromApplicationLog retrieves a set of all emitted events
-// with "Burn" name from the provided [result.ApplicationLog].
-func BurnEventsFromApplicationLog(log *result.ApplicationLog) ([]*BurnEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*BurnEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Burn" {
- continue
- }
- event := new(BurnEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize BurnEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to BurnEvent or
-// returns an error if it's not possible to do to so.
-func (e *BurnEvent) 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) != 2 {
- 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.Amount, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Amount: %w", err)
- }
-
- return nil
-}
diff --git a/rpcclient/container/client.go b/rpcclient/container/client.go
deleted file mode 100644
index 85b428a..0000000
--- a/rpcclient/container/client.go
+++ /dev/null
@@ -1,693 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package container contains RPC wrappers for Container contract.
-package container
-
-import (
- "crypto/elliptic"
- "errors"
- "fmt"
- "github.com/google/uuid"
- "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/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "math/big"
-)
-
-// PutSuccessEvent represents "PutSuccess" event emitted by the contract.
-type PutSuccessEvent struct {
- ContainerID util.Uint256
- PublicKey *keys.PublicKey
-}
-
-// DeleteSuccessEvent represents "DeleteSuccess" event emitted by the contract.
-type DeleteSuccessEvent struct {
- ContainerID util.Uint256
-}
-
-// SetEACLSuccessEvent represents "SetEACLSuccess" event emitted by the contract.
-type SetEACLSuccessEvent struct {
- ContainerID []byte
- PublicKey *keys.PublicKey
-}
-
-// StartEstimationEvent represents "StartEstimation" event emitted by the contract.
-type StartEstimationEvent struct {
- Epoch *big.Int
-}
-
-// StopEstimationEvent represents "StopEstimation" event emitted by the contract.
-type StopEstimationEvent struct {
- Epoch *big.Int
-}
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- 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)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// ContainersOf invokes `containersOf` method of contract.
-func (c *ContractReader) ContainersOf(owner []byte) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "containersOf", owner))
-}
-
-// ContainersOfExpanded is similar to ContainersOf (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
-// 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) ContainersOfExpanded(owner []byte, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "containersOf", _numOfIteratorItems, owner))
-}
-
-// Count invokes `count` method of contract.
-func (c *ContractReader) Count() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "count"))
-}
-
-// DeletionInfo invokes `deletionInfo` method of contract.
-func (c *ContractReader) DeletionInfo(containerID []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "deletionInfo", containerID))
-}
-
-// EACL invokes `eACL` method of contract.
-func (c *ContractReader) EACL(containerID []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "eACL", containerID))
-}
-
-// Get invokes `get` method of contract.
-func (c *ContractReader) Get(containerID []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "get", containerID))
-}
-
-// GetContainerSize invokes `getContainerSize` method of contract.
-func (c *ContractReader) GetContainerSize(id []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getContainerSize", id))
-}
-
-// IterateContainerSizes invokes `iterateContainerSizes` method of contract.
-func (c *ContractReader) IterateContainerSizes(epoch *big.Int) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "iterateContainerSizes", epoch))
-}
-
-// IterateContainerSizesExpanded is similar to IterateContainerSizes (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
-// 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) IterateContainerSizesExpanded(epoch *big.Int, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "iterateContainerSizes", _numOfIteratorItems, epoch))
-}
-
-// List invokes `list` method of contract.
-func (c *ContractReader) List(owner []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "list", owner))
-}
-
-// ListContainerSizes invokes `listContainerSizes` method of contract.
-func (c *ContractReader) ListContainerSizes(epoch *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "listContainerSizes", epoch))
-}
-
-// Owner invokes `owner` method of contract.
-func (c *ContractReader) Owner(containerID []byte) ([]byte, error) {
- return unwrap.Bytes(c.invoker.Call(c.hash, "owner", containerID))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// Delete creates a transaction invoking `delete` 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) Delete(containerID util.Uint256, signature []byte, publicKey *keys.PublicKey, token []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "delete", containerID, signature, publicKey, token)
-}
-
-// DeleteTransaction creates a transaction invoking `delete` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteTransaction(containerID util.Uint256, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "delete", containerID, signature, publicKey, token)
-}
-
-// DeleteUnsigned creates a transaction invoking `delete` 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) DeleteUnsigned(containerID util.Uint256, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "delete", nil, containerID, signature, publicKey, token)
-}
-
-// NewEpoch creates a transaction invoking `newEpoch` 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) NewEpoch(epochNum *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "newEpoch", epochNum)
-}
-
-// NewEpochTransaction creates a transaction invoking `newEpoch` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) NewEpochTransaction(epochNum *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "newEpoch", epochNum)
-}
-
-// NewEpochUnsigned creates a transaction invoking `newEpoch` 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) NewEpochUnsigned(epochNum *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "newEpoch", nil, epochNum)
-}
-
-// Put creates a transaction invoking `put` 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) Put(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "put", container, signature, publicKey, token)
-}
-
-// PutTransaction creates a transaction invoking `put` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) PutTransaction(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "put", container, signature, publicKey, token)
-}
-
-// PutUnsigned creates a transaction invoking `put` 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) PutUnsigned(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "put", nil, container, signature, publicKey, token)
-}
-
-// PutContainerSize creates a transaction invoking `putContainerSize` 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) PutContainerSize(epoch *big.Int, cid []byte, usedSize *big.Int, pubKey *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "putContainerSize", epoch, cid, usedSize, pubKey)
-}
-
-// PutContainerSizeTransaction creates a transaction invoking `putContainerSize` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) PutContainerSizeTransaction(epoch *big.Int, cid []byte, usedSize *big.Int, pubKey *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "putContainerSize", epoch, cid, usedSize, pubKey)
-}
-
-// PutContainerSizeUnsigned creates a transaction invoking `putContainerSize` 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) PutContainerSizeUnsigned(epoch *big.Int, cid []byte, usedSize *big.Int, pubKey *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "putContainerSize", nil, epoch, cid, usedSize, pubKey)
-}
-
-// PutNamed creates a transaction invoking `putNamed` 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) PutNamed(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte, name string, zone string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "putNamed", container, signature, publicKey, token, name, zone)
-}
-
-// PutNamedTransaction creates a transaction invoking `putNamed` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) PutNamedTransaction(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte, name string, zone string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "putNamed", container, signature, publicKey, token, name, zone)
-}
-
-// PutNamedUnsigned creates a transaction invoking `putNamed` 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) PutNamedUnsigned(container []byte, signature []byte, publicKey *keys.PublicKey, token []byte, name string, zone string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "putNamed", nil, container, signature, publicKey, token, name, zone)
-}
-
-// 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(admin util.Uint160) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setAdmin", 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(admin util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setAdmin", admin)
-}
-
-// SetAdminUnsigned creates a transaction invoking `setAdmin` 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) SetAdminUnsigned(admin util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, admin)
-}
-
-// SetEACL creates a transaction invoking `setEACL` 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) SetEACL(eACL []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setEACL", eACL, signature, publicKey, token)
-}
-
-// SetEACLTransaction creates a transaction invoking `setEACL` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetEACLTransaction(eACL []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setEACL", eACL, signature, publicKey, token)
-}
-
-// SetEACLUnsigned creates a transaction invoking `setEACL` 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) SetEACLUnsigned(eACL []byte, signature []byte, publicKey *keys.PublicKey, token []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setEACL", nil, eACL, signature, publicKey, token)
-}
-
-// StartContainerEstimation creates a transaction invoking `startContainerEstimation` 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) StartContainerEstimation(epoch *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "startContainerEstimation", epoch)
-}
-
-// StartContainerEstimationTransaction creates a transaction invoking `startContainerEstimation` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) StartContainerEstimationTransaction(epoch *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "startContainerEstimation", epoch)
-}
-
-// StartContainerEstimationUnsigned creates a transaction invoking `startContainerEstimation` 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) StartContainerEstimationUnsigned(epoch *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "startContainerEstimation", nil, epoch)
-}
-
-// StopContainerEstimation creates a transaction invoking `stopContainerEstimation` 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) StopContainerEstimation(epoch *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "stopContainerEstimation", epoch)
-}
-
-// StopContainerEstimationTransaction creates a transaction invoking `stopContainerEstimation` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) StopContainerEstimationTransaction(epoch *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "stopContainerEstimation", epoch)
-}
-
-// StopContainerEstimationUnsigned creates a transaction invoking `stopContainerEstimation` 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) StopContainerEstimationUnsigned(epoch *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "stopContainerEstimation", nil, epoch)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
-
-// PutSuccessEventsFromApplicationLog retrieves a set of all emitted events
-// with "PutSuccess" name from the provided [result.ApplicationLog].
-func PutSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*PutSuccessEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*PutSuccessEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "PutSuccess" {
- continue
- }
- event := new(PutSuccessEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize PutSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to PutSuccessEvent or
-// returns an error if it's not possible to do to so.
-func (e *PutSuccessEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.ContainerID, 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 ContainerID: %w", err)
- }
-
- index++
- e.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)
- }
-
- return nil
-}
-
-// DeleteSuccessEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteSuccess" name from the provided [result.ApplicationLog].
-func DeleteSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteSuccessEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteSuccessEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteSuccess" {
- continue
- }
- event := new(DeleteSuccessEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteSuccessEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteSuccessEvent) 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.ContainerID, 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 ContainerID: %w", err)
- }
-
- return nil
-}
-
-// SetEACLSuccessEventsFromApplicationLog retrieves a set of all emitted events
-// with "SetEACLSuccess" name from the provided [result.ApplicationLog].
-func SetEACLSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetEACLSuccessEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*SetEACLSuccessEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "SetEACLSuccess" {
- continue
- }
- event := new(SetEACLSuccessEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize SetEACLSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to SetEACLSuccessEvent or
-// returns an error if it's not possible to do to so.
-func (e *SetEACLSuccessEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.ContainerID, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field ContainerID: %w", err)
- }
-
- index++
- e.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)
- }
-
- return nil
-}
-
-// StartEstimationEventsFromApplicationLog retrieves a set of all emitted events
-// with "StartEstimation" name from the provided [result.ApplicationLog].
-func StartEstimationEventsFromApplicationLog(log *result.ApplicationLog) ([]*StartEstimationEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*StartEstimationEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "StartEstimation" {
- continue
- }
- event := new(StartEstimationEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize StartEstimationEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to StartEstimationEvent or
-// returns an error if it's not possible to do to so.
-func (e *StartEstimationEvent) 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.Epoch, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Epoch: %w", err)
- }
-
- return nil
-}
-
-// StopEstimationEventsFromApplicationLog retrieves a set of all emitted events
-// with "StopEstimation" name from the provided [result.ApplicationLog].
-func StopEstimationEventsFromApplicationLog(log *result.ApplicationLog) ([]*StopEstimationEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*StopEstimationEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "StopEstimation" {
- continue
- }
- event := new(StopEstimationEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize StopEstimationEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to StopEstimationEvent or
-// returns an error if it's not possible to do to so.
-func (e *StopEstimationEvent) 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.Epoch, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Epoch: %w", err)
- }
-
- return nil
-}
diff --git a/rpcclient/frostfs/client.go b/rpcclient/frostfs/client.go
deleted file mode 100644
index 057ae40..0000000
--- a/rpcclient/frostfs/client.go
+++ /dev/null
@@ -1,769 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package frostfs contains RPC wrappers for FrostFS contract.
-package frostfs
-
-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/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "math/big"
-)
-
-// DepositEvent represents "Deposit" event emitted by the contract.
-type DepositEvent struct {
- From util.Uint160
- Amount *big.Int
- Receiver util.Uint160
- TxHash util.Uint256
-}
-
-// WithdrawEvent represents "Withdraw" event emitted by the contract.
-type WithdrawEvent struct {
- User util.Uint160
- Amount *big.Int
- TxHash util.Uint256
-}
-
-// ChequeEvent represents "Cheque" event emitted by the contract.
-type ChequeEvent struct {
- Id []byte
- User util.Uint160
- Amount *big.Int
- LockAccount []byte
-}
-
-// BindEvent represents "Bind" event emitted by the contract.
-type BindEvent struct {
- User []byte
- Keys []any
-}
-
-// UnbindEvent represents "Unbind" event emitted by the contract.
-type UnbindEvent struct {
- User []byte
- Keys []any
-}
-
-// SetConfigEvent represents "SetConfig" event emitted by the contract.
-type SetConfigEvent struct {
- Id []byte
- Key []byte
- Value []byte
-}
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// Config invokes `config` method of contract.
-func (c *ContractReader) Config(key []byte) (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, "config", key)))
-}
-
-// InnerRingCandidates invokes `innerRingCandidates` method of contract.
-func (c *ContractReader) InnerRingCandidates() ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "innerRingCandidates"))
-}
-
-// ListConfig invokes `listConfig` method of contract.
-func (c *ContractReader) ListConfig() ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "listConfig"))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// Bind creates a transaction invoking `bind` 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) Bind(user []byte, keys []any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "bind", user, keys)
-}
-
-// BindTransaction creates a transaction invoking `bind` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) BindTransaction(user []byte, keys []any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "bind", user, keys)
-}
-
-// BindUnsigned creates a transaction invoking `bind` 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) BindUnsigned(user []byte, keys []any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "bind", nil, user, keys)
-}
-
-// Cheque creates a transaction invoking `cheque` 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) Cheque(id []byte, user util.Uint160, amount *big.Int, lockAcc []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "cheque", id, user, amount, lockAcc)
-}
-
-// ChequeTransaction creates a transaction invoking `cheque` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) ChequeTransaction(id []byte, user util.Uint160, amount *big.Int, lockAcc []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "cheque", id, user, amount, lockAcc)
-}
-
-// ChequeUnsigned creates a transaction invoking `cheque` 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) ChequeUnsigned(id []byte, user util.Uint160, amount *big.Int, lockAcc []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "cheque", nil, id, user, amount, lockAcc)
-}
-
-// InnerRingCandidateAdd creates a transaction invoking `innerRingCandidateAdd` 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) InnerRingCandidateAdd(key *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "innerRingCandidateAdd", key)
-}
-
-// InnerRingCandidateAddTransaction creates a transaction invoking `innerRingCandidateAdd` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) InnerRingCandidateAddTransaction(key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "innerRingCandidateAdd", key)
-}
-
-// InnerRingCandidateAddUnsigned creates a transaction invoking `innerRingCandidateAdd` 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) InnerRingCandidateAddUnsigned(key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "innerRingCandidateAdd", nil, key)
-}
-
-// InnerRingCandidateRemove creates a transaction invoking `innerRingCandidateRemove` 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) InnerRingCandidateRemove(key *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "innerRingCandidateRemove", key)
-}
-
-// InnerRingCandidateRemoveTransaction creates a transaction invoking `innerRingCandidateRemove` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) InnerRingCandidateRemoveTransaction(key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "innerRingCandidateRemove", key)
-}
-
-// InnerRingCandidateRemoveUnsigned creates a transaction invoking `innerRingCandidateRemove` 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) InnerRingCandidateRemoveUnsigned(key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "innerRingCandidateRemove", nil, key)
-}
-
-// SetConfig creates a transaction invoking `setConfig` 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) SetConfig(id []byte, key []byte, val []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setConfig", id, key, val)
-}
-
-// SetConfigTransaction creates a transaction invoking `setConfig` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetConfigTransaction(id []byte, key []byte, val []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setConfig", id, key, val)
-}
-
-// SetConfigUnsigned creates a transaction invoking `setConfig` 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) SetConfigUnsigned(id []byte, key []byte, val []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setConfig", nil, id, key, val)
-}
-
-// Unbind creates a transaction invoking `unbind` 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) Unbind(user []byte, keys []any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "unbind", user, keys)
-}
-
-// UnbindTransaction creates a transaction invoking `unbind` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) UnbindTransaction(user []byte, keys []any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "unbind", user, keys)
-}
-
-// UnbindUnsigned creates a transaction invoking `unbind` 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) UnbindUnsigned(user []byte, keys []any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "unbind", nil, user, keys)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
-
-// Withdraw creates a transaction invoking `withdraw` 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) Withdraw(user util.Uint160, amount *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "withdraw", user, amount)
-}
-
-// WithdrawTransaction creates a transaction invoking `withdraw` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) WithdrawTransaction(user util.Uint160, amount *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "withdraw", user, amount)
-}
-
-// WithdrawUnsigned creates a transaction invoking `withdraw` 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) WithdrawUnsigned(user util.Uint160, amount *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "withdraw", nil, user, amount)
-}
-
-// DepositEventsFromApplicationLog retrieves a set of all emitted events
-// with "Deposit" name from the provided [result.ApplicationLog].
-func DepositEventsFromApplicationLog(log *result.ApplicationLog) ([]*DepositEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DepositEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Deposit" {
- continue
- }
- event := new(DepositEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DepositEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DepositEvent or
-// returns an error if it's not possible to do to so.
-func (e *DepositEvent) 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.Amount, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Amount: %w", err)
- }
-
- index++
- e.Receiver, 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 Receiver: %w", err)
- }
-
- index++
- e.TxHash, 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 TxHash: %w", err)
- }
-
- return nil
-}
-
-// WithdrawEventsFromApplicationLog retrieves a set of all emitted events
-// with "Withdraw" name from the provided [result.ApplicationLog].
-func WithdrawEventsFromApplicationLog(log *result.ApplicationLog) ([]*WithdrawEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*WithdrawEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Withdraw" {
- continue
- }
- event := new(WithdrawEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize WithdrawEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to WithdrawEvent or
-// returns an error if it's not possible to do to so.
-func (e *WithdrawEvent) 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.User, 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 User: %w", err)
- }
-
- index++
- e.Amount, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Amount: %w", err)
- }
-
- index++
- e.TxHash, 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 TxHash: %w", err)
- }
-
- return nil
-}
-
-// ChequeEventsFromApplicationLog retrieves a set of all emitted events
-// with "Cheque" name from the provided [result.ApplicationLog].
-func ChequeEventsFromApplicationLog(log *result.ApplicationLog) ([]*ChequeEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*ChequeEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Cheque" {
- continue
- }
- event := new(ChequeEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize ChequeEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to ChequeEvent or
-// returns an error if it's not possible to do to so.
-func (e *ChequeEvent) 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.Id, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field Id: %w", err)
- }
-
- index++
- e.User, 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 User: %w", err)
- }
-
- index++
- e.Amount, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Amount: %w", err)
- }
-
- index++
- e.LockAccount, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field LockAccount: %w", err)
- }
-
- return nil
-}
-
-// BindEventsFromApplicationLog retrieves a set of all emitted events
-// with "Bind" name from the provided [result.ApplicationLog].
-func BindEventsFromApplicationLog(log *result.ApplicationLog) ([]*BindEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*BindEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Bind" {
- continue
- }
- event := new(BindEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize BindEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to BindEvent or
-// returns an error if it's not possible to do to so.
-func (e *BindEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.User, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field User: %w", err)
- }
-
- index++
- e.Keys, 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 Keys: %w", err)
- }
-
- return nil
-}
-
-// UnbindEventsFromApplicationLog retrieves a set of all emitted events
-// with "Unbind" name from the provided [result.ApplicationLog].
-func UnbindEventsFromApplicationLog(log *result.ApplicationLog) ([]*UnbindEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*UnbindEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "Unbind" {
- continue
- }
- event := new(UnbindEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize UnbindEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to UnbindEvent or
-// returns an error if it's not possible to do to so.
-func (e *UnbindEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.User, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field User: %w", err)
- }
-
- index++
- e.Keys, 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 Keys: %w", err)
- }
-
- return nil
-}
-
-// SetConfigEventsFromApplicationLog retrieves a set of all emitted events
-// with "SetConfig" name from the provided [result.ApplicationLog].
-func SetConfigEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetConfigEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*SetConfigEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "SetConfig" {
- continue
- }
- event := new(SetConfigEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize SetConfigEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to SetConfigEvent or
-// returns an error if it's not possible to do to so.
-func (e *SetConfigEvent) 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.Id, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field Id: %w", err)
- }
-
- index++
- e.Key, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field Key: %w", err)
- }
-
- index++
- e.Value, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field Value: %w", err)
- }
-
- return nil
-}
diff --git a/rpcclient/frostfsid/client.go b/rpcclient/frostfsid/client.go
deleted file mode 100644
index 498b472..0000000
--- a/rpcclient/frostfsid/client.go
+++ /dev/null
@@ -1,2207 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package identity contains RPC wrappers for Identity contract.
-package identity
-
-import (
- "crypto/elliptic"
- "errors"
- "fmt"
- "github.com/google/uuid"
- "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/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "math/big"
- "unicode/utf8"
-)
-
-// CreateSubjectEvent represents "CreateSubject" event emitted by the contract.
-type CreateSubjectEvent struct {
- SubjectAddress util.Uint160
-}
-
-// AddSubjectKeyEvent represents "AddSubjectKey" event emitted by the contract.
-type AddSubjectKeyEvent struct {
- SubjectAddress util.Uint160
- SubjectKey *keys.PublicKey
-}
-
-// RemoveSubjectKeyEvent represents "RemoveSubjectKey" event emitted by the contract.
-type RemoveSubjectKeyEvent struct {
- SubjectAddress util.Uint160
- SubjectKey *keys.PublicKey
-}
-
-// SetSubjectNameEvent represents "SetSubjectName" event emitted by the contract.
-type SetSubjectNameEvent struct {
- SubjectAddress util.Uint160
- Name string
-}
-
-// SetSubjectKVEvent represents "SetSubjectKV" event emitted by the contract.
-type SetSubjectKVEvent struct {
- SubjectAddress util.Uint160
- Key string
- Value string
-}
-
-// DeleteSubjectKVEvent represents "DeleteSubjectKV" event emitted by the contract.
-type DeleteSubjectKVEvent struct {
- SubjectAddress util.Uint160
- Key string
-}
-
-// DeleteSubjectEvent represents "DeleteSubject" event emitted by the contract.
-type DeleteSubjectEvent struct {
- SubjectAddress util.Uint160
-}
-
-// CreateNamespaceEvent represents "CreateNamespace" event emitted by the contract.
-type CreateNamespaceEvent struct {
- Namespace string
-}
-
-// UpdateNamespaceEvent represents "UpdateNamespace" event emitted by the contract.
-type UpdateNamespaceEvent struct {
- Namespace string
- State string
-}
-
-// DeleteNamespaceEvent represents "DeleteNamespace" event emitted by the contract.
-type DeleteNamespaceEvent struct {
- Namespace string
-}
-
-// AddSubjectToNamespaceEvent represents "AddSubjectToNamespace" event emitted by the contract.
-type AddSubjectToNamespaceEvent struct {
- SubjectAddress util.Uint160
- Namespace string
-}
-
-// RemoveSubjectFromNamespaceEvent represents "RemoveSubjectFromNamespace" event emitted by the contract.
-type RemoveSubjectFromNamespaceEvent struct {
- SubjectAddress util.Uint160
- Namespace string
-}
-
-// CreateGroupEvent represents "CreateGroup" event emitted by the contract.
-type CreateGroupEvent struct {
- Namespace string
- Group string
-}
-
-// SetGroupNameEvent represents "SetGroupName" event emitted by the contract.
-type SetGroupNameEvent struct {
- Namespace string
- GroupID *big.Int
- Name string
-}
-
-// SetGroupKVEvent represents "SetGroupKV" event emitted by the contract.
-type SetGroupKVEvent struct {
- Namespace string
- GroupID *big.Int
- Key string
- Value string
-}
-
-// DeleteGroupKVEvent represents "DeleteGroupKV" event emitted by the contract.
-type DeleteGroupKVEvent struct {
- Namespace string
- GroupID *big.Int
- Key string
-}
-
-// AddSubjectToGroupEvent represents "AddSubjectToGroup" event emitted by the contract.
-type AddSubjectToGroupEvent struct {
- SubjectAddress util.Uint160
- Namespace string
- GroupID *big.Int
-}
-
-// RemoveSubjectFromGroupEvent represents "RemoveSubjectFromGroup" event emitted by the contract.
-type RemoveSubjectFromGroupEvent struct {
- SubjectAddress util.Uint160
- Namespace string
- GroupID *big.Int
-}
-
-// DeleteGroupEvent represents "DeleteGroup" event emitted by the contract.
-type DeleteGroupEvent struct {
- Namespace string
- GroupID *big.Int
-}
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- 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)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// GetAdmin invokes `getAdmin` method of contract.
-func (c *ContractReader) GetAdmin() (util.Uint160, error) {
- return unwrap.Uint160(c.invoker.Call(c.hash, "getAdmin"))
-}
-
-// GetGroup invokes `getGroup` method of contract.
-func (c *ContractReader) GetGroup(ns string, groupID *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getGroup", ns, groupID))
-}
-
-// GetGroupByName invokes `getGroupByName` method of contract.
-func (c *ContractReader) GetGroupByName(ns string, name string) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getGroupByName", ns, name))
-}
-
-// GetGroupExtended invokes `getGroupExtended` method of contract.
-func (c *ContractReader) GetGroupExtended(ns string, groupID *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getGroupExtended", ns, groupID))
-}
-
-// GetGroupIDByName invokes `getGroupIDByName` method of contract.
-func (c *ContractReader) GetGroupIDByName(ns string, name string) (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "getGroupIDByName", ns, name))
-}
-
-// GetNamespace invokes `getNamespace` method of contract.
-func (c *ContractReader) GetNamespace(ns string) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getNamespace", ns))
-}
-
-// GetNamespaceExtended invokes `getNamespaceExtended` method of contract.
-func (c *ContractReader) GetNamespaceExtended(ns string) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getNamespaceExtended", ns))
-}
-
-// GetSubject invokes `getSubject` method of contract.
-func (c *ContractReader) GetSubject(addr util.Uint160) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getSubject", addr))
-}
-
-// GetSubjectByKey invokes `getSubjectByKey` method of contract.
-func (c *ContractReader) GetSubjectByKey(key *keys.PublicKey) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getSubjectByKey", key))
-}
-
-// GetSubjectByName invokes `getSubjectByName` method of contract.
-func (c *ContractReader) GetSubjectByName(ns string, name string) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getSubjectByName", ns, name))
-}
-
-// GetSubjectExtended invokes `getSubjectExtended` method of contract.
-func (c *ContractReader) GetSubjectExtended(addr util.Uint160) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getSubjectExtended", addr))
-}
-
-// GetSubjectKV invokes `getSubjectKV` method of contract.
-func (c *ContractReader) GetSubjectKV(addr util.Uint160, name string) (string, error) {
- return unwrap.UTF8String(c.invoker.Call(c.hash, "getSubjectKV", addr, name))
-}
-
-// GetSubjectKeyByName invokes `getSubjectKeyByName` method of contract.
-func (c *ContractReader) GetSubjectKeyByName(ns string, name string) (*keys.PublicKey, error) {
- return unwrap.PublicKey(c.invoker.Call(c.hash, "getSubjectKeyByName", ns, name))
-}
-
-// ListGroupSubjects invokes `listGroupSubjects` method of contract.
-func (c *ContractReader) ListGroupSubjects(ns string, groupID *big.Int) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listGroupSubjects", ns, groupID))
-}
-
-// ListGroupSubjectsExpanded is similar to ListGroupSubjects (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
-// 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) ListGroupSubjectsExpanded(ns string, groupID *big.Int, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listGroupSubjects", _numOfIteratorItems, ns, groupID))
-}
-
-// ListGroups invokes `listGroups` method of contract.
-func (c *ContractReader) ListGroups(ns string) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listGroups", ns))
-}
-
-// ListGroupsExpanded is similar to ListGroups (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
-// 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) ListGroupsExpanded(ns string, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listGroups", _numOfIteratorItems, ns))
-}
-
-// ListNamespaceSubjects invokes `listNamespaceSubjects` method of contract.
-func (c *ContractReader) ListNamespaceSubjects(ns string) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listNamespaceSubjects", ns))
-}
-
-// ListNamespaceSubjectsExpanded is similar to ListNamespaceSubjects (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
-// 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) ListNamespaceSubjectsExpanded(ns string, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listNamespaceSubjects", _numOfIteratorItems, ns))
-}
-
-// ListNamespaces invokes `listNamespaces` method of contract.
-func (c *ContractReader) ListNamespaces() (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listNamespaces"))
-}
-
-// ListNamespacesExpanded is similar to ListNamespaces (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
-// 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) ListNamespacesExpanded(_numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listNamespaces", _numOfIteratorItems))
-}
-
-// ListSubjects invokes `listSubjects` method of contract.
-func (c *ContractReader) ListSubjects() (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listSubjects"))
-}
-
-// ListSubjectsExpanded is similar to ListSubjects (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
-// 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) ListSubjectsExpanded(_numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listSubjects", _numOfIteratorItems))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// AddSubjectKey creates a transaction invoking `addSubjectKey` 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) AddSubjectKey(addr util.Uint160, key *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addSubjectKey", addr, key)
-}
-
-// AddSubjectKeyTransaction creates a transaction invoking `addSubjectKey` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddSubjectKeyTransaction(addr util.Uint160, key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addSubjectKey", addr, key)
-}
-
-// AddSubjectKeyUnsigned creates a transaction invoking `addSubjectKey` 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) AddSubjectKeyUnsigned(addr util.Uint160, key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addSubjectKey", nil, addr, key)
-}
-
-// AddSubjectToGroup creates a transaction invoking `addSubjectToGroup` 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) AddSubjectToGroup(addr util.Uint160, groupID *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addSubjectToGroup", addr, groupID)
-}
-
-// AddSubjectToGroupTransaction creates a transaction invoking `addSubjectToGroup` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddSubjectToGroupTransaction(addr util.Uint160, groupID *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addSubjectToGroup", addr, groupID)
-}
-
-// AddSubjectToGroupUnsigned creates a transaction invoking `addSubjectToGroup` 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) AddSubjectToGroupUnsigned(addr util.Uint160, groupID *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addSubjectToGroup", nil, addr, groupID)
-}
-
-// ClearAdmin creates a transaction invoking `clearAdmin` 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) ClearAdmin() (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "clearAdmin")
-}
-
-// ClearAdminTransaction creates a transaction invoking `clearAdmin` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) ClearAdminTransaction() (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "clearAdmin")
-}
-
-// ClearAdminUnsigned creates a transaction invoking `clearAdmin` 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) ClearAdminUnsigned() (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "clearAdmin", nil)
-}
-
-// CreateGroup creates a transaction invoking `createGroup` 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) CreateGroup(ns string, group string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "createGroup", ns, group)
-}
-
-// CreateGroupTransaction creates a transaction invoking `createGroup` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) CreateGroupTransaction(ns string, group string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "createGroup", ns, group)
-}
-
-// CreateGroupUnsigned creates a transaction invoking `createGroup` 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) CreateGroupUnsigned(ns string, group string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "createGroup", nil, ns, group)
-}
-
-// CreateNamespace creates a transaction invoking `createNamespace` 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) CreateNamespace(ns string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "createNamespace", ns)
-}
-
-// CreateNamespaceTransaction creates a transaction invoking `createNamespace` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) CreateNamespaceTransaction(ns string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "createNamespace", ns)
-}
-
-// CreateNamespaceUnsigned creates a transaction invoking `createNamespace` 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) CreateNamespaceUnsigned(ns string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "createNamespace", nil, ns)
-}
-
-// CreateSubject creates a transaction invoking `createSubject` 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) CreateSubject(ns string, key *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "createSubject", ns, key)
-}
-
-// CreateSubjectTransaction creates a transaction invoking `createSubject` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) CreateSubjectTransaction(ns string, key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "createSubject", ns, key)
-}
-
-// CreateSubjectUnsigned creates a transaction invoking `createSubject` 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) CreateSubjectUnsigned(ns string, key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "createSubject", nil, ns, key)
-}
-
-// DeleteGroup creates a transaction invoking `deleteGroup` 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) DeleteGroup(ns string, groupID *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteGroup", ns, groupID)
-}
-
-// DeleteGroupTransaction creates a transaction invoking `deleteGroup` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteGroupTransaction(ns string, groupID *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteGroup", ns, groupID)
-}
-
-// DeleteGroupUnsigned creates a transaction invoking `deleteGroup` 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) DeleteGroupUnsigned(ns string, groupID *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteGroup", nil, ns, groupID)
-}
-
-// DeleteGroupKV creates a transaction invoking `deleteGroupKV` 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) DeleteGroupKV(ns string, groupID *big.Int, key string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteGroupKV", ns, groupID, key)
-}
-
-// DeleteGroupKVTransaction creates a transaction invoking `deleteGroupKV` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteGroupKVTransaction(ns string, groupID *big.Int, key string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteGroupKV", ns, groupID, key)
-}
-
-// DeleteGroupKVUnsigned creates a transaction invoking `deleteGroupKV` 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) DeleteGroupKVUnsigned(ns string, groupID *big.Int, key string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteGroupKV", nil, ns, groupID, key)
-}
-
-// DeleteNamespace creates a transaction invoking `deleteNamespace` 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) DeleteNamespace(ns string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteNamespace", ns)
-}
-
-// DeleteNamespaceTransaction creates a transaction invoking `deleteNamespace` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteNamespaceTransaction(ns string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteNamespace", ns)
-}
-
-// DeleteNamespaceUnsigned creates a transaction invoking `deleteNamespace` 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) DeleteNamespaceUnsigned(ns string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteNamespace", nil, ns)
-}
-
-// DeleteSubject creates a transaction invoking `deleteSubject` 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) DeleteSubject(addr util.Uint160) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteSubject", addr)
-}
-
-// DeleteSubjectTransaction creates a transaction invoking `deleteSubject` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteSubjectTransaction(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteSubject", addr)
-}
-
-// DeleteSubjectUnsigned creates a transaction invoking `deleteSubject` 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) DeleteSubjectUnsigned(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteSubject", nil, addr)
-}
-
-// DeleteSubjectKV creates a transaction invoking `deleteSubjectKV` 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) DeleteSubjectKV(addr util.Uint160, key string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteSubjectKV", addr, key)
-}
-
-// DeleteSubjectKVTransaction creates a transaction invoking `deleteSubjectKV` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteSubjectKVTransaction(addr util.Uint160, key string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteSubjectKV", addr, key)
-}
-
-// DeleteSubjectKVUnsigned creates a transaction invoking `deleteSubjectKV` 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) DeleteSubjectKVUnsigned(addr util.Uint160, key string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteSubjectKV", nil, addr, key)
-}
-
-// RemoveSubjectFromGroup creates a transaction invoking `removeSubjectFromGroup` 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) RemoveSubjectFromGroup(addr util.Uint160, groupID *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "removeSubjectFromGroup", addr, groupID)
-}
-
-// RemoveSubjectFromGroupTransaction creates a transaction invoking `removeSubjectFromGroup` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) RemoveSubjectFromGroupTransaction(addr util.Uint160, groupID *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "removeSubjectFromGroup", addr, groupID)
-}
-
-// RemoveSubjectFromGroupUnsigned creates a transaction invoking `removeSubjectFromGroup` 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) RemoveSubjectFromGroupUnsigned(addr util.Uint160, groupID *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "removeSubjectFromGroup", nil, addr, groupID)
-}
-
-// RemoveSubjectKey creates a transaction invoking `removeSubjectKey` 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) RemoveSubjectKey(addr util.Uint160, key *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "removeSubjectKey", addr, key)
-}
-
-// RemoveSubjectKeyTransaction creates a transaction invoking `removeSubjectKey` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) RemoveSubjectKeyTransaction(addr util.Uint160, key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "removeSubjectKey", addr, key)
-}
-
-// RemoveSubjectKeyUnsigned creates a transaction invoking `removeSubjectKey` 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) RemoveSubjectKeyUnsigned(addr util.Uint160, key *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "removeSubjectKey", nil, addr, key)
-}
-
-// 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(addr util.Uint160) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setAdmin", addr)
-}
-
-// 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(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setAdmin", addr)
-}
-
-// SetAdminUnsigned creates a transaction invoking `setAdmin` 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) SetAdminUnsigned(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, addr)
-}
-
-// SetGroupKV creates a transaction invoking `setGroupKV` 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) SetGroupKV(ns string, groupID *big.Int, key string, val string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setGroupKV", ns, groupID, key, val)
-}
-
-// SetGroupKVTransaction creates a transaction invoking `setGroupKV` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetGroupKVTransaction(ns string, groupID *big.Int, key string, val string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setGroupKV", ns, groupID, key, val)
-}
-
-// SetGroupKVUnsigned creates a transaction invoking `setGroupKV` 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) SetGroupKVUnsigned(ns string, groupID *big.Int, key string, val string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setGroupKV", nil, ns, groupID, key, val)
-}
-
-// SetGroupName creates a transaction invoking `setGroupName` 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) SetGroupName(ns string, groupID *big.Int, name string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setGroupName", ns, groupID, name)
-}
-
-// SetGroupNameTransaction creates a transaction invoking `setGroupName` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetGroupNameTransaction(ns string, groupID *big.Int, name string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setGroupName", ns, groupID, name)
-}
-
-// SetGroupNameUnsigned creates a transaction invoking `setGroupName` 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) SetGroupNameUnsigned(ns string, groupID *big.Int, name string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setGroupName", nil, ns, groupID, name)
-}
-
-// SetSubjectKV creates a transaction invoking `setSubjectKV` 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) SetSubjectKV(addr util.Uint160, key string, val string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setSubjectKV", addr, key, val)
-}
-
-// SetSubjectKVTransaction creates a transaction invoking `setSubjectKV` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetSubjectKVTransaction(addr util.Uint160, key string, val string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setSubjectKV", addr, key, val)
-}
-
-// SetSubjectKVUnsigned creates a transaction invoking `setSubjectKV` 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) SetSubjectKVUnsigned(addr util.Uint160, key string, val string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setSubjectKV", nil, addr, key, val)
-}
-
-// SetSubjectName creates a transaction invoking `setSubjectName` 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) SetSubjectName(addr util.Uint160, name string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setSubjectName", addr, name)
-}
-
-// SetSubjectNameTransaction creates a transaction invoking `setSubjectName` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetSubjectNameTransaction(addr util.Uint160, name string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setSubjectName", addr, name)
-}
-
-// SetSubjectNameUnsigned creates a transaction invoking `setSubjectName` 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) SetSubjectNameUnsigned(addr util.Uint160, name string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setSubjectName", nil, addr, name)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
-
-// UpdateNamespace creates a transaction invoking `updateNamespace` 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) UpdateNamespace(ns string, state string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "updateNamespace", ns, state)
-}
-
-// UpdateNamespaceTransaction creates a transaction invoking `updateNamespace` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) UpdateNamespaceTransaction(ns string, state string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "updateNamespace", ns, state)
-}
-
-// UpdateNamespaceUnsigned creates a transaction invoking `updateNamespace` 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) UpdateNamespaceUnsigned(ns string, state string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "updateNamespace", nil, ns, state)
-}
-
-// CreateSubjectEventsFromApplicationLog retrieves a set of all emitted events
-// with "CreateSubject" name from the provided [result.ApplicationLog].
-func CreateSubjectEventsFromApplicationLog(log *result.ApplicationLog) ([]*CreateSubjectEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*CreateSubjectEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "CreateSubject" {
- continue
- }
- event := new(CreateSubjectEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize CreateSubjectEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to CreateSubjectEvent or
-// returns an error if it's not possible to do to so.
-func (e *CreateSubjectEvent) 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.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- return nil
-}
-
-// AddSubjectKeyEventsFromApplicationLog retrieves a set of all emitted events
-// with "AddSubjectKey" name from the provided [result.ApplicationLog].
-func AddSubjectKeyEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddSubjectKeyEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*AddSubjectKeyEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "AddSubjectKey" {
- continue
- }
- event := new(AddSubjectKeyEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize AddSubjectKeyEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to AddSubjectKeyEvent or
-// returns an error if it's not possible to do to so.
-func (e *AddSubjectKeyEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.SubjectKey, 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 SubjectKey: %w", err)
- }
-
- return nil
-}
-
-// RemoveSubjectKeyEventsFromApplicationLog retrieves a set of all emitted events
-// with "RemoveSubjectKey" name from the provided [result.ApplicationLog].
-func RemoveSubjectKeyEventsFromApplicationLog(log *result.ApplicationLog) ([]*RemoveSubjectKeyEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*RemoveSubjectKeyEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "RemoveSubjectKey" {
- continue
- }
- event := new(RemoveSubjectKeyEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize RemoveSubjectKeyEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to RemoveSubjectKeyEvent or
-// returns an error if it's not possible to do to so.
-func (e *RemoveSubjectKeyEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.SubjectKey, 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 SubjectKey: %w", err)
- }
-
- return nil
-}
-
-// SetSubjectNameEventsFromApplicationLog retrieves a set of all emitted events
-// with "SetSubjectName" name from the provided [result.ApplicationLog].
-func SetSubjectNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetSubjectNameEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*SetSubjectNameEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "SetSubjectName" {
- continue
- }
- event := new(SetSubjectNameEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize SetSubjectNameEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to SetSubjectNameEvent or
-// returns an error if it's not possible to do to so.
-func (e *SetSubjectNameEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- 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)
- }
-
- return nil
-}
-
-// SetSubjectKVEventsFromApplicationLog retrieves a set of all emitted events
-// with "SetSubjectKV" name from the provided [result.ApplicationLog].
-func SetSubjectKVEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetSubjectKVEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*SetSubjectKVEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "SetSubjectKV" {
- continue
- }
- event := new(SetSubjectKVEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize SetSubjectKVEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to SetSubjectKVEvent or
-// returns an error if it's not possible to do to so.
-func (e *SetSubjectKVEvent) 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.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.Key, 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 Key: %w", err)
- }
-
- index++
- e.Value, 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 Value: %w", err)
- }
-
- return nil
-}
-
-// DeleteSubjectKVEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteSubjectKV" name from the provided [result.ApplicationLog].
-func DeleteSubjectKVEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteSubjectKVEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteSubjectKVEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteSubjectKV" {
- continue
- }
- event := new(DeleteSubjectKVEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteSubjectKVEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteSubjectKVEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteSubjectKVEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.Key, 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 Key: %w", err)
- }
-
- return nil
-}
-
-// DeleteSubjectEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteSubject" name from the provided [result.ApplicationLog].
-func DeleteSubjectEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteSubjectEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteSubjectEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteSubject" {
- continue
- }
- event := new(DeleteSubjectEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteSubjectEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteSubjectEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteSubjectEvent) 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.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- return nil
-}
-
-// CreateNamespaceEventsFromApplicationLog retrieves a set of all emitted events
-// with "CreateNamespace" name from the provided [result.ApplicationLog].
-func CreateNamespaceEventsFromApplicationLog(log *result.ApplicationLog) ([]*CreateNamespaceEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*CreateNamespaceEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "CreateNamespace" {
- continue
- }
- event := new(CreateNamespaceEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize CreateNamespaceEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to CreateNamespaceEvent or
-// returns an error if it's not possible to do to so.
-func (e *CreateNamespaceEvent) 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.Namespace, 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 Namespace: %w", err)
- }
-
- return nil
-}
-
-// UpdateNamespaceEventsFromApplicationLog retrieves a set of all emitted events
-// with "UpdateNamespace" name from the provided [result.ApplicationLog].
-func UpdateNamespaceEventsFromApplicationLog(log *result.ApplicationLog) ([]*UpdateNamespaceEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*UpdateNamespaceEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "UpdateNamespace" {
- continue
- }
- event := new(UpdateNamespaceEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize UpdateNamespaceEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to UpdateNamespaceEvent or
-// returns an error if it's not possible to do to so.
-func (e *UpdateNamespaceEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.State, 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 State: %w", err)
- }
-
- return nil
-}
-
-// DeleteNamespaceEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteNamespace" name from the provided [result.ApplicationLog].
-func DeleteNamespaceEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteNamespaceEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteNamespaceEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteNamespace" {
- continue
- }
- event := new(DeleteNamespaceEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteNamespaceEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteNamespaceEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteNamespaceEvent) 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.Namespace, 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 Namespace: %w", err)
- }
-
- return nil
-}
-
-// AddSubjectToNamespaceEventsFromApplicationLog retrieves a set of all emitted events
-// with "AddSubjectToNamespace" name from the provided [result.ApplicationLog].
-func AddSubjectToNamespaceEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddSubjectToNamespaceEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*AddSubjectToNamespaceEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "AddSubjectToNamespace" {
- continue
- }
- event := new(AddSubjectToNamespaceEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize AddSubjectToNamespaceEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to AddSubjectToNamespaceEvent or
-// returns an error if it's not possible to do to so.
-func (e *AddSubjectToNamespaceEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- return nil
-}
-
-// RemoveSubjectFromNamespaceEventsFromApplicationLog retrieves a set of all emitted events
-// with "RemoveSubjectFromNamespace" name from the provided [result.ApplicationLog].
-func RemoveSubjectFromNamespaceEventsFromApplicationLog(log *result.ApplicationLog) ([]*RemoveSubjectFromNamespaceEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*RemoveSubjectFromNamespaceEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "RemoveSubjectFromNamespace" {
- continue
- }
- event := new(RemoveSubjectFromNamespaceEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize RemoveSubjectFromNamespaceEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to RemoveSubjectFromNamespaceEvent or
-// returns an error if it's not possible to do to so.
-func (e *RemoveSubjectFromNamespaceEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- return nil
-}
-
-// CreateGroupEventsFromApplicationLog retrieves a set of all emitted events
-// with "CreateGroup" name from the provided [result.ApplicationLog].
-func CreateGroupEventsFromApplicationLog(log *result.ApplicationLog) ([]*CreateGroupEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*CreateGroupEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "CreateGroup" {
- continue
- }
- event := new(CreateGroupEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize CreateGroupEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to CreateGroupEvent or
-// returns an error if it's not possible to do to so.
-func (e *CreateGroupEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.Group, 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 Group: %w", err)
- }
-
- return nil
-}
-
-// SetGroupNameEventsFromApplicationLog retrieves a set of all emitted events
-// with "SetGroupName" name from the provided [result.ApplicationLog].
-func SetGroupNameEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetGroupNameEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*SetGroupNameEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "SetGroupName" {
- continue
- }
- event := new(SetGroupNameEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize SetGroupNameEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to SetGroupNameEvent or
-// returns an error if it's not possible to do to so.
-func (e *SetGroupNameEvent) 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.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.GroupID, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field GroupID: %w", err)
- }
-
- 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)
- }
-
- return nil
-}
-
-// SetGroupKVEventsFromApplicationLog retrieves a set of all emitted events
-// with "SetGroupKV" name from the provided [result.ApplicationLog].
-func SetGroupKVEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetGroupKVEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*SetGroupKVEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "SetGroupKV" {
- continue
- }
- event := new(SetGroupKVEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize SetGroupKVEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to SetGroupKVEvent or
-// returns an error if it's not possible to do to so.
-func (e *SetGroupKVEvent) 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.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.GroupID, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field GroupID: %w", err)
- }
-
- index++
- e.Key, 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 Key: %w", err)
- }
-
- index++
- e.Value, 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 Value: %w", err)
- }
-
- return nil
-}
-
-// DeleteGroupKVEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteGroupKV" name from the provided [result.ApplicationLog].
-func DeleteGroupKVEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteGroupKVEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteGroupKVEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteGroupKV" {
- continue
- }
- event := new(DeleteGroupKVEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteGroupKVEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteGroupKVEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteGroupKVEvent) 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.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.GroupID, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field GroupID: %w", err)
- }
-
- index++
- e.Key, 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 Key: %w", err)
- }
-
- return nil
-}
-
-// AddSubjectToGroupEventsFromApplicationLog retrieves a set of all emitted events
-// with "AddSubjectToGroup" name from the provided [result.ApplicationLog].
-func AddSubjectToGroupEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddSubjectToGroupEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*AddSubjectToGroupEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "AddSubjectToGroup" {
- continue
- }
- event := new(AddSubjectToGroupEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize AddSubjectToGroupEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to AddSubjectToGroupEvent or
-// returns an error if it's not possible to do to so.
-func (e *AddSubjectToGroupEvent) 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.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.GroupID, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field GroupID: %w", err)
- }
-
- return nil
-}
-
-// RemoveSubjectFromGroupEventsFromApplicationLog retrieves a set of all emitted events
-// with "RemoveSubjectFromGroup" name from the provided [result.ApplicationLog].
-func RemoveSubjectFromGroupEventsFromApplicationLog(log *result.ApplicationLog) ([]*RemoveSubjectFromGroupEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*RemoveSubjectFromGroupEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "RemoveSubjectFromGroup" {
- continue
- }
- event := new(RemoveSubjectFromGroupEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize RemoveSubjectFromGroupEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to RemoveSubjectFromGroupEvent or
-// returns an error if it's not possible to do to so.
-func (e *RemoveSubjectFromGroupEvent) 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.SubjectAddress, 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 SubjectAddress: %w", err)
- }
-
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.GroupID, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field GroupID: %w", err)
- }
-
- return nil
-}
-
-// DeleteGroupEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteGroup" name from the provided [result.ApplicationLog].
-func DeleteGroupEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteGroupEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteGroupEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteGroup" {
- continue
- }
- event := new(DeleteGroupEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteGroupEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteGroupEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteGroupEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.Namespace, 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 Namespace: %w", err)
- }
-
- index++
- e.GroupID, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field GroupID: %w", err)
- }
-
- return nil
-}
diff --git a/rpcclient/netmap/client.go b/rpcclient/netmap/client.go
deleted file mode 100644
index 3f018a5..0000000
--- a/rpcclient/netmap/client.go
+++ /dev/null
@@ -1,629 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package netmap contains RPC wrappers for Netmap contract.
-package netmap
-
-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/rpcclient/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "math/big"
-)
-
-// AddPeerEvent represents "AddPeer" event emitted by the contract.
-type AddPeerEvent struct {
- NodeInfo []byte
-}
-
-// AddPeerSuccessEvent represents "AddPeerSuccess" event emitted by the contract.
-type AddPeerSuccessEvent struct {
- PublicKey *keys.PublicKey
-}
-
-// UpdateStateEvent represents "UpdateState" event emitted by the contract.
-type UpdateStateEvent struct {
- State *big.Int
- PublicKey *keys.PublicKey
-}
-
-// UpdateStateSuccessEvent represents "UpdateStateSuccess" event emitted by the contract.
-type UpdateStateSuccessEvent struct {
- PublicKey *keys.PublicKey
- State *big.Int
-}
-
-// NewEpochEvent represents "NewEpoch" event emitted by the contract.
-type NewEpochEvent struct {
- Epoch *big.Int
-}
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// Config invokes `config` method of contract.
-func (c *ContractReader) Config(key []byte) (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, "config", key)))
-}
-
-// Epoch invokes `epoch` method of contract.
-func (c *ContractReader) Epoch() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "epoch"))
-}
-
-// ListConfig invokes `listConfig` method of contract.
-func (c *ContractReader) ListConfig() ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "listConfig"))
-}
-
-// Netmap invokes `netmap` method of contract.
-func (c *ContractReader) Netmap() ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "netmap"))
-}
-
-// NetmapCandidates invokes `netmapCandidates` method of contract.
-func (c *ContractReader) NetmapCandidates() ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "netmapCandidates"))
-}
-
-// Snapshot invokes `snapshot` method of contract.
-func (c *ContractReader) Snapshot(diff *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "snapshot", diff))
-}
-
-// SnapshotByEpoch invokes `snapshotByEpoch` method of contract.
-func (c *ContractReader) SnapshotByEpoch(epoch *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "snapshotByEpoch", epoch))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// AddPeer creates a transaction invoking `addPeer` 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) AddPeer(nodeInfo []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addPeer", nodeInfo)
-}
-
-// AddPeerTransaction creates a transaction invoking `addPeer` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddPeerTransaction(nodeInfo []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addPeer", nodeInfo)
-}
-
-// AddPeerUnsigned creates a transaction invoking `addPeer` 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) AddPeerUnsigned(nodeInfo []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addPeer", nil, nodeInfo)
-}
-
-// AddPeerIR creates a transaction invoking `addPeerIR` 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) AddPeerIR(nodeInfo []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addPeerIR", nodeInfo)
-}
-
-// AddPeerIRTransaction creates a transaction invoking `addPeerIR` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddPeerIRTransaction(nodeInfo []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addPeerIR", nodeInfo)
-}
-
-// AddPeerIRUnsigned creates a transaction invoking `addPeerIR` 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) AddPeerIRUnsigned(nodeInfo []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addPeerIR", nil, nodeInfo)
-}
-
-// LastEpochBlock creates a transaction invoking `lastEpochBlock` 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) LastEpochBlock() (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "lastEpochBlock")
-}
-
-// LastEpochBlockTransaction creates a transaction invoking `lastEpochBlock` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) LastEpochBlockTransaction() (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "lastEpochBlock")
-}
-
-// LastEpochBlockUnsigned creates a transaction invoking `lastEpochBlock` 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) LastEpochBlockUnsigned() (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "lastEpochBlock", nil)
-}
-
-// NewEpoch creates a transaction invoking `newEpoch` 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) NewEpoch(epochNum *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "newEpoch", epochNum)
-}
-
-// NewEpochTransaction creates a transaction invoking `newEpoch` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) NewEpochTransaction(epochNum *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "newEpoch", epochNum)
-}
-
-// NewEpochUnsigned creates a transaction invoking `newEpoch` 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) NewEpochUnsigned(epochNum *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "newEpoch", nil, epochNum)
-}
-
-// SetConfig creates a transaction invoking `setConfig` 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) SetConfig(id []byte, key []byte, val []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setConfig", id, key, val)
-}
-
-// SetConfigTransaction creates a transaction invoking `setConfig` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) SetConfigTransaction(id []byte, key []byte, val []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setConfig", id, key, val)
-}
-
-// SetConfigUnsigned creates a transaction invoking `setConfig` 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) SetConfigUnsigned(id []byte, key []byte, val []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setConfig", nil, id, key, val)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
-
-// UpdateSnapshotCount creates a transaction invoking `updateSnapshotCount` 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) UpdateSnapshotCount(count *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "updateSnapshotCount", count)
-}
-
-// UpdateSnapshotCountTransaction creates a transaction invoking `updateSnapshotCount` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) UpdateSnapshotCountTransaction(count *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "updateSnapshotCount", count)
-}
-
-// UpdateSnapshotCountUnsigned creates a transaction invoking `updateSnapshotCount` 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) UpdateSnapshotCountUnsigned(count *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "updateSnapshotCount", nil, count)
-}
-
-// UpdateState creates a transaction invoking `updateState` 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) UpdateState(state *big.Int, publicKey *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "updateState", state, publicKey)
-}
-
-// UpdateStateTransaction creates a transaction invoking `updateState` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) UpdateStateTransaction(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "updateState", state, publicKey)
-}
-
-// UpdateStateUnsigned creates a transaction invoking `updateState` 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) UpdateStateUnsigned(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "updateState", nil, state, publicKey)
-}
-
-// UpdateStateIR creates a transaction invoking `updateStateIR` 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) UpdateStateIR(state *big.Int, publicKey *keys.PublicKey) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "updateStateIR", state, publicKey)
-}
-
-// UpdateStateIRTransaction creates a transaction invoking `updateStateIR` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) UpdateStateIRTransaction(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "updateStateIR", state, publicKey)
-}
-
-// UpdateStateIRUnsigned creates a transaction invoking `updateStateIR` 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) UpdateStateIRUnsigned(state *big.Int, publicKey *keys.PublicKey) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "updateStateIR", nil, state, publicKey)
-}
-
-// AddPeerEventsFromApplicationLog retrieves a set of all emitted events
-// with "AddPeer" name from the provided [result.ApplicationLog].
-func AddPeerEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddPeerEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*AddPeerEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "AddPeer" {
- continue
- }
- event := new(AddPeerEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize AddPeerEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to AddPeerEvent or
-// returns an error if it's not possible to do to so.
-func (e *AddPeerEvent) 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.NodeInfo, err = arr[index].TryBytes()
- if err != nil {
- return fmt.Errorf("field NodeInfo: %w", err)
- }
-
- return nil
-}
-
-// AddPeerSuccessEventsFromApplicationLog retrieves a set of all emitted events
-// with "AddPeerSuccess" name from the provided [result.ApplicationLog].
-func AddPeerSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddPeerSuccessEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*AddPeerSuccessEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "AddPeerSuccess" {
- continue
- }
- event := new(AddPeerSuccessEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize AddPeerSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to AddPeerSuccessEvent or
-// returns an error if it's not possible to do to so.
-func (e *AddPeerSuccessEvent) 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.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)
- }
-
- return nil
-}
-
-// UpdateStateEventsFromApplicationLog retrieves a set of all emitted events
-// with "UpdateState" name from the provided [result.ApplicationLog].
-func UpdateStateEventsFromApplicationLog(log *result.ApplicationLog) ([]*UpdateStateEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*UpdateStateEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "UpdateState" {
- continue
- }
- event := new(UpdateStateEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize UpdateStateEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to UpdateStateEvent or
-// returns an error if it's not possible to do to so.
-func (e *UpdateStateEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.State, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field State: %w", err)
- }
-
- index++
- e.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)
- }
-
- return nil
-}
-
-// UpdateStateSuccessEventsFromApplicationLog retrieves a set of all emitted events
-// with "UpdateStateSuccess" name from the provided [result.ApplicationLog].
-func UpdateStateSuccessEventsFromApplicationLog(log *result.ApplicationLog) ([]*UpdateStateSuccessEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*UpdateStateSuccessEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "UpdateStateSuccess" {
- continue
- }
- event := new(UpdateStateSuccessEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize UpdateStateSuccessEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to UpdateStateSuccessEvent or
-// returns an error if it's not possible to do to so.
-func (e *UpdateStateSuccessEvent) 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) != 2 {
- return errors.New("wrong number of structure elements")
- }
-
- var (
- index = -1
- err error
- )
- index++
- e.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++
- e.State, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field State: %w", err)
- }
-
- return nil
-}
-
-// NewEpochEventsFromApplicationLog retrieves a set of all emitted events
-// with "NewEpoch" name from the provided [result.ApplicationLog].
-func NewEpochEventsFromApplicationLog(log *result.ApplicationLog) ([]*NewEpochEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*NewEpochEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "NewEpoch" {
- continue
- }
- event := new(NewEpochEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize NewEpochEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to NewEpochEvent or
-// returns an error if it's not possible to do to so.
-func (e *NewEpochEvent) 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.Epoch, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Epoch: %w", err)
- }
-
- return nil
-}
diff --git a/rpcclient/nns/client.go b/rpcclient/nns/client.go
deleted file mode 100644
index 43c0d0a..0000000
--- a/rpcclient/nns/client.go
+++ /dev/null
@@ -1,720 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package nameservice contains RPC wrappers for NameService contract.
-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"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
- "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"
- "math/big"
- "unicode/utf8"
-)
-
-// RegisterDomainEvent represents "RegisterDomain" event emitted by the contract.
-type RegisterDomainEvent struct {
- Name string
-}
-
-// AddRecordEvent represents "AddRecord" event emitted by the contract.
-type AddRecordEvent struct {
- Name string
- Type *big.Int
-}
-
-// DeleteRecordEvent represents "DeleteRecord" event emitted by the contract.
-type DeleteRecordEvent struct {
- Name string
- Type *big.Int
-}
-
-// DeleteRecordsEvent represents "DeleteRecords" event emitted by the contract.
-type DeleteRecordsEvent struct {
- Name string
- Type *big.Int
-}
-
-// DeleteDomainEvent represents "DeleteDomain" event emitted by the contract.
-type DeleteDomainEvent struct {
- Name string
-}
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- nep11.Invoker
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- nep11.Actor
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- nep11.NonDivisibleReader
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- nep11.BaseWriter
- actor Actor
- 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{*nep11.NewNonDivisibleReader(invoker, hash), invoker, hash}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- var nep11ndt = nep11.NewNonDivisible(actor, hash)
- return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor, hash}, nep11ndt.BaseWriter, actor, hash}
-}
-
-// GetAllRecords invokes `getAllRecords` method of contract.
-func (c *ContractReader) GetAllRecords(name string) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "getAllRecords", name))
-}
-
-// GetAllRecordsExpanded is similar to GetAllRecords (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
-// 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(c.hash, "getAllRecords", _numOfIteratorItems, name))
-}
-
-// GetPrice invokes `getPrice` method of contract.
-func (c *ContractReader) GetPrice() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "getPrice"))
-}
-
-// GetRecords invokes `getRecords` method of contract.
-func (c *ContractReader) GetRecords(name string, typ *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "getRecords", name, typ))
-}
-
-// IsAvailable invokes `isAvailable` method of contract.
-func (c *ContractReader) IsAvailable(name string) (bool, error) {
- return unwrap.Bool(c.invoker.Call(c.hash, "isAvailable", name))
-}
-
-// Resolve invokes `resolve` method of contract.
-func (c *ContractReader) Resolve(name string, typ *big.Int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "resolve", name, typ))
-}
-
-// Roots invokes `roots` method of contract.
-func (c *ContractReader) Roots() (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "roots"))
-}
-
-// RootsExpanded is similar to Roots (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
-// 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(c.hash, "roots", _numOfIteratorItems))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// AddRecord creates a transaction invoking `addRecord` 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) AddRecord(name string, typ *big.Int, data string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addRecord", name, typ, data)
-}
-
-// AddRecordTransaction creates a transaction invoking `addRecord` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddRecordTransaction(name string, typ *big.Int, data string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addRecord", name, typ, data)
-}
-
-// AddRecordUnsigned creates a transaction invoking `addRecord` 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) AddRecordUnsigned(name string, typ *big.Int, data string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addRecord", nil, name, typ, data)
-}
-
-// DeleteDomain creates a transaction invoking `deleteDomain` 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) DeleteDomain(name string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteDomain", name)
-}
-
-// DeleteDomainTransaction creates a transaction invoking `deleteDomain` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteDomainTransaction(name string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteDomain", name)
-}
-
-// DeleteDomainUnsigned creates a transaction invoking `deleteDomain` 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) DeleteDomainUnsigned(name string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteDomain", nil, name)
-}
-
-func (c *Contract) scriptForDeleteRecord(name string, typ *big.Int, data string) ([]byte, error) {
- return smartcontract.CreateCallWithAssertScript(c.hash, "deleteRecord", name, typ, 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, typ *big.Int, data string) (util.Uint256, uint32, error) {
- script, err := c.scriptForDeleteRecord(name, typ, data)
- if err != nil {
- return util.Uint256{}, 0, err
- }
- return c.actor.SendRun(script)
-}
-
-// 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, typ *big.Int, data string) (*transaction.Transaction, error) {
- script, err := c.scriptForDeleteRecord(name, typ, data)
- if err != nil {
- return nil, err
- }
- return c.actor.MakeRun(script)
-}
-
-// DeleteRecordUnsigned creates a transaction invoking `deleteRecord` 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) DeleteRecordUnsigned(name string, typ *big.Int, data string) (*transaction.Transaction, error) {
- script, err := c.scriptForDeleteRecord(name, typ, data)
- if err != nil {
- return nil, err
- }
- return c.actor.MakeUnsignedRun(script, nil)
-}
-
-// DeleteRecords creates a transaction invoking `deleteRecords` 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) DeleteRecords(name string, typ *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "deleteRecords", name, typ)
-}
-
-// DeleteRecordsTransaction creates a transaction invoking `deleteRecords` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) DeleteRecordsTransaction(name string, typ *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "deleteRecords", name, typ)
-}
-
-// DeleteRecordsUnsigned creates a transaction invoking `deleteRecords` 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) DeleteRecordsUnsigned(name string, typ *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "deleteRecords", nil, name, typ)
-}
-
-func (c *Contract) scriptForRegister(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) ([]byte, error) {
- return smartcontract.CreateCallWithAssertScript(c.hash, "register", name, owner, email, refresh, retry, expire, ttl)
-}
-
-// Register creates a transaction invoking `register` 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) Register(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (util.Uint256, uint32, error) {
- script, err := c.scriptForRegister(name, owner, email, refresh, retry, expire, ttl)
- if err != nil {
- return util.Uint256{}, 0, err
- }
- return c.actor.SendRun(script)
-}
-
-// RegisterTransaction creates a transaction invoking `register` method of the contract.
-// 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, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) {
- script, err := c.scriptForRegister(name, owner, email, refresh, retry, expire, ttl)
- if err != nil {
- return nil, err
- }
- return c.actor.MakeRun(script)
-}
-
-// RegisterUnsigned creates a transaction invoking `register` 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) RegisterUnsigned(name string, owner util.Uint160, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) {
- script, err := c.scriptForRegister(name, owner, email, refresh, retry, expire, ttl)
- if err != nil {
- return nil, err
- }
- return c.actor.MakeUnsignedRun(script, nil)
-}
-
-// 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(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(c.hash, "setAdmin", name, admin)
-}
-
-// SetAdminUnsigned creates a transaction invoking `setAdmin` 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) SetAdminUnsigned(name string, admin util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, name, admin)
-}
-
-// 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(price *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setPrice", price)
-}
-
-// 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(price *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setPrice", price)
-}
-
-// SetPriceUnsigned creates a transaction invoking `setPrice` 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) SetPriceUnsigned(price *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setPrice", nil, price)
-}
-
-// 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, typ *big.Int, id *big.Int, data string) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setRecord", name, typ, id, 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, typ *big.Int, id *big.Int, data string) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setRecord", name, typ, id, data)
-}
-
-// SetRecordUnsigned creates a transaction invoking `setRecord` 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) SetRecordUnsigned(name string, typ *big.Int, id *big.Int, data string) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setRecord", nil, name, typ, id, 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 string, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", nef, manifest, data)
-}
-
-// 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, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", nef, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(nef []byte, manifest string, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, nef, manifest, data)
-}
-
-// UpdateSOA creates a transaction invoking `updateSOA` 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) UpdateSOA(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "updateSOA", name, email, refresh, retry, expire, ttl)
-}
-
-// UpdateSOATransaction creates a transaction invoking `updateSOA` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) UpdateSOATransaction(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "updateSOA", name, email, refresh, retry, expire, ttl)
-}
-
-// UpdateSOAUnsigned creates a transaction invoking `updateSOA` 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) UpdateSOAUnsigned(name string, email string, refresh *big.Int, retry *big.Int, expire *big.Int, ttl *big.Int) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "updateSOA", nil, name, email, refresh, retry, expire, ttl)
-}
-
-// RegisterDomainEventsFromApplicationLog retrieves a set of all emitted events
-// with "RegisterDomain" name from the provided [result.ApplicationLog].
-func RegisterDomainEventsFromApplicationLog(log *result.ApplicationLog) ([]*RegisterDomainEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*RegisterDomainEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "RegisterDomain" {
- continue
- }
- event := new(RegisterDomainEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize RegisterDomainEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to RegisterDomainEvent or
-// returns an error if it's not possible to do to so.
-func (e *RegisterDomainEvent) 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.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)
- }
-
- return nil
-}
-
-// AddRecordEventsFromApplicationLog retrieves a set of all emitted events
-// with "AddRecord" name from the provided [result.ApplicationLog].
-func AddRecordEventsFromApplicationLog(log *result.ApplicationLog) ([]*AddRecordEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*AddRecordEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "AddRecord" {
- continue
- }
- event := new(AddRecordEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize AddRecordEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to AddRecordEvent or
-// returns an error if it's not possible to do to so.
-func (e *AddRecordEvent) 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) != 2 {
- 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.Type, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Type: %w", err)
- }
-
- return nil
-}
-
-// DeleteRecordEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteRecord" name from the provided [result.ApplicationLog].
-func DeleteRecordEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteRecordEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteRecordEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteRecord" {
- continue
- }
- event := new(DeleteRecordEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteRecordEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteRecordEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteRecordEvent) 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) != 2 {
- 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.Type, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Type: %w", err)
- }
-
- return nil
-}
-
-// DeleteRecordsEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteRecords" name from the provided [result.ApplicationLog].
-func DeleteRecordsEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteRecordsEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteRecordsEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteRecords" {
- continue
- }
- event := new(DeleteRecordsEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteRecordsEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteRecordsEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteRecordsEvent) 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) != 2 {
- 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.Type, err = arr[index].TryInteger()
- if err != nil {
- return fmt.Errorf("field Type: %w", err)
- }
-
- return nil
-}
-
-// DeleteDomainEventsFromApplicationLog retrieves a set of all emitted events
-// with "DeleteDomain" name from the provided [result.ApplicationLog].
-func DeleteDomainEventsFromApplicationLog(log *result.ApplicationLog) ([]*DeleteDomainEvent, error) {
- if log == nil {
- return nil, errors.New("nil application log")
- }
-
- var res []*DeleteDomainEvent
- for i, ex := range log.Executions {
- for j, e := range ex.Events {
- if e.Name != "DeleteDomain" {
- continue
- }
- event := new(DeleteDomainEvent)
- err := event.FromStackItem(e.Item)
- if err != nil {
- return nil, fmt.Errorf("failed to deserialize DeleteDomainEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
- }
- res = append(res, event)
- }
- }
-
- return res, nil
-}
-
-// FromStackItem converts provided [stackitem.Array] to DeleteDomainEvent or
-// returns an error if it's not possible to do to so.
-func (e *DeleteDomainEvent) 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.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)
- }
-
- return nil
-}
diff --git a/rpcclient/policy/client.go b/rpcclient/policy/client.go
deleted file mode 100644
index 36d1e5f..0000000
--- a/rpcclient/policy/client.go
+++ /dev/null
@@ -1,234 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package ape contains RPC wrappers for APE contract.
-package ape
-
-import (
- "github.com/google/uuid"
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
- "github.com/nspcc-dev/neo-go/pkg/neorpc/result"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "math/big"
-)
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- 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)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// GetAdmin invokes `getAdmin` method of contract.
-func (c *ContractReader) GetAdmin() (util.Uint160, error) {
- return unwrap.Uint160(c.invoker.Call(c.hash, "getAdmin"))
-}
-
-// GetChain invokes `getChain` method of contract.
-func (c *ContractReader) GetChain(entity *big.Int, entityName string, name []byte) ([]byte, error) {
- return unwrap.Bytes(c.invoker.Call(c.hash, "getChain", entity, entityName, name))
-}
-
-// IteratorChainsByPrefix invokes `iteratorChainsByPrefix` method of contract.
-func (c *ContractReader) IteratorChainsByPrefix(entity *big.Int, entityName string, prefix []byte) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "iteratorChainsByPrefix", entity, entityName, prefix))
-}
-
-// IteratorChainsByPrefixExpanded is similar to IteratorChainsByPrefix (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
-// 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) IteratorChainsByPrefixExpanded(entity *big.Int, entityName string, prefix []byte, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "iteratorChainsByPrefix", _numOfIteratorItems, entity, entityName, prefix))
-}
-
-// ListChainNames invokes `listChainNames` method of contract.
-func (c *ContractReader) ListChainNames(entity *big.Int, entityName string) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listChainNames", entity, entityName))
-}
-
-// ListChainNamesExpanded is similar to ListChainNames (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
-// 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) ListChainNamesExpanded(entity *big.Int, entityName string, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listChainNames", _numOfIteratorItems, entity, entityName))
-}
-
-// ListChains invokes `listChains` method of contract.
-func (c *ContractReader) ListChains(namespace string, container string, name []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "listChains", namespace, container, name))
-}
-
-// ListChainsByPrefix invokes `listChainsByPrefix` method of contract.
-func (c *ContractReader) ListChainsByPrefix(entity *big.Int, entityName string, prefix []byte) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.Call(c.hash, "listChainsByPrefix", entity, entityName, prefix))
-}
-
-// ListTargets invokes `listTargets` method of contract.
-func (c *ContractReader) ListTargets(entity *big.Int) (uuid.UUID, result.Iterator, error) {
- return unwrap.SessionIterator(c.invoker.Call(c.hash, "listTargets", entity))
-}
-
-// ListTargetsExpanded is similar to ListTargets (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
-// 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) ListTargetsExpanded(entity *big.Int, _numOfIteratorItems int) ([]stackitem.Item, error) {
- return unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "listTargets", _numOfIteratorItems, entity))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// AddChain creates a transaction invoking `addChain` 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) AddChain(entity *big.Int, entityName string, name []byte, chain []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addChain", entity, entityName, name, chain)
-}
-
-// AddChainTransaction creates a transaction invoking `addChain` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddChainTransaction(entity *big.Int, entityName string, name []byte, chain []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addChain", entity, entityName, name, chain)
-}
-
-// AddChainUnsigned creates a transaction invoking `addChain` 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) AddChainUnsigned(entity *big.Int, entityName string, name []byte, chain []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addChain", nil, entity, entityName, name, chain)
-}
-
-// RemoveChain creates a transaction invoking `removeChain` 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) RemoveChain(entity *big.Int, entityName string, name []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "removeChain", entity, entityName, name)
-}
-
-// RemoveChainTransaction creates a transaction invoking `removeChain` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) RemoveChainTransaction(entity *big.Int, entityName string, name []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "removeChain", entity, entityName, name)
-}
-
-// RemoveChainUnsigned creates a transaction invoking `removeChain` 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) RemoveChainUnsigned(entity *big.Int, entityName string, name []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "removeChain", nil, entity, entityName, name)
-}
-
-// RemoveChainsByPrefix creates a transaction invoking `removeChainsByPrefix` 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) RemoveChainsByPrefix(entity *big.Int, entityName string, name []byte) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "removeChainsByPrefix", entity, entityName, name)
-}
-
-// RemoveChainsByPrefixTransaction creates a transaction invoking `removeChainsByPrefix` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) RemoveChainsByPrefixTransaction(entity *big.Int, entityName string, name []byte) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "removeChainsByPrefix", entity, entityName, name)
-}
-
-// RemoveChainsByPrefixUnsigned creates a transaction invoking `removeChainsByPrefix` 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) RemoveChainsByPrefixUnsigned(entity *big.Int, entityName string, name []byte) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "removeChainsByPrefix", nil, entity, entityName, name)
-}
-
-// 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(addr util.Uint160) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "setAdmin", addr)
-}
-
-// 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(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "setAdmin", addr)
-}
-
-// SetAdminUnsigned creates a transaction invoking `setAdmin` 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) SetAdminUnsigned(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, addr)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
diff --git a/rpcclient/processing/client.go b/rpcclient/processing/client.go
deleted file mode 100644
index de296fb..0000000
--- a/rpcclient/processing/client.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package multisignatureprocessing contains RPC wrappers for Multi Signature Processing contract.
-package multisignatureprocessing
-
-import (
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
- "github.com/nspcc-dev/neo-go/pkg/neorpc/result"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "math/big"
-)
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// Verify invokes `verify` method of contract.
-func (c *ContractReader) Verify() (bool, error) {
- return unwrap.Bool(c.invoker.Call(c.hash, "verify"))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
diff --git a/rpcclient/proxy/client.go b/rpcclient/proxy/client.go
deleted file mode 100644
index 7c75af6..0000000
--- a/rpcclient/proxy/client.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT.
-
-// Package notaryproxy contains RPC wrappers for Notary Proxy contract.
-package notaryproxy
-
-import (
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
- "github.com/nspcc-dev/neo-go/pkg/neorpc/result"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
- "github.com/nspcc-dev/neo-go/pkg/util"
- "math/big"
-)
-
-// Invoker is used by ContractReader to call various safe methods.
-type Invoker interface {
- Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error)
-}
-
-// Actor is used by Contract to call state-changing methods.
-type Actor interface {
- Invoker
-
- 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)
-}
-
-// ContractReader implements safe contract methods.
-type ContractReader struct {
- invoker Invoker
- hash util.Uint160
-}
-
-// Contract implements all contract methods.
-type Contract struct {
- ContractReader
- actor Actor
- 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}
-}
-
-// New creates an instance of Contract using provided contract hash and the given Actor.
-func New(actor Actor, hash util.Uint160) *Contract {
- return &Contract{ContractReader{actor, hash}, actor, hash}
-}
-
-// Verify invokes `verify` method of contract.
-func (c *ContractReader) Verify() (bool, error) {
- return unwrap.Bool(c.invoker.Call(c.hash, "verify"))
-}
-
-// Version invokes `version` method of contract.
-func (c *ContractReader) Version() (*big.Int, error) {
- return unwrap.BigInt(c.invoker.Call(c.hash, "version"))
-}
-
-// AddAccount creates a transaction invoking `addAccount` 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) AddAccount(addr util.Uint160) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "addAccount", addr)
-}
-
-// AddAccountTransaction creates a transaction invoking `addAccount` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) AddAccountTransaction(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "addAccount", addr)
-}
-
-// AddAccountUnsigned creates a transaction invoking `addAccount` 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) AddAccountUnsigned(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "addAccount", nil, addr)
-}
-
-// RemoveAccount creates a transaction invoking `removeAccount` 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) RemoveAccount(addr util.Uint160) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "removeAccount", addr)
-}
-
-// RemoveAccountTransaction creates a transaction invoking `removeAccount` method of the contract.
-// This transaction is signed, but not sent to the network, instead it's
-// returned to the caller.
-func (c *Contract) RemoveAccountTransaction(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "removeAccount", addr)
-}
-
-// RemoveAccountUnsigned creates a transaction invoking `removeAccount` 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) RemoveAccountUnsigned(addr util.Uint160) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "removeAccount", nil, addr)
-}
-
-// 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(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) {
- return c.actor.SendCall(c.hash, "update", script, manifest, data)
-}
-
-// 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(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeCall(c.hash, "update", script, manifest, data)
-}
-
-// UpdateUnsigned creates a transaction invoking `update` 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) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) {
- return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data)
-}
diff --git a/tests/alphabet_test.go b/tests/alphabet_test.go
index 463dd61..3d15a43 100644
--- a/tests/alphabet_test.go
+++ b/tests/alphabet_test.go
@@ -21,12 +21,13 @@ const alphabetPath = "../alphabet"
func deployAlphabetContract(t *testing.T, e *neotest.Executor, addrNetmap, addrProxy util.Uint160, name string, index, total int64) util.Uint160 {
c := neotest.CompileFile(t, e.CommitteeHash, alphabetPath, path.Join(alphabetPath, "config.yml"))
- args := make([]any, 5)
- args[0] = addrNetmap
- args[1] = addrProxy
- args[2] = name
- args[3] = index
- args[4] = total
+ args := make([]interface{}, 6)
+ args[0] = false
+ args[1] = addrNetmap
+ args[2] = addrProxy
+ args[3] = name
+ args[4] = index
+ args[5] = total
e.DeployContract(t, c, args)
return c.Hash
@@ -47,7 +48,7 @@ func newAlphabetInvoker(t *testing.T) (*neotest.Executor, *neotest.ContractInvok
container.AliasFeeKey, int64(containerAliasFee))
deployBalanceContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
deployContainerContract(t, e, ctrNetmap.Hash, ctrBalance.Hash, ctrNNS.Hash)
- deployProxyContract(t, e)
+ deployProxyContract(t, e, ctrNetmap.Hash)
hash := deployAlphabetContract(t, e, ctrNetmap.Hash, ctrProxy.Hash, "Az", 0, 1)
alphabet := getAlphabetAcc(t, e)
@@ -87,8 +88,8 @@ func TestVote(t *testing.T) {
require.True(t, ok)
cNewAlphabet := c.WithSigners(newAlphabet)
- cNewAlphabet.InvokeFail(t, common.ErrAlphabetWitnessFailed, method, int64(0), []any{newAlphabetPub})
- c.InvokeFail(t, "invalid epoch", method, int64(1), []any{newAlphabetPub})
+ cNewAlphabet.InvokeFail(t, common.ErrAlphabetWitnessFailed, method, int64(0), []interface{}{newAlphabetPub})
+ c.InvokeFail(t, "invalid epoch", method, int64(1), []interface{}{newAlphabetPub})
setAlphabetRole(t, e, newAlphabetPub)
transferNeoToContract(t, c)
@@ -108,7 +109,7 @@ func TestVote(t *testing.T) {
newInvoker := neoInvoker.WithSigners(newAlphabet)
newInvoker.Invoke(t, stackitem.NewBool(true), "registerCandidate", newAlphabetPub)
- c.Invoke(t, stackitem.Null{}, method, int64(0), []any{newAlphabetPub})
+ c.Invoke(t, stackitem.Null{}, method, int64(0), []interface{}{newAlphabetPub})
// wait one block util
// a new committee is accepted
@@ -138,7 +139,7 @@ func setAlphabetRole(t *testing.T, e *neotest.Executor, new []byte) {
designInvoker := e.CommitteeInvoker(designSH)
// set committee as NeoFSAlphabet
- designInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(noderoles.NeoFSAlphabet), []any{new})
+ designInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(noderoles.NeoFSAlphabet), []interface{}{new})
}
func getAlphabetAcc(t *testing.T, e *neotest.Executor) *wallet.Account {
diff --git a/tests/balance_test.go b/tests/balance_test.go
index 22d319b..03b076e 100644
--- a/tests/balance_test.go
+++ b/tests/balance_test.go
@@ -14,9 +14,10 @@ const balancePath = "../balance"
func deployBalanceContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
c := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
- args := make([]any, 3)
- args[0] = addrNetmap
- args[1] = addrContainer
+ args := make([]interface{}, 3)
+ args[0] = false
+ args[1] = addrNetmap
+ args[2] = addrContainer
e.DeployContract(t, c, args)
return c.Hash
diff --git a/tests/common_test.go b/tests/common_test.go
deleted file mode 100644
index 0085d2c..0000000
--- a/tests/common_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package tests
-
-import (
- "math"
- "math/big"
- "path"
- "testing"
-
- "github.com/nspcc-dev/neo-go/pkg/neotest"
- "github.com/stretchr/testify/require"
-)
-
-const testdataPath = "./testdata"
-
-func newTestdataInvoker(t *testing.T) *neotest.ContractInvoker {
- e := newExecutor(t)
- ctr := neotest.CompileFile(t, e.CommitteeHash, testdataPath, path.Join(testdataPath, "config.yml"))
- e.DeployContract(t, ctr, nil)
- return e.CommitteeInvoker(ctr.Hash)
-}
-
-func TestEncodeU64(t *testing.T) {
- // Let's check boundary values for all bit sizes:
- var nums []uint64
- for i := 0; i < 64; i++ {
- if i != 0 {
- nums = append(nums, (1< 0, isSet)
- if isSet {
- require.Equal(t, owners[0], address)
- }
-}
-
-func TestFrostFSID_Client_SubjectManagement(t *testing.T) {
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- subjKey, subjAddr := newKey(t)
- extraKey, _ := newKey(t)
- subjLogin := "subj-login"
- iamPathKV := "iam/path"
-
- ffsid.a.await(ffsid.cli.CreateSubject(defaultNamespace, subjKey.PublicKey()))
- ffsid.a.await(ffsid.cli.SetSubjectName(subjAddr, subjLogin))
- ffsid.a.await(ffsid.cli.SetSubjectKV(subjAddr, client.IAMPathKey, iamPathKV))
- ffsid.a.await(ffsid.cli.AddSubjectKey(subjAddr, extraKey.PublicKey()))
-
- subj, err := ffsid.cli.GetSubject(subjAddr)
- require.NoError(t, err)
- require.True(t, subjKey.PublicKey().Equal(subj.PrimaryKey))
- require.Equal(t, subj.Name, subjLogin)
- require.Equal(t, map[string]string{client.IAMPathKey: iamPathKV}, subj.KV)
- require.ElementsMatch(t, []*keys.PublicKey{extraKey.PublicKey()}, subj.AdditionalKeys)
-
- ffsid.a.await(ffsid.cli.DeleteSubjectKV(subjAddr, client.IAMPathKey))
- subj, err = ffsid.cli.GetSubject(subjAddr)
- require.NoError(t, err)
- require.Empty(t, subj.KV)
-
- subjects, err := ffsid.cli.ListSubjects()
- require.NoError(t, err)
- require.ElementsMatch(t, subjects, []util.Uint160{subjAddr})
-
- subj, err = ffsid.cli.GetSubjectByKey(extraKey.PublicKey())
- require.NoError(t, err)
- require.True(t, subjKey.PublicKey().Equal(subj.PrimaryKey))
-
- ffsid.a.await(ffsid.cli.RemoveSubjectKey(subjAddr, extraKey.PublicKey()))
- _, err = ffsid.cli.GetSubjectByKey(extraKey.PublicKey())
- require.ErrorContains(t, err, "not found")
-
- ffsid.a.await(ffsid.cli.DeleteSubject(subjAddr))
-
- _, err = ffsid.cli.GetSubject(subjAddr)
- require.ErrorContains(t, err, "not found")
- subjects, err = ffsid.cli.ListSubjects()
- require.NoError(t, err)
- require.Empty(t, subjects)
-}
-
-func TestFrostFSID_Client_NamespaceManagement(t *testing.T) {
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- namespace := "namespace"
- subjKey, subjAddr := newKey(t)
-
- ffsid.a.await(ffsid.cli.CreateNamespace(namespace))
- _, _, err := ffsid.cli.CreateNamespace(namespace)
- require.ErrorContains(t, err, "already exists")
-
- ffsid.a.await(ffsid.cli.CreateSubject(namespace, subjKey.PublicKey()))
-
- ns, err := ffsid.cli.GetNamespace(namespace)
- require.NoError(t, err)
- require.Equal(t, namespace, ns.Name)
- require.Equal(t, client.Active, ns.State)
-
- namespaces, err := ffsid.cli.ListNamespaces()
- require.NoError(t, err)
- require.ElementsMatch(t, []*client.Namespace{{State: client.Active}, ns}, namespaces)
-
- subj, err := ffsid.cli.GetSubject(subjAddr)
- require.NoError(t, err)
- require.Equal(t, namespace, subj.Namespace)
-
- subjects, err := ffsid.cli.ListNamespaceSubjects(namespace)
- require.NoError(t, err)
- require.ElementsMatch(t, []util.Uint160{subjAddr}, subjects)
-
- ffsid.a.await(ffsid.cli.DeleteSubject(subjAddr))
-
- subjects, err = ffsid.cli.ListNamespaceSubjects(namespace)
- require.NoError(t, err)
- require.Empty(t, subjects)
-
- namespace2 := "namespace2"
- ffsid.a.await(ffsid.cli.CreateNamespace(namespace2))
- ns1, err := ffsid.cli.GetNamespace(namespace)
- require.NoError(t, err)
- require.Equal(t, namespace, ns1.Name)
- require.Equal(t, client.Active, ns1.State)
-
- nsExt2, err := ffsid.cli.GetNamespaceExtended(namespace2)
- require.NoError(t, err)
- require.Equal(t, namespace2, nsExt2.Name)
- require.Equal(t, client.Active, nsExt2.State)
-
- ffsid.a.await(ffsid.cli.UpdateNamespace(namespace2, client.Frozen))
- nsExt2, err = ffsid.cli.GetNamespaceExtended(namespace2)
- require.NoError(t, err)
- require.Equal(t, namespace2, nsExt2.Name)
- require.Equal(t, client.Frozen, nsExt2.State)
-
- _, _, err = ffsid.cli.DeleteNamespace(namespace2)
- require.ErrorContains(t, err, "namespace should be in 'purge' state for deletion")
-
- ffsid.a.await(ffsid.cli.UpdateNamespace(namespace2, client.Active))
- nsExt2, err = ffsid.cli.GetNamespaceExtended(namespace2)
- require.NoError(t, err)
- require.Equal(t, client.Active, nsExt2.State)
-
- subjKey2, subjAddr2 := newKey(t)
- ffsid.a.await(ffsid.cli.CreateSubject(namespace2, subjKey2.PublicKey()))
-
- subj2, err := ffsid.cli.GetSubject(subjAddr2)
- require.NoError(t, err)
- require.Equal(t, namespace2, subj2.Namespace)
-
- ffsid.a.await(ffsid.cli.UpdateNamespace(namespace2, client.Purge))
- nsExt2, err = ffsid.cli.GetNamespaceExtended(namespace2)
- require.NoError(t, err)
- require.Equal(t, client.Purge, nsExt2.State)
-
- _, _, err = ffsid.cli.DeleteNamespace(namespace2)
- require.ErrorContains(t, err, "can't delete non-empty namespace: users still present")
-
- ffsid.a.await(ffsid.cli.DeleteSubject(subjAddr2))
-
- ffsid.a.await(ffsid.cli.UpdateNamespace(namespace2, client.Active))
- nsExt2, err = ffsid.cli.GetNamespaceExtended(namespace2)
- require.NoError(t, err)
- require.Equal(t, client.Active, nsExt2.State)
-
- groupName := "ns_group"
- ffsid.a.await(ffsid.cli.CreateGroup(namespace2, groupName))
- group, err := ffsid.cli.GetGroupByName(namespace2, groupName)
- require.NoError(t, err)
-
- ffsid.a.await(ffsid.cli.UpdateNamespace(namespace2, client.Purge))
- nsExt2, err = ffsid.cli.GetNamespaceExtended(namespace2)
- require.NoError(t, err)
- require.Equal(t, client.Purge, nsExt2.State)
-
- _, _, err = ffsid.cli.DeleteNamespace(namespace2)
- require.ErrorContains(t, err, "can't delete non-empty namespace: groups still present")
-
- ffsid.a.await(ffsid.cli.DeleteGroup(namespace2, group.ID))
-
- ffsid.a.await(ffsid.cli.DeleteNamespace(namespace2))
- _, err = ffsid.cli.GetNamespace(namespace2)
- require.ErrorContains(t, err, "not found")
-
- namespace3 := "namespace3"
- _, err = ffsid.cli.GetNamespace(namespace3)
- require.ErrorContains(t, err, "not found")
- _, _, err = ffsid.cli.DeleteNamespace(namespace3)
- require.NoError(t, err)
-}
-
-func TestFrostFSID_Client_DefaultNamespace(t *testing.T) {
- ctx := context.Background()
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- group := "group"
- subjKey, subjAddr := newKey(t)
-
- ffsid.a.await(ffsid.cli.CreateSubject(defaultNamespace, subjKey.PublicKey()))
-
- txHash, vub, err := ffsid.cli.CreateGroup(defaultNamespace, group)
- groupID, err := ffsid.cli.ParseGroupID(ffsid.cli.Waiter().WaitCtx(ctx, txHash, vub, err))
- require.NoError(t, err)
- ffsid.a.await(ffsid.cli.AddSubjectToGroup(subjAddr, groupID))
-
- namespaces, err := ffsid.cli.ListNamespaces()
- require.NoError(t, err)
- require.EqualValues(t, []*client.Namespace{{State: client.Active}}, namespaces)
-
- groups, err := ffsid.cli.ListGroups(defaultNamespace)
- require.NoError(t, err)
- require.EqualValues(t, []*client.Group{{ID: groupID, Name: group, Namespace: defaultNamespace}}, groups)
-
- subjects, err := ffsid.cli.ListNamespaceSubjects(defaultNamespace)
- require.NoError(t, err)
- require.EqualValues(t, []util.Uint160{subjAddr}, subjects)
-
- subjects, err = ffsid.cli.ListGroupSubjects(defaultNamespace, groupID)
- require.NoError(t, err)
- require.EqualValues(t, []util.Uint160{subjAddr}, subjects)
-
- subject, err := ffsid.cli.GetSubjectExtended(subjAddr)
- require.NoError(t, err)
- require.True(t, subjKey.PublicKey().Equal(subject.PrimaryKey))
- require.Equal(t, defaultNamespace, subject.Namespace)
- require.EqualValues(t, []*client.Group{{ID: groupID, Name: group, Namespace: defaultNamespace}}, subject.Groups)
-}
-
-func TestFrostFSID_Client_GroupManagement(t *testing.T) {
- ctx := context.Background()
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- namespace := "namespace"
- subjKey, subjAddr := newKey(t)
-
- ffsid.a.await(ffsid.cli.CreateNamespace(namespace))
- ffsid.a.await(ffsid.cli.CreateSubject(namespace, subjKey.PublicKey()))
-
- groupName := "group"
- groupID := int64(1)
- txHash, vub, err := ffsid.cli.CreateGroup(namespace, groupName)
- actGroupID, err := ffsid.cli.ParseGroupID(ffsid.cli.Waiter().WaitCtx(ctx, txHash, vub, err))
- require.NoError(t, err)
- require.Equal(t, groupID, actGroupID)
-
- _, _, err = ffsid.cli.CreateGroup(namespace, groupName)
- require.ErrorContains(t, err, "is not available")
-
- iamARN := "arn"
- ffsid.a.await(ffsid.cli.SetGroupKV(namespace, groupID, client.IAMARNKey, iamARN))
-
- group, err := ffsid.cli.GetGroup(namespace, groupID)
- require.NoError(t, err)
- require.Equal(t, groupName, group.Name)
- require.Equal(t, map[string]string{client.IAMARNKey: iamARN}, group.KV)
-
- ffsid.a.await(ffsid.cli.DeleteGroupKV(namespace, groupID, client.IAMARNKey))
-
- groupExt, err := ffsid.cli.GetGroupExtended(namespace, groupID)
- require.NoError(t, err)
- require.Zero(t, groupExt.SubjectsCount)
-
- ffsid.a.await(ffsid.cli.AddSubjectToGroup(subjAddr, groupID))
-
- subjExt, err := ffsid.cli.GetSubjectExtended(subjAddr)
- require.NoError(t, err)
- require.ElementsMatch(t, []*client.Group{{ID: groupID, Name: groupName, Namespace: namespace, KV: map[string]string{}}}, subjExt.Groups)
-
- groupExt, err = ffsid.cli.GetGroupExtended(namespace, groupID)
- require.NoError(t, err)
- require.EqualValues(t, 1, groupExt.SubjectsCount)
-
- subjects, err := ffsid.cli.ListGroupSubjects(namespace, groupID)
- require.NoError(t, err)
- require.ElementsMatch(t, []util.Uint160{subjAddr}, subjects)
-
- ffsid.a.await(ffsid.cli.RemoveSubjectFromGroup(subjAddr, groupID))
-
- subjects, err = ffsid.cli.ListGroupSubjects(namespace, groupID)
- require.NoError(t, err)
- require.Empty(t, subjects)
-
- subjects, err = ffsid.cli.ListNamespaceSubjects(namespace)
- require.NoError(t, err)
- require.ElementsMatch(t, []util.Uint160{subjAddr}, subjects)
-
- groups, err := ffsid.cli.ListGroups(namespace)
- require.NoError(t, err)
- require.ElementsMatch(t, []*client.Group{{ID: groupID, Name: groupName, Namespace: namespace, KV: map[string]string{}}}, groups)
-
- ffsid.a.await(ffsid.cli.DeleteGroup(namespace, groupID))
- _, err = ffsid.cli.GetGroup(namespace, groupID)
- require.ErrorContains(t, err, "not found")
-
- groups, err = ffsid.cli.ListGroups(namespace)
- require.NoError(t, err)
- require.Empty(t, groups)
-}
-
-type testSubject struct {
- key *keys.PrivateKey
- addr util.Uint160
-}
-
-func TestFrostFSID_Client_Lists(t *testing.T) {
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- namespaces := append([]string{defaultNamespace}, createNamespaces(t, ffsid, 3)...)
-
- subjects := createSubjectsInNS(t, ffsid, namespaces[1], 3)
- subjects = append(subjects, createSubjectsInNS(t, ffsid, namespaces[2], 2)...)
- subjects = append(subjects, createSubjectsInNS(t, ffsid, namespaces[3], 5)...)
-
- groups := createGroupsInNS(t, ffsid, namespaces[0], 1)
- groups = append(groups, createGroupsInNS(t, ffsid, namespaces[1], 2)...)
- groups = append(groups, createGroupsInNS(t, ffsid, namespaces[2], 1)...)
- groups = append(groups, createGroupsInNS(t, ffsid, namespaces[3], 2)...)
-
- addSubjectsToGroups(t, ffsid, groups, subjects)
-
- nsList, err := ffsid.cli.ListNamespaces()
- require.NoError(t, err)
- require.ElementsMatch(t,
- []*client.Namespace{
- {Name: namespaces[0], State: client.Active},
- {Name: namespaces[1], State: client.Active},
- {Name: namespaces[2], State: client.Active},
- {Name: namespaces[3], State: client.Active},
- },
- nsList)
-
- nonEmptyNs, err := ffsid.cli.ListNonEmptyNamespaces()
- require.NoError(t, err)
- require.ElementsMatch(t, namespaces[1:], nonEmptyNs)
-
- checkNamespaceSubjects(t, ffsid.cli, namespaces[0], subjects, 0, 0)
- checkNamespaceSubjects(t, ffsid.cli, namespaces[1], subjects, 0, 3)
- checkNamespaceSubjects(t, ffsid.cli, namespaces[2], subjects, 3, 5)
- checkNamespaceSubjects(t, ffsid.cli, namespaces[3], subjects, 5, 10)
-
- nonEmptyGroups, err := ffsid.cli.ListNonEmptyGroups(namespaces[1])
- require.NoError(t, err)
- require.ElementsMatch(t, []string{groups[2].Name}, nonEmptyGroups)
-
- checkGroupSubjects(t, ffsid.cli, groups[0], subjects, 0, 0)
- checkGroupSubjects(t, ffsid.cli, groups[1], subjects, 0, 0)
- checkGroupSubjects(t, ffsid.cli, groups[2], subjects, 2, 3)
- checkGroupSubjects(t, ffsid.cli, groups[3], subjects, 3, 5)
- checkGroupSubjects(t, ffsid.cli, groups[4], subjects, 6, 8)
- checkGroupSubjects(t, ffsid.cli, groups[5], subjects, 8, 10)
-}
-
-func createSubjectsInNS(t *testing.T, ffsid *testFrostFSIDClientInvoker, ns string, count int) []testSubject {
- subjects := make([]testSubject, count)
-
- tx := ffsid.cli.StartTx()
- for i := range subjects {
- subjects[i].key, subjects[i].addr = newKey(t)
- err := tx.WrapCall(ffsid.cli.CreateSubjectCall(ns, subjects[i].key.PublicKey()))
- require.NoError(t, err)
- }
- ffsid.a.await(ffsid.cli.SendTx(tx))
-
- return subjects
-}
-
-func createGroupsInNS(t *testing.T, ffsid *testFrostFSIDClientInvoker, ns string, count int) []client.Group {
- groups := make([]client.Group, count)
-
- tx := ffsid.cli.StartTx()
- for i := range groups {
- groups[i].Namespace = ns
- groups[i].Name = ns + "/group" + strconv.Itoa(i+1)
-
- err := tx.WrapCall(ffsid.cli.CreateGroupCall(ns, groups[i].Name))
- require.NoError(t, err)
- }
- res := ffsid.a.await(ffsid.cli.SendTx(tx))
-
- ids, err := unwrap.ArrayOfBigInts(makeValidRes(stackitem.NewArray(res.Stack)), nil)
- require.NoError(t, err)
-
- for i, id := range ids {
- groups[i].ID = id.Int64()
- }
-
- return groups
-}
-
-func createNamespaces(t *testing.T, ffsid *testFrostFSIDClientInvoker, count int) []string {
- namespaces := make([]string, count)
-
- tx := ffsid.cli.StartTx()
- for i := range namespaces {
- namespaces[i] = "ns" + strconv.Itoa(i+1)
- err := tx.WrapCall(ffsid.cli.CreateNamespaceCall(namespaces[i]))
- require.NoError(t, err)
- }
- ffsid.a.await(ffsid.cli.SendTx(tx))
-
- return namespaces
-}
-
-func addSubjectsToGroups(t *testing.T, ffsid *testFrostFSIDClientInvoker, groups []client.Group, subjects []testSubject) {
- cli := ffsid.cli
- tx := cli.StartTx()
-
- err := tx.WrapCall(cli.AddSubjectToGroupCall(subjects[2].addr, groups[2].ID))
- require.NoError(t, err)
-
- err = tx.WrapCall(cli.AddSubjectToGroupCall(subjects[3].addr, groups[3].ID))
- require.NoError(t, err)
- err = tx.WrapCall(cli.AddSubjectToGroupCall(subjects[4].addr, groups[3].ID))
- require.NoError(t, err)
-
- ffsid.a.await(cli.SendTx(tx))
-
- // we have to start new tx because of insufficient gas / gas limit exceeded error
- tx = cli.StartTx()
-
- err = tx.WrapCall(cli.AddSubjectToGroupCall(subjects[6].addr, groups[4].ID))
- require.NoError(t, err)
- err = tx.WrapCall(cli.AddSubjectToGroupCall(subjects[7].addr, groups[4].ID))
- require.NoError(t, err)
- err = tx.WrapCall(cli.AddSubjectToGroupCall(subjects[8].addr, groups[5].ID))
- require.NoError(t, err)
- err = tx.WrapCall(cli.AddSubjectToGroupCall(subjects[9].addr, groups[5].ID))
- require.NoError(t, err)
-
- ffsid.a.await(cli.SendTx(tx))
-}
-
-func checkNamespaceSubjects(t *testing.T, cli *client.Client, ns string, subjects []testSubject, start, end int) {
- nsSubjects, err := cli.ListNamespaceSubjects(ns)
- require.NoError(t, err)
- require.ElementsMatch(t, subjSlice(subjects, start, end), nsSubjects)
-}
-
-func checkGroupSubjects(t *testing.T, cli *client.Client, group client.Group, subjects []testSubject, start, end int) {
- groupSubjects, err := cli.ListGroupSubjects(group.Namespace, group.ID)
- require.NoError(t, err)
- require.ElementsMatch(t, subjSlice(subjects, start, end), groupSubjects)
-}
-
-func subjSlice(subjects []testSubject, start, end int) []util.Uint160 {
- res := make([]util.Uint160, 0, end-start)
- for i := start; i < end; i++ {
- res = append(res, subjects[i].addr)
- }
- return res
-}
-
-func TestFrostFSID_Client_UseCaseWithS3GW(t *testing.T) {
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- namespace := "namespace"
- login := "login"
- dataUserKey, dataUserAddr := newKey(t)
- extraDataUserKey, _ := newKey(t)
-
- // admin
- tx := ffsid.cli.StartTx()
- err := tx.WrapCall(ffsid.cli.CreateNamespaceCall(namespace))
- require.NoError(t, err)
- err = tx.WrapCall(ffsid.cli.CreateSubjectCall(namespace, dataUserKey.PublicKey()))
- require.NoError(t, err)
- err = tx.WrapCall(ffsid.cli.SetSubjectNameCall(dataUserAddr, login))
- require.NoError(t, err)
- err = tx.WrapCall(ffsid.cli.AddSubjectKeyCall(dataUserAddr, extraDataUserKey.PublicKey()))
- require.NoError(t, err)
- ffsid.a.await(ffsid.cli.SendTx(tx))
-
- // s3-gw
- subj, err := ffsid.cli.GetSubjectByKey(extraDataUserKey.PublicKey())
- require.NoError(t, err)
- require.Equal(t, login, subj.Name)
- require.True(t, dataUserKey.PublicKey().Equal(subj.PrimaryKey))
- require.Equal(t, namespace, subj.Namespace)
-}
-
-func TestFrostFSID_Client_UseCaseListNSSubjects(t *testing.T) {
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- namespace := "namespace"
- group := "group"
- groupID := int64(1)
-
- tx := ffsid.cli.StartTx()
- err := tx.WrapCall(ffsid.cli.CreateNamespaceCall(namespace))
- require.NoError(t, err)
- err = tx.WrapCall(ffsid.cli.CreateGroupCall(namespace, group))
- require.NoError(t, err)
- ffsid.a.await(ffsid.cli.SendTx(tx))
-
- // admin
-
- subjects := make([]testSubject, 5)
-
- for i := range subjects {
- tx = ffsid.cli.StartTx()
- subjects[i].key, subjects[i].addr = newKey(t)
- err = tx.WrapCall(ffsid.cli.CreateSubjectCall(namespace, subjects[i].key.PublicKey()))
- require.NoError(t, err)
- err = tx.WrapCall(ffsid.cli.SetSubjectNameCall(subjects[i].addr, "login"+strconv.Itoa(i)))
- require.NoError(t, err)
-
- if i > len(subjects)/2 {
- err = tx.WrapCall(ffsid.cli.AddSubjectToGroupCall(subjects[i].addr, groupID))
- require.NoError(t, err)
- }
- ffsid.a.await(ffsid.cli.SendTx(tx))
- }
-
- nsSubjects, err := ffsid.cli.ListNamespaceSubjects(namespace)
- require.NoError(t, err)
-
- res := make([]*client.SubjectExtended, len(nsSubjects))
- for i, subj := range nsSubjects {
- res[i], err = ffsid.cli.GetSubjectExtended(subj)
- require.NoError(t, err)
- }
- prettyPrintExtendedSubjects(res)
-}
-
-func TestFrostFSID_Client_GetSubjectByName(t *testing.T) {
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- key, addr := newKey(t)
- subjName := "name"
-
- tx := ffsid.cli.StartTx()
- err := tx.WrapCall(ffsid.cli.CreateSubjectCall(defaultNamespace, key.PublicKey()))
- require.NoError(t, err)
- err = tx.WrapCall(ffsid.cli.SetSubjectNameCall(addr, subjName))
- require.NoError(t, err)
- ffsid.a.await(ffsid.cli.SendTx(tx))
-
- subj, err := ffsid.cli.GetSubjectByName(defaultNamespace, subjName)
- require.NoError(t, err)
- require.Equal(t, subjName, subj.Name)
- require.True(t, key.PublicKey().Equal(subj.PrimaryKey))
- require.Equal(t, defaultNamespace, subj.Namespace)
-}
-
-func TestFrostFSID_Client_GetGroupByName(t *testing.T) {
- ctx := context.Background()
- ffsid, cancel := initFrostfsIFClientTest(t)
- defer cancel()
-
- groupName := "group"
- txHash, vub, err := ffsid.cli.CreateGroup(defaultNamespace, groupName)
- actGroupID, err := ffsid.cli.ParseGroupID(ffsid.cli.Waiter().WaitCtx(ctx, txHash, vub, err))
- require.NoError(t, err)
-
- group, err := ffsid.cli.GetGroupByName(defaultNamespace, groupName)
- require.NoError(t, err)
- require.Equal(t, actGroupID, group.ID)
- require.Equal(t, defaultNamespace, group.Namespace)
- require.Equal(t, groupName, group.Name)
-}
-
-func prettyPrintExtendedSubjects(subjects []*client.SubjectExtended) {
- for _, subj := range subjects {
- var sb strings.Builder
- sb.WriteString(fmt.Sprintf("login: %s, namespace: %v, groups: [ ", subj.Name, subj.Namespace))
-
- for _, group := range subj.Groups {
- sb.WriteString(group.Namespace + ":" + group.Name + " ")
- }
-
- sb.WriteByte(']')
- fmt.Println(sb.String())
- }
-}
-
-func TestFrostfsID_ConcurrentAddSubjectKey(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- newKey := func(t *testing.T) *keys.PrivateKey {
- pk, err := keys.NewPrivateKey()
- require.NoError(t, err)
- return pk
- }
-
- subjKey := newKey(t)
- subjKeyAddr := subjKey.PublicKey().GetScriptHash()
- invoker := f.OwnerInvoker()
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjKey.PublicKey().Bytes())
-
- additionalKey1 := newKey(t)
- additionalKey2 := newKey(t)
- tx1 := invoker.PrepareInvoke(t, addSubjectKeyMethod, subjKeyAddr, additionalKey1.PublicKey().Bytes())
- tx2 := invoker.PrepareInvoke(t, addSubjectKeyMethod, subjKeyAddr, additionalKey2.PublicKey().Bytes())
-
- invoker.AddBlockCheckHalt(t, tx1, tx2)
-}
diff --git a/tests/frostfsid_test.go b/tests/frostfsid_test.go
index f91865b..4089b9b 100644
--- a/tests/frostfsid_test.go
+++ b/tests/frostfsid_test.go
@@ -1,1142 +1,113 @@
package tests
import (
- "encoding/json"
- "errors"
- "fmt"
+ "bytes"
"path"
+ "sort"
"testing"
- "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
- "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
- "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
+ "git.frostfs.info/TrueCloudLab/frostfs-contract/container"
+ "github.com/mr-tron/base58"
"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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/neotest"
- "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"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
- "github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/require"
)
const frostfsidPath = "../frostfsid"
-const (
- defaultNamespace = ""
- customNamespace = "custom"
-)
-
-const (
- setAdminMethod = "setAdmin"
- getAdminMethod = "getAdmin"
- clearAdminMethod = "clearAdmin"
-
- createSubjectMethod = "createSubject"
- getSubjectMethod = "getSubject"
- listSubjectsMethod = "listSubjects"
- addSubjectKeyMethod = "addSubjectKey"
- removeSubjectKeyMethod = "removeSubjectKey"
- getSubjectByKeyMethod = "getSubjectByKey"
- getSubjectKeyByNameMethod = "getSubjectKeyByName"
- setSubjectNameMethod = "setSubjectName"
- setSubjectKVMethod = "setSubjectKV"
- deleteSubjectKVMethod = "deleteSubjectKV"
- deleteSubjectMethod = "deleteSubject"
-
- createNamespaceMethod = "createNamespace"
- getNamespaceMethod = "getNamespace"
- getNamespaceExtendedMethod = "getNamespaceExtended"
- updateNamespaceMethod = "updateNamespace"
- deleteNamespaceMethod = "deleteNamespace"
- listNamespacesMethod = "listNamespaces"
- listNamespaceSubjectsMethod = "listNamespaceSubjects"
-
- createGroupMethod = "createGroup"
- getGroupMethod = "getGroup"
- getGroupExtendedMethod = "getGroupExtended"
- getGroupIDByNameMethod = "getGroupIDByName"
- setGroupNameMethod = "setGroupName"
- setGroupKVMethod = "setGroupKV"
- deleteGroupKVMethod = "deleteGroupKV"
- listGroupsMethod = "listGroups"
- addSubjectToGroupMethod = "addSubjectToGroup"
- removeSubjectFromGroupMethod = "removeSubjectFromGroup"
- listGroupSubjectsMethod = "listGroupSubjects"
- deleteGroupMethod = "deleteGroup"
-
- nsActiveState = "active"
-)
-
-const (
- frozenState = "frozen"
- purgeState = "purge"
- namespaceNonActive = "namespace is non-active"
- notWitnessedError = "not witnessed"
- notFoundError = "namespace not found"
- cantDeleteNonEmptyNamespceGroupsPresent = "can't delete non-empty namespace: groups still present"
- cantDeleteNonEmptyNamespceUsersPresent = "can't delete non-empty namespace: users still present"
- namespaceShouldBeInPurgeStateError = "namespace should be in 'purge' state for deletion"
-)
-
-type testFrostFSIDInvoker struct {
- e *neotest.Executor
- contractHash util.Uint160
- owner *wallet.Account
-}
-
-func (f *testFrostFSIDInvoker) OwnerInvoker() *neotest.ContractInvoker {
- return f.e.NewInvoker(f.contractHash, neotest.NewSingleSigner(f.owner))
-}
-
-func (f *testFrostFSIDInvoker) CommitteeInvoker() *neotest.ContractInvoker {
- return f.e.CommitteeInvoker(f.contractHash)
-}
-
-func (f *testFrostFSIDInvoker) AnonInvoker(t *testing.T) *neotest.ContractInvoker {
- acc, err := wallet.NewAccount()
- require.NoError(t, err)
-
- return f.e.NewInvoker(f.contractHash, newSigner(t, f.CommitteeInvoker(), acc))
-}
-
-func newSigner(t *testing.T, c *neotest.ContractInvoker, acc *wallet.Account) neotest.Signer {
- amount := int64(100_0000_0000)
-
- tx := c.NewTx(t, []neotest.Signer{c.Validator},
- c.NativeHash(t, nativenames.Gas), "transfer",
- c.Validator.ScriptHash(), acc.Contract.ScriptHash(), amount, nil)
- c.AddNewBlock(t, tx)
- c.CheckHalt(t, tx.Hash())
- return neotest.NewSingleSigner(acc)
-}
-
-func deployFrostFSIDContract(t *testing.T, e *neotest.Executor, contractOwner util.Uint160) util.Uint160 {
- args := make([]any, 5)
- args[0] = contractOwner
+func deployFrostFSIDContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
+ args := make([]interface{}, 5)
+ args[0] = false
+ args[1] = addrNetmap
+ args[2] = addrContainer
c := neotest.CompileFile(t, e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
e.DeployContract(t, c, args)
return c.Hash
}
-func newFrostFSIDInvoker(t *testing.T) *testFrostFSIDInvoker {
+func newFrostFSIDInvoker(t *testing.T) *neotest.ContractInvoker {
e := newExecutor(t)
- acc, err := wallet.NewAccount()
- require.NoError(t, err)
+ ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
+ ctrNetmap := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
+ ctrBalance := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
+ ctrContainer := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
- h := deployFrostFSIDContract(t, e, acc.ScriptHash())
+ e.DeployContract(t, ctrNNS, nil)
+ deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash,
+ container.RegistrationFeeKey, int64(containerFee),
+ container.AliasFeeKey, int64(containerAliasFee))
+ deployBalanceContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
+ deployContainerContract(t, e, ctrNetmap.Hash, ctrBalance.Hash, ctrNNS.Hash)
+ h := deployFrostFSIDContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
+ return e.CommitteeInvoker(h)
+}
- newSigner(t, e.CommitteeInvoker(h), acc)
+func TestFrostFSID_AddKey(t *testing.T) {
+ e := newFrostFSIDInvoker(t)
- return &testFrostFSIDInvoker{
- e: e,
- contractHash: h,
- owner: acc,
+ pubs := make([][]byte, 6)
+ for i := range pubs {
+ p, err := keys.NewPrivateKey()
+ require.NoError(t, err)
+ pubs[i] = p.PublicKey().Bytes()
}
-}
+ acc := e.NewAccount(t)
+ owner, _ := base58.Decode(address.Uint160ToString(acc.ScriptHash()))
+ e.Invoke(t, stackitem.Null{}, "addKey", owner,
+ []interface{}{pubs[0], pubs[1]})
-func TestFrostFSID_ContractOwnersManagement(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- anonInvoker := f.AnonInvoker(t)
- anonInvokerHash := anonInvoker.Signers[0].ScriptHash()
- invoker := f.OwnerInvoker()
- invokerHash := invoker.Signers[0].ScriptHash()
- committeeInvoker := f.CommitteeInvoker()
-
- checkOwner(t, anonInvoker, invokerHash)
-
- anonInvoker.InvokeFail(t, notWitnessedError, createNamespaceMethod, "namespace")
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, "namespace")
-
- t.Run("setAdmin is only allowed for committee", func(t *testing.T) {
- invoker.InvokeFail(t, notWitnessedError, setAdminMethod, anonInvokerHash)
+ sort.Slice(pubs[:2], func(i, j int) bool {
+ return bytes.Compare(pubs[i], pubs[j]) == -1
})
-
- t.Run("replace owner", func(t *testing.T) {
- committeeInvoker.Invoke(t, stackitem.Null{}, setAdminMethod, anonInvokerHash)
- checkOwner(t, anonInvoker, anonInvokerHash)
-
- invoker.InvokeFail(t, notWitnessedError, createNamespaceMethod, "namespace2")
- anonInvoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, "namespace2")
- })
- t.Run("remove owner", func(t *testing.T) {
- committeeInvoker.Invoke(t, stackitem.Null{}, clearAdminMethod)
- checkOwner(t, anonInvoker)
-
- invoker.InvokeFail(t, notWitnessedError, createNamespaceMethod, "namespace3")
- anonInvoker.InvokeFail(t, notWitnessedError, createNamespaceMethod, "namespace3")
- })
-}
-
-func checkOwner(t *testing.T, invoker *neotest.ContractInvoker, owner ...util.Uint160) {
- if len(owner) > 1 {
- require.Fail(t, "invalid testcase")
+ arr := []stackitem.Item{
+ stackitem.NewBuffer(pubs[0]),
+ stackitem.NewBuffer(pubs[1]),
}
+ e.Invoke(t, stackitem.NewArray(arr), "key", owner)
- s, err := invoker.TestInvoke(t, getAdminMethod)
- require.NoError(t, err)
- require.Equal(t, 1, s.Len(), "unexpected number items on stack")
- if len(owner) == 0 {
- _, isMissing := s.Pop().Item().(stackitem.Null)
- require.True(t, isMissing)
- return
- }
+ t.Run("multiple addKey per block", func(t *testing.T) {
+ tx1 := e.PrepareInvoke(t, "addKey", owner, []interface{}{pubs[2]})
+ tx2 := e.PrepareInvoke(t, "addKey", owner, []interface{}{pubs[3], pubs[4]})
+ e.AddNewBlock(t, tx1, tx2)
+ e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
+ e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
- bs, err := s.Pop().Item().TryBytes()
- require.NoError(t, err)
- require.Equal(t, bs, owner[0].BytesBE())
-}
-
-func TestFrostFSID_DefaultNamespace(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- subjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjKeyAddr := subjKey.PublicKey().GetScriptHash()
-
- invoker := f.OwnerInvoker()
-
- groupID := int64(1)
- groupName := "group"
-
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Make(groupID), createGroupMethod, defaultNamespace, groupName)
- invoker.Invoke(t, stackitem.Null{}, addSubjectToGroupMethod, subjKeyAddr, groupID)
- invoker.Invoke(t, stackitem.Null{}, removeSubjectFromGroupMethod, subjKeyAddr, groupID)
- invoker.Invoke(t, stackitem.Null{}, deleteGroupMethod, defaultNamespace, groupID)
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectMethod, subjKeyAddr)
-}
-
-func TestFrostFSID_SubjectManagement(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- subjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjKeyAddr := subjKey.PublicKey().GetScriptHash()
-
- anonInvoker := f.AnonInvoker(t)
- invoker := f.OwnerInvoker()
-
- anonInvoker.InvokeFail(t, notWitnessedError, createSubjectMethod, defaultNamespace, subjKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjKey.PublicKey().Bytes())
- invoker.InvokeFail(t, "already exists", createSubjectMethod, defaultNamespace, subjKey.PublicKey().Bytes())
-
- s, err := anonInvoker.TestInvoke(t, getSubjectMethod, subjKeyAddr)
- require.NoError(t, err)
-
- subj := parseSubject(t, s)
- require.True(t, subjKey.PublicKey().Equal(&subj.PrimaryKey))
-
- t.Run("add subject key", func(t *testing.T) {
- subjNewKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
-
- anonInvoker.InvokeFail(t, notWitnessedError, addSubjectKeyMethod, subjKeyAddr, subjNewKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, addSubjectKeyMethod, subjKeyAddr, subjNewKey.PublicKey().Bytes())
-
- s, err = anonInvoker.TestInvoke(t, getSubjectMethod, subjKeyAddr)
- require.NoError(t, err)
- subj := parseSubject(t, s)
- require.Len(t, subj.AdditionalKeys, 1)
- require.True(t, subjNewKey.PublicKey().Equal(subj.AdditionalKeys[0]))
-
- t.Run("get subject by additional key", func(t *testing.T) {
- s, err = anonInvoker.TestInvoke(t, getSubjectByKeyMethod, subjNewKey.PublicKey().Bytes())
- require.NoError(t, err)
- subj := parseSubject(t, s)
- require.True(t, subjKey.PublicKey().Equal(&subj.PrimaryKey), "keys must be the same")
-
- s, err = anonInvoker.TestInvoke(t, getSubjectByKeyMethod, subjKey.PublicKey().Bytes())
- require.NoError(t, err)
- subj = parseSubject(t, s)
- require.True(t, subjKey.PublicKey().Equal(&subj.PrimaryKey), "keys must be the same")
-
- t.Run("with GetSubject", func(t *testing.T) {
- s, err = anonInvoker.TestInvoke(t, getSubjectMethod, subjKey.PublicKey().GetScriptHash())
- require.NoError(t, err)
- subj = parseSubject(t, s)
- require.True(t, subjKey.PublicKey().Equal(&subj.PrimaryKey), "keys must be the same")
- })
-
- t.Run("remove subject key", func(t *testing.T) {
- anonInvoker.InvokeFail(t, notWitnessedError, removeSubjectKeyMethod, subjKeyAddr, subjNewKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, removeSubjectKeyMethod, subjKeyAddr, subjNewKey.PublicKey().Bytes())
-
- anonInvoker.InvokeFail(t, "not found", getSubjectByKeyMethod, subjNewKey.PublicKey().Bytes())
- })
+ sort.Slice(pubs[:5], func(i, j int) bool {
+ return bytes.Compare(pubs[i], pubs[j]) == -1
})
- })
-
- t.Run("set subject name", func(t *testing.T) {
- login := "some-login"
-
- anonInvoker.InvokeFail(t, notWitnessedError, setSubjectNameMethod, subjKeyAddr, login)
- invoker.Invoke(t, stackitem.Null{}, setSubjectNameMethod, subjKeyAddr, login)
-
- s, err = anonInvoker.TestInvoke(t, getSubjectMethod, subjKeyAddr)
- require.NoError(t, err)
- subj = parseSubject(t, s)
- require.Equal(t, login, subj.Name)
- })
-
- t.Run("set subject KVs", func(t *testing.T) {
- iamPath := "iam/path"
-
- anonInvoker.InvokeFail(t, notWitnessedError, setSubjectKVMethod, subjKeyAddr, client.IAMPathKey, iamPath)
- invoker.Invoke(t, stackitem.Null{}, setSubjectKVMethod, subjKeyAddr, client.IAMPathKey, iamPath)
-
- s, err = anonInvoker.TestInvoke(t, getSubjectMethod, subjKeyAddr)
- require.NoError(t, err)
- subj = parseSubject(t, s)
- require.Equal(t, iamPath, subj.KV[client.IAMPathKey])
-
- anonInvoker.InvokeFail(t, notWitnessedError, deleteSubjectKVMethod, subjKeyAddr, client.IAMPathKey)
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectKVMethod, subjKeyAddr, client.IAMPathKey)
-
- s, err = anonInvoker.TestInvoke(t, getSubjectMethod, subjKeyAddr)
- require.NoError(t, err)
- subj = parseSubject(t, s)
- require.Empty(t, subj.KV)
- })
-
- t.Run("list subjects", func(t *testing.T) {
- newSubjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
-
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, newSubjKey.PublicKey().Bytes())
-
- s, err = anonInvoker.TestInvoke(t, listSubjectsMethod)
- require.NoError(t, err)
-
- addresses, err := unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(readIteratorAll(s))), nil)
- require.NoError(t, err)
- require.Len(t, addresses, 2)
- require.ElementsMatch(t, addresses, []util.Uint160{subjKeyAddr, newSubjKey.PublicKey().GetScriptHash()})
- })
-
- t.Run("subject operations for non-active namespace", func(t *testing.T) {
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, customNamespace)
-
- baseKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- baseAddr, baseBytes := baseKey.PublicKey().GetScriptHash(), baseKey.PublicKey().Bytes()
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
-
- invoker.InvokeFail(t, namespaceNonActive, createSubjectMethod, customNamespace, baseBytes)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, createSubjectMethod, customNamespace, baseBytes)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, "active")
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, customNamespace, baseBytes)
-
- t.Run("addSubjectKey", func(t *testing.T) {
- newSubjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- keyBytes := newSubjKey.PublicKey().Bytes()
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, addSubjectKeyMethod, baseAddr, keyBytes)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, addSubjectKeyMethod, baseAddr, keyBytes)
- })
-
- t.Run("setSubjectKV", func(t *testing.T) {
- const key, val = "key", "val"
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, setSubjectKVMethod, baseAddr, key, val)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, setSubjectKVMethod, baseAddr, key, val)
- })
-
- t.Run("setSubjectName", func(t *testing.T) {
- const login = "testlogin"
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, setSubjectNameMethod, baseAddr, login)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, setSubjectNameMethod, baseAddr, login)
- })
- })
-
- anonInvoker.InvokeFail(t, notWitnessedError, deleteSubjectMethod, subjKeyAddr)
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectMethod, subjKeyAddr)
-
- anonInvoker.InvokeFail(t, "subject not found", getSubjectMethod, subjKeyAddr)
-}
-
-func TestFrostFSIS_SubjectNameRelatedInvariants(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- subjName1 := "subj1"
- subjKey1, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjKeyAddr1 := subjKey1.PublicKey().GetScriptHash()
-
- subjName2 := "subj2"
- subjKey2, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjKeyAddr2 := subjKey2.PublicKey().GetScriptHash()
-
- subjName3 := "subj3"
- subjKey3, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjKeyAddr3 := subjKey3.PublicKey().GetScriptHash()
-
- invoker := f.OwnerInvoker()
-
- ns1, ns2 := "ns1", "ns2"
-
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, ns1)
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, ns2)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, ns1, subjKey1.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, setSubjectNameMethod, subjKeyAddr1, subjName1)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, ns1, subjKey2.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, ns2, subjKey3.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, setSubjectNameMethod, subjKeyAddr3, subjName3)
-
- // Check that we can find public key by name for subj1 (with name)
- // and cannot find key for subj2 (without name)
- s, err := invoker.TestInvoke(t, getSubjectKeyByNameMethod, ns1, subjName1)
- checkPublicKeyResult(t, s, err, subjKey1)
- s, err = invoker.TestInvoke(t, getSubjectKeyByNameMethod, ns1, subjName2)
- checkPublicKeyResult(t, s, err, nil)
-
- // Check that we can find public key for by name for subj2 when we set its name
- invoker.Invoke(t, stackitem.Null{}, setSubjectNameMethod, subjKeyAddr2, subjName2)
- s, err = invoker.TestInvoke(t, getSubjectKeyByNameMethod, ns1, subjName2)
- checkPublicKeyResult(t, s, err, subjKey2)
-
- // Check that we cannot set for second subject name that the first subject has already taken
- invoker.InvokeFail(t, "not available", setSubjectNameMethod, subjKeyAddr2, subjName1)
-
- // Check that we cannot find public key by name for subject that was removed
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectMethod, subjKeyAddr2)
- s, err = invoker.TestInvoke(t, getSubjectKeyByNameMethod, ns1, subjName2)
- checkPublicKeyResult(t, s, err, nil)
-
- // Check that subj3 can have the same name as subj1 if they belong to different namespaces
- // Also check that after subject renaming its key cannot be found by old name
- invoker.Invoke(t, stackitem.Null{}, setSubjectNameMethod, subjKeyAddr3, subjName1)
- s, err = invoker.TestInvoke(t, getSubjectKeyByNameMethod, ns2, subjName1)
- checkPublicKeyResult(t, s, err, subjKey3)
- s, err = invoker.TestInvoke(t, getSubjectKeyByNameMethod, ns2, subjName3)
- checkPublicKeyResult(t, s, err, nil)
-}
-
-func TestFrostFSIS_GroupNameRelatedInvariants(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- groupName1, groupName2 := "group1", "group2"
- groupID1, groupID2 := int64(1), int64(2)
-
- invoker := f.OwnerInvoker()
-
- ns1, ns2 := "ns1", "ns2"
-
- // Create two group
- // Create two namespace.
- // Add these groups to ns1
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, ns1)
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, ns2)
- invoker.Invoke(t, stackitem.Make(groupID1), createGroupMethod, ns1, groupName1)
- invoker.Invoke(t, stackitem.Make(groupID2), createGroupMethod, ns1, groupName2)
-
- // Check that we can find group id by name for group1 in ns1 and not in ns2
- s, err := invoker.TestInvoke(t, getGroupIDByNameMethod, ns1, groupName1)
- checkGroupIDResult(t, s, err, groupID1)
- s, err = invoker.TestInvoke(t, getGroupIDByNameMethod, ns2, groupName1)
- checkGroupIDResult(t, s, err, -1)
-
- // Check that we cannot set for second group name that the first subject has already taken
- invoker.InvokeFail(t, "not available", setGroupNameMethod, ns1, groupID1, groupName2)
-
- // Check that we cannot create group with the same name in namespace, but can in another
- invoker.InvokeFail(t, "not available", createGroupMethod, ns1, groupName2)
- invoker.Invoke(t, stackitem.Make(3), createGroupMethod, ns2, groupName2)
-
- // Check that we cannot find group id by name for group that was removed
- invoker.Invoke(t, stackitem.Null{}, deleteGroupMethod, ns1, groupID2)
- s, err = invoker.TestInvoke(t, getGroupIDByNameMethod, ns1, groupName2)
- checkGroupIDResult(t, s, err, -1)
-
- // Check that we can create group with the name that was freed after deleting
- invoker.Invoke(t, stackitem.Make(4), createGroupMethod, ns1, groupName2)
-
- // Check that after group renaming its id cannot be found by old name
- newGroupName := "new"
- invoker.Invoke(t, stackitem.Null{}, setGroupNameMethod, ns1, groupID1, newGroupName)
- s, err = invoker.TestInvoke(t, getGroupIDByNameMethod, ns1, groupName1)
- checkGroupIDResult(t, s, err, -1)
- s, err = invoker.TestInvoke(t, getGroupIDByNameMethod, ns1, newGroupName)
- checkGroupIDResult(t, s, err, groupID1)
-}
-
-func TestFrostFSID_NamespaceManagement(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- anonInvoker := f.AnonInvoker(t)
- invoker := f.OwnerInvoker()
-
- namespace := "some-namespace"
-
- anonInvoker.InvokeFail(t, notWitnessedError, createNamespaceMethod, namespace)
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, namespace)
- invoker.InvokeFail(t, "already exists", createNamespaceMethod, namespace)
-
- s, err := anonInvoker.TestInvoke(t, getNamespaceMethod, namespace)
- require.NoError(t, err)
-
- ns := parseNamespace(t, s.Pop().Item())
- require.Equal(t, namespace, ns.Name)
- require.Equal(t, nsActiveState, ns.State)
-
- t.Run("add user to namespace", func(t *testing.T) {
- subjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, ns.Name, subjKey.PublicKey().Bytes())
-
- subjName := "name"
- subjAddress := subjKey.PublicKey().GetScriptHash()
- invoker.Invoke(t, stackitem.Null{}, setSubjectNameMethod, subjAddress, subjName)
-
- s, err := anonInvoker.TestInvoke(t, getSubjectMethod, subjAddress)
- require.NoError(t, err)
- subj := parseSubject(t, s)
- require.Equal(t, namespace, subj.Namespace)
-
- t.Run("list namespace subjects", func(t *testing.T) {
- s, err := anonInvoker.TestInvoke(t, listNamespaceSubjectsMethod, namespace)
- require.NoError(t, err)
-
- addresses, err := unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(readIteratorAll(s))), nil)
- require.NoError(t, err)
- require.ElementsMatch(t, addresses, []util.Uint160{subjAddress})
- })
-
- t.Run("get subject key by name", func(t *testing.T) {
- s, err := anonInvoker.TestInvoke(t, getSubjectKeyByNameMethod, namespace, subjName)
- require.NoError(t, err)
-
- foundKey, err := unwrap.PublicKey(makeValidRes(s.Pop().Item()), nil)
- require.NoError(t, err)
- require.Equal(t, subjKey.PublicKey(), foundKey)
- })
-
- t.Run("list namespaces", func(t *testing.T) {
- namespace2 := "some-namespace2"
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, namespace2)
-
- s, err := anonInvoker.TestInvoke(t, listNamespacesMethod)
- require.NoError(t, err)
-
- namespaces := parseNamespaces(t, readIteratorAll(s))
- require.NoError(t, err)
- require.ElementsMatch(t,
- namespaces,
- []Namespace{
- {Name: defaultNamespace, State: nsActiveState},
- {Name: namespace, State: nsActiveState},
- {Name: namespace2, State: nsActiveState},
- })
-
- t.Run("find namespaces with some subjects", func(t *testing.T) {
- for _, ns := range namespaces {
- s, err := anonInvoker.TestInvoke(t, getNamespaceExtendedMethod, ns.Name)
- require.NoError(t, err)
-
- nsExt := parseNamespaceExtended(t, s.Pop().Item())
- if nsExt.SubjectsCount > 0 {
- require.Equal(t, namespace, nsExt.Name)
- require.Equal(t, nsActiveState, nsExt.State)
- }
- }
- })
- })
- })
-
- t.Run("update namespace", func(t *testing.T) {
- anonInvoker.InvokeFail(t, notWitnessedError, updateNamespaceMethod, namespace, "frozen")
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, namespace, "frozen")
- require.NoError(t, err)
-
- s, err = invoker.TestInvoke(t, getNamespaceMethod, namespace)
- require.NoError(t, err)
-
- ns := parseNamespace(t, s.Pop().Item())
- require.Equal(t, namespace, ns.Name)
- require.Equal(t, "frozen", ns.State)
- })
-
- t.Run("delete namespace", func(t *testing.T) {
- namespace3 := "some-namespace3"
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, namespace3)
-
- s, err = invoker.TestInvoke(t, getNamespaceMethod, namespace3)
- require.NoError(t, err)
-
- ns := parseNamespace(t, s.Pop().Item())
- require.Equal(t, namespace3, ns.Name)
-
- t.Run("delete existing namespace not in a 'purge' state", func(t *testing.T) {
- anonInvoker.InvokeFail(t, notWitnessedError, deleteNamespaceMethod, namespace3)
- invoker.InvokeFail(t, namespaceShouldBeInPurgeStateError, deleteNamespaceMethod, namespace3)
- })
-
- subjKey, err := keys.NewPrivateKey()
- subjKeyAddr := subjKey.PublicKey().GetScriptHash()
- require.NoError(t, err)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, ns.Name, subjKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, namespace3, "purge")
-
- t.Run("delete namespace with user fails", func(t *testing.T) {
- invoker.InvokeFail(t, cantDeleteNonEmptyNamespceUsersPresent, deleteNamespaceMethod, namespace3)
- })
-
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectMethod, subjKeyAddr)
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, namespace3, "active")
-
- groupID1 := int64(1)
- groupName1 := "group1"
- invoker.Invoke(t, stackitem.Make(groupID1), createGroupMethod, ns.Name, groupName1)
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, namespace3, "purge")
-
- t.Run("delete namespace with group fails", func(t *testing.T) {
- invoker.InvokeFail(t, cantDeleteNonEmptyNamespceGroupsPresent, deleteNamespaceMethod, namespace3)
- })
-
- invoker.Invoke(t, stackitem.Null{}, deleteGroupMethod, ns.Name, groupID1)
-
- t.Run("delete existing namespace", func(t *testing.T) {
- anonInvoker.InvokeFail(t, notWitnessedError, deleteNamespaceMethod, namespace3)
- invoker.Invoke(t, stackitem.Null{}, deleteNamespaceMethod, namespace3)
- invoker.InvokeFail(t, notFoundError, getNamespaceMethod, namespace3)
- })
-
- t.Run("delete non-existing namespace", func(t *testing.T) {
- nonExistingNamespace := "non-existing-namespace"
- invoker.InvokeFail(t, notFoundError, getNamespaceMethod, nonExistingNamespace)
- anonInvoker.InvokeFail(t, notWitnessedError, deleteNamespaceMethod, nonExistingNamespace)
- invoker.Invoke(t, stackitem.Null{}, deleteNamespaceMethod, nonExistingNamespace)
- })
- })
-}
-
-func TestFrostFSID_GroupManagement(t *testing.T) {
- f := newFrostFSIDInvoker(t)
-
- anonInvoker := f.AnonInvoker(t)
- invoker := f.OwnerInvoker()
-
- nsName := "namespace"
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, nsName)
-
- groupID := int64(1)
- groupName := "group"
- anonInvoker.InvokeFail(t, notWitnessedError, createGroupMethod, nsName, groupName)
- invoker.Invoke(t, stackitem.Make(groupID), createGroupMethod, nsName, groupName)
-
- s, err := anonInvoker.TestInvoke(t, getGroupMethod, nsName, groupID)
- require.NoError(t, err)
- group := parseGroup(t, s.Pop().Item())
- require.Equal(t, groupID, group.ID)
- require.Equal(t, groupName, group.Name)
-
- s, err = anonInvoker.TestInvoke(t, listGroupsMethod, nsName)
- require.NoError(t, err)
- groups := parseGroups(t, readIteratorAll(s))
- require.ElementsMatch(t, groups, []Group{{ID: groupID, Name: groupName, Namespace: nsName}})
-
- t.Run("add subjects to group", func(t *testing.T) {
- subjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, nsName, subjKey.PublicKey().Bytes())
-
- subjAddress := subjKey.PublicKey().GetScriptHash()
- anonInvoker.InvokeFail(t, "not witnessed", addSubjectToGroupMethod, subjAddress, groupID)
- invoker.Invoke(t, stackitem.Null{}, addSubjectToGroupMethod, subjAddress, groupID)
-
- t.Run("list group subjects", func(t *testing.T) {
- s, err = anonInvoker.TestInvoke(t, listGroupSubjectsMethod, nsName, groupID)
- require.NoError(t, err)
-
- addresses, err := unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(readIteratorAll(s))), nil)
- require.NoError(t, err)
- require.ElementsMatch(t, addresses, []util.Uint160{subjAddress})
-
- anonInvoker.InvokeFail(t, "not witnessed", removeSubjectFromGroupMethod, subjAddress, groupID)
- invoker.Invoke(t, stackitem.Null{}, removeSubjectFromGroupMethod, subjAddress, groupID)
-
- s, err = anonInvoker.TestInvoke(t, listGroupSubjectsMethod, nsName, groupID)
- require.NoError(t, err)
-
- addresses, err = unwrap.ArrayOfUint160(makeValidRes(stackitem.NewArray(readIteratorAll(s))), nil)
- require.NoError(t, err)
- require.Empty(t, addresses)
-
- t.Run("get group extended", func(t *testing.T) {
- subjectsCount := 10
- for i := 0; i < subjectsCount; i++ {
- subjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, nsName, subjKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, addSubjectToGroupMethod, subjKey.PublicKey().GetScriptHash(), groupID)
- }
-
- s, err = anonInvoker.TestInvoke(t, getGroupExtendedMethod, nsName, groupID)
- require.NoError(t, err)
- groupExt := parseGroupExtended(t, s.Pop().Item())
- require.Equal(t, groupID, groupExt.ID)
- require.Equal(t, groupName, groupExt.Name)
- require.Empty(t, groupExt.KV)
- require.EqualValues(t, subjectsCount, groupExt.SubjectsCount)
- })
- })
- })
-
- t.Run("set group name", func(t *testing.T) {
- newGroupName := "new-name"
-
- anonInvoker.InvokeFail(t, notWitnessedError, setGroupNameMethod, nsName, groupID, newGroupName)
- invoker.Invoke(t, stackitem.Null{}, setGroupNameMethod, nsName, groupID, newGroupName)
-
- s, err = anonInvoker.TestInvoke(t, getGroupIDByNameMethod, nsName, newGroupName)
- require.NoError(t, err)
- require.Equal(t, groupID, s.Pop().BigInt().Int64())
-
- s, err = anonInvoker.TestInvoke(t, getGroupMethod, nsName, groupID)
- require.NoError(t, err)
- group = parseGroup(t, s.Pop().Item())
- require.Equal(t, newGroupName, group.Name)
- })
-
- t.Run("set group KVs", func(t *testing.T) {
- iamARN := "arn"
-
- anonInvoker.InvokeFail(t, notWitnessedError, setGroupKVMethod, nsName, groupID, client.IAMARNKey, iamARN)
- invoker.Invoke(t, stackitem.Null{}, setGroupKVMethod, nsName, groupID, client.IAMARNKey, iamARN)
-
- s, err = anonInvoker.TestInvoke(t, getGroupMethod, nsName, groupID)
- require.NoError(t, err)
- group = parseGroup(t, s.Pop().Item())
- require.Equal(t, iamARN, group.KV[client.IAMARNKey])
-
- anonInvoker.InvokeFail(t, notWitnessedError, deleteGroupKVMethod, nsName, groupID, client.IAMARNKey)
- invoker.Invoke(t, stackitem.Null{}, deleteGroupKVMethod, nsName, groupID, client.IAMARNKey)
-
- s, err = anonInvoker.TestInvoke(t, getGroupMethod, nsName, groupID)
- require.NoError(t, err)
- group = parseGroup(t, s.Pop().Item())
- require.Empty(t, group.KV)
- })
-
- t.Run("delete group", func(t *testing.T) {
- anonInvoker.InvokeFail(t, notWitnessedError, deleteGroupMethod, nsName, groupID)
- invoker.Invoke(t, stackitem.Null{}, deleteGroupMethod, nsName, groupID)
-
- anonInvoker.InvokeFail(t, "group not found", getGroupMethod, nsName, groupID)
-
- s, err = anonInvoker.TestInvoke(t, listGroupsMethod, nsName)
- require.NoError(t, err)
- groups := parseGroups(t, readIteratorAll(s))
- require.Empty(t, groups)
- })
-
- t.Run("operations with non-active namespace", func(t *testing.T) {
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, customNamespace)
-
- customGroupID := int64(2)
- customGroupName := "customGroup"
- invoker.Invoke(t, stackitem.Make(customGroupID), createGroupMethod, customNamespace, customGroupName)
-
- subjKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, customNamespace, subjKey.PublicKey().Bytes())
-
- t.Run("createGroup", func(t *testing.T) {
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, createGroupMethod, customNamespace, customGroupName)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, createGroupMethod, customNamespace, customGroupName)
- })
-
- t.Run("addSubjectToGroup", func(t *testing.T) {
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, addSubjectToGroupMethod, subjKey.PublicKey().GetScriptHash(), customGroupID)
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, addSubjectToGroupMethod, subjKey.PublicKey().GetScriptHash(), customGroupID)
- })
-
- t.Run("setGroupKV", func(t *testing.T) {
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, setGroupKVMethod, customNamespace, customGroupID, client.IAMARNKey, "arn")
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, setGroupKVMethod, customNamespace, customGroupID, client.IAMARNKey, "arn")
- })
-
- t.Run("setGroupName", func(t *testing.T) {
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, frozenState)
- invoker.InvokeFail(t, namespaceNonActive, setGroupNameMethod, customNamespace, customGroupID, "newCustomGroup")
-
- invoker.Invoke(t, stackitem.Null{}, updateNamespaceMethod, customNamespace, purgeState)
- invoker.InvokeFail(t, namespaceNonActive, setGroupNameMethod, customNamespace, customGroupID, "newCustomGroup")
- })
- })
-}
-
-func TestAdditionalKeyFromPrimarySubject(t *testing.T) {
- f := newFrostFSIDInvoker(t)
- invoker := f.OwnerInvoker()
-
- subjAPrimaryKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjAKeyAddr := subjAPrimaryKey.PublicKey().GetScriptHash()
-
- subjBPrimaryKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
- subjBKeyAddr := subjBPrimaryKey.PublicKey().GetScriptHash()
-
- subjCPrimaryKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
-
- subjDPrimaryKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
-
- subjFPrimaryKey, err := keys.NewPrivateKey()
- require.NoError(t, err)
-
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjAPrimaryKey.PublicKey().Bytes())
-
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjBPrimaryKey.PublicKey().Bytes())
-
- invoker.InvokeFail(t, "key is occupied", addSubjectKeyMethod, subjBKeyAddr, subjAPrimaryKey.PublicKey().Bytes())
-
- invoker.Invoke(t, stackitem.Null{}, addSubjectKeyMethod, subjAKeyAddr, subjCPrimaryKey.PublicKey().Bytes())
- invoker.InvokeFail(t, "key is occupied", addSubjectKeyMethod, subjBKeyAddr, subjCPrimaryKey.PublicKey().Bytes())
-
- invoker.Invoke(t, stackitem.Null{}, addSubjectKeyMethod, subjAKeyAddr, subjDPrimaryKey.PublicKey().Bytes())
-
- invoker.InvokeFail(t, "key is occupied", addSubjectKeyMethod, subjBKeyAddr, subjDPrimaryKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, removeSubjectKeyMethod, subjAKeyAddr, subjDPrimaryKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, addSubjectKeyMethod, subjBKeyAddr, subjDPrimaryKey.PublicKey().Bytes())
-
- invoker.InvokeFail(t, "key is occupied", addSubjectKeyMethod, subjAKeyAddr, subjDPrimaryKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectMethod, subjBKeyAddr)
- invoker.Invoke(t, stackitem.Null{}, addSubjectKeyMethod, subjAKeyAddr, subjDPrimaryKey.PublicKey().Bytes())
-
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjFPrimaryKey.PublicKey().Bytes())
- invoker.Invoke(t, stackitem.Null{}, deleteSubjectMethod, subjFPrimaryKey.PublicKey().GetScriptHash())
- invoker.Invoke(t, stackitem.Null{}, createSubjectMethod, defaultNamespace, subjFPrimaryKey.PublicKey().Bytes())
-}
-
-func TestFrostFSIS_GroupsAfterUpdate(t *testing.T) {
- countNamesepce := 2
- f := newFrostFSIDInvoker(t)
- invoker := f.OwnerInvoker()
-
- groupid := int64(1)
-
- for i := range countNamesepce {
- namespace := fmt.Sprintf("nm_%d", i)
- invoker.Invoke(t, stackitem.Null{}, createNamespaceMethod, namespace)
- }
-
- for i := range 5 {
- namespace := fmt.Sprintf("nm_%d", i%2)
- groupName := fmt.Sprintf("group_%d", groupid)
-
- invoker.Invoke(t, stackitem.Make(groupid), createGroupMethod, namespace, groupName)
- s, err := invoker.TestInvoke(t, getGroupIDByNameMethod, namespace, groupName)
- checkGroupIDResult(t, s, err, groupid)
- groupid++
- }
-
- args := make([]any, 2)
- args[0] = f.owner.ScriptHash()
- args[1] = 21 * 1_000
-
- c := neotest.CompileFile(t, f.e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
-
- nef, err := c.NEF.Bytes()
- require.NoError(t, err)
-
- manifest, err := json.Marshal(c.Manifest)
- require.NoError(t, err)
-
- f.CommitteeInvoker().Invoke(t, stackitem.Null{}, "update", nef, manifest, args)
-
- for i := range 5 {
- namespace := fmt.Sprintf("nm_%d", i%2)
- groupName := fmt.Sprintf("group_%d", groupid)
-
- invoker.Invoke(t, stackitem.Make(groupid), createGroupMethod, namespace, groupName)
- s, err := invoker.TestInvoke(t, getGroupIDByNameMethod, namespace, groupName)
- checkGroupIDResult(t, s, err, groupid)
- groupid++
- }
-}
-
-func checkPublicKeyResult(t *testing.T, s *vm.Stack, err error, key *keys.PrivateKey) {
- if key == nil {
- require.ErrorContains(t, err, "not found")
- return
- }
-
- require.NoError(t, err)
- foundKey, err := unwrap.PublicKey(makeValidRes(s.Pop().Item()), nil)
- require.NoError(t, err)
- require.Equal(t, key.PublicKey(), foundKey)
-}
-
-func checkGroupIDResult(t *testing.T, s *vm.Stack, err error, groupID int64) {
- if groupID == -1 {
- require.ErrorContains(t, err, "not found")
- return
- }
-
- require.NoError(t, err)
- foundGroupID, err := unwrap.Int64(makeValidRes(s.Pop().Item()), nil)
- require.NoError(t, err)
- require.Equal(t, groupID, foundGroupID)
-}
-
-func readIteratorAll(s *vm.Stack) []stackitem.Item {
- iter := s.Pop().Value().(*storage.Iterator)
-
- stackItems := make([]stackitem.Item, 0)
- for iter.Next() {
- stackItems = append(stackItems, iter.Value())
- }
-
- return stackItems
-}
-
-type Subject struct {
- PrimaryKey keys.PublicKey
- AdditionalKeys keys.PublicKeys
- Namespace string
- Name string
- KV map[string]string
-}
-
-func parseSubject(t *testing.T, s *vm.Stack) Subject {
- var subj Subject
-
- subjStruct := s.Pop().Array()
- require.Len(t, subjStruct, 5)
-
- pkBytes, err := subjStruct[0].TryBytes()
- require.NoError(t, err)
- err = subj.PrimaryKey.DecodeBytes(pkBytes)
- require.NoError(t, err)
-
- if !subjStruct[1].Equals(stackitem.Null{}) {
- subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(subjStruct[1]), nil)
- require.NoError(t, err)
- }
-
- nsBytes, err := subjStruct[2].TryBytes()
- require.NoError(t, err)
- subj.Namespace = string(nsBytes)
-
- nameBytes, err := subjStruct[3].TryBytes()
- require.NoError(t, err)
- subj.Name = string(nameBytes)
-
- subj.KV, err = parseMap(subjStruct[4])
- require.NoError(t, err)
-
- return subj
-}
-
-func parseMap(item stackitem.Item) (map[string]string, error) {
- if item.Equals(stackitem.Null{}) {
- return nil, nil
- }
-
- metaMap, err := unwrap.Map(makeValidRes(item), nil)
- if err != nil {
- return nil, err
- }
-
- meta, ok := metaMap.Value().([]stackitem.MapElement)
- if !ok {
- return nil, errors.New("invalid map type")
- }
-
- res := make(map[string]string, len(meta))
- for _, element := range meta {
- key, err := element.Key.TryBytes()
- if err != nil {
- return nil, err
+ arr = []stackitem.Item{
+ stackitem.NewBuffer(pubs[0]),
+ stackitem.NewBuffer(pubs[1]),
+ stackitem.NewBuffer(pubs[2]),
+ stackitem.NewBuffer(pubs[3]),
+ stackitem.NewBuffer(pubs[4]),
}
- val, err := element.Value.TryBytes()
- if err != nil {
- return nil, err
- }
- res[string(key)] = string(val)
+ e.Invoke(t, stackitem.NewArray(arr), "key", owner)
+ })
+
+ e.Invoke(t, stackitem.Null{}, "removeKey", owner,
+ []interface{}{pubs[1], pubs[5]})
+ arr = []stackitem.Item{
+ stackitem.NewBuffer(pubs[0]),
+ stackitem.NewBuffer(pubs[2]),
+ stackitem.NewBuffer(pubs[3]),
+ stackitem.NewBuffer(pubs[4]),
}
+ e.Invoke(t, stackitem.NewArray(arr), "key", owner)
- return res, nil
-}
-
-type Namespace struct {
- Name string
- State string
-}
-
-type NamespaceExtended struct {
- Name string
- State string
- SubjectsCount int64
- GroupsCount int64
-}
-
-func parseNamespace(t *testing.T, item stackitem.Item) Namespace {
- var ns Namespace
-
- subjStruct := item.Value().([]stackitem.Item)
- require.Len(t, subjStruct, 2)
-
- nameBytes, err := subjStruct[0].TryBytes()
- require.NoError(t, err)
- ns.Name = string(nameBytes)
-
- stateBytes, err := subjStruct[1].TryBytes()
- require.NoError(t, err)
- ns.State = string(stateBytes)
-
- return ns
-}
-
-func parseNamespaceExtended(t *testing.T, item stackitem.Item) NamespaceExtended {
- var ns NamespaceExtended
-
- subjStruct := item.Value().([]stackitem.Item)
- require.Len(t, subjStruct, 4)
-
- nameBytes, err := subjStruct[0].TryBytes()
- require.NoError(t, err)
- ns.Name = string(nameBytes)
-
- groupCountInt, err := subjStruct[1].TryInteger()
- require.NoError(t, err)
- ns.GroupsCount = groupCountInt.Int64()
-
- subjectsCountInt, err := subjStruct[2].TryInteger()
- require.NoError(t, err)
- ns.SubjectsCount = subjectsCountInt.Int64()
-
- stateBytes, err := subjStruct[3].TryBytes()
- require.NoError(t, err)
- ns.State = string(stateBytes)
-
- return ns
-}
-
-func parseNamespaces(t *testing.T, items []stackitem.Item) []Namespace {
- res := make([]Namespace, len(items))
-
- for i := 0; i < len(items); i++ {
- res[i] = parseNamespace(t, items[i])
- }
-
- return res
-}
-
-type Group struct {
- ID int64
- Name string
- Namespace string
- KV map[string]string
-}
-
-type GroupExtended struct {
- ID int64
- Name string
- Namespace string
- KV map[string]string
- SubjectsCount int64
-}
-
-func parseGroup(t *testing.T, item stackitem.Item) Group {
- var group Group
-
- subjStruct := item.Value().([]stackitem.Item)
- require.Len(t, subjStruct, 4)
-
- groupID, err := subjStruct[0].TryInteger()
- require.NoError(t, err)
- group.ID = groupID.Int64()
-
- nameBytes, err := subjStruct[1].TryBytes()
- require.NoError(t, err)
- group.Name = string(nameBytes)
-
- namespaceBytes, err := subjStruct[2].TryBytes()
- require.NoError(t, err)
- group.Namespace = string(namespaceBytes)
-
- group.KV, err = parseMap(subjStruct[3])
- require.NoError(t, err)
-
- return group
-}
-
-func parseGroupExtended(t *testing.T, item stackitem.Item) GroupExtended {
- var gr GroupExtended
-
- subjStruct := item.Value().([]stackitem.Item)
- require.Len(t, subjStruct, 5)
-
- groupID, err := subjStruct[0].TryInteger()
- require.NoError(t, err)
- gr.ID = groupID.Int64()
-
- nameBytes, err := subjStruct[1].TryBytes()
- require.NoError(t, err)
- gr.Name = string(nameBytes)
-
- namespaceBytes, err := subjStruct[2].TryBytes()
- require.NoError(t, err)
- gr.Namespace = string(namespaceBytes)
-
- gr.KV, err = parseMap(subjStruct[3])
- require.NoError(t, err)
-
- subjectsCountInt, err := subjStruct[4].TryInteger()
- require.NoError(t, err)
- gr.SubjectsCount = subjectsCountInt.Int64()
-
- return gr
-}
-
-func parseGroups(t *testing.T, items []stackitem.Item) []Group {
- res := make([]Group, len(items))
-
- for i := 0; i < len(items); i++ {
- res[i] = parseGroup(t, items[i])
- }
-
- return res
-}
-
-func makeValidRes(item stackitem.Item) *result.Invoke {
- return &result.Invoke{
- Stack: []stackitem.Item{item},
- State: vmstate.Halt.String(),
- }
+ t.Run("multiple removeKey per block", func(t *testing.T) {
+ tx1 := e.PrepareInvoke(t, "removeKey", owner, []interface{}{pubs[2]})
+ tx2 := e.PrepareInvoke(t, "removeKey", owner, []interface{}{pubs[0], pubs[4]})
+ e.AddNewBlock(t, tx1, tx2)
+ e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
+ e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
+
+ arr = []stackitem.Item{stackitem.NewBuffer(pubs[3])}
+ e.Invoke(t, stackitem.NewArray(arr), "key", owner)
+ })
}
diff --git a/tests/netmap_test.go b/tests/netmap_test.go
index a2f7ae4..4c08c0f 100644
--- a/tests/netmap_test.go
+++ b/tests/netmap_test.go
@@ -20,22 +20,23 @@ import (
const netmapPath = "../netmap"
-func deployNetmapContract(t *testing.T, e *neotest.Executor, addrBalance, addrContainer util.Uint160, config ...any) util.Uint160 {
+func deployNetmapContract(t *testing.T, e *neotest.Executor, addrBalance, addrContainer util.Uint160, config ...interface{}) util.Uint160 {
_, pubs, ok := vm.ParseMultiSigContract(e.Committee.Script())
require.True(t, ok)
- args := make([]any, 4)
- args[0] = addrBalance
- args[1] = addrContainer
- args[2] = []any{pubs[0]}
- args[3] = append([]any{}, config...)
+ args := make([]interface{}, 5)
+ args[0] = false
+ args[1] = addrBalance
+ args[2] = addrContainer
+ args[3] = []interface{}{pubs[0]}
+ args[4] = append([]interface{}{}, config...)
c := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
e.DeployContract(t, c, args)
return c.Hash
}
-func newNetmapInvoker(t *testing.T, config ...any) *neotest.ContractInvoker {
+func newNetmapInvoker(t *testing.T, config ...interface{}) *neotest.ContractInvoker {
e := newExecutor(t)
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
diff --git a/tests/nns_test.go b/tests/nns_test.go
index 24f5761..1b738d9 100644
--- a/tests/nns_test.go
+++ b/tests/nns_test.go
@@ -4,19 +4,14 @@ import (
"fmt"
"math/big"
"path"
+ "strings"
"testing"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
- "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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/neotest"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
- "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/require"
)
@@ -24,7 +19,8 @@ const nnsPath = "../nns"
const msPerYear = 365 * 24 * time.Hour / time.Millisecond
-func deployNNS(t *testing.T, e *neotest.Executor, addRoot bool) *neotest.ContractInvoker {
+func newNNSInvoker(t *testing.T, addRoot bool) *neotest.ContractInvoker {
+ e := newExecutor(t)
ctr := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
e.DeployContract(t, ctr, nil)
@@ -34,33 +30,11 @@ func deployNNS(t *testing.T, e *neotest.Executor, addRoot bool) *neotest.Contrac
refresh, retry, expire, ttl := int64(101), int64(102), int64(msPerYear/1000*100), int64(104)
c.Invoke(t, true, "register",
"com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
}
return c
}
-func newNNSInvoker(t *testing.T, addRoot bool) *neotest.ContractInvoker {
- e := newExecutor(t)
- return deployNNS(t, e, addRoot)
-}
-
-func newNNSInvokerWithFrostfsID(t *testing.T, addRoot bool) (*neotest.ContractInvoker, *neotest.ContractInvoker) {
- e := newExecutor(t)
- c := deployNNS(t, e, addRoot)
-
- frostfdID := deployFrostFSIDContract(t, e, e.CommitteeHash)
- c.Invoke(t, true, "register",
- nns.FrostfsIDNNSName, c.CommitteeHash,
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c.Invoke(t, stackitem.Null{}, "addRecord",
- nns.FrostfsIDNNSName, int64(nns.TXT), frostfdID.StringLE())
-
- c.Invoke(t, stackitem.Null{}, "addRecord",
- nns.FrostfsIDNNSName, int64(nns.TXT), address.Uint160ToString(frostfdID))
- return e.NewInvoker(c.Hash), e.CommitteeInvoker(frostfdID)
-}
-
func TestNNSGeneric(t *testing.T) {
c := newNNSInvoker(t, false)
@@ -76,40 +50,21 @@ func TestNNSRegisterTLD(t *testing.T) {
c.InvokeFail(t, "invalid domain name format", "register",
"0com", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
- c.InvokeFail(t, "invalid fragment '0com'", "register",
- "0com", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
+ "email@nspcc.ru", refresh, retry, expire, ttl)
acc := c.NewAccount(t)
cAcc := c.WithSigners(acc)
cAcc.InvokeFail(t, "not witnessed by committee", "register",
"com", acc.ScriptHash(),
- "email@frostfs.info", refresh, retry, expire, ttl)
-
- t.Run("size checks", func(t *testing.T) {
- c.Invoke(t, true, "register",
- "ns", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
-
- c.InvokeFail(t, "invalid domain name format", "register",
- "x", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
- c.InvokeFail(t, "domain name too short", "register",
- "x", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
- c.InvokeFail(t, "domain name too long", "register",
- getTooLongDomainName(255), c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
- })
+ "email@nspcc.ru", refresh, retry, expire, ttl)
c.Invoke(t, true, "register",
"com", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
+ "email@nspcc.ru", refresh, retry, expire, ttl)
c.InvokeFail(t, "TLD already exists", "register",
"com", c.CommitteeHash,
- "email@frostfs.info", refresh, retry, expire, ttl)
+ "email@nspcc.ru", refresh, retry, expire, ttl)
}
func TestNNSRegister(t *testing.T) {
@@ -120,70 +75,39 @@ func TestNNSRegister(t *testing.T) {
c1 := c.WithSigners(c.Committee, accTop)
c1.Invoke(t, true, "register",
"com", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, true, "register",
- "aa.bb.zz", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.InvokeFail(t, "TLD already exists", "register",
- "zz", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, true, "register",
- "xx.bb.zz", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
acc := c.NewAccount(t)
c2 := c.WithSigners(c.Committee, acc)
c2.InvokeFail(t, "not witnessed by admin", "register",
"testdomain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c3 := c.WithSigners(accTop, acc)
t.Run("domain names with hyphen", func(t *testing.T) {
c3.InvokeFail(t, "invalid domain name format", "register",
"-testdomain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
- c3.InvokeFail(t, "invalid fragment '-testdomain'", "register",
- "-testdomain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c3.InvokeFail(t, "invalid domain name format", "register",
"testdomain-.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
- c3.InvokeFail(t, "invalid fragment 'testdomain-'", "register",
- "testdomain-.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c3.Invoke(t, true, "register",
"test-domain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
})
- expected := stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("testdomain.com")),
- })
- tx := c3.Invoke(t, true, "register",
+ c3.Invoke(t, true, "register",
"testdomain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
- c.CheckTxNotificationEvent(t, tx, -1, state.NotificationEvent{ScriptHash: c.Hash, Name: "RegisterDomain", Item: expected})
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
b := c.TopBlock(t)
- expected = stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
- []byte(fmt.Sprintf("testdomain.com myemail@frostfs.info %d %d %d %d %d",
+ expected := stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
+ []byte(fmt.Sprintf("testdomain.com myemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.SOA))
cAcc := c.WithSigners(acc)
-
- expected = stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("testdomain.com")),
- stackitem.NewBigInteger(big.NewInt(int64(nns.TXT))),
- })
- tx = cAcc.Invoke(t, stackitem.Null{}, "addRecord",
+ cAcc.Invoke(t, stackitem.Null{}, "addRecord",
"testdomain.com", int64(nns.TXT), "first TXT record")
- c.CheckTxNotificationEvent(t, tx, 0, state.NotificationEvent{ScriptHash: c.Hash, Name: "AddRecord", Item: expected})
-
cAcc.InvokeFail(t, "record already exists", "addRecord",
"testdomain.com", int64(nns.TXT), "first TXT record")
cAcc.Invoke(t, stackitem.Null{}, "addRecord",
@@ -191,243 +115,16 @@ func TestNNSRegister(t *testing.T) {
expected = stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte("first TXT record")),
- stackitem.NewByteArray([]byte("second TXT record")),
- })
+ stackitem.NewByteArray([]byte("second TXT record"))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
- expected = stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("testdomain.com")),
- stackitem.NewBigInteger(big.NewInt(int64(nns.TXT))),
- })
- tx = cAcc.Invoke(t, stackitem.Null{}, "setRecord",
+ cAcc.Invoke(t, stackitem.Null{}, "setRecord",
"testdomain.com", int64(nns.TXT), int64(0), "replaced first")
- c.CheckTxNotificationEvent(t, tx, 0, state.NotificationEvent{ScriptHash: c.Hash, Name: "AddRecord", Item: expected})
expected = stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte("replaced first")),
- stackitem.NewByteArray([]byte("second TXT record")),
- })
+ stackitem.NewByteArray([]byte("second TXT record"))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
-
- tx = cAcc.Invoke(t, stackitem.Null{}, "deleteRecords", "testdomain.com", int64(nns.TXT))
- expected = stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("testdomain.com")),
- stackitem.NewBigInteger(big.NewInt(int64(nns.TXT))),
- })
- c.CheckTxNotificationEvent(t, tx, 0, state.NotificationEvent{ScriptHash: c.Hash, Name: "DeleteRecords", Item: expected})
-
- c.Invoke(t, stackitem.Null{}, "getRecords", "testdomain.com", int64(nns.TXT))
-
- cAcc.Invoke(t, stackitem.Null{}, "addRecord",
- "testdomain.com", int64(nns.TXT), "rec1")
-
- cAcc.Invoke(t, stackitem.Null{}, "addRecord",
- "testdomain.com", int64(nns.TXT), "rec2")
-
- cAcc.Invoke(t, stackitem.Null{}, "addRecord",
- "testdomain.com", int64(nns.TXT), "rec3")
-
- cAcc.Invoke(t, stackitem.Null{}, "addRecord",
- "testdomain.com", int64(nns.TXT), "rec4")
-
- cAcc.Invoke(t, false, "deleteRecord",
- "testdomain.com", int64(nns.TXT), "rec9999")
-
- cAcc.Invoke(t, true, "deleteRecord",
- "testdomain.com", int64(nns.TXT), "rec1")
-
- expected = stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("rec2")),
- stackitem.NewByteArray([]byte("rec3")),
- stackitem.NewByteArray([]byte("rec4")),
- })
- c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
-
- cAcc.Invoke(t, true, "deleteRecord",
- "testdomain.com", int64(nns.TXT), "rec4")
-
- cAcc.Invoke(t, true, "deleteRecord",
- "testdomain.com", int64(nns.TXT), "rec2")
-
- expected = stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("rec3")),
- })
- c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
-
- cAcc.Invoke(t, true, "deleteRecord",
- "testdomain.com", int64(nns.TXT), "rec3")
-
- c.Invoke(t, stackitem.Null{}, "getRecords", "testdomain.com", int64(nns.TXT))
-
- tx = cAcc.Invoke(t, stackitem.Null{}, "deleteDomain", "testdomain.com")
- expected = stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("testdomain.com")),
- stackitem.NewBigInteger(big.NewInt(int64(nns.CNAME))),
- })
- c.CheckTxNotificationEvent(t, tx, 0, state.NotificationEvent{ScriptHash: c.Hash, Name: "DeleteRecords", Item: expected})
-
- expected = stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray([]byte("testdomain.com"))})
- c.CheckTxNotificationEvent(t, tx, 4, state.NotificationEvent{ScriptHash: c.Hash, Name: "DeleteDomain", Item: expected})
-
- c.Invoke(t, stackitem.Null{}, "getRecords", "testdomain.com", int64(nns.SOA))
-}
-
-func TestDeleteRecords_SubdomainNoRegister(t *testing.T) {
- c := newNNSInvoker(t, true)
-
- refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
- c.Invoke(t, true, "register",
- "test.com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- checkRecords := func(t *testing.T, domain string, typ nns.RecordType, expected ...string) {
- s, err := c.TestInvoke(t, "getRecords", domain, int64(typ))
- require.NoError(t, err)
-
- if len(expected) == 0 {
- _, ok := s.Pop().Item().(stackitem.Null)
- require.True(t, ok, "expected 0 records")
- return
- }
-
- arr, ok := s.Pop().Value().([]stackitem.Item)
- require.True(t, ok, "expected an array '%s' %d", domain, typ)
-
- actual := make([]string, len(arr))
- for i := range actual {
- b, err := arr[i].TryBytes()
- require.NoError(t, err)
- actual[i] = string(b)
- }
-
- require.ElementsMatch(t, expected, actual)
- }
-
- c.Invoke(t, stackitem.Null{}, "addRecord", "a.test.com", int64(nns.TXT), "recA1")
- c.Invoke(t, stackitem.Null{}, "addRecord", "a.test.com", int64(nns.TXT), "recA2")
- c.Invoke(t, stackitem.Null{}, "addRecord", "b.test.com", int64(nns.TXT), "recB")
- c.Invoke(t, stackitem.Null{}, "addRecord", "test.com", int64(nns.TXT), "recTop")
-
- { // Delete subdomain records.
- c.Invoke(t, stackitem.Null{}, "deleteRecords", "a.test.com", int64(nns.TXT))
- checkRecords(t, "test.com", nns.TXT, "recTop")
- checkRecords(t, "a.test.com", nns.TXT)
- checkRecords(t, "b.test.com", nns.TXT, "recB")
- }
-
- { // Delete domain records.
- c.Invoke(t, stackitem.Null{}, "deleteRecords", "test.com", int64(nns.TXT))
- checkRecords(t, "test.com", nns.TXT)
- checkRecords(t, "a.test.com", nns.TXT)
- checkRecords(t, "b.test.com", nns.TXT, "recB")
- }
-}
-
-func TestDeleteDomain(t *testing.T) {
- c := newNNSInvoker(t, false)
-
- acc1 := c.NewAccount(t)
- c1 := c.WithSigners(c.Committee, acc1)
-
- acc2 := c.NewAccount(t)
- c2 := c.WithSigners(c.Committee, acc2)
- c1.Invoke(t, true, "register",
- "com", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, true, "register",
- "testdomain.com", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, true, "register",
- "domik.testdomain.com", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.InvokeFail(t, "domain not found", "deleteDomain", "ru")
- c1.InvokeFail(t, "can't delete TLD domain that has subdomains", "deleteDomain", "com")
- c1.Invoke(t, stackitem.Null{}, "deleteDomain", "testdomain.com")
-
- c1.Invoke(t, true, "register",
- "aa.bb.zz", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.InvokeFail(t, "TLD already exists", "register",
- "zz", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, stackitem.Null{}, "deleteDomain", "aa.bb.zz")
-
- c1.Invoke(t, true, "register",
- "zz", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, true, "register",
- "cn", acc1.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c2.InvokeFail(t, "not witnessed by admin", "deleteDomain", "cn")
-
- c1.Invoke(t, stackitem.Null{}, "deleteDomain", "cn")
-
- c2.Invoke(t, true, "register",
- "cn", acc2.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, true, "register",
- "gu.bububu.bubu.bu", c.CommitteeHash,
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, true, "register",
- "buu.gu.bububu.bubu.bu", c.CommitteeHash,
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- c1.Invoke(t, true, "register",
- "bubu.bu", c.CommitteeHash,
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-}
-
-func TestGlobalDomain(t *testing.T) {
- c := newNNSInvoker(t, false)
-
- accTop := c.NewAccount(t)
- refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
- c1 := c.WithSigners(c.Committee, accTop)
- c1.Invoke(t, true, "register",
- "com", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, true, "register",
- "testdomain.com", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, true, "register",
- "globaldomain.com", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, true, "register",
- "domik.testdomain.com", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
- c1.Invoke(t, stackitem.Null{}, "addRecord",
- "domik.testdomain.com", int64(nns.TXT), "CID")
-
- c.Invoke(t, true, "isAvailable", "domik.globaldomain.com")
-
- c1.Invoke(t, stackitem.Null{}, "addRecord",
- "testdomain.com", int64(nns.TXT), nns.Cnametgt+"=globaldomain.com")
- c.Invoke(t, true, "isAvailable", "dom.testdomain.com")
-
- c1.Invoke(t, stackitem.Null{}, "addRecord",
- "domik.testdomain.com", int64(nns.TXT), "random txt record")
- c.Invoke(t, true, "isAvailable", "domik.globaldomain.com")
-
- c1.Invoke(t, true, "register",
- "dom.testdomain.com", accTop.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, stackitem.Null{}, "addRecord",
- "dom.testdomain.com", int64(nns.TXT), "CID")
-
- c.InvokeFail(t, "global domain is already taken", "isAvailable", "dom.testdomain.com")
}
func TestTLDRecord(t *testing.T) {
@@ -437,17 +134,13 @@ func TestTLDRecord(t *testing.T) {
result := []stackitem.Item{stackitem.NewByteArray([]byte("1.2.3.4"))}
c.Invoke(t, result, "resolve", "com", int64(nns.A))
-
- t.Run("subdomain", func(t *testing.T) {
- c.Invoke(t, stackitem.Null{}, "addRecord", "a.com", int64(nns.TXT), "test=frostfs")
- })
}
func TestNNSRegisterMulti(t *testing.T) {
c := newNNSInvoker(t, true)
- newArgs := func(domain string, account neotest.Signer) []any {
- return []any{
+ newArgs := func(domain string, account neotest.Signer) []interface{} {
+ return []interface{}{
domain, account.ScriptHash(), "doesnt@matter.com",
int64(101), int64(102), int64(103), int64(104),
}
@@ -458,6 +151,11 @@ func TestNNSRegisterMulti(t *testing.T) {
cBoth.Invoke(t, true, "register", args...)
c1 := c.WithSigners(acc)
+ t.Run("parent domain is missing", func(t *testing.T) {
+ msg := "one of the parent domains is not registered"
+ args[0] = "testnet.fs.neo.com"
+ c1.InvokeFail(t, msg, "register", args...)
+ })
args[0] = "fs.neo.com"
c1.Invoke(t, true, "register", args...)
@@ -487,8 +185,7 @@ func TestNNSRegisterMulti(t *testing.T) {
c2.Invoke(t, stackitem.Null{}, "addRecord",
"cdn.mainnet.fs.neo.com", int64(nns.A), "166.15.14.13")
result := stackitem.NewArray([]stackitem.Item{
- stackitem.NewByteArray([]byte("166.15.14.13")),
- })
+ stackitem.NewByteArray([]byte("166.15.14.13"))})
c2.Invoke(t, result, "resolve", "cdn.mainnet.fs.neo.com", int64(nns.A))
}
@@ -498,18 +195,18 @@ func TestNNSUpdateSOA(t *testing.T) {
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
refresh *= 2
retry *= 2
expire *= 2
ttl *= 2
c.Invoke(t, stackitem.Null{}, "updateSOA",
- "testdomain.com", "newemail@frostfs.info", refresh, retry, expire, ttl)
+ "testdomain.com", "newemail@nspcc.ru", refresh, retry, expire, ttl)
b := c.TopBlock(t)
expected := stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
- []byte(fmt.Sprintf("testdomain.com newemail@frostfs.info %d %d %d %d %d",
+ []byte(fmt.Sprintf("testdomain.com newemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.SOA))
}
@@ -520,13 +217,13 @@ func TestNNSGetAllRecords(t *testing.T) {
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c.Invoke(t, stackitem.Null{}, "addRecord", "testdomain.com", int64(nns.TXT), "first TXT record")
c.Invoke(t, stackitem.Null{}, "addRecord", "testdomain.com", int64(nns.A), "1.2.3.4")
b := c.TopBlock(t)
- expSOA := fmt.Sprintf("testdomain.com myemail@frostfs.info %d %d %d %d %d",
+ expSOA := fmt.Sprintf("testdomain.com myemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)
s, err := c.TestInvoke(t, "getAllRecords", "testdomain.com")
@@ -554,13 +251,51 @@ func TestNNSGetAllRecords(t *testing.T) {
require.False(t, iter.Next())
}
+func TestExpiration(t *testing.T) {
+ c := newNNSInvoker(t, true)
+
+ refresh, retry, expire, ttl := int64(101), int64(102), int64(msPerYear/1000*10), int64(104)
+ c.Invoke(t, true, "register",
+ "testdomain.com", c.CommitteeHash,
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
+
+ checkProperties := func(t *testing.T, expiration uint64) {
+ expected := stackitem.NewMapWithValue([]stackitem.MapElement{
+ {Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")},
+ {Key: stackitem.Make("expiration"), Value: stackitem.Make(expiration)}})
+ s, err := c.TestInvoke(t, "properties", "testdomain.com")
+ require.NoError(t, err)
+ require.Equal(t, expected.Value(), s.Top().Item().Value())
+ }
+
+ top := c.TopBlock(t)
+ expiration := top.Timestamp + uint64(expire*1000)
+ checkProperties(t, expiration)
+
+ b := c.NewUnsignedBlock(t)
+ b.Timestamp = expiration - 2 // test invoke is done with +1 timestamp
+ require.NoError(t, c.Chain.AddBlock(c.SignBlock(b)))
+ checkProperties(t, expiration)
+
+ b = c.NewUnsignedBlock(t)
+ b.Timestamp = expiration - 1
+ require.NoError(t, c.Chain.AddBlock(c.SignBlock(b)))
+
+ _, err := c.TestInvoke(t, "properties", "testdomain.com")
+ require.Error(t, err)
+ require.True(t, strings.Contains(err.Error(), "name has expired"))
+
+ c.InvokeFail(t, "name has expired", "getAllRecords", "testdomain.com")
+ c.InvokeFail(t, "name has expired", "ownerOf", "testdomain.com")
+}
+
func TestNNSSetAdmin(t *testing.T) {
c := newNNSInvoker(t, true)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
acc := c.NewAccount(t)
cAcc := c.WithSigners(acc)
@@ -574,85 +309,50 @@ func TestNNSSetAdmin(t *testing.T) {
"testdomain.com", int64(nns.TXT), "will be added")
}
-func TestNNS_Frostfsid(t *testing.T) {
- nnsInv, f := newNNSInvokerWithFrostfsID(t, false)
-
- acc, err := wallet.NewAccount()
- require.NoError(t, err)
- nnsUserInv := nnsInv.NewInvoker(nnsInv.Hash, newSigner(t, nnsInv, acc))
-
- nnsUserInv.InvokeFail(t, "not witnessed by committee", "register",
- "ddd", acc.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- nnsUserInv.InvokeFail(t, "not witnessed by committee", "register",
- "testdomain.kz", acc.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- f.Invoke(t, stackitem.Null{}, createSubjectMethod, "", acc.PrivateKey().PublicKey().Bytes())
-
- nnsUserInv.InvokeFail(t, "not witnessed by committee", "register",
- "testdomain.kz", acc.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- f.Invoke(t, stackitem.Null{}, setSubjectKVMethod, acc.ScriptHash(), nns.FrostfsIDNNSTLDPermissionKey, nns.FrostfsIDTLDRegistrationAllowed)
-
- nnsUserInv.Invoke(t, true, "register",
- "testdomain.kz", acc.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-
- f.Invoke(t, stackitem.Null{}, deleteSubjectKVMethod, acc.ScriptHash(), nns.FrostfsIDNNSTLDPermissionKey)
-
- nnsUserInv.InvokeFail(t, "not witnessed by committee", "register",
- "testdomain.uz", acc.ScriptHash(),
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
-}
-
func TestNNSIsAvailable(t *testing.T) {
c := newNNSInvoker(t, false)
c.Invoke(t, true, "isAvailable", "com")
+ c.InvokeFail(t, "TLD not found", "isAvailable", "domain.com")
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c.Invoke(t, true, "register",
"com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c.Invoke(t, false, "isAvailable", "com")
c.Invoke(t, true, "isAvailable", "domain.com")
acc := c.NewAccount(t)
c1 := c.WithSigners(c.Committee, acc)
-
c1.Invoke(t, true, "register",
"domain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c1.Invoke(t, true, "register",
- "globaldomain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c.Invoke(t, false, "isAvailable", "domain.com")
+}
- c.Invoke(t, true, "isAvailable", "dom.domain.com")
+func TestNNSRenew(t *testing.T) {
+ c := newNNSInvoker(t, true)
+ acc := c.NewAccount(t)
+ c1 := c.WithSigners(c.Committee, acc)
+ refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c1.Invoke(t, true, "register",
- "dom.domain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
- c.Invoke(t, false, "isAvailable", "dom.domain.com")
- c.Invoke(t, true, "isAvailable", "dom.dom.domain.com")
+ "testdomain.com", c.CommitteeHash,
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
- c1.Invoke(t, stackitem.Null{}, "addRecord",
- "dom.domain.com", int64(nns.TXT), nns.Cnametgt+"=globaldomain.com")
- c.Invoke(t, true, "isAvailable", "dom.dom.domain.com")
+ const msPerYear = 365 * 24 * time.Hour / time.Millisecond
+ b := c.TopBlock(t)
+ ts := b.Timestamp + uint64(expire*1000) + uint64(msPerYear)
- c1.Invoke(t, true, "register",
- "dom.globaldomain.com", acc.ScriptHash(),
- "myemail@frostfs.info", refresh, retry, expire, ttl)
-
- c.InvokeFail(t, "global domain is already taken", "isAvailable", "dom.dom.domain.com")
-
- c.InvokeFail(t, "domain name too long", "isAvailable", getTooLongDomainName(255))
+ cAcc := c.WithSigners(acc)
+ cAcc.InvokeFail(t, "not witnessed by admin", "renew", "testdomain.com")
+ c1.Invoke(t, ts, "renew", "testdomain.com")
+ expected := stackitem.NewMapWithValue([]stackitem.MapElement{
+ {Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")},
+ {Key: stackitem.Make("expiration"), Value: stackitem.Make(ts)}})
+ cAcc.Invoke(t, expected, "properties", "testdomain.com")
}
func TestNNSResolve(t *testing.T) {
@@ -661,7 +361,7 @@ func TestNNSResolve(t *testing.T) {
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c.Invoke(t, true, "register",
"test.com", c.CommitteeHash,
- "myemail@frostfs.info", refresh, retry, expire, ttl)
+ "myemail@nspcc.ru", refresh, retry, expire, ttl)
c.Invoke(t, stackitem.Null{}, "addRecord",
"test.com", int64(nns.TXT), "expected result")
@@ -671,42 +371,3 @@ func TestNNSResolve(t *testing.T) {
c.Invoke(t, records, "resolve", "test.com.", int64(nns.TXT))
c.InvokeFail(t, "invalid domain name format", "resolve", "test.com..", int64(nns.TXT))
}
-
-func TestNNSAndProxy(t *testing.T) {
- c := newNNSInvoker(t, false)
- proxyHash := deployProxyContract(t, c.Executor)
- proxySigner := neotest.NewContractSigner(proxyHash, func(*transaction.Transaction) []any { return nil })
-
- g := c.NewInvoker(gas.Hash, c.Validator)
- g.Invoke(t, true, "transfer",
- c.Validator.ScriptHash(), proxyHash, 100_0000_0000, nil)
-
- cc := c.WithSigners(proxySigner, c.Committee)
- cc.Invoke(t, true, "register", "ns", proxyHash,
- "ops@frostfs.info", 100, 100, 100, 100)
-
- checkBalance := func(t *testing.T, owner util.Uint160, balance int64) {
- s, err := cc.TestInvoke(t, "balanceOf", owner)
- require.NoError(t, err)
- require.Equal(t, 1, s.Len())
- require.Equal(t, int64(balance), s.Pop().BigInt().Int64())
- }
-
- checkBalance(t, proxyHash, 1)
- checkBalance(t, c.CommitteeHash, 0)
-
- t.Run("ensure domain is not lost", func(t *testing.T) {
- cc.Invoke(t, true, "transfer", c.CommitteeHash, "ns", nil)
-
- checkBalance(t, proxyHash, 0)
- checkBalance(t, c.CommitteeHash, 1)
- })
-}
-
-func getTooLongDomainName(max int) (res string) {
- for len(res) < max {
- res += "dom."
- }
- res += "com"
- return res
-}
diff --git a/tests/policy_test.go b/tests/policy_test.go
deleted file mode 100644
index 361d435..0000000
--- a/tests/policy_test.go
+++ /dev/null
@@ -1,268 +0,0 @@
-package tests
-
-import (
- "bytes"
- "path"
- "testing"
-
- "git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
- "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
- "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
- "github.com/nspcc-dev/neo-go/pkg/encoding/address"
- "github.com/nspcc-dev/neo-go/pkg/neotest"
- "github.com/nspcc-dev/neo-go/pkg/vm"
- "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/nspcc-dev/neo-go/pkg/wallet"
- "github.com/stretchr/testify/require"
-)
-
-const policyPath = "../policy"
-
-type policyContracts struct {
- policy *neotest.ContractInvoker
- frostfsid *neotest.ContractInvoker
-}
-
-func newPolicyInvokers(t *testing.T) *policyContracts {
- e := newExecutor(t)
-
- n := deployNNSContract(t, e)
- ffid := deployFrostfsid(t, e)
- polic := deployPolicyContract(t, e)
-
- n.Invoke(t, true, "register",
- nns.FrostfsIDNNSName, n.CommitteeHash,
- "myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
- n.Invoke(t, stackitem.Null{}, "addRecord",
- nns.FrostfsIDNNSName, int64(nns.TXT), ffid.Hash.StringLE())
- n.Invoke(t, stackitem.Null{}, "addRecord",
- nns.FrostfsIDNNSName, int64(nns.TXT), address.Uint160ToString(ffid.Hash))
-
- return &policyContracts{
- policy: polic,
- frostfsid: ffid,
- }
-}
-
-func deployNNSContract(t *testing.T, e *neotest.Executor) *neotest.ContractInvoker {
- ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
- e.DeployContract(t, ctrNNS, nil)
-
- n := e.CommitteeInvoker(ctrNNS.Hash)
-
- return n
-}
-
-func deployFrostfsid(t *testing.T, e *neotest.Executor) *neotest.ContractInvoker {
- acc, err := wallet.NewAccount()
- require.NoError(t, err)
- args := make([]any, 5)
- args[0] = acc.ScriptHash()
- frostfsID := neotest.CompileFile(t, e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
- e.DeployContract(t, frostfsID, args)
- return e.CommitteeInvoker(frostfsID.Hash)
-}
-
-func deployPolicyContract(t *testing.T, e *neotest.Executor) *neotest.ContractInvoker {
- cfgPath := path.Join(policyPath, "config.yml")
- c := neotest.CompileFile(t, e.CommitteeHash, policyPath, cfgPath)
- e.DeployContract(t, c, []any{nil})
- return e.CommitteeInvoker(c.Hash)
-}
-
-func TestPolicy(t *testing.T) {
- c := newPolicyInvokers(t)
-
- checkChainsIteratorByPrefix(t, c.policy, policy.Namespace, "mynamespace", "ingress", [][]byte{})
- checkChainsIteratorByPrefix(t, c.policy, policy.Container, "cnr1", "ingress", [][]byte{})
-
- // Policies are opaque to the contract and are just raw bytes to store.
- p1 := []byte("chain1")
- p2 := []byte("chain2")
- p3 := []byte("chain3")
- p33 := []byte("chain33")
-
- c.frostfsid.Invoke(t, stackitem.Null{}, "createNamespace", "mynamespace")
-
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Namespace, "mynamespace", "ingress:123", p1)
- checkTargets(t, c.policy, policy.Namespace, [][]byte{[]byte("mynamespace")})
- checkChains(t, c.policy, "mynamespace", "", "ingress", [][]byte{p1})
- checkChains(t, c.policy, "mynamespace", "", "all", nil)
-
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Container, "cnr1", "ingress:myrule2", p2)
- checkTargets(t, c.policy, policy.Namespace, [][]byte{[]byte("mynamespace")})
- checkTargets(t, c.policy, policy.Container, [][]byte{[]byte("cnr1")})
- checkChains(t, c.policy, "mynamespace", "", "ingress", [][]byte{p1}) // Only namespace chains.
- checkChains(t, c.policy, "mynamespace", "cnr1", "ingress", [][]byte{p1, p2})
- checkChains(t, c.policy, "mynamespace", "cnr1", "all", nil) // No chains attached to 'all'.
- checkChains(t, c.policy, "mynamespace", "cnr2", "ingress", [][]byte{p1}) // Only namespace, no chains for the container.
-
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Container, "cnr1", "ingress:myrule3", p3)
- checkTargets(t, c.policy, policy.Namespace, [][]byte{[]byte("mynamespace")})
- checkTargets(t, c.policy, policy.Container, [][]byte{[]byte("cnr1")})
- checkChains(t, c.policy, "mynamespace", "cnr1", "ingress", [][]byte{p1, p2, p3})
-
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Container, "cnr1", "ingress:myrule3", p33)
- checkTargets(t, c.policy, policy.Namespace, [][]byte{[]byte("mynamespace")})
- checkTargets(t, c.policy, policy.Container, [][]byte{[]byte("cnr1")})
- checkChain(t, c.policy, policy.Container, "cnr1", "ingress:myrule3", p33)
- checkChains(t, c.policy, "mynamespace", "cnr1", "ingress", [][]byte{p1, p2, p33}) // Override chain.
- checkChainsByPrefix(t, c.policy, policy.Container, "cnr1", "", [][]byte{p2, p33})
- checkChainsByPrefix(t, c.policy, policy.IAM, "", "", nil)
- checkChainKeys(t, c.policy, policy.Container, "cnr1", []string{"ingress:myrule2", "ingress:myrule3"})
-
- checkChainsIteratorByPrefix(t, c.policy, policy.Container, "cnr1", "ingress:myrule3", [][]byte{p33})
- checkChainsIteratorByPrefix(t, c.policy, policy.Container, "cnr1", "ingress", [][]byte{p2, p33})
-
- t.Run("removal", func(t *testing.T) {
- t.Run("wrong name", func(t *testing.T) {
- c.policy.Invoke(t, stackitem.Null{}, "removeChain", policy.Namespace, "mynamespace", "ingress")
- checkChains(t, c.policy, "mynamespace", "", "ingress", [][]byte{p1})
- })
-
- c.policy.Invoke(t, stackitem.Null{}, "removeChain", policy.Namespace, "mynamespace", "ingress:123")
- checkChains(t, c.policy, "mynamespace", "", "ingress", nil)
- checkChains(t, c.policy, "mynamespace", "cnr1", "ingress", [][]byte{p2, p33}) // Container chains still exist.
-
- // Remove by prefix.
- c.policy.Invoke(t, stackitem.Null{}, "removeChainsByPrefix", policy.Container, "cnr1", "ingress")
- checkChains(t, c.policy, "mynamespace", "cnr1", "ingress", nil)
-
- // Remove by prefix.
- c.policy.Invoke(t, stackitem.Null{}, "removeChainsByPrefix", policy.Container, "cnr1", "ingress")
- checkChains(t, c.policy, "mynamespace", "cnr1", "ingress", nil)
-
- checkTargets(t, c.policy, policy.Namespace, [][]byte{})
- checkTargets(t, c.policy, policy.Container, [][]byte{})
- })
-
- t.Run("add again after removal", func(t *testing.T) {
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Namespace, "mynamespace", "ingress:123", p1)
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Container, "cnr1", "ingress:myrule3", p33)
-
- checkTargets(t, c.policy, policy.Namespace, [][]byte{[]byte("mynamespace")})
- checkTargets(t, c.policy, policy.Container, [][]byte{[]byte("cnr1")})
- })
-
- t.Run("add chain for non-active namespace", func(t *testing.T) {
- c.frostfsid.Invoke(t, stackitem.Null{}, "createNamespace", "nsdisabled")
-
- c.frostfsid.Invoke(t, stackitem.Null{}, "updateNamespace", "nsdisabled", "frozen")
- c.policy.InvokeFail(t, "namespace is non-active", "addChain", policy.Namespace, "nsdisabled", "ingress:3", p1)
-
- c.frostfsid.Invoke(t, stackitem.Null{}, "updateNamespace", "nsdisabled", "purge")
- c.policy.InvokeFail(t, "namespace is non-active", "addChain", policy.Namespace, "nsdisabled", "ingress:3", p1)
-
- c.frostfsid.Invoke(t, stackitem.Null{}, "updateNamespace", "nsdisabled", "active")
- c.policy.Invoke(t, stackitem.Null{}, "addChain", policy.Namespace, "nsdisabled", "ingress:3", p1)
- })
-}
-
-func TestAutorization(t *testing.T) {
- c := newPolicyInvokers(t)
-
- c.policy.Invoke(t, stackitem.Null{}, "getAdmin")
-
- s := c.policy.NewAccount(t, 1_0000_0000)
- cs := c.policy.WithSigners(s)
-
- args := []any{policy.Container, "cnr1", "ingress:myrule3", []byte("opaque")}
- cs.InvokeFail(t, policy.ErrNotAuthorized, "addChain", args...)
-
- c.policy.Invoke(t, stackitem.Null{}, "setAdmin", s.ScriptHash())
- c.policy.Invoke(t, stackitem.NewBuffer(s.ScriptHash().BytesBE()), "getAdmin")
-
- cs.Invoke(t, stackitem.Null{}, "addChain", args...)
-}
-
-func checkChains(t *testing.T, e *neotest.ContractInvoker, namespace, container, name string, expected [][]byte) {
- s, err := e.TestInvoke(t, "listChains", namespace, container, name)
- require.NoError(t, err)
-
- checksChainsOnStack(t, s, expected)
-}
-
-func checkChainsByPrefix(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName, prefix string, expected [][]byte) {
- s, err := e.TestInvoke(t, "listChainsByPrefix", kind, entityName, prefix)
- require.NoError(t, err)
-
- checksChainsOnStack(t, s, expected)
-}
-
-func checkChainsIteratorByPrefix(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName, prefix string, expected [][]byte) {
- s, err := e.TestInvoke(t, "iteratorChainsByPrefix", kind, entityName, prefix)
- require.NoError(t, err)
-
- if s.Len() == 0 {
- t.Fatal("Stack is empty")
- }
-
- iteratorItem := s.Pop().Value().(*storage.Iterator)
- policys := iteratorToArray(iteratorItem)
- require.Equal(t, len(expected), len(policys))
-
- for i := range expected {
- bytesPolicy, err := policys[i].TryBytes()
- require.NoError(t, err)
- require.Equal(t, expected[i], bytesPolicy)
- }
-}
-
-func checkChainKeys(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName string, expected []string) {
- s, err := e.TestInvoke(t, "listChainNames", kind, entityName)
- require.NoError(t, err)
-
- if s.Len() == 0 {
- t.Fatal("Stack is empty")
- }
-
- iteratorItem := s.Pop().Value().(*storage.Iterator)
- policys := iteratorToArray(iteratorItem)
- require.Equal(t, len(expected), len(policys))
-
- for i := range expected {
- bytesPolicy, err := policys[i].TryBytes()
- require.NoError(t, err)
- require.Equal(t, expected[i], string(bytesPolicy))
- }
-}
-
-func checksChainsOnStack(t *testing.T, s *vm.Stack, expected [][]byte) {
- require.Equal(t, 1, s.Len())
-
- var actual [][]byte
- arr := s.Pop().Array()
- for i := range arr {
- bs, err := arr[i].TryBytes()
-
- require.NoError(t, err)
- actual = append(actual, bs)
- }
-
- require.ElementsMatch(t, expected, actual)
-}
-
-func checkChain(t *testing.T, e *neotest.ContractInvoker, kind byte, entityName, name string, expected []byte) {
- s, err := e.TestInvoke(t, "getChain", kind, entityName, name)
- require.NoError(t, err)
- require.Equal(t, 1, s.Len())
-
- require.True(t, bytes.Equal(expected, s.Pop().Bytes()))
-}
-
-func checkTargets(t *testing.T, e *neotest.ContractInvoker, kind byte, expected [][]byte) {
- s, err := e.TestInvoke(t, "listTargets", kind)
- require.NoError(t, err)
-
- require.NotEqual(t, 0, s.Len(), "stack is empty")
-
- iteratorItem := s.Pop().Value().(*storage.Iterator)
- targets := iteratorToArray(iteratorItem)
- require.Equal(t, len(expected), len(targets))
-
- for i := range expected {
- bytesTargets, err := targets[i].TryBytes()
- require.NoError(t, err)
- require.Equal(t, expected[i], bytesTargets)
- }
-}
diff --git a/tests/processing_test.go b/tests/processing_test.go
index 6c16bb7..ac6c4e9 100644
--- a/tests/processing_test.go
+++ b/tests/processing_test.go
@@ -4,41 +4,28 @@ import (
"path"
"testing"
- "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/nspcc-dev/neo-go/pkg/wallet"
- "github.com/stretchr/testify/require"
)
const processingPath = "../processing"
-func deployProcessingContract(t *testing.T, e *neotest.Executor) util.Uint160 {
+func deployProcessingContract(t *testing.T, e *neotest.Executor, addrFrostFS util.Uint160) util.Uint160 {
c := neotest.CompileFile(t, e.CommitteeHash, processingPath, path.Join(processingPath, "config.yml"))
- e.DeployContract(t, c, nil)
+ args := make([]interface{}, 1)
+ args[0] = addrFrostFS
+
+ e.DeployContract(t, c, args)
return c.Hash
}
-func newProcessingInvoker(t *testing.T) (*neotest.ContractInvoker, neotest.SingleSigner) {
- e := newExecutor(t)
+func newProcessingInvoker(t *testing.T) (*neotest.ContractInvoker, neotest.Signer) {
+ frostfsInvoker, irMultiAcc, _ := newFrostFSInvoker(t, 2)
+ hash := deployProcessingContract(t, frostfsInvoker.Executor, frostfsInvoker.Hash)
- acc, err := wallet.NewAccount()
- require.NoError(t, err)
-
- sig := neotest.NewSingleSigner(acc)
-
- gasHash, err := e.Chain.GetNativeContractScriptHash(nativenames.Gas)
- require.NoError(t, err)
- vc := e.CommitteeInvoker(gasHash).WithSigners(e.Validator)
- vc.Invoke(t, true, "transfer",
- e.Validator.ScriptHash(), sig.ScriptHash(),
- int64(10_0000_0000), nil)
-
- hash := deployProcessingContract(t, e)
-
- return e.CommitteeInvoker(hash), sig
+ return frostfsInvoker.CommitteeInvoker(hash), irMultiAcc
}
func TestVerify_Processing(t *testing.T) {
@@ -48,6 +35,6 @@ func TestVerify_Processing(t *testing.T) {
cIR := c.WithSigners(irMultiAcc)
- cIR.Invoke(t, stackitem.NewBool(false), method)
- c.Invoke(t, stackitem.NewBool(true), method)
+ cIR.Invoke(t, stackitem.NewBool(true), method)
+ c.Invoke(t, stackitem.NewBool(false), method)
}
diff --git a/tests/proxy_test.go b/tests/proxy_test.go
index f36754d..67b363c 100644
--- a/tests/proxy_test.go
+++ b/tests/proxy_test.go
@@ -4,52 +4,45 @@ import (
"path"
"testing"
- "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
- "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/util"
- "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/stretchr/testify/require"
)
const proxyPath = "../proxy"
-func deployProxyContract(t *testing.T, e *neotest.Executor) util.Uint160 {
+func deployProxyContract(t *testing.T, e *neotest.Executor, addrNetmap util.Uint160) util.Uint160 {
+ args := make([]interface{}, 1)
+ args[0] = addrNetmap
+
c := neotest.CompileFile(t, e.CommitteeHash, proxyPath, path.Join(proxyPath, "config.yml"))
- e.DeployContract(t, c, []any{})
+ e.DeployContract(t, c, args)
return c.Hash
}
func newProxyInvoker(t *testing.T) *neotest.ContractInvoker {
e := newExecutor(t)
- proxyHash := deployProxyContract(t, e)
+ ctrNetmap := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
+ ctrBalance := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
+ ctrContainer := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
+ ctrProxy := neotest.CompileFile(t, e.CommitteeHash, proxyPath, path.Join(proxyPath, "config.yml"))
- return e.CommitteeInvoker(proxyHash)
+ deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash)
+ deployProxyContract(t, e, ctrNetmap.Hash)
+
+ return e.CommitteeInvoker(ctrProxy.Hash)
}
func TestVerify(t *testing.T) {
e := newProxyInvoker(t)
- acc := e.NewAccount(t)
- gas := e.NewInvoker(e.NativeHash(t, nativenames.Gas), e.Validator)
- gas.Invoke(t, true, "transfer", e.Validator.ScriptHash(), e.Hash, 100_0000_0000, nil)
+ const method = "verify"
- s := neotest.NewContractSigner(e.Hash, func(*transaction.Transaction) []any { return nil })
- t.Run("proxy + committee", func(t *testing.T) {
- tx := e.PrepareInvocation(t, []byte{byte(opcode.RET)}, []neotest.Signer{s, e.Committee})
- require.NoError(t, e.Chain.VerifyTx(tx))
- })
- t.Run("proxy + custom account", func(t *testing.T) {
- t.Run("bad, only proxy", func(t *testing.T) {
- tx := e.PrepareInvocation(t, []byte{byte(opcode.RET)}, []neotest.Signer{s, acc})
- require.Error(t, e.Chain.VerifyTx(tx))
- })
+ e.Invoke(t, stackitem.NewBool(true), method)
- e.Invoke(t, stackitem.Null{}, "addAccount", acc.ScriptHash())
+ notAlphabet := e.NewAccount(t)
+ cNotAlphabet := e.WithSigners(notAlphabet)
- tx := e.PrepareInvocation(t, []byte{byte(opcode.RET)}, []neotest.Signer{s, acc})
- require.NoError(t, e.Chain.VerifyTx(tx))
- })
+ cNotAlphabet.Invoke(t, stackitem.NewBool(false), method)
}
diff --git a/tests/reputation_test.go b/tests/reputation_test.go
new file mode 100644
index 0000000..8b09a25
--- /dev/null
+++ b/tests/reputation_test.go
@@ -0,0 +1,80 @@
+package tests
+
+import (
+ "path"
+ "testing"
+
+ "github.com/nspcc-dev/neo-go/pkg/neotest"
+ "github.com/nspcc-dev/neo-go/pkg/neotest/chain"
+ "github.com/nspcc-dev/neo-go/pkg/util"
+ "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
+)
+
+const reputationPath = "../reputation"
+
+func deployReputationContract(t *testing.T, e *neotest.Executor) util.Uint160 {
+ c := neotest.CompileFile(t, e.CommitteeHash, reputationPath,
+ path.Join(reputationPath, "config.yml"))
+
+ args := make([]interface{}, 1)
+ args[0] = false
+
+ e.DeployContract(t, c, args)
+ return c.Hash
+}
+
+func newReputationInvoker(t *testing.T) *neotest.ContractInvoker {
+ bc, acc := chain.NewSingle(t)
+ e := neotest.NewExecutor(t, bc, acc, acc)
+ h := deployReputationContract(t, e)
+ return e.CommitteeInvoker(h)
+}
+
+func TestReputation_Put(t *testing.T) {
+ e := newReputationInvoker(t)
+
+ peerID := []byte{1, 2, 3}
+ e.Invoke(t, stackitem.Null{}, "put", int64(1), peerID, []byte{4})
+
+ t.Run("concurrent invocations", func(t *testing.T) {
+ repValue1 := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+ repValue2 := []byte{10, 20, 30, 40, 50, 60, 70, 80}
+ tx1 := e.PrepareInvoke(t, "put", int64(1), peerID, repValue1)
+ tx2 := e.PrepareInvoke(t, "put", int64(1), peerID, repValue2)
+
+ e.AddNewBlock(t, tx1, tx2)
+ e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
+ e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
+
+ t.Run("get all", func(t *testing.T) {
+ result := stackitem.NewArray([]stackitem.Item{
+ stackitem.NewBuffer([]byte{4}),
+ stackitem.NewBuffer(repValue1),
+ stackitem.NewBuffer(repValue2),
+ })
+ e.Invoke(t, result, "get", int64(1), peerID)
+ })
+ })
+}
+
+func TestReputation_ListByEpoch(t *testing.T) {
+ e := newReputationInvoker(t)
+
+ peerIDs := []string{"peer1", "peer2"}
+ e.Invoke(t, stackitem.Null{}, "put", int64(1), peerIDs[0], []byte{1})
+ e.Invoke(t, stackitem.Null{}, "put", int64(1), peerIDs[0], []byte{2})
+ e.Invoke(t, stackitem.Null{}, "put", int64(2), peerIDs[1], []byte{3})
+ e.Invoke(t, stackitem.Null{}, "put", int64(2), peerIDs[0], []byte{4})
+ e.Invoke(t, stackitem.Null{}, "put", int64(2), peerIDs[1], []byte{5})
+
+ result := stackitem.NewArray([]stackitem.Item{
+ stackitem.NewBuffer(append([]byte{1}, peerIDs[0]...)),
+ })
+ e.Invoke(t, result, "listByEpoch", int64(1))
+
+ result = stackitem.NewArray([]stackitem.Item{
+ stackitem.NewBuffer(append([]byte{2}, peerIDs[0]...)),
+ stackitem.NewBuffer(append([]byte{2}, peerIDs[1]...)),
+ })
+ e.Invoke(t, result, "listByEpoch", int64(2))
+}
diff --git a/tests/testdata/config.yml b/tests/testdata/config.yml
deleted file mode 100644
index 6294558..0000000
--- a/tests/testdata/config.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: "TestContract"
-safemethods: ["encodeDecode"]
diff --git a/tests/testdata/encode.go b/tests/testdata/encode.go
deleted file mode 100644
index 02d9b4e..0000000
--- a/tests/testdata/encode.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package testdata
-
-import (
- "git.frostfs.info/TrueCloudLab/frostfs-contract/common"
-)
-
-// EncodeDecode encodes x in fixed-width little-endian representation
-// and deserializes it back.
-func EncodeDecode(x int) int {
- y := common.ToFixedWidth64(x)
- return common.FromFixedWidth64(y)
-}
-
-// Encode encodes x in fixed-width little-endian representation.
-func Encode(x int) []byte {
- return common.ToFixedWidth64(x)
-}
diff --git a/tests/util.go b/tests/util.go
index ed7c119..48f5f5d 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -1,76 +1,14 @@
package tests
import (
- "context"
- "net/http"
- "os"
"testing"
- "time"
- "github.com/nspcc-dev/neo-go/pkg/config"
- "github.com/nspcc-dev/neo-go/pkg/consensus"
- "github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
- "github.com/nspcc-dev/neo-go/pkg/core/state"
- corestate "github.com/nspcc-dev/neo-go/pkg/core/stateroot"
- "github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
- "github.com/nspcc-dev/neo-go/pkg/network"
- "github.com/nspcc-dev/neo-go/pkg/rpcclient"
- "github.com/nspcc-dev/neo-go/pkg/services/rpcsrv"
- "github.com/nspcc-dev/neo-go/pkg/services/stateroot"
- "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
- "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
- "github.com/stretchr/testify/require"
- "go.uber.org/zap"
)
-type awaiter struct {
- ctx context.Context
- t *testing.T
- rpc *rpcclient.Client
-}
-
-func (a awaiter) await(tx util.Uint256, vub uint32, err error) *state.AppExecResult {
- require.NoError(a.t, err)
- return await(a.ctx, a.t, a.rpc, tx, vub)
-}
-
-const nodeWallet = `
-{
- "version": "3.0",
- "accounts": [
- {
- "address": "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn",
- "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY",
- "label": "",
- "contract": {
- "script": "DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcJBVuezJw==",
- "parameters": [
- {
- "name": "parameter0",
- "type": "Signature"
- }
- ],
- "deployed": false
- },
- "lock": false,
- "isdefault": false
- }
- ],
- "scrypt": {
- "n": 16384,
- "r": 8,
- "p": 8
- },
- "extra": {
- "Tokens": null
- }
-}
-`
-
func iteratorToArray(iter *storage.Iterator) []stackitem.Item {
stackItems := make([]stackitem.Item, 0)
for iter.Next() {
@@ -83,146 +21,3 @@ func newExecutor(t *testing.T) *neotest.Executor {
bc, acc := chain.NewSingle(t)
return neotest.NewExecutor(t, bc, acc, acc)
}
-
-func initTmpWallet(t *testing.T) string {
- f, err := os.CreateTemp("", "tmp-neo-go-wallet")
- require.NoError(t, err)
-
- _, err = f.WriteString(nodeWallet)
- require.NoError(t, err)
-
- err = f.Close()
- require.NoError(t, err)
- return f.Name()
-}
-
-func await(ctx context.Context, t *testing.T, rpc *rpcclient.Client, tx util.Uint256, vub uint32) *state.AppExecResult {
- waitCtx, waitCancel := context.WithTimeout(ctx, 5*time.Second)
- defer waitCancel()
-
- for {
- select {
- case <-waitCtx.Done():
- require.NoError(t, waitCtx.Err())
- return nil
- default:
- bc, err := rpc.GetBlockCount()
- require.NoError(t, err)
-
- tr := trigger.Application
- if log, err := rpc.GetApplicationLog(tx, &tr); err == nil {
- return &state.AppExecResult{
- Container: log.Container,
- Execution: log.Executions[0],
- }
- }
-
- require.LessOrEqual(t, bc, vub, "vub is expired")
- time.Sleep(100 * time.Millisecond)
- }
- }
-}
-
-func neogoCfg() config.Config {
- return config.Config{
- ProtocolConfiguration: config.ProtocolConfiguration{},
- ApplicationConfiguration: config.ApplicationConfiguration{
- RPC: config.RPC{
- BasicService: config.BasicService{
- Enabled: true,
- // See how tests are done in the neo-go itself:
- // https://github.com/nspcc-dev/neo-go/blob/5fc61be5f6c5349d8de8b61967380feee6b51c55/config/protocol.unit_testnet.single.yml#L61
- Addresses: []string{"localhost:0"},
- },
- MaxGasInvoke: 200_000_000,
- SessionEnabled: true,
- MaxIteratorResultItems: 100,
- SessionPoolSize: 20,
- SessionExpirationTime: 15,
- },
- DBConfiguration: dbconfig.DBConfiguration{
- Type: dbconfig.InMemoryDB,
- },
- },
- }
-}
-
-func consensusCfg(chain *core.Blockchain, walletAddress string, srv *network.Server) consensus.Config {
- return consensus.Config{
- Logger: zap.NewExample(),
- Broadcast: srv.BroadcastExtensible,
- BlockQueue: srv.GetBlockQueue(),
- Chain: chain,
- ProtocolConfiguration: chain.GetConfig().ProtocolConfiguration,
- RequestTx: srv.RequestTx,
- StopTxFlow: srv.StopTxFlow,
- Wallet: config.Wallet{
- Path: walletAddress,
- Password: "one",
- },
- TimePerBlock: 100 * time.Millisecond,
- }
-}
-
-func runRPC(ctx context.Context, t *testing.T, chain *core.Blockchain, walletPath string) string {
- log := zap.NewExample()
- cfg := neogoCfg()
-
- srvCfg, err := network.NewServerConfig(cfg)
- require.NoError(t, err)
- srv, err := network.NewServer(srvCfg, chain, chain.GetStateSyncModule(), log)
- require.NoError(t, err)
-
- t.Cleanup(srv.Shutdown)
-
- errCh := make(chan error)
- go func() {
- for err := range errCh {
- require.NoError(t, err)
- return
- }
- }()
-
- srMod := chain.GetStateModule().(*corestate.Module)
- sr, err := stateroot.New(srvCfg.StateRootCfg, srMod, log, chain, srv.BroadcastExtensible)
- require.NoError(t, err)
- srv.AddExtensibleService(sr, stateroot.Category, sr.OnPayload)
-
- consens, err := consensus.NewService(consensusCfg(chain, walletPath, srv))
- require.NoError(t, err)
- srv.AddConsensusService(consens, consens.OnPayload, consens.OnTransaction)
-
- rpcSrv := rpcsrv.New(chain, cfg.ApplicationConfiguration.RPC, srv, nil, log, errCh)
- srv.AddService(&rpcSrv)
-
- initialAddr := rpcSrv.Addresses()[0]
-
- go srv.Start()
-
- // wait until RPC server is started
- startTimeout, cancel := context.WithTimeout(ctx, 5*time.Second)
- defer cancel()
-
- ticker := time.NewTicker(time.Millisecond * 100)
- defer ticker.Stop()
-
- var actualAddr string
- for {
- select {
- case <-startTimeout.Done():
- t.Fatalf("Waiting for server start: %v", startTimeout.Err())
- case <-ticker.C:
- if actualAddr == "" {
- newAddr := rpcSrv.Addresses()[0]
- if initialAddr == newAddr {
- continue
- }
- actualAddr = newAddr
- t.Logf("RPC server is listening at %s, checking health", actualAddr)
- }
- if _, err = http.Get("http://" + actualAddr); err == nil {
- return actualAddr
- }
- }
- }
-}