Merge pull request #3155 from nspcc-dev/apptr-pricing

*: introduce Policy attributes pricing
This commit is contained in:
Roman Khimov 2023-11-21 15:44:40 +03:00 committed by GitHub
commit 28ee1621b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 447 additions and 246 deletions

View file

@ -57,4 +57,4 @@ NeoGo retains certain deprecated error codes: `neorpc.ErrCompatGeneric`,
`neorpc.ErrCompatNoOpenedWallet`. They returned by nodes not compliant with the
neo-project/proposals#156 (NeoGo pre-0.102.0 and all known C# versions).
Removal of the deprecated RPC error codes is planned once all nodes adopt the new error standard.
Removal of the deprecated RPC error codes is planned once all nodes adopt the new error standard.

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -4,7 +4,7 @@ go 1.19
require (
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
github.com/stretchr/testify v1.8.4
)

View file

@ -200,8 +200,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689 h1:WnEdGAQwaW0C8wnNnQZ+rM/JfFKZDSTOqwm8cS0TOdk=
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689/go.mod h1:x+wmcYqpZYJwLp1l/pHZrqNp3RSWlkMymWGDij3/OPo=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -214,7 +214,7 @@ github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c h1:uyK5aLbAhrnZtnvo
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg=
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U=
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/zkp/xor
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

2
go.mod
View file

@ -14,7 +14,7 @@ require (
github.com/mr-tron/base58 v1.2.0
github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11
github.com/nspcc-dev/rfc6979 v0.2.0
github.com/pierrec/lz4 v2.6.1+incompatible

4
go.sum
View file

@ -229,8 +229,8 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaF
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U=
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM=
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=

View file

@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/internal/examples/oracle
go 1.19
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214
require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2

View file

@ -1,2 +1,2 @@
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214 h1:v8XJTwSAAF4Wwp20yfW8Ihz6BBPXBOGmLloWVa5EuSM=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231120162333-406c9f8b9214/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231121104256-0493ddbd70b2/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=

View file

@ -25,6 +25,7 @@ import (
// Ledger is an interface that abstracts the implementation of the blockchain.
type Ledger interface {
BlockHeight() uint32
CalculateAttributesFee(tx *transaction.Transaction) int64
FeePerByte() int64
GetBaseExecFee() int64
GetHeader(hash util.Uint256) (*block.Header, error)
@ -135,7 +136,7 @@ func signTxGeneric(bc Ledger, sign func(hash.Hashable) []byte, verif []byte, txs
netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), verif)
tx.NetworkFee += netFee
size += sizeDelta
tx.NetworkFee += int64(size) * bc.FeePerByte()
tx.NetworkFee += int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(tx)
tx.Scripts = []transaction.Witness{{
InvocationScript: sign(tx),
VerificationScript: verif,

View file

@ -123,6 +123,14 @@ func TestLedgerVMStates(t *testing.T) {
require.EqualValues(t, ledger.BreakState, vmstate.Break)
}
func TestPolicyAttributeType(t *testing.T) {
require.EqualValues(t, policy.HighPriorityT, transaction.HighPriority)
require.EqualValues(t, policy.OracleResponseT, transaction.OracleResponseT)
require.EqualValues(t, policy.NotValidBeforeT, transaction.NotValidBeforeT)
require.EqualValues(t, policy.ConflictsT, transaction.ConflictsT)
require.EqualValues(t, policy.NotaryAssistedT, transaction.NotaryAssistedT)
}
type nativeTestCase struct {
method string
params []string
@ -179,6 +187,8 @@ func TestNativeHelpersCompile(t *testing.T) {
{"setFeePerByte", []string{"42"}},
{"setStoragePrice", []string{"42"}},
{"unblockAccount", []string{u160}},
{"getAttributeFee", []string{"1"}},
{"setAttributeFee", []string{"1", "123"}},
})
runNativeTestCases(t, cs.Ledger.ContractMD, "ledger", []nativeTestCase{
{"currentHash", nil},
@ -197,8 +207,6 @@ func TestNativeHelpersCompile(t *testing.T) {
{"expirationOf", []string{u160}},
{"getMaxNotValidBeforeDelta", nil},
{"setMaxNotValidBeforeDelta", []string{"42"}},
{"getNotaryServiceFeePerKey", nil},
{"setNotaryServiceFeePerKey", []string{"42"}},
})
runNativeTestCases(t, cs.Management.ContractMD, "management", []nativeTestCase{
{"deploy", []string{"nil", "nil"}},

View file

@ -53,6 +53,7 @@ type Ledger interface {
SubscribeForBlocks(ch chan *coreb.Block)
UnsubscribeFromBlocks(ch chan *coreb.Block)
GetBaseExecFee() int64
CalculateAttributesFee(tx *transaction.Transaction) int64
interop.Ledger
mempool.Feer
}

View file

@ -592,7 +592,7 @@ func signTx(t *testing.T, bc Ledger, txs ...*transaction.Transaction) {
netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript)
tx.NetworkFee += +netFee
size += sizeDelta
tx.NetworkFee += int64(size) * bc.FeePerByte()
tx.NetworkFee += int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(tx)
buf := io.NewBufBinWriter()
for _, key := range privNetKeys {

View file

@ -2054,10 +2054,10 @@ func (bc *Blockchain) GetNotaryBalance(acc util.Uint160) *big.Int {
return bc.contracts.Notary.BalanceOf(bc.dao, acc)
}
// GetNotaryServiceFeePerKey returns NotaryServiceFeePerKey which is a reward per
// notary request key for designated notary nodes.
// GetNotaryServiceFeePerKey returns a NotaryAssisted transaction attribute fee
// per key which is a reward per notary request key for designated notary nodes.
func (bc *Blockchain) GetNotaryServiceFeePerKey() int64 {
return bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
return bc.contracts.Policy.GetAttributeFeeInternal(bc.dao, transaction.NotaryAssistedT)
}
// GetNotaryContractScriptHash returns Notary native contract hash.
@ -2479,14 +2479,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
if size > transaction.MaxTransactionSize {
return fmt.Errorf("%w: (%d > MaxTransactionSize %d)", ErrTxTooBig, size, transaction.MaxTransactionSize)
}
needNetworkFee := int64(size) * bc.FeePerByte()
if bc.P2PSigExtensionsEnabled() {
attrs := t.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
needNetworkFee += (int64(na.NKeys) + 1) * bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
}
}
needNetworkFee := int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(t)
netFee := t.NetworkFee - needNetworkFee
if netFee < 0 {
return fmt.Errorf("%w: net fee is %v, need %v", ErrTxSmallNetworkFee, t.NetworkFee, needNetworkFee)
@ -2502,7 +2495,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
return err
}
}
err = bc.verifyTxWitnesses(t, nil, isPartialTx)
err = bc.verifyTxWitnesses(t, nil, isPartialTx, netFee)
if err != nil {
return err
}
@ -2530,6 +2523,27 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
return nil
}
// CalculateAttributesFee returns network fee for all transaction attributes that should be
// paid according to native Policy.
func (bc *Blockchain) CalculateAttributesFee(tx *transaction.Transaction) int64 {
var feeSum int64
for _, attr := range tx.Attributes {
base := bc.contracts.Policy.GetAttributeFeeInternal(bc.dao, attr.Type)
switch attr.Type {
case transaction.ConflictsT:
feeSum += base * int64(len(tx.Signers))
case transaction.NotaryAssistedT:
if bc.P2PSigExtensionsEnabled() {
na := attr.Value.(*transaction.NotaryAssisted)
feeSum += base * (int64(na.NKeys) + 1)
}
default:
feeSum += base
}
}
return feeSum
}
func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transaction, isPartialTx bool) error {
for i := range tx.Attributes {
switch attrType := tx.Attributes[i].Type; attrType {
@ -2889,17 +2903,17 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
// transaction. It can reorder them by ScriptHash, because that's required to
// match a slice of script hashes from the Blockchain. Block parameter
// is used for easy interop access and can be omitted for transactions that are
// not yet added into any block.
// not yet added into any block. verificationFee argument can be provided to
// restrict the maximum amount of GAS allowed to spend on transaction
// verification.
// Golang implementation of VerifyWitnesses method in C# (https://github.com/neo-project/neo/blob/master/neo/SmartContract/Helper.cs#L87).
func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block.Block, isPartialTx bool) error {
func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block.Block, isPartialTx bool, verificationFee ...int64) error {
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, block, t)
gasLimit := t.NetworkFee - int64(t.Size())*bc.FeePerByte()
if bc.P2PSigExtensionsEnabled() {
attrs := t.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
gasLimit -= (int64(na.NKeys) + 1) * bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
}
var gasLimit int64
if len(verificationFee) == 0 {
gasLimit = t.NetworkFee - int64(t.Size())*bc.FeePerByte() - bc.CalculateAttributesFee(t)
} else {
gasLimit = verificationFee[0]
}
for i := range t.Signers {
gasConsumed, err := bc.verifyHashAgainstScript(t.Signers[i].Account, &t.Scripts[i], interopCtx, gasLimit)

View file

@ -74,10 +74,11 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
gas := newGAS(int64(cfg.InitialGASSupply), cfg.P2PSigExtensions)
neo := newNEO(cfg)
policy := newPolicy()
policy := newPolicy(cfg.P2PSigExtensions)
neo.GAS = gas
neo.Policy = policy
gas.NEO = neo
gas.Policy = policy
mgmt.NEO = neo
mgmt.Policy = policy
policy.NEO = neo
@ -104,8 +105,8 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
notary.GAS = gas
notary.NEO = neo
notary.Desig = desig
notary.Policy = policy
cs.Notary = notary
gas.Notary = notary
cs.Contracts = append(cs.Contracts, notary)
}

View file

@ -17,7 +17,7 @@ import (
func TestDeployGetUpdateDestroyContract(t *testing.T) {
mgmt := newManagement()
mgmt.Policy = newPolicy()
mgmt.Policy = newPolicy(false)
d := dao.NewSimple(storage.NewMemoryStore(), false)
ic := &interop.Context{DAO: d}
err := mgmt.Initialize(ic)
@ -97,7 +97,7 @@ func TestManagement_Initialize(t *testing.T) {
func TestManagement_GetNEP17Contracts(t *testing.T) {
mgmt := newManagement()
mgmt.Policy = newPolicy()
mgmt.Policy = newPolicy(false)
d := dao.NewSimple(storage.NewMemoryStore(), false)
err := mgmt.Initialize(&interop.Context{DAO: d})
require.NoError(t, err)

View file

@ -18,9 +18,8 @@ import (
// GAS represents GAS native contract.
type GAS struct {
nep17TokenNative
NEO *NEO
// Notary is a native Notary contract. It is set only when P2PSigExtensions are on.
Notary *Notary
NEO *NEO
Policy *Policy
initialSupply int64
p2pSigExtensionsEnabled bool
@ -124,7 +123,7 @@ func (g *GAS) OnPersist(ic *interop.Context) error {
attrs := tx.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
netFee -= (int64(na.NKeys) + 1) * g.Notary.GetNotaryServiceFeePerKey(ic.DAO)
netFee -= (int64(na.NKeys) + 1) * g.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
}
}
}

View file

@ -347,18 +347,30 @@ func toUint160(s stackitem.Item) util.Uint160 {
return u
}
func toUint32(s stackitem.Item) uint32 {
func toUint64(s stackitem.Item) uint64 {
bigInt := toBigInt(s)
if !bigInt.IsUint64() {
panic("bigint is not an uint64")
panic("bigint is not a uint64")
}
uint64Value := bigInt.Uint64()
return bigInt.Uint64()
}
func toUint32(s stackitem.Item) uint32 {
uint64Value := toUint64(s)
if uint64Value > math.MaxUint32 {
panic("bigint does not fit into uint32")
}
return uint32(uint64Value)
}
func toUint8(s stackitem.Item) uint8 {
uint64Value := toUint64(s)
if uint64Value > math.MaxUint8 {
panic("bigint does not fit into uint8")
}
return uint8(uint64Value)
}
func toInt64(s stackitem.Item) int64 {
bigInt := toBigInt(s)
if !bigInt.IsInt64() {

View file

@ -38,16 +38,6 @@ func TestNotary_MaxNotValidBeforeDeltaCache(t *testing.T) {
testGetSetCache(t, c, "MaxNotValidBeforeDelta", 140)
}
func TestNotary_NotaryServiceFeePerKey(t *testing.T) {
c := newNotaryClient(t)
testGetSet(t, c, "NotaryServiceFeePerKey", 1000_0000, 0, 0)
}
func TestNotary_NotaryServiceFeePerKeyCache(t *testing.T) {
c := newNotaryClient(t)
testGetSetCache(t, c, "NotaryServiceFeePerKey", 1000_0000)
}
func TestNotary_Pipeline(t *testing.T) {
notaryCommitteeInvoker := newNotaryClient(t)
e := notaryCommitteeInvoker.Executor

View file

@ -7,8 +7,14 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
func newPolicyClient(t *testing.T) *neotest.ContractInvoker {
@ -39,6 +45,67 @@ func TestPolicy_StoragePriceCache(t *testing.T) {
testGetSetCache(t, newPolicyClient(t), "StoragePrice", native.DefaultStoragePrice)
}
func TestPolicy_AttributeFee(t *testing.T) {
c := newPolicyClient(t)
getName := "getAttributeFee"
setName := "setAttributeFee"
randomInvoker := c.WithSigners(c.NewAccount(t))
committeeInvoker := c.WithSigners(c.Committee)
t.Run("set, not signed by committee", func(t *testing.T) {
randomInvoker.InvokeFail(t, "invalid committee signature", setName, byte(transaction.ConflictsT), 123)
})
t.Run("get, unknown attribute", func(t *testing.T) {
randomInvoker.InvokeFail(t, "invalid attribute type: 84", getName, byte(0x54))
})
t.Run("get, default value", func(t *testing.T) {
randomInvoker.Invoke(t, 0, getName, byte(transaction.ConflictsT))
})
t.Run("set, too large value", func(t *testing.T) {
committeeInvoker.InvokeFail(t, "out of range", setName, byte(transaction.ConflictsT), 10_0000_0001)
})
t.Run("set, unknown attribute", func(t *testing.T) {
committeeInvoker.InvokeFail(t, "invalid attribute type: 84", setName, 0x54, 5)
})
t.Run("set, success", func(t *testing.T) {
// Set and get in the same block.
txSet := committeeInvoker.PrepareInvoke(t, setName, byte(transaction.ConflictsT), 1)
txGet := randomInvoker.PrepareInvoke(t, getName, byte(transaction.ConflictsT))
c.AddNewBlock(t, txSet, txGet)
c.CheckHalt(t, txSet.Hash(), stackitem.Null{})
c.CheckHalt(t, txGet.Hash(), stackitem.Make(1))
// Get in the next block.
randomInvoker.Invoke(t, 1, getName, byte(transaction.ConflictsT))
})
}
func TestPolicy_AttributeFeeCache(t *testing.T) {
c := newPolicyClient(t)
getName := "getAttributeFee"
setName := "setAttributeFee"
committeeInvoker := c.WithSigners(c.Committee)
// Change fee, abort the transaction and check that contract cache wasn't persisted
// for FAULTed tx at the same block.
w := io.NewBufBinWriter()
emit.AppCall(w.BinWriter, committeeInvoker.Hash, setName, callflag.All, byte(transaction.ConflictsT), 5)
emit.Opcodes(w.BinWriter, opcode.ABORT)
tx1 := committeeInvoker.PrepareInvocation(t, w.Bytes(), committeeInvoker.Signers)
tx2 := committeeInvoker.PrepareInvoke(t, getName, byte(transaction.ConflictsT))
committeeInvoker.AddNewBlock(t, tx1, tx2)
committeeInvoker.CheckFault(t, tx1.Hash(), "ABORT")
committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(0))
// Change fee and check that change is available for the next tx.
tx1 = committeeInvoker.PrepareInvoke(t, setName, byte(transaction.ConflictsT), 5)
tx2 = committeeInvoker.PrepareInvoke(t, getName, byte(transaction.ConflictsT))
committeeInvoker.AddNewBlock(t, tx1, tx2)
committeeInvoker.CheckHalt(t, tx1.Hash())
committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(5))
}
func TestPolicy_BlockedAccounts(t *testing.T) {
c := newPolicyClient(t)
e := c.Executor

View file

@ -28,14 +28,14 @@ import (
// Notary represents Notary native contract.
type Notary struct {
interop.ContractMD
GAS *GAS
NEO *NEO
Desig *Designate
GAS *GAS
NEO *NEO
Desig *Designate
Policy *Policy
}
type NotaryCache struct {
maxNotValidBeforeDelta uint32
notaryServiceFeePerKey int64
}
// NotaryService is a Notary module interface.
@ -48,15 +48,10 @@ const (
// prefixDeposit is a prefix for storing Notary deposits.
prefixDeposit = 1
defaultDepositDeltaTill = 5760
defaultMaxNotValidBeforeDelta = 140 // 20 rounds for 7 validators, a little more than half an hour
defaultNotaryServiceFeePerKey = 1000_0000 // 0.1 GAS
maxNotaryServiceFeePerKey = 1_0000_0000 // 1 GAS
defaultMaxNotValidBeforeDelta = 140 // 20 rounds for 7 validators, a little more than half an hour
)
var (
maxNotValidBeforeDeltaKey = []byte{10}
notaryServiceFeeKey = []byte{5}
)
var maxNotValidBeforeDeltaKey = []byte{10}
var (
_ interop.Contract = (*Notary)(nil)
@ -122,15 +117,6 @@ func newNotary() *Notary {
md = newMethodAndPrice(n.setMaxNotValidBeforeDelta, 1<<15, callflag.States)
n.AddMethod(md, desc)
desc = newDescriptor("getNotaryServiceFeePerKey", smartcontract.IntegerType)
md = newMethodAndPrice(n.getNotaryServiceFeePerKey, 1<<15, callflag.ReadStates)
n.AddMethod(md, desc)
desc = newDescriptor("setNotaryServiceFeePerKey", smartcontract.VoidType,
manifest.NewParameter("value", smartcontract.IntegerType))
md = newMethodAndPrice(n.setNotaryServiceFeePerKey, 1<<15, callflag.States)
n.AddMethod(md, desc)
return n
}
@ -142,11 +128,9 @@ func (n *Notary) Metadata() *interop.ContractMD {
// Initialize initializes Notary native contract and implements the Contract interface.
func (n *Notary) Initialize(ic *interop.Context) error {
setIntWithKey(n.ID, ic.DAO, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta)
setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, defaultNotaryServiceFeePerKey)
cache := &NotaryCache{
maxNotValidBeforeDelta: defaultMaxNotValidBeforeDelta,
notaryServiceFeePerKey: defaultNotaryServiceFeePerKey,
}
ic.DAO.SetCache(n.ID, cache)
return nil
@ -155,7 +139,6 @@ func (n *Notary) Initialize(ic *interop.Context) error {
func (n *Notary) InitializeCache(blockHeight uint32, d *dao.Simple) error {
cache := &NotaryCache{
maxNotValidBeforeDelta: uint32(getIntWithKey(n.ID, d, maxNotValidBeforeDeltaKey)),
notaryServiceFeePerKey: getIntWithKey(n.ID, d, notaryServiceFeeKey),
}
d.SetCache(n.ID, cache)
@ -197,7 +180,7 @@ func (n *Notary) OnPersist(ic *interop.Context) error {
if nFees == 0 {
return nil
}
feePerKey := n.GetNotaryServiceFeePerKey(ic.DAO)
feePerKey := n.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
singleReward := calculateNotaryReward(nFees, feePerKey, len(notaries))
for _, notary := range notaries {
n.GAS.mint(ic, notary.GetScriptHash(), singleReward, false)
@ -238,7 +221,7 @@ func (n *Notary) onPayment(ic *interop.Context, args []stackitem.Item) stackitem
if deposit != nil && till < deposit.Till {
panic(fmt.Errorf("`till` shouldn't be less than the previous value %d", deposit.Till))
}
feePerKey := n.GetNotaryServiceFeePerKey(ic.DAO)
feePerKey := n.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
if deposit == nil {
if amount.Cmp(big.NewInt(2*feePerKey)) < 0 {
panic(fmt.Errorf("first deposit can not be less than %d, got %d", 2*feePerKey, amount.Int64()))
@ -435,32 +418,6 @@ func (n *Notary) setMaxNotValidBeforeDelta(ic *interop.Context, args []stackitem
return stackitem.Null{}
}
// getNotaryServiceFeePerKey is a Notary contract method and returns a reward per notary request key for notary nodes.
func (n *Notary) getNotaryServiceFeePerKey(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
return stackitem.NewBigInteger(big.NewInt(int64(n.GetNotaryServiceFeePerKey(ic.DAO))))
}
// GetNotaryServiceFeePerKey is an internal representation of Notary getNotaryServiceFeePerKey method.
func (n *Notary) GetNotaryServiceFeePerKey(dao *dao.Simple) int64 {
cache := dao.GetROCache(n.ID).(*NotaryCache)
return cache.notaryServiceFeePerKey
}
// setNotaryServiceFeePerKey is a Notary contract method and sets a reward per notary request key for notary nodes.
func (n *Notary) setNotaryServiceFeePerKey(ic *interop.Context, args []stackitem.Item) stackitem.Item {
value := toInt64(args[0])
if value < 0 || value > maxNotaryServiceFeePerKey {
panic("NotaryServiceFeePerKey value is out of range")
}
if !n.NEO.checkCommittee(ic) {
panic("invalid committee signature")
}
setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, int64(value))
cache := ic.DAO.GetRWCache(n.ID).(*NotaryCache)
cache.notaryServiceFeePerKey = value
return stackitem.Null{}
}
// GetDepositFor returns state.Deposit for the account specified. It returns nil in case
// the deposit is not found in the storage and panics in case of any other error.
func (n *Notary) GetDepositFor(dao *dao.Simple, acc util.Uint160) *state.Deposit {

View file

@ -1,6 +1,7 @@
package native
import (
"encoding/hex"
"fmt"
"math/big"
"sort"
@ -11,6 +12,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
@ -24,6 +26,10 @@ const (
defaultExecFeeFactor = interop.DefaultBaseExecFee
defaultFeePerByte = 1000
defaultMaxVerificationGas = 1_50000000
// defaultAttributeFee is a default fee for a transaction attribute those price wasn't set yet.
defaultAttributeFee = 0
// defaultNotaryAssistedFee is a default fee for a NotaryAssisted transaction attribute per key.
defaultNotaryAssistedFee = 1000_0000 // 0.1 GAS
// DefaultStoragePrice is the price to pay for 1 byte of storage.
DefaultStoragePrice = 100000
@ -33,9 +39,13 @@ const (
maxFeePerByte = 100_000_000
// maxStoragePrice is the maximum allowed price for a byte of storage.
maxStoragePrice = 10000000
// maxAttributeFee is the maximum allowed value for a transaction attribute fee.
maxAttributeFee = 10_00000000
// blockedAccountPrefix is a prefix used to store blocked account.
blockedAccountPrefix = 15
// attributeFeePrefix is a prefix used to store attribute fee.
attributeFeePrefix = 20
)
var (
@ -52,6 +62,9 @@ var (
type Policy struct {
interop.ContractMD
NEO *NEO
// p2pSigExtensionsEnabled defines whether the P2P signature extensions logic is relevant.
p2pSigExtensionsEnabled bool
}
type PolicyCache struct {
@ -59,6 +72,7 @@ type PolicyCache struct {
feePerByte int64
maxVerificationGas int64
storagePrice uint32
attributeFee map[transaction.AttrType]uint32
blockedAccounts []util.Uint160
}
@ -76,13 +90,20 @@ func (c *PolicyCache) Copy() dao.NativeContractCache {
func copyPolicyCache(src, dst *PolicyCache) {
*dst = *src
dst.attributeFee = make(map[transaction.AttrType]uint32, len(src.attributeFee))
for t, v := range src.attributeFee {
dst.attributeFee[t] = v
}
dst.blockedAccounts = make([]util.Uint160, len(src.blockedAccounts))
copy(dst.blockedAccounts, src.blockedAccounts)
}
// newPolicy returns Policy native contract.
func newPolicy() *Policy {
p := &Policy{ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID)}
func newPolicy(p2pSigExtensionsEnabled bool) *Policy {
p := &Policy{
ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID),
p2pSigExtensionsEnabled: p2pSigExtensionsEnabled,
}
defer p.UpdateHash()
desc := newDescriptor("getFeePerByte", smartcontract.IntegerType)
@ -112,6 +133,17 @@ func newPolicy() *Policy {
md = newMethodAndPrice(p.setStoragePrice, 1<<15, callflag.States)
p.AddMethod(md, desc)
desc = newDescriptor("getAttributeFee", smartcontract.IntegerType,
manifest.NewParameter("attributeType", smartcontract.IntegerType))
md = newMethodAndPrice(p.getAttributeFee, 1<<15, callflag.ReadStates)
p.AddMethod(md, desc)
desc = newDescriptor("setAttributeFee", smartcontract.VoidType,
manifest.NewParameter("attributeType", smartcontract.IntegerType),
manifest.NewParameter("value", smartcontract.IntegerType))
md = newMethodAndPrice(p.setAttributeFee, 1<<15, callflag.States)
p.AddMethod(md, desc)
desc = newDescriptor("setFeePerByte", smartcontract.VoidType,
manifest.NewParameter("value", smartcontract.IntegerType))
md = newMethodAndPrice(p.setFeePerByte, 1<<15, callflag.States)
@ -146,8 +178,13 @@ func (p *Policy) Initialize(ic *interop.Context) error {
feePerByte: defaultFeePerByte,
maxVerificationGas: defaultMaxVerificationGas,
storagePrice: DefaultStoragePrice,
attributeFee: map[transaction.AttrType]uint32{},
blockedAccounts: make([]util.Uint160, 0),
}
if p.p2pSigExtensionsEnabled {
setIntWithKey(p.ID, ic.DAO, []byte{attributeFeePrefix, byte(transaction.NotaryAssistedT)}, defaultNotaryAssistedFee)
cache.attributeFee[transaction.NotaryAssistedT] = defaultNotaryAssistedFee
}
ic.DAO.SetCache(p.ID, cache)
return nil
@ -183,6 +220,25 @@ func (p *Policy) fillCacheFromDAO(cache *PolicyCache, d *dao.Simple) error {
if fErr != nil {
return fmt.Errorf("failed to initialize blocked accounts: %w", fErr)
}
cache.attributeFee = make(map[transaction.AttrType]uint32)
d.Seek(p.ID, storage.SeekRange{Prefix: []byte{attributeFeePrefix}}, func(k, v []byte) bool {
if len(k) != 1 {
fErr = fmt.Errorf("unexpected attribute type len %d (%s)", len(k), hex.EncodeToString(k))
return false
}
t := transaction.AttrType(k[0])
value := bigint.FromBytes(v)
if value == nil {
fErr = fmt.Errorf("unexpected attribute value format: key=%s, value=%s", hex.EncodeToString(k), hex.EncodeToString(v))
return false
}
cache.attributeFee[t] = uint32(value.Int64())
return true
})
if fErr != nil {
return fmt.Errorf("failed to initialize attribute fees: %w", fErr)
}
return nil
}
@ -297,6 +353,43 @@ func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) sta
return stackitem.Null{}
}
func (p *Policy) getAttributeFee(ic *interop.Context, args []stackitem.Item) stackitem.Item {
t := transaction.AttrType(toUint8(args[0]))
if !transaction.IsValidAttrType(ic.Chain.GetConfig().ReservedAttributes, t) {
panic(fmt.Errorf("invalid attribute type: %d", t))
}
return stackitem.NewBigInteger(big.NewInt(p.GetAttributeFeeInternal(ic.DAO, t)))
}
// GetAttributeFeeInternal returns required transaction's attribute fee.
func (p *Policy) GetAttributeFeeInternal(d *dao.Simple, t transaction.AttrType) int64 {
cache := d.GetROCache(p.ID).(*PolicyCache)
v, ok := cache.attributeFee[t]
if !ok {
// We may safely omit this part, but let it be here in case if defaultAttributeFee value is changed.
v = defaultAttributeFee
}
return int64(v)
}
func (p *Policy) setAttributeFee(ic *interop.Context, args []stackitem.Item) stackitem.Item {
t := transaction.AttrType(toUint8(args[0]))
value := toUint32(args[1])
if !transaction.IsValidAttrType(ic.Chain.GetConfig().ReservedAttributes, t) {
panic(fmt.Errorf("invalid attribute type: %d", t))
}
if value > maxAttributeFee {
panic(fmt.Errorf("attribute value is out of range: %d", value))
}
if !p.NEO.checkCommittee(ic) {
panic("invalid committee signature")
}
setIntWithKey(p.ID, ic.DAO, []byte{attributeFeePrefix, byte(t)}, int64(value))
cache := ic.DAO.GetRWCache(p.ID).(*PolicyCache)
cache.attributeFee[t] = value
return stackitem.Null{}
}
// setFeePerByte is a Policy contract method that sets transaction's fee per byte.
func (p *Policy) setFeePerByte(ic *interop.Context, args []stackitem.Item) stackitem.Item {
value := toBigInt(args[0]).Int64()

View file

@ -21,6 +21,15 @@ const (
NotaryAssistedT AttrType = 0x22 // NotaryAssisted
)
// attrTypes contains a set of valid attribute types (does not include reserved attributes).
var attrTypes = map[AttrType]struct{}{
HighPriority: {},
OracleResponseT: {},
NotValidBeforeT: {},
ConflictsT: {},
NotaryAssistedT: {},
}
func (a AttrType) allowMultiple() bool {
switch a {
case ConflictsT:
@ -29,3 +38,11 @@ func (a AttrType) allowMultiple() bool {
return false
}
}
// IsValidAttrType returns whether the provided attribute type is valid.
func IsValidAttrType(reservedAttributesEnabled bool, attrType AttrType) bool {
if _, ok := attrTypes[attrType]; ok {
return true
}
return reservedAttributesEnabled && ReservedLowerBound <= attrType && attrType <= ReservedUpperBound
}

View file

@ -45,13 +45,3 @@ func GetMaxNotValidBeforeDelta() int {
func SetMaxNotValidBeforeDelta(value int) {
neogointernal.CallWithTokenNoRet(Hash, "setMaxNotValidBeforeDelta", int(contract.States), value)
}
// GetNotaryServiceFeePerKey represents `getNotaryServiceFeePerKey` method of Notary native contract.
func GetNotaryServiceFeePerKey() int {
return neogointernal.CallWithToken(Hash, "getNotaryServiceFeePerKey", int(contract.ReadStates)).(int)
}
// SetNotaryServiceFeePerKey represents `setNotaryServiceFeePerKey` method of Notary native contract.
func SetNotaryServiceFeePerKey(value int) {
neogointernal.CallWithTokenNoRet(Hash, "setNotaryServiceFeePerKey", int(contract.States), value)
}

View file

@ -0,0 +1,14 @@
package policy
// AttributeType represents a transaction attribute type.
type AttributeType byte
// List of valid transaction attribute types.
const (
HighPriorityT AttributeType = 1
OracleResponseT AttributeType = 0x11
NotValidBeforeT AttributeType = 0x20
ConflictsT AttributeType = 0x21
// NotaryAssistedT is an extension of Neo protocol available on specifically configured NeoGo networks.
NotaryAssistedT AttributeType = 0x22
)

View file

@ -43,6 +43,16 @@ func SetStoragePrice(value int) {
neogointernal.CallWithTokenNoRet(Hash, "setStoragePrice", int(contract.States), value)
}
// GetAttributeFee represents `getAttributeFee` method of Policy native contract.
func GetAttributeFee(t AttributeType) int {
return neogointernal.CallWithToken(Hash, "getAttributeFee", int(contract.ReadStates), t).(int)
}
// SetAttributeFee represents `setAttributeFee` method of Policy native contract.
func SetAttributeFee(t AttributeType, value int) {
neogointernal.CallWithTokenNoRet(Hash, "setAttributeFee", int(contract.States), t, value)
}
// IsBlocked represents `isBlocked` method of Policy native contract.
func IsBlocked(addr interop.Hash160) bool {
return neogointernal.CallWithToken(Hash, "isBlocked", int(contract.ReadStates), addr).(bool)

View file

@ -305,7 +305,7 @@ func AddNetworkFee(bc *core.Blockchain, tx *transaction.Transaction, signers ...
tx.NetworkFee += netFee
size += sizeDelta
}
tx.NetworkFee += int64(size) * bc.FeePerByte()
tx.NetworkFee += int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(tx)
}
// NewUnsignedBlock creates a new unsigned block from txs.

View file

@ -111,12 +111,6 @@ func (c *ContractReader) GetMaxNotValidBeforeDelta() (uint32, error) {
return uint32(ret), err
}
// GetNotaryServiceFeePerKey returns the per-key fee amount paid by transactions
// for the NotaryAssisted attribute.
func (c *ContractReader) GetNotaryServiceFeePerKey() (int64, error) {
return unwrap.Int64(c.invoker.Call(Hash, "getNotaryServiceFeePerKey"))
}
// LockDepositUntil creates and sends a transaction that extends the deposit lock
// time for the given account. The return result from the "lockDepositUntil"
// method is checked to be true, so transaction fails (with FAULT state) if not
@ -182,33 +176,6 @@ func (c *Contract) SetMaxNotValidBeforeDeltaUnsigned(blocks uint32) (*transactio
return c.actor.MakeUnsignedCall(Hash, setMaxNVBDeltaMethod, nil, blocks)
}
// SetNotaryServiceFeePerKey creates and sends a transaction that sets the new
// per-key fee value paid for using the notary service. The action is successful
// when transaction ends in HALT state. Notice that this setting can be changed
// only by the network's committee, so use an appropriate Actor. The returned
// values are transaction hash, its ValidUntilBlock value and an error if any.
func (c *Contract) SetNotaryServiceFeePerKey(fee int64) (util.Uint256, uint32, error) {
return c.actor.SendCall(Hash, setFeePKMethod, fee)
}
// SetNotaryServiceFeePerKeyTransaction creates a transaction that sets the new
// per-key fee value paid for using the notary service. The action is successful
// when transaction ends in HALT state. Notice that this setting can be changed
// only by the network's committee, so use an appropriate Actor. The transaction
// is signed, but not sent to the network, instead it's returned to the caller.
func (c *Contract) SetNotaryServiceFeePerKeyTransaction(fee int64) (*transaction.Transaction, error) {
return c.actor.MakeCall(Hash, setFeePKMethod, fee)
}
// SetNotaryServiceFeePerKeyUnsigned creates a transaction that sets the new
// per-key fee value paid for using the notary service. The action is successful
// when transaction ends in HALT state. Notice that this setting can be changed
// only by the network's committee, so use an appropriate Actor. The transaction
// is not signed and just returned to the caller.
func (c *Contract) SetNotaryServiceFeePerKeyUnsigned(fee int64) (*transaction.Transaction, error) {
return c.actor.MakeUnsignedCall(Hash, setFeePKMethod, nil, fee)
}
// Withdraw creates and sends a transaction that withdraws the deposit belonging
// to "from" account and sends it to "to" account. The return result from the
// "withdraw" method is checked to be true, so transaction fails (with FAULT

View file

@ -103,26 +103,6 @@ func TestUint32Getters(t *testing.T) {
}
}
func TestGetNotaryServiceFeePerKey(t *testing.T) {
ta := &testAct{}
ntr := NewReader(ta)
ta.err = errors.New("")
_, err := ntr.GetNotaryServiceFeePerKey()
require.Error(t, err)
ta.err = nil
ta.res = &result.Invoke{
State: "HALT",
Stack: []stackitem.Item{
stackitem.Make(42),
},
}
res, err := ntr.GetNotaryServiceFeePerKey()
require.NoError(t, err)
require.Equal(t, int64(42), res)
}
func TestTxSenders(t *testing.T) {
ta := new(testAct)
ntr := New(ta)
@ -134,9 +114,6 @@ func TestTxSenders(t *testing.T) {
"SetMaxNotValidBeforeDelta": func() (util.Uint256, uint32, error) {
return ntr.SetMaxNotValidBeforeDelta(42)
},
"SetNotaryServiceFeePerKey": func() (util.Uint256, uint32, error) {
return ntr.SetNotaryServiceFeePerKey(100500)
},
"Withdraw": func() (util.Uint256, uint32, error) {
return ntr.Withdraw(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
},
@ -174,12 +151,6 @@ func TestTxMakers(t *testing.T) {
"SetMaxNotValidBeforeDeltaUnsigned": func() (*transaction.Transaction, error) {
return ntr.SetMaxNotValidBeforeDeltaUnsigned(42)
},
"SetNotaryServiceFeePerKeyTransaction": func() (*transaction.Transaction, error) {
return ntr.SetNotaryServiceFeePerKeyTransaction(100500)
},
"SetNotaryServiceFeePerKeyUnsigned": func() (*transaction.Transaction, error) {
return ntr.SetNotaryServiceFeePerKeyUnsigned(100500)
},
"WithdrawTransaction": func() (*transaction.Transaction, error) {
return ntr.WithdrawTransaction(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
},

View file

@ -40,6 +40,7 @@ const (
execFeeSetter = "setExecFeeFactor"
feePerByteSetter = "setFeePerByte"
storagePriceSetter = "setStoragePrice"
attributeFeeSetter = "setAttributeFee"
)
// ContractReader provides an interface to call read-only PolicyContract
@ -88,6 +89,12 @@ func (c *ContractReader) GetStoragePrice() (int64, error) {
return unwrap.Int64(c.invoker.Call(Hash, "getStoragePrice"))
}
// GetAttributeFee returns current fee for the specified attribute usage. Any
// contract saving data to the storage pays for it according to this value.
func (c *ContractReader) GetAttributeFee(t transaction.AttrType) (int64, error) {
return unwrap.Int64(c.invoker.Call(Hash, "getAttributeFee", byte(t)))
}
// 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))
@ -158,6 +165,28 @@ func (c *Contract) SetStoragePriceUnsigned(value int64) (*transaction.Transactio
return c.actor.MakeUnsignedCall(Hash, storagePriceSetter, nil, value)
}
// SetAttributeFee creates and sends a transaction that sets the new attribute
// fee value for the specified attribute. The action is successful when
// transaction ends in HALT state. The returned values are transaction hash, its
// ValidUntilBlock value and an error if any.
func (c *Contract) SetAttributeFee(t transaction.AttrType, value int64) (util.Uint256, uint32, error) {
return c.actor.SendCall(Hash, attributeFeeSetter, byte(t), value)
}
// SetAttributeFeeTransaction creates a transaction that sets the new attribute
// fee value for the specified attribute. This transaction is signed, but not
// sent to the network, instead it's returned to the caller.
func (c *Contract) SetAttributeFeeTransaction(t transaction.AttrType, value int64) (*transaction.Transaction, error) {
return c.actor.MakeCall(Hash, attributeFeeSetter, byte(t), value)
}
// SetAttributeFeeUnsigned creates a transaction that sets the new attribute fee
// value for the specified attribute. This transaction is not signed and just
// returned to the caller.
func (c *Contract) SetAttributeFeeUnsigned(t transaction.AttrType, value int64) (*transaction.Transaction, error) {
return c.actor.MakeUnsignedCall(Hash, attributeFeeSetter, nil, byte(t), value)
}
// BlockAccount creates and sends a transaction that blocks an account on the
// network (via `blockAccount` method), it fails (with FAULT state) if it's not
// successful. The returned values are transaction hash, its

View file

@ -58,6 +58,8 @@ func TestReader(t *testing.T) {
}
_, err := pc.IsBlocked(util.Uint160{1, 2, 3})
require.Error(t, err)
_, err = pc.GetAttributeFee(transaction.ConflictsT)
require.Error(t, err)
ta.err = nil
ta.res = &result.Invoke{
@ -71,6 +73,9 @@ func TestReader(t *testing.T) {
require.NoError(t, err)
require.Equal(t, int64(42), val)
}
v, err := pc.GetAttributeFee(transaction.ConflictsT)
require.NoError(t, err)
require.Equal(t, int64(42), v)
ta.res = &result.Invoke{
State: "HALT",
Stack: []stackitem.Item{
@ -97,6 +102,8 @@ func TestIntSetters(t *testing.T) {
_, _, err := m(42)
require.Error(t, err)
}
_, _, err := pc.SetAttributeFee(transaction.OracleResponseT, 123)
require.Error(t, err)
ta.err = nil
ta.txh = util.Uint256{1, 2, 3}
@ -107,6 +114,10 @@ func TestIntSetters(t *testing.T) {
require.Equal(t, ta.txh, h)
require.Equal(t, ta.vub, vub)
}
h, vub, err := pc.SetAttributeFee(transaction.OracleResponseT, 123)
require.NoError(t, err)
require.Equal(t, ta.txh, h)
require.Equal(t, ta.vub, vub)
}
func TestUint160Setters(t *testing.T) {

View file

@ -183,6 +183,10 @@ func TestClientPolicyContract(t *testing.T) {
require.NoError(t, err)
require.Equal(t, int64(100000), val)
val, err = polizei.GetAttributeFee(transaction.NotaryAssistedT)
require.NoError(t, err)
require.Equal(t, int64(1000_0000), val)
ret, err := polizei.IsBlocked(util.Uint160{})
require.NoError(t, err)
require.False(t, ret)
@ -212,14 +216,17 @@ func TestClientPolicyContract(t *testing.T) {
txstorage, err := polis.SetStoragePriceUnsigned(100500)
require.NoError(t, err)
txattr, err := polis.SetAttributeFeeUnsigned(transaction.NotaryAssistedT, 100500)
require.NoError(t, err)
txblock, err := polis.BlockAccountUnsigned(util.Uint160{1, 2, 3})
require.NoError(t, err)
for _, tx := range []*transaction.Transaction{txblock, txstorage, txnetfee, txexec} {
for _, tx := range []*transaction.Transaction{txattr, txblock, txstorage, txnetfee, txexec} {
tx.Scripts[0].InvocationScript = testchain.SignCommittee(tx)
}
bl := testchain.NewBlock(t, chain, 1, 0, txblock, txstorage, txnetfee, txexec)
bl := testchain.NewBlock(t, chain, 1, 0, txattr, txblock, txstorage, txnetfee, txexec)
_, err = c.SubmitBlock(*bl)
require.NoError(t, err)
@ -235,6 +242,10 @@ func TestClientPolicyContract(t *testing.T) {
require.NoError(t, err)
require.Equal(t, int64(100500), val)
val, err = polizei.GetAttributeFee(transaction.NotaryAssistedT)
require.NoError(t, err)
require.Equal(t, int64(100500), val)
ret, err = polizei.IsBlocked(util.Uint160{1, 2, 3})
require.NoError(t, err)
require.True(t, ret)
@ -480,10 +491,6 @@ func TestClientNotary(t *testing.T) {
require.NoError(t, err)
require.Equal(t, uint32(140), maxNVBd)
feePerKey, err := notaReader.GetNotaryServiceFeePerKey()
require.NoError(t, err)
require.Equal(t, int64(1000_0000), feePerKey)
commAct, err := actor.New(c, []actor.SignerAccount{{
Signer: transaction.Signer{
Account: testchain.CommitteeScriptHash(),
@ -501,12 +508,9 @@ func TestClientNotary(t *testing.T) {
txNVB, err := notaComm.SetMaxNotValidBeforeDeltaUnsigned(210)
require.NoError(t, err)
txFee, err := notaComm.SetNotaryServiceFeePerKeyUnsigned(500_0000)
require.NoError(t, err)
txNVB.Scripts[0].InvocationScript = testchain.SignCommittee(txNVB)
txFee.Scripts[0].InvocationScript = testchain.SignCommittee(txFee)
bl := testchain.NewBlock(t, chain, 1, 0, txNVB, txFee)
bl := testchain.NewBlock(t, chain, 1, 0, txNVB)
_, err = c.SubmitBlock(*bl)
require.NoError(t, err)
@ -514,10 +518,6 @@ func TestClientNotary(t *testing.T) {
require.NoError(t, err)
require.Equal(t, uint32(210), maxNVBd)
feePerKey, err = notaReader.GetNotaryServiceFeePerKey()
require.NoError(t, err)
require.Equal(t, int64(500_0000), feePerKey)
privAct, err := actor.New(c, []actor.SignerAccount{{
Signer: transaction.Signer{
Account: priv0Hash,
@ -743,12 +743,13 @@ func TestCalculateNetworkFee(t *testing.T) {
require.NoError(t, err)
require.NoError(t, c.Init())
h, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
require.NoError(t, err)
priv := testchain.PrivateKeyByID(0)
acc0 := wallet.NewAccountFromPrivateKey(priv)
t.Run("ContractWithArgs", func(t *testing.T) {
check := func(t *testing.T, extraFee int64) {
h, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
require.NoError(t, err)
priv := testchain.PrivateKeyByID(0)
acc0 := wallet.NewAccountFromPrivateKey(priv)
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
require.NoError(t, err)
tx.ValidUntilBlock = chain.BlockHeight() + 10
@ -802,6 +803,62 @@ func TestCalculateNetworkFee(t *testing.T) {
check(t, -1)
})
})
t.Run("extra attribute fee", func(t *testing.T) {
const conflictsFee = 100
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = chain.BlockHeight() + 10
signer0 := transaction.Signer{
Account: acc0.ScriptHash(),
Scopes: transaction.CalledByEntry,
}
priv1 := testchain.PrivateKeyByID(1)
acc1 := wallet.NewAccountFromPrivateKey(priv1)
signer1 := transaction.Signer{
Account: acc1.ScriptHash(),
Scopes: transaction.CalledByEntry,
}
tx.Signers = []transaction.Signer{signer0, signer1}
tx.Attributes = []transaction.Attribute{
{
Type: transaction.ConflictsT,
Value: &transaction.Conflicts{Hash: util.Uint256{1, 2, 3}},
},
}
tx.Scripts = []transaction.Witness{
{VerificationScript: acc0.Contract.Script},
{VerificationScript: acc1.Contract.Script},
}
oldFee, err := c.CalculateNetworkFee(tx)
require.NoError(t, err)
// Set fee per Conflicts attribute.
script, err := smartcontract.CreateCallScript(state.CreateNativeContractHash(nativenames.Policy), "setAttributeFee", byte(transaction.ConflictsT), conflictsFee)
require.NoError(t, err)
txSetFee := transaction.New(script, 1_0000_0000)
txSetFee.ValidUntilBlock = chain.BlockHeight() + 1
txSetFee.Signers = []transaction.Signer{
signer0,
{
Account: testchain.CommitteeScriptHash(),
Scopes: transaction.CalledByEntry,
},
}
txSetFee.NetworkFee = 10_0000_0000
require.NoError(t, acc0.SignTx(testchain.Network(), txSetFee))
txSetFee.Scripts = append(txSetFee.Scripts, transaction.Witness{
InvocationScript: testchain.SignCommittee(txSetFee),
VerificationScript: testchain.CommitteeVerificationScript(),
})
require.NoError(t, chain.AddBlock(testchain.NewBlock(t, chain, 1, 0, txSetFee)))
// Calculate network fee one more time with updated Conflicts price.
newFee, err := c.CalculateNetworkFee(tx)
require.NoError(t, err)
expectedDiff := len(tx.Signers) * len(tx.GetAttributes(transaction.ConflictsT)) * conflictsFee
require.Equal(t, int64(expectedDiff), newFee-oldFee)
})
}
func TestNotaryActor(t *testing.T) {

View file

@ -65,6 +65,7 @@ type (
Ledger interface {
AddBlock(block *block.Block) error
BlockHeight() uint32
CalculateAttributesFee(tx *transaction.Transaction) int64
CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error)
CurrentBlockHash() util.Uint256
FeePerByte() int64
@ -89,7 +90,6 @@ type (
GetNatives() []state.NativeContract
GetNextBlockValidators() ([]*keys.PublicKey, error)
GetNotaryContractScriptHash() util.Uint160
GetNotaryServiceFeePerKey() int64
GetStateModule() core.StateRoot
GetStorageItem(id int32, key []byte) state.StorageItem
GetTestHistoricVM(t trigger.Type, tx *transaction.Transaction, nextBlockHeight uint32) (*interop.Context, error)
@ -975,15 +975,7 @@ func (s *Server) calculateNetworkFee(reqParams params.Params) (any, *neorpc.Erro
netFee += gasConsumed
size += io.GetVarSize(w.VerificationScript) + io.GetVarSize(w.InvocationScript)
}
if s.chain.P2PSigExtensionsEnabled() {
attrs := tx.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
netFee += (int64(na.NKeys) + 1) * s.chain.GetNotaryServiceFeePerKey()
}
}
fee := s.chain.FeePerByte()
netFee += int64(size) * fee
netFee += int64(size)*s.chain.FeePerByte() + s.chain.CalculateAttributesFee(tx)
return result.NetworkFee{Value: netFee}, nil
}

View file

@ -138,7 +138,7 @@ func initClearServerWithCustomConfig(t testing.TB, ccfg func(configuration *conf
}
func initClearServerWithInMemoryChain(t testing.TB) (*core.Blockchain, *Server, *httptest.Server) {
return initClearServerWithServices(t, false, false, false)
return initClearServerWithServices(t, false, true, false)
}
func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *httptest.Server) {

View file

@ -87,7 +87,7 @@ const (
faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60"
faultedTxBlock uint32 = 23
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
block20StateRootLE = "cc8315751c5b6edf39c14f1637bfa0595d6ca86b8ed4d41cb495d572b680504f"
block20StateRootLE = "858c873539d6d24a70f2be13f9dafc61aef2b63c2aa16bb440676de6e44e3cf1"
)
var (