Merge pull request #2447 from nspcc-dev/gettransactionsigners
core: add GetTransactionSigners method to native Ledger
This commit is contained in:
commit
3ae1647940
35 changed files with 533 additions and 61 deletions
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
8
examples/nft-d/us.stackdump
Normal file
8
examples/nft-d/us.stackdump
Normal file
|
@ -0,0 +1,8 @@
|
|||
MSYS-1.0.19 Build:2016-07-13 17:45
|
||||
Exception: STATUS_ACCESS_VIOLATION at eip=0072174E
|
||||
eax=608F9138 ebx=00000000 ecx=60EA0000 edx=60EA4184 esi=00993208 edi=00000001
|
||||
ebp=0069FEB0 esp=0069FE48 program=us
|
||||
cs=0023 ds=002B es=002B fs=0053 gs=002B ss=002B
|
||||
Stack trace:
|
||||
Frame Function Args
|
||||
15750 [main] us 0 handle_exceptions: Error while dumping state (probably corrupted stack)
|
|
@ -3,7 +3,7 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd-nns
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/nspcc-dev/neo-go v0.98.3-pre.0.20220421162730-3463d7292fb9
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
github.com/nspcc-dev/neo-go v0.98.3-pre.0.20220429082343-69b70c5e933a
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
github.com/stretchr/testify v1.7.0
|
||||
)
|
||||
|
|
|
@ -177,10 +177,10 @@ 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.98.3-pre.0.20220421162730-3463d7292fb9 h1:hflyJ+EnjaLPXtpxM4Wibqo4ppnfXCjf4kBUzxvp/MU=
|
||||
github.com/nspcc-dev/neo-go v0.98.3-pre.0.20220421162730-3463d7292fb9/go.mod h1:LGZ16CRv4Nfh7KTt99CH/bhjOlTPQPbJcICJ4onP4Ds=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go v0.98.3-pre.0.20220429082343-69b70c5e933a h1:5tTKYXxz/DRDopPpf2/2rcdkESDm/RWH3t5aNXyGtAc=
|
||||
github.com/nspcc-dev/neo-go v0.98.3-pre.0.20220429082343-69b70c5e933a/go.mod h1:hKgAWnSYaq5FIg8XclLvG5gjsjjFMkFhklyO092/sGM=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
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=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token
|
|||
|
||||
go 1.16
|
||||
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
|
|
2
go.mod
2
go.mod
|
@ -12,7 +12,7 @@ require (
|
|||
github.com/mr-tron/base58 v1.2.0
|
||||
github.com/nspcc-dev/dbft v0.0.0-20220414131237-e497bbf7868e
|
||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47
|
||||
github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible
|
||||
|
|
4
go.sum
4
go.sum
|
@ -185,8 +185,8 @@ github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
|
|||
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
|
||||
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
|
||||
github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c h1:D0iDtGEnFbld/tllTbv3ah4BQPPaItTs/Y8Li5zrEOw=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220421162616-d942940a826c/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47 h1:9PVLOwD2khKIb4BQR7nqeslE1pRSGxJoXvul2/Rk1wY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220429082221-441a3eb34c47/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y=
|
||||
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=
|
||||
|
|
|
@ -89,6 +89,32 @@ func TestOracleContractValues(t *testing.T) {
|
|||
require.EqualValues(t, oracle.MinimumResponseGas, native.MinimumResponseGas)
|
||||
}
|
||||
|
||||
func TestLedgerTransactionWitnessScope(t *testing.T) {
|
||||
require.EqualValues(t, ledger.None, transaction.None)
|
||||
require.EqualValues(t, ledger.CalledByEntry, transaction.CalledByEntry)
|
||||
require.EqualValues(t, ledger.CustomContracts, transaction.CustomContracts)
|
||||
require.EqualValues(t, ledger.CustomGroups, transaction.CustomGroups)
|
||||
require.EqualValues(t, ledger.Rules, transaction.Rules)
|
||||
require.EqualValues(t, ledger.Global, transaction.Global)
|
||||
}
|
||||
|
||||
func TestLedgerTransactionWitnessAction(t *testing.T) {
|
||||
require.EqualValues(t, ledger.WitnessAllow, transaction.WitnessAllow)
|
||||
require.EqualValues(t, ledger.WitnessDeny, transaction.WitnessDeny)
|
||||
}
|
||||
|
||||
func TestLedgerTransactionWitnessCondition(t *testing.T) {
|
||||
require.EqualValues(t, ledger.WitnessBoolean, transaction.WitnessBoolean)
|
||||
require.EqualValues(t, ledger.WitnessNot, transaction.WitnessNot)
|
||||
require.EqualValues(t, ledger.WitnessAnd, transaction.WitnessAnd)
|
||||
require.EqualValues(t, ledger.WitnessOr, transaction.WitnessOr)
|
||||
require.EqualValues(t, ledger.WitnessScriptHash, transaction.WitnessScriptHash)
|
||||
require.EqualValues(t, ledger.WitnessGroup, transaction.WitnessGroup)
|
||||
require.EqualValues(t, ledger.WitnessCalledByEntry, transaction.WitnessCalledByEntry)
|
||||
require.EqualValues(t, ledger.WitnessCalledByContract, transaction.WitnessCalledByContract)
|
||||
require.EqualValues(t, ledger.WitnessCalledByGroup, transaction.WitnessCalledByGroup)
|
||||
}
|
||||
|
||||
func TestLedgerVMStates(t *testing.T) {
|
||||
require.EqualValues(t, ledger.NoneState, vm.NoneState)
|
||||
require.EqualValues(t, ledger.HaltState, vm.HaltState)
|
||||
|
@ -158,6 +184,7 @@ func TestNativeHelpersCompile(t *testing.T) {
|
|||
{"getTransaction", []string{u256}},
|
||||
{"getTransactionFromBlock", []string{u256, "1"}},
|
||||
{"getTransactionHeight", []string{u256}},
|
||||
{"getTransactionSigners", []string{u256}},
|
||||
{"getTransactionVMState", []string{u256}},
|
||||
})
|
||||
runNativeTestCases(t, cs.Notary.ContractMD, "notary", []nativeTestCase{
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
|
@ -63,6 +64,11 @@ func newLedger() *Ledger {
|
|||
md = newMethodAndPrice(l.getTransactionFromBlock, 1<<16, callflag.ReadStates)
|
||||
l.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("getTransactionSigners", smartcontract.ArrayType,
|
||||
manifest.NewParameter("hash", smartcontract.Hash256Type))
|
||||
md = newMethodAndPrice(l.getTransactionSigners, 1<<15, callflag.ReadStates)
|
||||
l.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("getTransactionVMState", smartcontract.IntegerType,
|
||||
manifest.NewParameter("hash", smartcontract.Hash256Type))
|
||||
md = newMethodAndPrice(l.getTransactionVMState, 1<<15, callflag.ReadStates)
|
||||
|
@ -148,6 +154,15 @@ func (l *Ledger) getTransactionFromBlock(ic *interop.Context, params []stackitem
|
|||
return TransactionToStackItem(block.Transactions[index])
|
||||
}
|
||||
|
||||
// getTransactionSigners returns transaction signers to the SC.
|
||||
func (l *Ledger) getTransactionSigners(ic *interop.Context, params []stackitem.Item) stackitem.Item {
|
||||
tx, h, err := getTransactionAndHeight(ic.DAO, params[0])
|
||||
if err != nil || !isTraceableBlock(ic.Chain, h) {
|
||||
return stackitem.Null{}
|
||||
}
|
||||
return SignersToStackItem(tx.Signers)
|
||||
}
|
||||
|
||||
// getTransactionVMState returns VM state got after transaction invocation.
|
||||
func (l *Ledger) getTransactionVMState(ic *interop.Context, params []stackitem.Item) stackitem.Item {
|
||||
hash, err := getUint256FromItem(params[0])
|
||||
|
@ -242,3 +257,37 @@ func TransactionToStackItem(t *transaction.Transaction) stackitem.Item {
|
|||
stackitem.NewByteArray(t.Script),
|
||||
})
|
||||
}
|
||||
|
||||
// SignersToStackItem converts transaction.Signers to stackitem.Item.
|
||||
func SignersToStackItem(signers []transaction.Signer) stackitem.Item {
|
||||
res := make([]stackitem.Item, len(signers))
|
||||
bw := io.NewBufBinWriter()
|
||||
for i, s := range signers {
|
||||
s.EncodeBinary(bw.BinWriter)
|
||||
if bw.Err != nil {
|
||||
panic(fmt.Errorf("failed to serialize signer %d to stackitem: %w", i, bw.Err))
|
||||
}
|
||||
contracts := make([]stackitem.Item, len(s.AllowedContracts))
|
||||
for j, c := range s.AllowedContracts {
|
||||
contracts[j] = stackitem.NewByteArray(c.BytesBE())
|
||||
}
|
||||
groups := make([]stackitem.Item, len(s.AllowedGroups))
|
||||
for j, g := range s.AllowedGroups {
|
||||
groups[j] = stackitem.NewByteArray(g.Bytes())
|
||||
}
|
||||
rules := make([]stackitem.Item, len(s.Rules))
|
||||
for j, r := range s.Rules {
|
||||
rules[j] = r.ToStackItem()
|
||||
}
|
||||
res[i] = stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray(bw.Bytes()),
|
||||
stackitem.NewByteArray(s.Account.BytesBE()),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(s.Scopes))),
|
||||
stackitem.NewArray(contracts),
|
||||
stackitem.NewArray(groups),
|
||||
stackitem.NewArray(rules),
|
||||
})
|
||||
bw.Reset()
|
||||
}
|
||||
return stackitem.NewArray(res)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
package native_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"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/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/util"
|
||||
|
@ -172,3 +177,127 @@ func TestLedger_GetBlock(t *testing.T) {
|
|||
ledgerInvoker.Invoke(t, stackitem.Null{}, "getBlock", b.Hash())
|
||||
})
|
||||
}
|
||||
|
||||
func TestLedger_GetTransactionSigners(t *testing.T) {
|
||||
c := newLedgerClient(t)
|
||||
e := c.Executor
|
||||
ledgerInvoker := c.WithSigners(c.Committee)
|
||||
|
||||
txHash := ledgerInvoker.Invoke(t, e.Chain.BlockHeight(), "currentIndex")
|
||||
|
||||
t.Run("good", func(t *testing.T) {
|
||||
s := &transaction.Signer{
|
||||
Account: c.CommitteeHash,
|
||||
Scopes: transaction.Global,
|
||||
}
|
||||
bw := io.NewBufBinWriter()
|
||||
s.EncodeBinary(bw.BinWriter)
|
||||
require.NoError(t, bw.Err)
|
||||
expected := stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray(bw.Bytes()),
|
||||
stackitem.NewByteArray(s.Account.BytesBE()),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(s.Scopes))),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
}),
|
||||
})
|
||||
ledgerInvoker.Invoke(t, expected, "getTransactionSigners", txHash)
|
||||
})
|
||||
t.Run("unknown transaction", func(t *testing.T) {
|
||||
ledgerInvoker.Invoke(t, stackitem.Null{}, "getTransactionSigners", util.Uint256{1, 2, 3})
|
||||
})
|
||||
t.Run("not a hash", func(t *testing.T) {
|
||||
ledgerInvoker.InvokeFail(t, "expected []byte of size 32", "getTransactionSigners", []byte{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
func TestLedger_GetTransactionSignersInteropAPI(t *testing.T) {
|
||||
c := newLedgerClient(t)
|
||||
e := c.Executor
|
||||
ledgerInvoker := c.WithSigners(c.Committee)
|
||||
|
||||
// Firstly, add transaction with CalledByEntry rule-based signer scope to the chain.
|
||||
tx := e.NewUnsignedTx(t, ledgerInvoker.Hash, "currentIndex")
|
||||
tx.Signers = []transaction.Signer{{
|
||||
Account: c.Committee.ScriptHash(),
|
||||
Scopes: transaction.Rules,
|
||||
Rules: []transaction.WitnessRule{
|
||||
{
|
||||
Action: transaction.WitnessAllow,
|
||||
Condition: transaction.ConditionCalledByEntry{},
|
||||
},
|
||||
},
|
||||
}}
|
||||
neotest.AddNetworkFee(e.Chain, tx, c.Committee)
|
||||
neotest.AddSystemFee(e.Chain, tx, -1)
|
||||
require.NoError(t, c.Committee.SignTx(e.Chain.GetConfig().Magic, tx))
|
||||
c.AddNewBlock(t, tx)
|
||||
c.CheckHalt(t, tx.Hash(), stackitem.Make(e.Chain.BlockHeight()-1))
|
||||
|
||||
var (
|
||||
hashStr string
|
||||
accStr string
|
||||
txHash = tx.Hash().BytesBE()
|
||||
acc = c.Committee.ScriptHash().BytesBE()
|
||||
)
|
||||
for i := 0; i < util.Uint256Size; i++ {
|
||||
hashStr += fmt.Sprintf("%#x", txHash[i])
|
||||
if i != util.Uint256Size-1 {
|
||||
hashStr += ", "
|
||||
}
|
||||
}
|
||||
for i := 0; i < util.Uint160Size; i++ {
|
||||
accStr += fmt.Sprintf("%#x", acc[i])
|
||||
if i != util.Uint160Size-1 {
|
||||
accStr += ", "
|
||||
}
|
||||
}
|
||||
|
||||
// After that ensure interop API allows to retrieve signer with CalledByEntry rule-based scope.
|
||||
src := `package callledger
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||
)
|
||||
func CallLedger(accessValue bool) int {
|
||||
signers := ledger.GetTransactionSigners(interop.Hash256{` + hashStr + `})
|
||||
if len(signers) != 1 {
|
||||
panic("bad length")
|
||||
}
|
||||
s0 := signers[0]
|
||||
expectedAcc := interop.Hash160{` + accStr + `}
|
||||
if !util.Equals(string(s0.Account), string(expectedAcc)) {
|
||||
panic("bad account")
|
||||
}
|
||||
if s0.Scopes != ledger.Rules {
|
||||
panic("bad signer scope")
|
||||
}
|
||||
if len(s0.Rules) != 1 {
|
||||
panic("bad rules length")
|
||||
}
|
||||
r0 := s0.Rules[0]
|
||||
if r0.Action != ledger.WitnessAllow {
|
||||
panic("bad action")
|
||||
}
|
||||
c0 := r0.Condition
|
||||
if c0.Type != ledger.WitnessCalledByEntry {
|
||||
panic("bad condition type")
|
||||
}
|
||||
if accessValue {
|
||||
// Panic should occur here, because there's only Type inside the CalledByEntry condition.
|
||||
_ = c0.Value
|
||||
}
|
||||
return 1
|
||||
}`
|
||||
ctr := neotest.CompileSource(t, c.Committee.ScriptHash(), strings.NewReader(src), &compiler.Options{
|
||||
Name: "calledger_contract",
|
||||
})
|
||||
e.DeployContract(t, ctr, nil)
|
||||
|
||||
ctrInvoker := e.NewInvoker(ctr.Hash, e.Committee)
|
||||
ctrInvoker.Invoke(t, 1, "callLedger", false) // Firstly, don't access CalledByEnrty Condition value => the call should be successful.
|
||||
ctrInvoker.InvokeFail(t, `(PICKITEM): unhandled exception: "The value 1 is out of range."`, "callLedger", true) // Then, access the value to ensure it will panic.
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ package transaction
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=WitnessConditionType -linecomment
|
||||
|
@ -50,6 +52,8 @@ type WitnessCondition interface {
|
|||
// DecodeBinarySpecific decodes type-specific binary data from the given
|
||||
// reader (not including type data).
|
||||
DecodeBinarySpecific(*io.BinReader, int)
|
||||
// ToStackItem converts WitnessCondition to stackitem.Item.
|
||||
ToStackItem() stackitem.Item
|
||||
|
||||
json.Marshaler
|
||||
}
|
||||
|
@ -129,6 +133,12 @@ func (c *ConditionBoolean) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionBoolean) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), bool(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionNot) Type() WitnessConditionType {
|
||||
return WitnessNot
|
||||
|
@ -166,6 +176,12 @@ func (c *ConditionNot) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionNot) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), c.Condition)
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionAnd) Type() WitnessConditionType {
|
||||
return WitnessAnd
|
||||
|
@ -242,6 +258,12 @@ func (c *ConditionAnd) MarshalJSON() ([]byte, error) {
|
|||
return arrayToJSON(c, []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionAnd) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionOr) Type() WitnessConditionType {
|
||||
return WitnessOr
|
||||
|
@ -282,6 +304,12 @@ func (c *ConditionOr) MarshalJSON() ([]byte, error) {
|
|||
return arrayToJSON(c, []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionOr) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionScriptHash) Type() WitnessConditionType {
|
||||
return WitnessScriptHash
|
||||
|
@ -314,6 +342,12 @@ func (c *ConditionScriptHash) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionScriptHash) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), util.Uint160(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionGroup) Type() WitnessConditionType {
|
||||
return WitnessGroup
|
||||
|
@ -346,6 +380,12 @@ func (c *ConditionGroup) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionGroup) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), keys.PublicKey(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c ConditionCalledByEntry) Type() WitnessConditionType {
|
||||
return WitnessCalledByEntry
|
||||
|
@ -376,6 +416,12 @@ func (c ConditionCalledByEntry) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c ConditionCalledByEntry) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), nil)
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionCalledByContract) Type() WitnessConditionType {
|
||||
return WitnessCalledByContract
|
||||
|
@ -408,6 +454,12 @@ func (c *ConditionCalledByContract) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionCalledByContract) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), util.Uint160(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionCalledByGroup) Type() WitnessConditionType {
|
||||
return WitnessCalledByGroup
|
||||
|
@ -440,6 +492,12 @@ func (c *ConditionCalledByGroup) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionCalledByGroup) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), keys.PublicKey(*c))
|
||||
}
|
||||
|
||||
// DecodeBinaryCondition decodes and returns condition from the given binary stream.
|
||||
func DecodeBinaryCondition(r *io.BinReader) WitnessCondition {
|
||||
return decodeBinaryCondition(r, MaxConditionNesting)
|
||||
|
@ -573,3 +631,29 @@ func unmarshalConditionJSON(data []byte, maxDepth int) (WitnessCondition, error)
|
|||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func condToStackItem(typ WitnessConditionType, c interface{}) stackitem.Item {
|
||||
res := make([]stackitem.Item, 0, 2)
|
||||
res = append(res, stackitem.NewBigInteger(big.NewInt(int64(typ))))
|
||||
switch typ {
|
||||
case WitnessBoolean:
|
||||
res = append(res, stackitem.NewBool(c.(bool)))
|
||||
case WitnessNot:
|
||||
res = append(res, c.(WitnessCondition).ToStackItem())
|
||||
case WitnessAnd, WitnessOr:
|
||||
v := c.([]WitnessCondition)
|
||||
operands := make([]stackitem.Item, len(v))
|
||||
for i, op := range v {
|
||||
operands[i] = op.ToStackItem()
|
||||
}
|
||||
res = append(res, stackitem.NewArray(operands))
|
||||
case WitnessScriptHash, WitnessCalledByContract:
|
||||
res = append(res, stackitem.NewByteArray(c.(util.Uint160).BytesBE()))
|
||||
case WitnessGroup, WitnessCalledByGroup:
|
||||
g := c.(keys.PublicKey)
|
||||
res = append(res, stackitem.NewByteArray((&g).Bytes()))
|
||||
case WitnessCalledByEntry:
|
||||
// No additional item should be added.
|
||||
}
|
||||
return stackitem.NewArray(res)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -30,10 +32,14 @@ func (c InvalidCondition) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
return json.Marshal(aux)
|
||||
}
|
||||
func (c InvalidCondition) ToStackItem() stackitem.Item {
|
||||
panic("invalid")
|
||||
}
|
||||
|
||||
type condCase struct {
|
||||
condition WitnessCondition
|
||||
success bool
|
||||
condition WitnessCondition
|
||||
success bool
|
||||
expectedStackItem []stackitem.Item
|
||||
}
|
||||
|
||||
func TestWitnessConditionSerDes(t *testing.T) {
|
||||
|
@ -41,19 +47,25 @@ func TestWitnessConditionSerDes(t *testing.T) {
|
|||
pk, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
var cases = []condCase{
|
||||
{(*ConditionBoolean)(&someBool), true},
|
||||
{&ConditionNot{(*ConditionBoolean)(&someBool)}, true},
|
||||
{&ConditionAnd{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true},
|
||||
{&ConditionOr{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true},
|
||||
{&ConditionScriptHash{1, 2, 3}, true},
|
||||
{(*ConditionGroup)(pk.PublicKey()), true},
|
||||
{ConditionCalledByEntry{}, true},
|
||||
{&ConditionCalledByContract{1, 2, 3}, true},
|
||||
{(*ConditionCalledByGroup)(pk.PublicKey()), true},
|
||||
{InvalidCondition{}, false},
|
||||
{&ConditionAnd{}, false},
|
||||
{&ConditionOr{}, false},
|
||||
{&ConditionNot{&ConditionNot{&ConditionNot{(*ConditionBoolean)(&someBool)}}}, false},
|
||||
{(*ConditionBoolean)(&someBool), true, []stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}},
|
||||
{&ConditionNot{(*ConditionBoolean)(&someBool)}, true, []stackitem.Item{stackitem.Make(WitnessNot), stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)})}},
|
||||
{&ConditionAnd{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true, []stackitem.Item{stackitem.Make(WitnessAnd), stackitem.Make([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
})}},
|
||||
{&ConditionOr{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true, []stackitem.Item{stackitem.Make(WitnessOr), stackitem.Make([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
})}},
|
||||
{&ConditionScriptHash{1, 2, 3}, true, []stackitem.Item{stackitem.Make(WitnessScriptHash), stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}},
|
||||
{(*ConditionGroup)(pk.PublicKey()), true, []stackitem.Item{stackitem.Make(WitnessGroup), stackitem.Make(pk.PublicKey().Bytes())}},
|
||||
{ConditionCalledByEntry{}, true, []stackitem.Item{stackitem.Make(WitnessCalledByEntry)}},
|
||||
{&ConditionCalledByContract{1, 2, 3}, true, []stackitem.Item{stackitem.Make(WitnessCalledByContract), stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}},
|
||||
{(*ConditionCalledByGroup)(pk.PublicKey()), true, []stackitem.Item{stackitem.Make(WitnessCalledByGroup), stackitem.Make(pk.PublicKey().Bytes())}},
|
||||
{InvalidCondition{}, false, nil},
|
||||
{&ConditionAnd{}, false, nil},
|
||||
{&ConditionOr{}, false, nil},
|
||||
{&ConditionNot{&ConditionNot{&ConditionNot{(*ConditionBoolean)(&someBool)}}}, false, nil},
|
||||
}
|
||||
var maxSubCondAnd = &ConditionAnd{}
|
||||
var maxSubCondOr = &ConditionAnd{}
|
||||
|
@ -61,8 +73,8 @@ func TestWitnessConditionSerDes(t *testing.T) {
|
|||
*maxSubCondAnd = append(*maxSubCondAnd, (*ConditionBoolean)(&someBool))
|
||||
*maxSubCondOr = append(*maxSubCondOr, (*ConditionBoolean)(&someBool))
|
||||
}
|
||||
cases = append(cases, condCase{maxSubCondAnd, false})
|
||||
cases = append(cases, condCase{maxSubCondOr, false})
|
||||
cases = append(cases, condCase{maxSubCondAnd, false, nil})
|
||||
cases = append(cases, condCase{maxSubCondOr, false, nil})
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
for i, c := range cases {
|
||||
w := io.NewBufBinWriter()
|
||||
|
@ -94,6 +106,15 @@ func TestWitnessConditionSerDes(t *testing.T) {
|
|||
require.Equal(t, c.condition, res)
|
||||
}
|
||||
})
|
||||
t.Run("stackitem", func(t *testing.T) {
|
||||
for i, c := range cases[1:] {
|
||||
if c.expectedStackItem != nil {
|
||||
expected := stackitem.NewArray(c.expectedStackItem)
|
||||
actual := c.condition.ToStackItem()
|
||||
assert.Equal(t, expected, actual, i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWitnessConditionZeroDeser(t *testing.T) {
|
||||
|
|
|
@ -3,8 +3,10 @@ package transaction
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=WitnessAction -linecomment
|
||||
|
@ -84,3 +86,11 @@ func (w *WitnessRule) UnmarshalJSON(data []byte) error {
|
|||
w.Condition = cond
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem implements Convertible interface.
|
||||
func (w *WitnessRule) ToStackItem() stackitem.Item {
|
||||
return stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewBigInteger(big.NewInt(int64(w.Action))),
|
||||
w.Condition.ToStackItem(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -54,3 +55,21 @@ func TestWitnessRuleBadJSON(t *testing.T) {
|
|||
require.Errorf(t, err, "case %d, json %s", i, cases[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestWitnessRule_ToStackItem(t *testing.T) {
|
||||
var b bool
|
||||
for _, act := range []WitnessAction{WitnessDeny, WitnessAllow} {
|
||||
expected := stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.Make(int64(act)),
|
||||
stackitem.Make([]stackitem.Item{
|
||||
stackitem.Make(WitnessBoolean),
|
||||
stackitem.Make(b),
|
||||
}),
|
||||
})
|
||||
actual := (&WitnessRule{
|
||||
Action: act,
|
||||
Condition: (*ConditionBoolean)(&b),
|
||||
}).ToStackItem()
|
||||
require.Equal(t, expected, actual, act)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,12 @@ func GetTransactionFromBlock(indexOrHash interface{}, txIndex int) *Transaction
|
|||
indexOrHash, txIndex).(*Transaction)
|
||||
}
|
||||
|
||||
// GetTransactionSigners represents `getTransactionSigners` method of Ledger native contract.
|
||||
func GetTransactionSigners(hash interop.Hash256) []TransactionSigner {
|
||||
return neogointernal.CallWithToken(Hash, "getTransactionSigners", int(contract.ReadStates),
|
||||
hash).([]TransactionSigner)
|
||||
}
|
||||
|
||||
// GetTransactionVMState represents `getTransactionVMState` method of Ledger native contract.
|
||||
func GetTransactionVMState(hash interop.Hash256) VMState {
|
||||
return neogointernal.CallWithToken(Hash, "getTransactionVMState", int(contract.ReadStates), hash).(VMState)
|
||||
|
|
116
pkg/interop/native/ledger/transaction_signer.go
Normal file
116
pkg/interop/native/ledger/transaction_signer.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
package ledger
|
||||
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
|
||||
// TransactionSigner represent the signer of a NEO transaction. It's similar to
|
||||
// Signer class in Neo .net framework.
|
||||
type TransactionSigner struct {
|
||||
// Bytes is a binary serialized representation of the given signer.
|
||||
Bytes []byte
|
||||
// Account represents the account (160 bit BE value in a 20 byte slice) of
|
||||
// the given signer.
|
||||
Account interop.Hash160
|
||||
// Scopes represents a set of witness flags for the given signer.
|
||||
Scopes SignerScope
|
||||
// Contracts represents the set of contract hashes (160 bit BE value in a 20
|
||||
// byte slice) allowed to be called by the signer. It is only non-empty if
|
||||
// CustomContracts scope flag is set.
|
||||
AllowedContracts []interop.Hash160
|
||||
// AllowedGroups represents the set of contract groups (ecdsa public key
|
||||
// bytes in a 33 byte slice) allowed to be called by the signer. It is only
|
||||
// non-empty if CustomGroups scope flag is set.
|
||||
AllowedGroups []interop.PublicKey
|
||||
// Rules represents a rule-based witness scope of the given signer. It is
|
||||
// only non-empty if Rules scope flag is set.
|
||||
Rules []WitnessRule
|
||||
}
|
||||
|
||||
// SignerScope represents a signer's witness scope.
|
||||
type SignerScope byte
|
||||
|
||||
// Various witness scopes.
|
||||
const (
|
||||
// None specifies that no contract was witnessed. Only signs the transaction
|
||||
// and pays GAS fee if a sender.
|
||||
None SignerScope = 0
|
||||
// CalledByEntry means that the witness is valid only when the witness
|
||||
// checking contract is called from the entry script.
|
||||
CalledByEntry SignerScope = 0x01
|
||||
// CustomContracts define custom hash for contract-specific witness.
|
||||
CustomContracts SignerScope = 0x10
|
||||
// CustomGroups define custom public key for group members.
|
||||
CustomGroups SignerScope = 0x20
|
||||
// Rules is a set of conditions with boolean operators.
|
||||
Rules SignerScope = 0x40
|
||||
// Global allows this witness in all contexts. This cannot be combined with
|
||||
// other flags.
|
||||
Global SignerScope = 0x80
|
||||
)
|
||||
|
||||
// WitnessRule represents a single rule for Rules witness scope.
|
||||
type WitnessRule struct {
|
||||
// Action denotes whether the witness condition should be accepted or denied.
|
||||
Action WitnessAction
|
||||
// Condition holds a set of nested witness rules. Max nested depth is 2.
|
||||
Condition WitnessCondition
|
||||
}
|
||||
|
||||
// WitnessAction represents an action to perform in WitnessRule if
|
||||
// witness condition matches.
|
||||
type WitnessAction byte
|
||||
|
||||
// Various rule-based witness actions.
|
||||
const (
|
||||
// WitnessDeny rejects current witness if condition is met.
|
||||
WitnessDeny WitnessAction = 0
|
||||
// WitnessAllow approves current witness if condition is met.
|
||||
WitnessAllow WitnessAction = 1
|
||||
)
|
||||
|
||||
// WitnessCondition represents a single witness condition for a rule-based
|
||||
// witness. Its type can always be safely accessed, but trying to access its
|
||||
// value causes runtime exception for those types that don't have value
|
||||
// (currently, it's only CalledByEntry witness condition).
|
||||
type WitnessCondition struct {
|
||||
Type WitnessConditionType
|
||||
// Depends on the witness condition Type, its value can be asserted to the
|
||||
// certain structure according to the following rule:
|
||||
// WitnessBoolean -> bool
|
||||
// WitnessNot -> []WitnessCondition with one element
|
||||
// WitnessAnd -> []WitnessCondition
|
||||
// WitnessOr -> []WitnessCondition
|
||||
// WitnessScriptHash -> interop.Hash160
|
||||
// WitnessGroup -> interop.PublicKey
|
||||
// WitnessCalledByContract -> interop.Hash160
|
||||
// WitnessCalledByGroup -> interop.PublicKey
|
||||
// WitnessCalledByEntry -> doesn't have value, thus, an attempt to access the Value leads to runtime exception.
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// WitnessConditionType represents the type of rule-based witness condition.
|
||||
type WitnessConditionType byte
|
||||
|
||||
// Various witness condition types
|
||||
const (
|
||||
// WitnessBoolean is a generic boolean condition.
|
||||
WitnessBoolean WitnessConditionType = 0x00
|
||||
// WitnessNot reverses another condition.
|
||||
WitnessNot WitnessConditionType = 0x01
|
||||
// WitnessAnd means that all conditions must be met.
|
||||
WitnessAnd WitnessConditionType = 0x02
|
||||
// WitnessOr means that any of conditions must be met.
|
||||
WitnessOr WitnessConditionType = 0x03
|
||||
// WitnessScriptHash matches executing contract's script hash.
|
||||
WitnessScriptHash WitnessConditionType = 0x18
|
||||
// WitnessGroup matches executing contract's group key.
|
||||
WitnessGroup WitnessConditionType = 0x19
|
||||
// WitnessCalledByEntry matches when current script is an entry script or is
|
||||
// called by an entry script.
|
||||
WitnessCalledByEntry WitnessConditionType = 0x20
|
||||
// WitnessCalledByContract matches when current script is called by the
|
||||
// specified contract.
|
||||
WitnessCalledByContract WitnessConditionType = 0x28
|
||||
// WitnessCalledByGroup matches when current script is called by contract
|
||||
// belonging to the specified group.
|
||||
WitnessCalledByGroup WitnessConditionType = 0x29
|
||||
)
|
|
@ -107,8 +107,8 @@ func (e *Executor) SignTx(t testing.TB, tx *transaction.Transaction, sysFee int6
|
|||
Scopes: transaction.Global,
|
||||
})
|
||||
}
|
||||
addNetworkFee(e.Chain, tx, signers...)
|
||||
addSystemFee(e.Chain, tx, sysFee)
|
||||
AddNetworkFee(e.Chain, tx, signers...)
|
||||
AddSystemFee(e.Chain, tx, sysFee)
|
||||
|
||||
for _, acc := range signers {
|
||||
require.NoError(t, acc.SignTx(e.Chain.GetConfig().Magic, tx))
|
||||
|
@ -276,12 +276,14 @@ func NewDeployTxBy(t testing.TB, bc blockchainer.Blockchainer, signer Signer, c
|
|||
Account: signer.ScriptHash(),
|
||||
Scopes: transaction.Global,
|
||||
}}
|
||||
addNetworkFee(bc, tx, signer)
|
||||
AddNetworkFee(bc, tx, signer)
|
||||
require.NoError(t, signer.SignTx(netmode.UnitTestNet, tx))
|
||||
return tx
|
||||
}
|
||||
|
||||
func addSystemFee(bc blockchainer.Blockchainer, tx *transaction.Transaction, sysFee int64) {
|
||||
// AddSystemFee adds system fee to the transaction. If negative value specified,
|
||||
// then system fee is defined by test invocation.
|
||||
func AddSystemFee(bc blockchainer.Blockchainer, tx *transaction.Transaction, sysFee int64) {
|
||||
if sysFee >= 0 {
|
||||
tx.SystemFee = sysFee
|
||||
return
|
||||
|
@ -290,7 +292,8 @@ func addSystemFee(bc blockchainer.Blockchainer, tx *transaction.Transaction, sys
|
|||
tx.SystemFee = v.GasConsumed()
|
||||
}
|
||||
|
||||
func addNetworkFee(bc blockchainer.Blockchainer, tx *transaction.Transaction, signers ...Signer) {
|
||||
// AddNetworkFee adds network fee to the transaction.
|
||||
func AddNetworkFee(bc blockchainer.Blockchainer, tx *transaction.Transaction, signers ...Signer) {
|
||||
baseFee := bc.GetBaseExecFee()
|
||||
size := io.GetVarSize(tx)
|
||||
for _, sgr := range signers {
|
||||
|
|
Loading…
Reference in a new issue