diff --git a/docs/node-configuration.md b/docs/node-configuration.md
index d45651ee71..2a802419af 100644
--- a/docs/node-configuration.md
+++ b/docs/node-configuration.md
@@ -582,7 +582,7 @@ in development and can change in an incompatible way.
| `Cockatrice` | Introduces the ability to update native contracts. Includes a couple of new native smart contract APIs: `keccak256` of native CryptoLib contract and `getCommitteeAddress` of native NeoToken contract. | https://github.com/nspcc-dev/neo-go/pull/3402
https://github.com/neo-project/neo/pull/2942
https://github.com/nspcc-dev/neo-go/pull/3301
https://github.com/neo-project/neo/pull/2925
https://github.com/nspcc-dev/neo-go/pull/3362
https://github.com/neo-project/neo/pull/3154 |
| `Domovoi` | Makes node use executing contract state for the contract call permissions check instead of the state stored in the native Management contract. In C# also makes System.Runtime.GetNotifications interop properly count stack references of notification parameters which prevents users from creating objects that exceed MaxStackSize constraint, but NeoGo has never had this bug, thus proper behaviour is preserved even before HFDomovoi. It results in the fact that some T5 testnet transactions have different ApplicationLogs compared to the C# node, but the node states match. | https://github.com/nspcc-dev/neo-go/pull/3476
https://github.com/neo-project/neo/pull/3290
https://github.com/nspcc-dev/neo-go/pull/3473
https://github.com/neo-project/neo/pull/3290
https://github.com/neo-project/neo/pull/3301
https://github.com/nspcc-dev/neo-go/pull/3485 |
| `Echidna` | Introduces `Designation` event extension with `Old` and `New` roles data to native RoleManagement contract. Adds support for `base64UrlEncode` and `base64UrlDecode` methods to native StdLib contract. Extends the list of required call flags for `registerCandidate`, `unregisterCandidate`and `vote` methods of native NeoToken contract with AllowNotify flag. Enables `onNEP17Payment` method of NEO contract for candidate registration. Introduces constraint for maximum number of execution notifications. Adds support for `recoverSecp256K1` method of native CryptoLib contract. Introduces `setMillisecondsPerBlock` and `getMillisecondsPerBlock` methods of native Policy contract. Introduces support for NotaryAssisted transaction attribute and native Notary contract. | https://github.com/nspcc-dev/neo-go/pull/3554
https://github.com/nspcc-dev/neo-go/pull/3761
https://github.com/nspcc-dev/neo-go/pull/3554
https://github.com/neo-project/neo/pull/3597
https://github.com/nspcc-dev/neo-go/pull/3700
https://github.com/nspcc-dev/neo-go/pull/3640
https://github.com/neo-project/neo/pull/3548
https://github.com/nspcc-dev/neo-go/pull/3863
https://github.com/neo-project/neo/pull/3696
https://github.com/neo-project/neo/pull/3895
https://github.com/nspcc-dev/neo-go/pull/3835
https://github.com/nspcc-dev/neo-go/pull/3854
https://github.com/neo-project/neo/pull/3175
https://github.com/nspcc-dev/neo-go/pull/3478
https://github.com/neo-project/neo/pull/3178 |
-| `Faun` | Doesn't introduce any new functionality yet. | https://github.com/nspcc-dev/neo-go/pull/3932 |
+| `Faun` | Adds `getBlockedAccounts` method to native Policy contract. | https://github.com/nspcc-dev/neo-go/pull/3932
https://github.com/nspcc-dev/neo-go/pull/4004
https://github.com/neo-project/neo/pull/4147
https://github.com/neo-project/neo/pull/4150 |
## DB compatibility
diff --git a/examples/engine/go.mod b/examples/engine/go.mod
index 5798eb23f1..4fa5c39986 100644
--- a/examples/engine/go.mod
+++ b/examples/engine/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/engine/go.sum b/examples/engine/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/engine/go.sum
+++ b/examples/engine/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/events/go.mod b/examples/events/go.mod
index ff92d8d6d8..67485e6055 100644
--- a/examples/events/go.mod
+++ b/examples/events/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/events/go.sum b/examples/events/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/events/go.sum
+++ b/examples/events/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/iterator/go.mod b/examples/iterator/go.mod
index 47549e7546..2bf38f0be7 100644
--- a/examples/iterator/go.mod
+++ b/examples/iterator/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/iterator/go.sum b/examples/iterator/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/iterator/go.sum
+++ b/examples/iterator/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/nft-d/go.mod b/examples/nft-d/go.mod
index deaffdeef6..db1eea90cb 100644
--- a/examples/nft-d/go.mod
+++ b/examples/nft-d/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/nft-d/go.sum b/examples/nft-d/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/nft-d/go.sum
+++ b/examples/nft-d/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/nft-nd-nns/go.mod b/examples/nft-nd-nns/go.mod
index 15eecd1ba8..117c97292c 100644
--- a/examples/nft-nd-nns/go.mod
+++ b/examples/nft-nd-nns/go.mod
@@ -3,8 +3,8 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd-nns
go 1.24.0
require (
- github.com/nspcc-dev/neo-go v0.112.1-0.20250918123036-a20366b13c36
- github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+ github.com/nspcc-dev/neo-go v0.112.1-0.20250923153827-17512a0749f6
+ github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
github.com/stretchr/testify v1.11.1
)
diff --git a/examples/nft-nd-nns/go.sum b/examples/nft-nd-nns/go.sum
index a71e4863cc..4dcf8e6e99 100644
--- a/examples/nft-nd-nns/go.sum
+++ b/examples/nft-nd-nns/go.sum
@@ -124,10 +124,10 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20250911084817-6fb4472993d1 h1:U3wvY
github.com/nspcc-dev/go-ordered-json v0.0.0-20250911084817-6fb4472993d1/go.mod h1:CHwf1nwquA6ecSfxmNF0YuemOPHAnRGoLuZUv/WPjeY=
github.com/nspcc-dev/hrw/v2 v2.0.3 h1:GUIitIiDpAaQat9SZccp7XVAuwtqaM40+uZ9D8Q4A84=
github.com/nspcc-dev/hrw/v2 v2.0.3/go.mod h1:VWlFSGGPcHG1abuIDJb5u83tIF2EqOatC8Z7svZmgWQ=
-github.com/nspcc-dev/neo-go v0.112.1-0.20250918123036-a20366b13c36 h1:1LEFjT4N7p0dXb+OycVyOj7mIroEGnnwadLKPoa367I=
-github.com/nspcc-dev/neo-go v0.112.1-0.20250918123036-a20366b13c36/go.mod h1:iGT8NmM813b+LYG792Lc7kv1LbwXmaofFdHTMl8rvu8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go v0.112.1-0.20250923153827-17512a0749f6 h1:t9TVutI4yMgMQl4tVrpyKNYI6nZV9uEAUwuEKH+uSBE=
+github.com/nspcc-dev/neo-go v0.112.1-0.20250923153827-17512a0749f6/go.mod h1:wcWOspKlqzay5XGkCUV1x0AVB/ZAmiKu3RhcB+O7DVM=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.14 h1:Q0Zbu91VXckoaeNyIrQh3r/9xNnBneqBeID5FPXLmJo=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.14/go.mod h1:j/NUu5iOGFkOVYM42XoC1X9DZD0/y89Pws++w5vxtQk=
github.com/nspcc-dev/rfc6979 v0.2.4 h1:NBgsdCjhLpEPJZqmC9rciMZDcSY297po2smeaRjw57k=
diff --git a/examples/nft-nd/go.mod b/examples/nft-nd/go.mod
index e9444917a7..9501b2cb27 100644
--- a/examples/nft-nd/go.mod
+++ b/examples/nft-nd/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/nft-nd/go.sum b/examples/nft-nd/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/nft-nd/go.sum
+++ b/examples/nft-nd/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/oracle/go.mod b/examples/oracle/go.mod
index 7311748039..33ce6bfe77 100644
--- a/examples/oracle/go.mod
+++ b/examples/oracle/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/oracle/go.sum b/examples/oracle/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/oracle/go.sum
+++ b/examples/oracle/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/runtime/go.mod b/examples/runtime/go.mod
index c19d7d79e3..01e82fef5c 100644
--- a/examples/runtime/go.mod
+++ b/examples/runtime/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/runtime/go.sum b/examples/runtime/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/runtime/go.sum
+++ b/examples/runtime/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/storage/go.mod b/examples/storage/go.mod
index 93722dc194..726c955a76 100644
--- a/examples/storage/go.mod
+++ b/examples/storage/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/storage/go.sum b/examples/storage/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/storage/go.sum
+++ b/examples/storage/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/timer/go.mod b/examples/timer/go.mod
index 92799e5e7e..b7f99a33ed 100644
--- a/examples/timer/go.mod
+++ b/examples/timer/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/timer/go.sum b/examples/timer/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/timer/go.sum
+++ b/examples/timer/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/token/go.mod b/examples/token/go.mod
index 3f2f980195..77ea78bf1f 100644
--- a/examples/token/go.mod
+++ b/examples/token/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/token/go.sum b/examples/token/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/token/go.sum
+++ b/examples/token/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/examples/zkp/cubic_circuit/go.mod b/examples/zkp/cubic_circuit/go.mod
index a9a092fbb2..a0e8a4ff84 100644
--- a/examples/zkp/cubic_circuit/go.mod
+++ b/examples/zkp/cubic_circuit/go.mod
@@ -29,7 +29,7 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect
- github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca // indirect
+ github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f // 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
diff --git a/examples/zkp/cubic_circuit/go.sum b/examples/zkp/cubic_circuit/go.sum
index ea740a3a83..4001152a76 100644
--- a/examples/zkp/cubic_circuit/go.sum
+++ b/examples/zkp/cubic_circuit/go.sum
@@ -83,8 +83,8 @@ github.com/nspcc-dev/hrw/v2 v2.0.1 h1:CxYUkBeJvNfMEn2lHhrV6FjY8pZPceSxXUtMVq0BUO
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-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
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=
diff --git a/examples/zkp/xor_compat/go.mod b/examples/zkp/xor_compat/go.mod
index 38f5d363aa..9c9f37f0b2 100644
--- a/examples/zkp/xor_compat/go.mod
+++ b/examples/zkp/xor_compat/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/zkp/xor
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/examples/zkp/xor_compat/go.sum b/examples/zkp/xor_compat/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/examples/zkp/xor_compat/go.sum
+++ b/examples/zkp/xor_compat/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/go.mod b/go.mod
index 6ef9fc34a4..88448bd1fb 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/nspcc-dev/bbolt v0.0.0-20250911202005-807225ebb0c8
github.com/nspcc-dev/dbft v0.4.0
github.com/nspcc-dev/go-ordered-json v0.0.0-20250911084817-6fb4472993d1
- github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+ github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.14
github.com/nspcc-dev/rfc6979 v0.2.4
github.com/pierrec/lz4 v2.6.1+incompatible
diff --git a/go.sum b/go.sum
index edd541c735..d9e7fbca20 100644
--- a/go.sum
+++ b/go.sum
@@ -151,8 +151,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20250911084817-6fb4472993d1 h1:U3wvY
github.com/nspcc-dev/go-ordered-json v0.0.0-20250911084817-6fb4472993d1/go.mod h1:CHwf1nwquA6ecSfxmNF0YuemOPHAnRGoLuZUv/WPjeY=
github.com/nspcc-dev/hrw/v2 v2.0.3 h1:GUIitIiDpAaQat9SZccp7XVAuwtqaM40+uZ9D8Q4A84=
github.com/nspcc-dev/hrw/v2 v2.0.3/go.mod h1:VWlFSGGPcHG1abuIDJb5u83tIF2EqOatC8Z7svZmgWQ=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.14 h1:Q0Zbu91VXckoaeNyIrQh3r/9xNnBneqBeID5FPXLmJo=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.14/go.mod h1:j/NUu5iOGFkOVYM42XoC1X9DZD0/y89Pws++w5vxtQk=
github.com/nspcc-dev/rfc6979 v0.2.4 h1:NBgsdCjhLpEPJZqmC9rciMZDcSY297po2smeaRjw57k=
diff --git a/internal/contracts/oracle_contract/go.mod b/internal/contracts/oracle_contract/go.mod
index 2309156e6e..62bab0abb2 100644
--- a/internal/contracts/oracle_contract/go.mod
+++ b/internal/contracts/oracle_contract/go.mod
@@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/internal/examples/oracle
go 1.24
-require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca
+require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f
diff --git a/internal/contracts/oracle_contract/go.sum b/internal/contracts/oracle_contract/go.sum
index 26be22f0df..7d53d90bb3 100644
--- a/internal/contracts/oracle_contract/go.sum
+++ b/internal/contracts/oracle_contract/go.sum
@@ -1,2 +1,2 @@
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca h1:4KDoJ+rCKuq5jmX2HIf9rGUBxPYPyEJKMU58lmSTBb8=
-github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250918074331-047e468014ca/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f h1:EOV4T/lbNIdUwAYBay3XbV3fL2Tq4TUvwg+GnwDX5aw=
+github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20250923153235-ffb84619d02f/go.mod h1:X2spkE8hK/l08CYulOF19fpK5n3p2xO0L1GnJFIywQg=
diff --git a/pkg/compiler/native_test.go b/pkg/compiler/native_test.go
index 665c52022a..25b3032f2b 100644
--- a/pkg/compiler/native_test.go
+++ b/pkg/compiler/native_test.go
@@ -202,6 +202,7 @@ func TestNativeHelpersCompile(t *testing.T) {
{"setMaxValidUntilBlockIncrement", []string{"10"}},
{"getMillisecondsPerBlock", nil},
{"setMillisecondsPerBlock", []string{"10"}},
+ {"getBlockedAccounts", nil},
})
runNativeTestCases(t, *cs.ByName(nativenames.Ledger).Metadata(), "ledger", []nativeTestCase{
{"currentHash", nil},
@@ -271,6 +272,8 @@ func TestNativeHelpersCompile(t *testing.T) {
{"memorySearchLastIndex", []string{"[]byte{1}", "[]byte{2}", "3"}},
{"stringSplit", []string{`"a,b"`, `","`}},
{"stringSplitNonEmpty", []string{`"a,b"`, `","`}},
+ {"hexEncode", []string{"[]byte{0, 1, 2, 3}"}},
+ {"hexDecode", []string{`"00010203"`}},
})
}
diff --git a/pkg/config/hardfork.go b/pkg/config/hardfork.go
index 142a513d61..6579826fca 100644
--- a/pkg/config/hardfork.go
+++ b/pkg/config/hardfork.go
@@ -50,8 +50,9 @@ const (
// https://github.com/neo-project/neo/pull/3895), #3854 (ported from
// https://github.com/neo-project/neo/pull/3175).
HFEchidna // Echidna
- // HFFaun represents hard-fork introduced in #3931, it's currently
- // under development and doesn't introduce any new functionality yet.
+ // HFFaun represents hard-fork introduced in #3931, #4004 (ported from
+ // https://github.com/neo-project/neo/pull/4147,
+ // https://github.com/neo-project/neo/pull/4150).
HFFaun // Faun
// hfLast denotes the end of hardforks enum. Consider adding new hardforks
// before hfLast.
diff --git a/pkg/core/native/native_test/management_test.go b/pkg/core/native/native_test/management_test.go
index 96a62e4d71..a5c8d50b14 100644
--- a/pkg/core/native/native_test/management_test.go
+++ b/pkg/core/native/native_test/management_test.go
@@ -67,6 +67,12 @@ var (
nativenames.Designation: `{"id":-8,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","abi":{"methods":[{"name":"designateAsRole","offset":0,"parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","safe":false},{"name":"getDesignatedByRole","offset":7,"parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"},{"name":"Old","type":"Array"},{"name":"New","type":"Array"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
nativenames.Notary: `{"id":-10,"hash":"0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"Notary","abi":{"methods":[{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"expirationOf","offset":7,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"getMaxNotValidBeforeDelta","offset":14,"parameters":[],"returntype":"Integer","safe":true},{"name":"lockDepositUntil","offset":21,"parameters":[{"name":"account","type":"Hash160"},{"name":"till","type":"Integer"}],"returntype":"Boolean","safe":false},{"name":"onNEP17Payment","offset":28,"parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false},{"name":"setMaxNotValidBeforeDelta","offset":35,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"verify","offset":42,"parameters":[{"name":"signature","type":"ByteArray"}],"returntype":"Boolean","safe":true},{"name":"withdraw","offset":49,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"}],"returntype":"Boolean","safe":false}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-27"],"trusts":[],"extra":null},"updatecounter":0}`,
}
+ // faunCSS holds serialized native contract states built for genesis block (with UpdateCounter 0)
+ // under assumption that hardforks from Aspidochelone to Faun (included) are enabled.
+ faunCSS = map[string]string{
+ nativenames.StdLib: `{"id":-2,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQA==","checksum":2426471238},"manifest":{"name":"StdLib","abi":{"methods":[{"name":"atoi","offset":0,"parameters":[{"name":"value","type":"String"}],"returntype":"Integer","safe":true},{"name":"atoi","offset":7,"parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","safe":true},{"name":"base58CheckDecode","offset":14,"parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","safe":true},{"name":"base58CheckEncode","offset":21,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"base58Decode","offset":28,"parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","safe":true},{"name":"base58Encode","offset":35,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"base64Decode","offset":42,"parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","safe":true},{"name":"base64Encode","offset":49,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"base64UrlDecode","offset":56,"parameters":[{"name":"s","type":"String"}],"returntype":"String","safe":true},{"name":"base64UrlEncode","offset":63,"parameters":[{"name":"data","type":"String"}],"returntype":"String","safe":true},{"name":"deserialize","offset":70,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","safe":true},{"name":"hexDecode","offset":77,"parameters":[{"name":"str","type":"String"}],"returntype":"ByteArray","safe":true},{"name":"hexEncode","offset":84,"parameters":[{"name":"bytes","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"itoa","offset":91,"parameters":[{"name":"value","type":"Integer"}],"returntype":"String","safe":true},{"name":"itoa","offset":98,"parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","safe":true},{"name":"jsonDeserialize","offset":105,"parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","safe":true},{"name":"jsonSerialize","offset":112,"parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","safe":true},{"name":"memoryCompare","offset":119,"parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","safe":true},{"name":"memorySearch","offset":126,"parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","safe":true},{"name":"memorySearch","offset":133,"parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","safe":true},{"name":"memorySearch","offset":140,"parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","safe":true},{"name":"serialize","offset":147,"parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","safe":true},{"name":"strLen","offset":154,"parameters":[{"name":"str","type":"String"}],"returntype":"Integer","safe":true},{"name":"stringSplit","offset":161,"parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","safe":true},{"name":"stringSplit","offset":168,"parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","safe":true}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
+ nativenames.Policy: `{"id":-7,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":2208257578},"manifest":{"name":"PolicyContract","abi":{"methods":[{"name":"blockAccount","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":false},{"name":"getAttributeFee","offset":7,"parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","safe":true},{"name":"getBlockedAccounts","offset":14,"parameters":[],"returntype":"InteropInterface","safe":true},{"name":"getExecFeeFactor","offset":21,"parameters":[],"returntype":"Integer","safe":true},{"name":"getFeePerByte","offset":28,"parameters":[],"returntype":"Integer","safe":true},{"name":"getMaxTraceableBlocks","offset":35,"parameters":[],"returntype":"Integer","safe":true},{"name":"getMaxValidUntilBlockIncrement","offset":42,"parameters":[],"returntype":"Integer","safe":true},{"name":"getMillisecondsPerBlock","offset":49,"parameters":[],"returntype":"Integer","safe":true},{"name":"getStoragePrice","offset":56,"parameters":[],"returntype":"Integer","safe":true},{"name":"isBlocked","offset":63,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":true},{"name":"setAttributeFee","offset":70,"parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setExecFeeFactor","offset":77,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setFeePerByte","offset":84,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setMaxTraceableBlocks","offset":91,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setMaxValidUntilBlockIncrement","offset":98,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setMillisecondsPerBlock","offset":105,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setStoragePrice","offset":112,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"unblockAccount","offset":119,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":false}],"events":[{"name":"MillisecondsPerBlockChanged","parameters":[{"name":"old","type":"Integer"},{"name":"new","type":"Integer"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
+ }
)
func init() {
@@ -80,6 +86,11 @@ func init() {
echidnaCSS[k] = v
}
}
+ for k, v := range echidnaCSS {
+ if _, ok := faunCSS[k]; !ok {
+ faunCSS[k] = v
+ }
+ }
}
func newManagementClient(t *testing.T) *neotest.ContractInvoker {
@@ -189,6 +200,19 @@ func TestManagement_GenesisNativeState(t *testing.T) {
check(t, mgmt, echidnaCSS)
})
+ t.Run("Faun enabled", func(t *testing.T) {
+ mgmt := newCustomManagementClient(t, func(cfg *config.Blockchain) {
+ cfg.Hardforks = map[string]uint32{
+ config.HFAspidochelone.String(): 0,
+ config.HFBasilisk.String(): 0,
+ config.HFCockatrice.String(): 0,
+ config.HFDomovoi.String(): 0,
+ config.HFEchidna.String(): 0,
+ config.HFFaun.String(): 0,
+ }
+ })
+ check(t, mgmt, faunCSS)
+ })
}
func TestManagement_NativeDeployUpdateNotifications(t *testing.T) {
diff --git a/pkg/core/native/native_test/policy_test.go b/pkg/core/native/native_test/policy_test.go
index 1eaf89cebb..492b747397 100644
--- a/pkg/core/native/native_test/policy_test.go
+++ b/pkg/core/native/native_test/policy_test.go
@@ -1,17 +1,24 @@
package native_test
import (
+ "bytes"
"fmt"
+ "slices"
+ "strings"
"testing"
"time"
+ "github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
+ "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
"github.com/nspcc-dev/neo-go/pkg/core/native"
+ "github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
"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/io"
"github.com/nspcc-dev/neo-go/pkg/neotest"
+ "github.com/nspcc-dev/neo-go/pkg/neotest/chain"
"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"
@@ -363,3 +370,91 @@ func TestPolicy_BlockedAccounts(t *testing.T) {
helperInvoker.Invoke(t, true, "do")
})
}
+
+func TestPolicy_GetBlockedAccounts(t *testing.T) {
+ bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
+ c.Hardforks = map[string]uint32{
+ config.HFFaun.String(): 2,
+ }
+ })
+ e := neotest.NewExecutor(t, bc, acc, acc)
+ p := e.CommitteeInvoker(nativehashes.PolicyContract)
+
+ p.InvokeFail(t, "method not found: getBlockedAccounts/0", "getBlockedAccounts")
+
+ blockedCount := 3
+ blocked := make([]util.Uint160, 0, blockedCount)
+ expected := make([]stackitem.Item, 0, blockedCount)
+ for i := range blockedCount {
+ blocked = append(blocked, e.NewAccount(t, 0).ScriptHash())
+ p.Invoke(t, true, "blockAccount", blocked[i])
+ expected = append(expected, stackitem.Make(blocked[i]))
+ }
+ slices.SortFunc(expected, func(a, b stackitem.Item) int {
+ return bytes.Compare(a.Value().([]byte), b.Value().([]byte))
+ })
+
+ checkGetBlockedAccounts := func(t *testing.T, expected []stackitem.Item) {
+ for i := range expected {
+ w := io.NewBufBinWriter()
+ emit.AppCall(w.BinWriter, p.Hash, "getBlockedAccounts", callflag.All)
+
+ for range i + 1 {
+ emit.Opcodes(w.BinWriter, opcode.DUP)
+ emit.Syscall(w.BinWriter, interopnames.SystemIteratorNext)
+ emit.Opcodes(w.BinWriter, opcode.DROP)
+ }
+
+ emit.Syscall(w.BinWriter, interopnames.SystemIteratorValue)
+ require.NoError(t, w.Err)
+ h := p.InvokeScript(t, w.Bytes(), p.Signers)
+
+ if i < len(expected) {
+ e.CheckHalt(t, h, expected[i])
+ } else {
+ e.CheckFault(t, h, "iterator index out of range")
+ }
+ w.Reset()
+ }
+ }
+
+ checkGetBlockedAccounts(t, expected)
+ p.Invoke(t, true, "unblockAccount", expected[0])
+ checkGetBlockedAccounts(t, expected[1:])
+}
+
+func TestPolicy_GetBlockedAccountsInteropAPI(t *testing.T) {
+ bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
+ c.Hardforks = map[string]uint32{
+ config.HFFaun.String(): 0,
+ }
+ })
+ e := neotest.NewExecutor(t, bc, acc, acc)
+ p := e.CommitteeInvoker(nativehashes.PolicyContract)
+
+ unlucky := e.NewAccount(t, 0)
+ p.Invoke(t, true, "blockAccount", unlucky.ScriptHash())
+
+ src := `package testpolicy
+ import (
+ "github.com/nspcc-dev/neo-go/pkg/interop"
+ "github.com/nspcc-dev/neo-go/pkg/interop/native/policy"
+ "github.com/nspcc-dev/neo-go/pkg/interop/iterator"
+ )
+ func GetBlockedAccounts() []interop.Hash160 {
+ i := policy.GetBlockedAccounts()
+ var res []interop.Hash160
+ for iterator.Next(i) {
+ res = append(res, iterator.Value(i).(interop.Hash160))
+ }
+ return res
+ }`
+
+ ctr := neotest.CompileSource(t, e.Validator.ScriptHash(), strings.NewReader(src), &compiler.Options{
+ Name: "testpolicy_contract",
+ })
+ e.DeployContract(t, ctr, nil)
+
+ ctrInvoker := e.NewInvoker(ctr.Hash, e.Committee)
+ ctrInvoker.Invoke(t, []stackitem.Item{stackitem.NewBuffer(unlucky.ScriptHash().BytesBE())}, "getBlockedAccounts")
+}
diff --git a/pkg/core/native/native_test/std_test.go b/pkg/core/native/native_test/std_test.go
new file mode 100644
index 0000000000..f824e523a5
--- /dev/null
+++ b/pkg/core/native/native_test/std_test.go
@@ -0,0 +1,66 @@
+package native
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/nspcc-dev/neo-go/pkg/compiler"
+ "github.com/nspcc-dev/neo-go/pkg/config"
+ "github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
+ "github.com/nspcc-dev/neo-go/pkg/neotest"
+ "github.com/nspcc-dev/neo-go/pkg/neotest/chain"
+ "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
+)
+
+func TestStd_HexEncodeDecodeCompat(t *testing.T) {
+ bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
+ c.Hardforks = map[string]uint32{
+ config.HFFaun.String(): 2,
+ }
+ })
+ e := neotest.NewExecutor(t, bc, acc, acc)
+ p := e.CommitteeInvoker(nativehashes.StdLib)
+
+ expectedBytes := []byte{0x00, 0x01, 0x02, 0x03}
+ expectedString := "00010203"
+
+ p.InvokeFail(t, "method not found: hexEncode/1", "hexEncode", expectedBytes)
+
+ e.AddNewBlock(t)
+
+ p.Invoke(t, expectedString, "hexEncode", expectedBytes)
+ p.Invoke(t, expectedBytes, "hexDecode", expectedString)
+}
+
+func TestStd_HexEncodeDecodeInteropAPI(t *testing.T) {
+ bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
+ c.Hardforks = map[string]uint32{
+ config.HFFaun.String(): 0,
+ }
+ })
+ e := neotest.NewExecutor(t, bc, acc, acc)
+
+ src := `package teststd
+ import (
+ "github.com/nspcc-dev/neo-go/pkg/interop/native/std"
+ )
+ func Encode(args []any) string {
+ return std.HexEncode(args[0].([]byte))
+ }
+ func Decode(args []any) []byte {
+ return std.HexDecode(args[0].(string))
+ }`
+
+ ctr := neotest.CompileSource(t, e.Validator.ScriptHash(), strings.NewReader(src), &compiler.Options{
+ Name: "teststd_contract",
+ })
+ e.DeployContract(t, ctr, nil)
+
+ expectedBytes := []byte{0x00, 0x01, 0x02, 0x03}
+ expectedString := "00010203"
+
+ ctrInvoker := e.NewInvoker(ctr.Hash, e.Committee)
+
+ ctrInvoker.Invoke(t, stackitem.Make(expectedString), "encode", []any{expectedBytes})
+ ctrInvoker.Invoke(t, stackitem.Make(expectedBytes), "decode", []any{expectedString})
+}
diff --git a/pkg/core/native/policy.go b/pkg/core/native/policy.go
index 64480edcb9..55dc049949 100644
--- a/pkg/core/native/policy.go
+++ b/pkg/core/native/policy.go
@@ -211,6 +211,10 @@ func newPolicy() *Policy {
md = NewMethodAndPrice(p.setMaxTraceableBlocks, 1<<15, callflag.States, config.HFEchidna)
p.AddMethod(md, desc)
+ desc = NewDescriptor("getBlockedAccounts", smartcontract.InteropInterfaceType)
+ md = NewMethodAndPrice(p.getBlockedAccounts, 1<<15, callflag.ReadStates, config.HFFaun)
+ p.AddMethod(md, desc)
+
return p
}
@@ -445,6 +449,12 @@ func (p *Policy) getAttributeFeeGeneric(ic *interop.Context, args []stackitem.It
return stackitem.NewBigInteger(big.NewInt(p.GetAttributeFeeInternal(ic.DAO, t)))
}
+func (p *Policy) getBlockedAccounts(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
+ cache := ic.DAO.GetROCache(p.ID).(*PolicyCache)
+ cloned := slices.Clone(cache.blockedAccounts)
+ return stackitem.NewInterop(&iterator{keys: cloned})
+}
+
// GetAttributeFeeInternal returns required transaction's attribute fee.
func (p *Policy) GetAttributeFeeInternal(d *dao.Simple, t transaction.AttrType) int64 {
cache := d.GetROCache(p.ID).(*PolicyCache)
@@ -668,3 +678,27 @@ func (p *Policy) CheckPolicy(d *dao.Simple, tx *transaction.Transaction) error {
}
return nil
}
+
+// iterator provides an iterator over a slice of keys.
+type iterator struct {
+ keys []util.Uint160
+ next bool
+}
+
+// Next advances the iterator and returns true if Value can be called at the
+// current position.
+func (i *iterator) Next() bool {
+ if i.next {
+ i.keys = i.keys[1:]
+ }
+ i.next = len(i.keys) > 0
+ return i.next
+}
+
+// Value returns current iterators value.
+func (i *iterator) Value() stackitem.Item {
+ if !i.next {
+ panic("iterator index out of range")
+ }
+ return stackitem.Make(i.keys[0])
+}
diff --git a/pkg/core/native/std.go b/pkg/core/native/std.go
index e3a1956e48..117829b17b 100644
--- a/pkg/core/native/std.go
+++ b/pkg/core/native/std.go
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/hex"
"errors"
+ "fmt"
"math/big"
"slices"
"strings"
@@ -172,6 +173,16 @@ func newStd() *Std {
md = NewMethodAndPrice(s.strLen, 1<<8, callflag.NoneFlag)
s.AddMethod(md, desc)
+ desc = NewDescriptor("hexEncode", smartcontract.StringType,
+ manifest.NewParameter("bytes", smartcontract.ByteArrayType))
+ md = NewMethodAndPrice(s.hexEncode, 1<<5, callflag.NoneFlag, config.HFFaun)
+ s.AddMethod(md, desc)
+
+ desc = NewDescriptor("hexDecode", smartcontract.ByteArrayType,
+ manifest.NewParameter("str", smartcontract.StringType))
+ md = NewMethodAndPrice(s.hexDecode, 1<<5, callflag.NoneFlag, config.HFFaun)
+ s.AddMethod(md, desc)
+
return s
}
@@ -321,6 +332,20 @@ func (s *Std) base64Decode(_ *interop.Context, args []stackitem.Item) stackitem.
return stackitem.NewByteArray(result)
}
+func (s *Std) hexEncode(_ *interop.Context, args []stackitem.Item) stackitem.Item {
+ src := toLimitedBytes(args[0])
+ return stackitem.NewByteArray([]byte(hex.EncodeToString(src)))
+}
+
+func (s *Std) hexDecode(_ *interop.Context, args []stackitem.Item) stackitem.Item {
+ src := toLimitedString(args[0])
+ dst, err := hex.DecodeString(src)
+ if err != nil {
+ panic(fmt.Errorf("hexDecode: invalid hex string %q: %w", src, err))
+ }
+ return stackitem.NewByteArray(dst)
+}
+
func (s *Std) base64UrlEncode(_ *interop.Context, args []stackitem.Item) stackitem.Item {
src := toLimitedBytes(args[0])
result := base64.URLEncoding.EncodeToString(src)
diff --git a/pkg/core/native/std_test.go b/pkg/core/native/std_test.go
index 88c5a4d7e9..bc3daeb486 100644
--- a/pkg/core/native/std_test.go
+++ b/pkg/core/native/std_test.go
@@ -639,3 +639,51 @@ func TestStd_StrLen(t *testing.T) {
check(t, 1, bad)
check(t, 3, bad+"ab")
}
+
+func TestStd_HexEncodeDecode(t *testing.T) {
+ s := newStd()
+ var actual stackitem.Item
+
+ original := []byte("abc")
+ hexStr := hex.EncodeToString(original)
+
+ t.Run("hexEncode positive", func(t *testing.T) {
+ require.NotPanics(t, func() {
+ actual = s.hexEncode(nil, []stackitem.Item{stackitem.Make(original)})
+ })
+ require.Equal(t, stackitem.Make(hexStr), actual)
+ })
+
+ t.Run("hexEncode error big input", func(t *testing.T) {
+ bigBytes := make([]byte, stdMaxInputLength+1)
+ require.PanicsWithError(t, ErrTooBigInput.Error(), func() {
+ _ = s.hexEncode(nil, []stackitem.Item{stackitem.Make(bigBytes)})
+ })
+ })
+
+ t.Run("hexDecode positive", func(t *testing.T) {
+ require.NotPanics(t, func() {
+ actual = s.hexDecode(nil, []stackitem.Item{stackitem.Make(hexStr)})
+ })
+ require.Equal(t, stackitem.Make(original), actual)
+ })
+
+ t.Run("hexDecode error invalid chars", func(t *testing.T) {
+ require.Panics(t, func() {
+ _ = s.hexDecode(nil, []stackitem.Item{stackitem.Make("zz")})
+ })
+ })
+
+ t.Run("hexDecode error invalid conversion", func(t *testing.T) {
+ require.Panics(t, func() {
+ _ = s.hexDecode(nil, []stackitem.Item{stackitem.NewMap()})
+ })
+ })
+
+ t.Run("hexDecode error big input", func(t *testing.T) {
+ bigBytes := []stackitem.Item{stackitem.NewByteArray(make([]byte, stdMaxInputLength+1))}
+ require.PanicsWithError(t, ErrTooBigInput.Error(), func() {
+ _ = s.hexDecode(nil, bigBytes)
+ })
+ })
+}
diff --git a/pkg/interop/native/policy/policy.go b/pkg/interop/native/policy/policy.go
index 45dfe869c3..e30b7f3efb 100644
--- a/pkg/interop/native/policy/policy.go
+++ b/pkg/interop/native/policy/policy.go
@@ -7,6 +7,7 @@ package policy
import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
+ "github.com/nspcc-dev/neo-go/pkg/interop/iterator"
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
)
@@ -91,3 +92,9 @@ func GetMillisecondsPerBlock() int {
func SetMillisecondsPerBlock(value int) {
neogointernal.CallWithTokenNoRet(Hash, "setMillisecondsPerBlock", int(contract.States|contract.AllowNotify), value)
}
+
+// GetBlockedAccounts represents `getBlockedAccounts` method of Policy native contract.
+// Note that this method is available starting from [config.HFFaun] hardfork.
+func GetBlockedAccounts() iterator.Iterator {
+ return neogointernal.CallWithToken(Hash, "getBlockedAccounts", int(contract.ReadStates)).(iterator.Iterator)
+}
diff --git a/pkg/interop/native/std/std.go b/pkg/interop/native/std/std.go
index 8bf2b8fbf5..17d38d7c00 100644
--- a/pkg/interop/native/std/std.go
+++ b/pkg/interop/native/std/std.go
@@ -180,3 +180,19 @@ func StrLen(s string) int {
return neogointernal.CallWithToken(Hash, "strLen", int(contract.NoneFlag),
s).(int)
}
+
+// HexEncode encodes a given byte slice into a hex string and returns it.
+// It uses `hexEncode` method of StdLib native contract. Note that this method is
+// available starting from [config.HFFaun] hardfork.
+func HexEncode(b []byte) string {
+ return neogointernal.CallWithToken(Hash, "hexEncode", int(contract.NoneFlag),
+ b).(string)
+}
+
+// HexDecode decodes a given hex string into a byte slice and returns it.
+// It uses `hexDecode` method of StdLib native contract. Note that this method is
+// available starting from [config.HFFaun] hardfork.
+func HexDecode(s string) []byte {
+ return neogointernal.CallWithToken(Hash, "hexDecode", int(contract.NoneFlag),
+ s).([]byte)
+}
diff --git a/pkg/rpcclient/policy/policy.go b/pkg/rpcclient/policy/policy.go
index f90478565c..72b222cc1b 100644
--- a/pkg/rpcclient/policy/policy.go
+++ b/pkg/rpcclient/policy/policy.go
@@ -7,17 +7,24 @@ various methods to perform PolicyContract state-changing calls.
package policy
import (
+ "fmt"
+
+ "github.com/google/uuid"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
+ "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
// Invoker is used by ContractReader to call various 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 create and send transactions.
@@ -58,6 +65,13 @@ type Contract struct {
actor Actor
}
+// BlockedAccountsIterator is used for iterating over GetBlockedAccounts results.
+type BlockedAccountsIterator struct {
+ client Invoker
+ session uuid.UUID
+ iterator result.Iterator
+}
+
// NewReader creates an instance of ContractReader that can be used to read
// data from the contract.
func NewReader(invoker Invoker) *ContractReader {
@@ -108,6 +122,62 @@ func (c *ContractReader) GetMillisecondsPerBlock() (int64, error) {
return unwrap.Int64(c.invoker.Call(Hash, "getMillisecondsPerBlock"))
}
+// GetBlockedAccounts returns current blocked accounts. Note that this method is
+// available starting from [config.HFFaun] hardfork.
+func (c *ContractReader) GetBlockedAccounts() (*BlockedAccountsIterator, error) {
+ sess, iter, err := unwrap.SessionIterator(c.invoker.Call(Hash, "getBlockedAccounts"))
+ if err != nil {
+ return nil, err
+ }
+
+ return &BlockedAccountsIterator{
+ client: c.invoker,
+ iterator: iter,
+ session: sess,
+ }, nil
+}
+
+// GetBlockedAccountsExpanded is similar to GetBlockedAccounts (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 num
+// 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) GetBlockedAccountsExpanded(num int) ([]util.Uint160, error) {
+ return unwrap.ArrayOfUint160(c.invoker.CallAndExpandIterator(Hash, "getBlockedAccounts", num))
+}
+
+// Next returns the next set of elements from the iterator (up to num of them).
+// It can return less than num elements in case iterator doesn't have that many
+// or zero elements if the iterator has no more elements or the session is
+// expired.
+func (b *BlockedAccountsIterator) Next(num int) ([]util.Uint160, error) {
+ items, err := b.client.TraverseIterator(b.session, &b.iterator, num)
+ if err != nil {
+ return nil, err
+ }
+ res := make([]util.Uint160, len(items))
+ for i, itm := range items {
+ hb, err := itm.TryBytes()
+ if err != nil {
+ return nil, fmt.Errorf("item #%d has wrong hash: %w", i, err)
+ }
+ res[i], err = util.Uint160DecodeBytesBE(hb)
+ if err != nil {
+ return nil, fmt.Errorf("item #%d has wrong hash: %w", i, err)
+ }
+ }
+ return res, nil
+}
+
+// Terminate closes the iterator session used by BlockedAccountsIterator (if it's
+// session-based).
+func (b *BlockedAccountsIterator) Terminate() error {
+ if b.iterator.ID == nil {
+ return nil
+ }
+ return b.client.TerminateSession(b.session)
+}
+
// IsBlocked checks if the given account is blocked in the PolicyContract.
func (c *ContractReader) IsBlocked(account util.Uint160) (bool, error) {
return unwrap.Bool(c.invoker.Call(Hash, "isBlocked", account))
diff --git a/pkg/rpcclient/policy/policy_test.go b/pkg/rpcclient/policy/policy_test.go
index 88808d5bf2..bc03f4865d 100644
--- a/pkg/rpcclient/policy/policy_test.go
+++ b/pkg/rpcclient/policy/policy_test.go
@@ -4,6 +4,7 @@ import (
"errors"
"testing"
+ "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/util"
@@ -40,6 +41,15 @@ func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute)
func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) {
return t.txh, t.vub, t.err
}
+func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) {
+ return t.res, t.err
+}
+func (t *testAct) TerminateSession(sessionID uuid.UUID) error {
+ return t.err
+}
+func (t *testAct) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) {
+ return t.res.Stack, t.err
+}
func TestReader(t *testing.T) {
ta := new(testAct)
@@ -89,6 +99,91 @@ func TestReader(t *testing.T) {
require.True(t, val)
}
+func TestGetBlockedAccounts(t *testing.T) {
+ ta := &testAct{}
+ man := NewReader(ta)
+
+ ta.err = errors.New("")
+ _, err := man.GetBlockedAccounts()
+ require.Error(t, err)
+ _, err = man.GetBlockedAccountsExpanded(5)
+ require.Error(t, err)
+
+ ta.err = nil
+ iid := uuid.New()
+ ta.res = &result.Invoke{
+ State: "HALT",
+ Stack: []stackitem.Item{
+ stackitem.NewInterop(result.Iterator{
+ ID: &iid,
+ }),
+ },
+ }
+ _, err = man.GetBlockedAccounts()
+ require.Error(t, err)
+
+ sid := uuid.New()
+ ta.res = &result.Invoke{
+ Session: sid,
+ State: "HALT",
+ Stack: []stackitem.Item{
+ stackitem.NewInterop(result.Iterator{
+ ID: &iid,
+ }),
+ },
+ }
+ iter, err := man.GetBlockedAccounts()
+ require.NoError(t, err)
+
+ ta.res = &result.Invoke{
+ Stack: []stackitem.Item{
+ stackitem.Make(util.Uint160{1, 2, 3}),
+ },
+ }
+ vals, err := iter.Next(10)
+ require.NoError(t, err)
+ require.Equal(t, 1, len(vals))
+ require.Equal(t, util.Uint160{1, 2, 3}, vals[0])
+
+ ta.err = errors.New("")
+ _, err = iter.Next(1)
+ require.Error(t, err)
+ err = iter.Terminate()
+ require.Error(t, err)
+
+ ta.err = nil
+ ta.res = &result.Invoke{
+ State: "HALT",
+ Stack: []stackitem.Item{
+ stackitem.NewInterop(result.Iterator{
+ Values: []stackitem.Item{
+ stackitem.Make(util.Uint160{1, 2, 3}),
+ },
+ }),
+ },
+ }
+ iter, err = man.GetBlockedAccounts()
+ require.NoError(t, err)
+
+ ta.err = errors.New("")
+ err = iter.Terminate()
+ require.NoError(t, err)
+
+ ta.err = nil
+ ta.res = &result.Invoke{
+ State: "HALT",
+ Stack: []stackitem.Item{
+ stackitem.Make([]stackitem.Item{
+ stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()),
+ }),
+ },
+ }
+ expandedVals, err := man.GetBlockedAccountsExpanded(5)
+ require.NoError(t, err)
+ require.Equal(t, 1, len(expandedVals))
+ require.Equal(t, util.Uint160{1, 2, 3}, expandedVals[0])
+}
+
func TestIntSetters(t *testing.T) {
ta := new(testAct)
pc := New(ta)
diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go
index 651228a6da..63c1d2e47f 100644
--- a/pkg/services/rpcsrv/client_test.go
+++ b/pkg/services/rpcsrv/client_test.go
@@ -164,7 +164,14 @@ func TestClientRoleManagement(t *testing.T) {
}
func TestClientPolicyContract(t *testing.T) {
- chain, _, httpSrv := initServerWithInMemoryChain(t)
+ chain, _, httpSrv := initClearServerWithCustomConfig(t, func(cfg *config.Config) {
+ cfg.ProtocolConfiguration.Hardforks = map[string]uint32{
+ config.HFFaun.String(): 0,
+ }
+ })
+ for _, b := range getTestBlocks(t) {
+ require.NoError(t, chain.AddBlock(b))
+ }
c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{})
require.NoError(t, err)
@@ -221,14 +228,19 @@ func TestClientPolicyContract(t *testing.T) {
txattr, err := polis.SetAttributeFeeUnsigned(transaction.NotaryAssistedT, 100500)
require.NoError(t, err)
- txblock, err := polis.BlockAccountUnsigned(util.Uint160{1, 2, 3})
+ blocked := []util.Uint160{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
+ txblock1, err := polis.BlockAccountUnsigned(blocked[0])
+ require.NoError(t, err)
+ txblock2, err := polis.BlockAccountUnsigned(blocked[1])
+ require.NoError(t, err)
+ txblock3, err := polis.BlockAccountUnsigned(blocked[2])
require.NoError(t, err)
- for _, tx := range []*transaction.Transaction{txattr, txblock, txstorage, txnetfee, txexec} {
+ for _, tx := range []*transaction.Transaction{txattr, txblock1, txblock2, txblock3, txstorage, txnetfee, txexec} {
tx.Scripts[0].InvocationScript = testchain.SignCommittee(tx)
}
- bl := testchain.NewBlock(t, chain, 1, 0, txattr, txblock, txstorage, txnetfee, txexec)
+ bl := testchain.NewBlock(t, chain, 1, 0, txattr, txblock1, txblock2, txblock3, txstorage, txnetfee, txexec)
_, err = c.SubmitBlock(*bl)
require.NoError(t, err)
@@ -251,6 +263,19 @@ func TestClientPolicyContract(t *testing.T) {
ret, err = polizei.IsBlocked(util.Uint160{1, 2, 3})
require.NoError(t, err)
require.True(t, ret)
+
+ all, err := polizei.GetBlockedAccountsExpanded(100)
+ require.NoError(t, err)
+ slices.SortFunc(blocked, func(a, b util.Uint160) int {
+ return bytes.Compare(a[:], b[:])
+ })
+ require.Equal(t, blocked, all)
+
+ it, err := polizei.GetBlockedAccounts()
+ require.NoError(t, err)
+ all, err = it.Next(100)
+ require.NoError(t, err)
+ require.Equal(t, blocked, all)
}
func TestClientManagementContract(t *testing.T) {