Merge pull request #3155 from nspcc-dev/apptr-pricing
*: introduce Policy attributes pricing
This commit is contained in:
commit
28ee1621b8
56 changed files with 447 additions and 246 deletions
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/engine
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/events
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/iterator
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -4,7 +4,7 @@ go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/nspcc-dev/neo-go v0.102.1-0.20231020181554-d89c8801d689
|
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
|
github.com/stretchr/testify v1.8.4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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/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 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 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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/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 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
|
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=
|
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/nft-nd
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/oracle
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/runtime
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/storage
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/timer
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/token
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -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 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg=
|
||||||
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U=
|
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 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-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-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
|
||||||
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=
|
github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/examples/zkp/xor
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -14,7 +14,7 @@ require (
|
||||||
github.com/mr-tron/base58 v1.2.0
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c
|
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/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/neofs-sdk-go v1.0.0-rc.11
|
||||||
github.com/nspcc-dev/rfc6979 v0.2.0
|
github.com/nspcc-dev/rfc6979 v0.2.0
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible
|
github.com/pierrec/lz4 v2.6.1+incompatible
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -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/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 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
|
||||||
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
|
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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/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 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
|
||||||
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM=
|
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
|
github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4=
|
||||||
|
|
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neo-go/internal/examples/oracle
|
||||||
|
|
||||||
go 1.19
|
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
|
||||||
|
|
|
@ -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-20231121104256-0493ddbd70b2 h1:hPVF8iMmsQ15GSemj1ma6C9BkwfAugEXsUAVTEniK5M=
|
||||||
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/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag=
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
// Ledger is an interface that abstracts the implementation of the blockchain.
|
// Ledger is an interface that abstracts the implementation of the blockchain.
|
||||||
type Ledger interface {
|
type Ledger interface {
|
||||||
BlockHeight() uint32
|
BlockHeight() uint32
|
||||||
|
CalculateAttributesFee(tx *transaction.Transaction) int64
|
||||||
FeePerByte() int64
|
FeePerByte() int64
|
||||||
GetBaseExecFee() int64
|
GetBaseExecFee() int64
|
||||||
GetHeader(hash util.Uint256) (*block.Header, error)
|
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)
|
netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), verif)
|
||||||
tx.NetworkFee += netFee
|
tx.NetworkFee += netFee
|
||||||
size += sizeDelta
|
size += sizeDelta
|
||||||
tx.NetworkFee += int64(size) * bc.FeePerByte()
|
tx.NetworkFee += int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(tx)
|
||||||
tx.Scripts = []transaction.Witness{{
|
tx.Scripts = []transaction.Witness{{
|
||||||
InvocationScript: sign(tx),
|
InvocationScript: sign(tx),
|
||||||
VerificationScript: verif,
|
VerificationScript: verif,
|
||||||
|
|
|
@ -123,6 +123,14 @@ func TestLedgerVMStates(t *testing.T) {
|
||||||
require.EqualValues(t, ledger.BreakState, vmstate.Break)
|
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 {
|
type nativeTestCase struct {
|
||||||
method string
|
method string
|
||||||
params []string
|
params []string
|
||||||
|
@ -179,6 +187,8 @@ func TestNativeHelpersCompile(t *testing.T) {
|
||||||
{"setFeePerByte", []string{"42"}},
|
{"setFeePerByte", []string{"42"}},
|
||||||
{"setStoragePrice", []string{"42"}},
|
{"setStoragePrice", []string{"42"}},
|
||||||
{"unblockAccount", []string{u160}},
|
{"unblockAccount", []string{u160}},
|
||||||
|
{"getAttributeFee", []string{"1"}},
|
||||||
|
{"setAttributeFee", []string{"1", "123"}},
|
||||||
})
|
})
|
||||||
runNativeTestCases(t, cs.Ledger.ContractMD, "ledger", []nativeTestCase{
|
runNativeTestCases(t, cs.Ledger.ContractMD, "ledger", []nativeTestCase{
|
||||||
{"currentHash", nil},
|
{"currentHash", nil},
|
||||||
|
@ -197,8 +207,6 @@ func TestNativeHelpersCompile(t *testing.T) {
|
||||||
{"expirationOf", []string{u160}},
|
{"expirationOf", []string{u160}},
|
||||||
{"getMaxNotValidBeforeDelta", nil},
|
{"getMaxNotValidBeforeDelta", nil},
|
||||||
{"setMaxNotValidBeforeDelta", []string{"42"}},
|
{"setMaxNotValidBeforeDelta", []string{"42"}},
|
||||||
{"getNotaryServiceFeePerKey", nil},
|
|
||||||
{"setNotaryServiceFeePerKey", []string{"42"}},
|
|
||||||
})
|
})
|
||||||
runNativeTestCases(t, cs.Management.ContractMD, "management", []nativeTestCase{
|
runNativeTestCases(t, cs.Management.ContractMD, "management", []nativeTestCase{
|
||||||
{"deploy", []string{"nil", "nil"}},
|
{"deploy", []string{"nil", "nil"}},
|
||||||
|
|
|
@ -53,6 +53,7 @@ type Ledger interface {
|
||||||
SubscribeForBlocks(ch chan *coreb.Block)
|
SubscribeForBlocks(ch chan *coreb.Block)
|
||||||
UnsubscribeFromBlocks(ch chan *coreb.Block)
|
UnsubscribeFromBlocks(ch chan *coreb.Block)
|
||||||
GetBaseExecFee() int64
|
GetBaseExecFee() int64
|
||||||
|
CalculateAttributesFee(tx *transaction.Transaction) int64
|
||||||
interop.Ledger
|
interop.Ledger
|
||||||
mempool.Feer
|
mempool.Feer
|
||||||
}
|
}
|
||||||
|
|
|
@ -592,7 +592,7 @@ func signTx(t *testing.T, bc Ledger, txs ...*transaction.Transaction) {
|
||||||
netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript)
|
netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript)
|
||||||
tx.NetworkFee += +netFee
|
tx.NetworkFee += +netFee
|
||||||
size += sizeDelta
|
size += sizeDelta
|
||||||
tx.NetworkFee += int64(size) * bc.FeePerByte()
|
tx.NetworkFee += int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(tx)
|
||||||
|
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
for _, key := range privNetKeys {
|
for _, key := range privNetKeys {
|
||||||
|
|
|
@ -2054,10 +2054,10 @@ func (bc *Blockchain) GetNotaryBalance(acc util.Uint160) *big.Int {
|
||||||
return bc.contracts.Notary.BalanceOf(bc.dao, acc)
|
return bc.contracts.Notary.BalanceOf(bc.dao, acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNotaryServiceFeePerKey returns NotaryServiceFeePerKey which is a reward per
|
// GetNotaryServiceFeePerKey returns a NotaryAssisted transaction attribute fee
|
||||||
// notary request key for designated notary nodes.
|
// per key which is a reward per notary request key for designated notary nodes.
|
||||||
func (bc *Blockchain) GetNotaryServiceFeePerKey() int64 {
|
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.
|
// GetNotaryContractScriptHash returns Notary native contract hash.
|
||||||
|
@ -2479,14 +2479,7 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
|
||||||
if size > transaction.MaxTransactionSize {
|
if size > transaction.MaxTransactionSize {
|
||||||
return fmt.Errorf("%w: (%d > MaxTransactionSize %d)", ErrTxTooBig, size, transaction.MaxTransactionSize)
|
return fmt.Errorf("%w: (%d > MaxTransactionSize %d)", ErrTxTooBig, size, transaction.MaxTransactionSize)
|
||||||
}
|
}
|
||||||
needNetworkFee := int64(size) * bc.FeePerByte()
|
needNetworkFee := int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(t)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
netFee := t.NetworkFee - needNetworkFee
|
netFee := t.NetworkFee - needNetworkFee
|
||||||
if netFee < 0 {
|
if netFee < 0 {
|
||||||
return fmt.Errorf("%w: net fee is %v, need %v", ErrTxSmallNetworkFee, t.NetworkFee, needNetworkFee)
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = bc.verifyTxWitnesses(t, nil, isPartialTx)
|
err = bc.verifyTxWitnesses(t, nil, isPartialTx, netFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2530,6 +2523,27 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
|
||||||
return nil
|
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 {
|
func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transaction, isPartialTx bool) error {
|
||||||
for i := range tx.Attributes {
|
for i := range tx.Attributes {
|
||||||
switch attrType := tx.Attributes[i].Type; attrType {
|
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
|
// transaction. It can reorder them by ScriptHash, because that's required to
|
||||||
// match a slice of script hashes from the Blockchain. Block parameter
|
// 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
|
// 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).
|
// 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)
|
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, block, t)
|
||||||
gasLimit := t.NetworkFee - int64(t.Size())*bc.FeePerByte()
|
var gasLimit int64
|
||||||
if bc.P2PSigExtensionsEnabled() {
|
if len(verificationFee) == 0 {
|
||||||
attrs := t.GetAttributes(transaction.NotaryAssistedT)
|
gasLimit = t.NetworkFee - int64(t.Size())*bc.FeePerByte() - bc.CalculateAttributesFee(t)
|
||||||
if len(attrs) != 0 {
|
} else {
|
||||||
na := attrs[0].Value.(*transaction.NotaryAssisted)
|
gasLimit = verificationFee[0]
|
||||||
gasLimit -= (int64(na.NKeys) + 1) * bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for i := range t.Signers {
|
for i := range t.Signers {
|
||||||
gasConsumed, err := bc.verifyHashAgainstScript(t.Signers[i].Account, &t.Scripts[i], interopCtx, gasLimit)
|
gasConsumed, err := bc.verifyHashAgainstScript(t.Signers[i].Account, &t.Scripts[i], interopCtx, gasLimit)
|
||||||
|
|
|
@ -74,10 +74,11 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
||||||
|
|
||||||
gas := newGAS(int64(cfg.InitialGASSupply), cfg.P2PSigExtensions)
|
gas := newGAS(int64(cfg.InitialGASSupply), cfg.P2PSigExtensions)
|
||||||
neo := newNEO(cfg)
|
neo := newNEO(cfg)
|
||||||
policy := newPolicy()
|
policy := newPolicy(cfg.P2PSigExtensions)
|
||||||
neo.GAS = gas
|
neo.GAS = gas
|
||||||
neo.Policy = policy
|
neo.Policy = policy
|
||||||
gas.NEO = neo
|
gas.NEO = neo
|
||||||
|
gas.Policy = policy
|
||||||
mgmt.NEO = neo
|
mgmt.NEO = neo
|
||||||
mgmt.Policy = policy
|
mgmt.Policy = policy
|
||||||
policy.NEO = neo
|
policy.NEO = neo
|
||||||
|
@ -104,8 +105,8 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
||||||
notary.GAS = gas
|
notary.GAS = gas
|
||||||
notary.NEO = neo
|
notary.NEO = neo
|
||||||
notary.Desig = desig
|
notary.Desig = desig
|
||||||
|
notary.Policy = policy
|
||||||
cs.Notary = notary
|
cs.Notary = notary
|
||||||
gas.Notary = notary
|
|
||||||
cs.Contracts = append(cs.Contracts, notary)
|
cs.Contracts = append(cs.Contracts, notary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
|
|
||||||
func TestDeployGetUpdateDestroyContract(t *testing.T) {
|
func TestDeployGetUpdateDestroyContract(t *testing.T) {
|
||||||
mgmt := newManagement()
|
mgmt := newManagement()
|
||||||
mgmt.Policy = newPolicy()
|
mgmt.Policy = newPolicy(false)
|
||||||
d := dao.NewSimple(storage.NewMemoryStore(), false)
|
d := dao.NewSimple(storage.NewMemoryStore(), false)
|
||||||
ic := &interop.Context{DAO: d}
|
ic := &interop.Context{DAO: d}
|
||||||
err := mgmt.Initialize(ic)
|
err := mgmt.Initialize(ic)
|
||||||
|
@ -97,7 +97,7 @@ func TestManagement_Initialize(t *testing.T) {
|
||||||
|
|
||||||
func TestManagement_GetNEP17Contracts(t *testing.T) {
|
func TestManagement_GetNEP17Contracts(t *testing.T) {
|
||||||
mgmt := newManagement()
|
mgmt := newManagement()
|
||||||
mgmt.Policy = newPolicy()
|
mgmt.Policy = newPolicy(false)
|
||||||
d := dao.NewSimple(storage.NewMemoryStore(), false)
|
d := dao.NewSimple(storage.NewMemoryStore(), false)
|
||||||
err := mgmt.Initialize(&interop.Context{DAO: d})
|
err := mgmt.Initialize(&interop.Context{DAO: d})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -19,8 +19,7 @@ import (
|
||||||
type GAS struct {
|
type GAS struct {
|
||||||
nep17TokenNative
|
nep17TokenNative
|
||||||
NEO *NEO
|
NEO *NEO
|
||||||
// Notary is a native Notary contract. It is set only when P2PSigExtensions are on.
|
Policy *Policy
|
||||||
Notary *Notary
|
|
||||||
|
|
||||||
initialSupply int64
|
initialSupply int64
|
||||||
p2pSigExtensionsEnabled bool
|
p2pSigExtensionsEnabled bool
|
||||||
|
@ -124,7 +123,7 @@ func (g *GAS) OnPersist(ic *interop.Context) error {
|
||||||
attrs := tx.GetAttributes(transaction.NotaryAssistedT)
|
attrs := tx.GetAttributes(transaction.NotaryAssistedT)
|
||||||
if len(attrs) != 0 {
|
if len(attrs) != 0 {
|
||||||
na := attrs[0].Value.(*transaction.NotaryAssisted)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,18 +347,30 @@ func toUint160(s stackitem.Item) util.Uint160 {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func toUint32(s stackitem.Item) uint32 {
|
func toUint64(s stackitem.Item) uint64 {
|
||||||
bigInt := toBigInt(s)
|
bigInt := toBigInt(s)
|
||||||
if !bigInt.IsUint64() {
|
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 {
|
if uint64Value > math.MaxUint32 {
|
||||||
panic("bigint does not fit into uint32")
|
panic("bigint does not fit into uint32")
|
||||||
}
|
}
|
||||||
return uint32(uint64Value)
|
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 {
|
func toInt64(s stackitem.Item) int64 {
|
||||||
bigInt := toBigInt(s)
|
bigInt := toBigInt(s)
|
||||||
if !bigInt.IsInt64() {
|
if !bigInt.IsInt64() {
|
||||||
|
|
|
@ -38,16 +38,6 @@ func TestNotary_MaxNotValidBeforeDeltaCache(t *testing.T) {
|
||||||
testGetSetCache(t, c, "MaxNotValidBeforeDelta", 140)
|
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) {
|
func TestNotary_Pipeline(t *testing.T) {
|
||||||
notaryCommitteeInvoker := newNotaryClient(t)
|
notaryCommitteeInvoker := newNotaryClient(t)
|
||||||
e := notaryCommitteeInvoker.Executor
|
e := notaryCommitteeInvoker.Executor
|
||||||
|
|
|
@ -7,8 +7,14 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"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"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"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 {
|
func newPolicyClient(t *testing.T) *neotest.ContractInvoker {
|
||||||
|
@ -39,6 +45,67 @@ func TestPolicy_StoragePriceCache(t *testing.T) {
|
||||||
testGetSetCache(t, newPolicyClient(t), "StoragePrice", native.DefaultStoragePrice)
|
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) {
|
func TestPolicy_BlockedAccounts(t *testing.T) {
|
||||||
c := newPolicyClient(t)
|
c := newPolicyClient(t)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
|
|
@ -31,11 +31,11 @@ type Notary struct {
|
||||||
GAS *GAS
|
GAS *GAS
|
||||||
NEO *NEO
|
NEO *NEO
|
||||||
Desig *Designate
|
Desig *Designate
|
||||||
|
Policy *Policy
|
||||||
}
|
}
|
||||||
|
|
||||||
type NotaryCache struct {
|
type NotaryCache struct {
|
||||||
maxNotValidBeforeDelta uint32
|
maxNotValidBeforeDelta uint32
|
||||||
notaryServiceFeePerKey int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotaryService is a Notary module interface.
|
// NotaryService is a Notary module interface.
|
||||||
|
@ -49,14 +49,9 @@ const (
|
||||||
prefixDeposit = 1
|
prefixDeposit = 1
|
||||||
defaultDepositDeltaTill = 5760
|
defaultDepositDeltaTill = 5760
|
||||||
defaultMaxNotValidBeforeDelta = 140 // 20 rounds for 7 validators, a little more than half an hour
|
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var maxNotValidBeforeDeltaKey = []byte{10}
|
||||||
maxNotValidBeforeDeltaKey = []byte{10}
|
|
||||||
notaryServiceFeeKey = []byte{5}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ interop.Contract = (*Notary)(nil)
|
_ interop.Contract = (*Notary)(nil)
|
||||||
|
@ -122,15 +117,6 @@ func newNotary() *Notary {
|
||||||
md = newMethodAndPrice(n.setMaxNotValidBeforeDelta, 1<<15, callflag.States)
|
md = newMethodAndPrice(n.setMaxNotValidBeforeDelta, 1<<15, callflag.States)
|
||||||
n.AddMethod(md, desc)
|
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
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +128,9 @@ func (n *Notary) Metadata() *interop.ContractMD {
|
||||||
// Initialize initializes Notary native contract and implements the Contract interface.
|
// Initialize initializes Notary native contract and implements the Contract interface.
|
||||||
func (n *Notary) Initialize(ic *interop.Context) error {
|
func (n *Notary) Initialize(ic *interop.Context) error {
|
||||||
setIntWithKey(n.ID, ic.DAO, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta)
|
setIntWithKey(n.ID, ic.DAO, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta)
|
||||||
setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, defaultNotaryServiceFeePerKey)
|
|
||||||
|
|
||||||
cache := &NotaryCache{
|
cache := &NotaryCache{
|
||||||
maxNotValidBeforeDelta: defaultMaxNotValidBeforeDelta,
|
maxNotValidBeforeDelta: defaultMaxNotValidBeforeDelta,
|
||||||
notaryServiceFeePerKey: defaultNotaryServiceFeePerKey,
|
|
||||||
}
|
}
|
||||||
ic.DAO.SetCache(n.ID, cache)
|
ic.DAO.SetCache(n.ID, cache)
|
||||||
return nil
|
return nil
|
||||||
|
@ -155,7 +139,6 @@ func (n *Notary) Initialize(ic *interop.Context) error {
|
||||||
func (n *Notary) InitializeCache(blockHeight uint32, d *dao.Simple) error {
|
func (n *Notary) InitializeCache(blockHeight uint32, d *dao.Simple) error {
|
||||||
cache := &NotaryCache{
|
cache := &NotaryCache{
|
||||||
maxNotValidBeforeDelta: uint32(getIntWithKey(n.ID, d, maxNotValidBeforeDeltaKey)),
|
maxNotValidBeforeDelta: uint32(getIntWithKey(n.ID, d, maxNotValidBeforeDeltaKey)),
|
||||||
notaryServiceFeePerKey: getIntWithKey(n.ID, d, notaryServiceFeeKey),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetCache(n.ID, cache)
|
d.SetCache(n.ID, cache)
|
||||||
|
@ -197,7 +180,7 @@ func (n *Notary) OnPersist(ic *interop.Context) error {
|
||||||
if nFees == 0 {
|
if nFees == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
feePerKey := n.GetNotaryServiceFeePerKey(ic.DAO)
|
feePerKey := n.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
|
||||||
singleReward := calculateNotaryReward(nFees, feePerKey, len(notaries))
|
singleReward := calculateNotaryReward(nFees, feePerKey, len(notaries))
|
||||||
for _, notary := range notaries {
|
for _, notary := range notaries {
|
||||||
n.GAS.mint(ic, notary.GetScriptHash(), singleReward, false)
|
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 {
|
if deposit != nil && till < deposit.Till {
|
||||||
panic(fmt.Errorf("`till` shouldn't be less than the previous value %d", 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 deposit == nil {
|
||||||
if amount.Cmp(big.NewInt(2*feePerKey)) < 0 {
|
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()))
|
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{}
|
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
|
// 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.
|
// 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 {
|
func (n *Notary) GetDepositFor(dao *dao.Simple, acc util.Uint160) *state.Deposit {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package native
|
package native
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
@ -24,6 +26,10 @@ const (
|
||||||
defaultExecFeeFactor = interop.DefaultBaseExecFee
|
defaultExecFeeFactor = interop.DefaultBaseExecFee
|
||||||
defaultFeePerByte = 1000
|
defaultFeePerByte = 1000
|
||||||
defaultMaxVerificationGas = 1_50000000
|
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 is the price to pay for 1 byte of storage.
|
||||||
DefaultStoragePrice = 100000
|
DefaultStoragePrice = 100000
|
||||||
|
|
||||||
|
@ -33,9 +39,13 @@ const (
|
||||||
maxFeePerByte = 100_000_000
|
maxFeePerByte = 100_000_000
|
||||||
// maxStoragePrice is the maximum allowed price for a byte of storage.
|
// maxStoragePrice is the maximum allowed price for a byte of storage.
|
||||||
maxStoragePrice = 10000000
|
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 is a prefix used to store blocked account.
|
||||||
blockedAccountPrefix = 15
|
blockedAccountPrefix = 15
|
||||||
|
// attributeFeePrefix is a prefix used to store attribute fee.
|
||||||
|
attributeFeePrefix = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -52,6 +62,9 @@ var (
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
interop.ContractMD
|
interop.ContractMD
|
||||||
NEO *NEO
|
NEO *NEO
|
||||||
|
|
||||||
|
// p2pSigExtensionsEnabled defines whether the P2P signature extensions logic is relevant.
|
||||||
|
p2pSigExtensionsEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type PolicyCache struct {
|
type PolicyCache struct {
|
||||||
|
@ -59,6 +72,7 @@ type PolicyCache struct {
|
||||||
feePerByte int64
|
feePerByte int64
|
||||||
maxVerificationGas int64
|
maxVerificationGas int64
|
||||||
storagePrice uint32
|
storagePrice uint32
|
||||||
|
attributeFee map[transaction.AttrType]uint32
|
||||||
blockedAccounts []util.Uint160
|
blockedAccounts []util.Uint160
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,13 +90,20 @@ func (c *PolicyCache) Copy() dao.NativeContractCache {
|
||||||
|
|
||||||
func copyPolicyCache(src, dst *PolicyCache) {
|
func copyPolicyCache(src, dst *PolicyCache) {
|
||||||
*dst = *src
|
*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))
|
dst.blockedAccounts = make([]util.Uint160, len(src.blockedAccounts))
|
||||||
copy(dst.blockedAccounts, src.blockedAccounts)
|
copy(dst.blockedAccounts, src.blockedAccounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPolicy returns Policy native contract.
|
// newPolicy returns Policy native contract.
|
||||||
func newPolicy() *Policy {
|
func newPolicy(p2pSigExtensionsEnabled bool) *Policy {
|
||||||
p := &Policy{ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID)}
|
p := &Policy{
|
||||||
|
ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID),
|
||||||
|
p2pSigExtensionsEnabled: p2pSigExtensionsEnabled,
|
||||||
|
}
|
||||||
defer p.UpdateHash()
|
defer p.UpdateHash()
|
||||||
|
|
||||||
desc := newDescriptor("getFeePerByte", smartcontract.IntegerType)
|
desc := newDescriptor("getFeePerByte", smartcontract.IntegerType)
|
||||||
|
@ -112,6 +133,17 @@ func newPolicy() *Policy {
|
||||||
md = newMethodAndPrice(p.setStoragePrice, 1<<15, callflag.States)
|
md = newMethodAndPrice(p.setStoragePrice, 1<<15, callflag.States)
|
||||||
p.AddMethod(md, desc)
|
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,
|
desc = newDescriptor("setFeePerByte", smartcontract.VoidType,
|
||||||
manifest.NewParameter("value", smartcontract.IntegerType))
|
manifest.NewParameter("value", smartcontract.IntegerType))
|
||||||
md = newMethodAndPrice(p.setFeePerByte, 1<<15, callflag.States)
|
md = newMethodAndPrice(p.setFeePerByte, 1<<15, callflag.States)
|
||||||
|
@ -146,8 +178,13 @@ func (p *Policy) Initialize(ic *interop.Context) error {
|
||||||
feePerByte: defaultFeePerByte,
|
feePerByte: defaultFeePerByte,
|
||||||
maxVerificationGas: defaultMaxVerificationGas,
|
maxVerificationGas: defaultMaxVerificationGas,
|
||||||
storagePrice: DefaultStoragePrice,
|
storagePrice: DefaultStoragePrice,
|
||||||
|
attributeFee: map[transaction.AttrType]uint32{},
|
||||||
blockedAccounts: make([]util.Uint160, 0),
|
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)
|
ic.DAO.SetCache(p.ID, cache)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -183,6 +220,25 @@ func (p *Policy) fillCacheFromDAO(cache *PolicyCache, d *dao.Simple) error {
|
||||||
if fErr != nil {
|
if fErr != nil {
|
||||||
return fmt.Errorf("failed to initialize blocked accounts: %w", fErr)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +353,43 @@ func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) sta
|
||||||
return stackitem.Null{}
|
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.
|
// 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 {
|
func (p *Policy) setFeePerByte(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
value := toBigInt(args[0]).Int64()
|
value := toBigInt(args[0]).Int64()
|
||||||
|
|
|
@ -21,6 +21,15 @@ const (
|
||||||
NotaryAssistedT AttrType = 0x22 // NotaryAssisted
|
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 {
|
func (a AttrType) allowMultiple() bool {
|
||||||
switch a {
|
switch a {
|
||||||
case ConflictsT:
|
case ConflictsT:
|
||||||
|
@ -29,3 +38,11 @@ func (a AttrType) allowMultiple() bool {
|
||||||
return false
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -45,13 +45,3 @@ func GetMaxNotValidBeforeDelta() int {
|
||||||
func SetMaxNotValidBeforeDelta(value int) {
|
func SetMaxNotValidBeforeDelta(value int) {
|
||||||
neogointernal.CallWithTokenNoRet(Hash, "setMaxNotValidBeforeDelta", int(contract.States), value)
|
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)
|
|
||||||
}
|
|
||||||
|
|
14
pkg/interop/native/policy/attrtype.go
Normal file
14
pkg/interop/native/policy/attrtype.go
Normal 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
|
||||||
|
)
|
|
@ -43,6 +43,16 @@ func SetStoragePrice(value int) {
|
||||||
neogointernal.CallWithTokenNoRet(Hash, "setStoragePrice", int(contract.States), value)
|
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.
|
// IsBlocked represents `isBlocked` method of Policy native contract.
|
||||||
func IsBlocked(addr interop.Hash160) bool {
|
func IsBlocked(addr interop.Hash160) bool {
|
||||||
return neogointernal.CallWithToken(Hash, "isBlocked", int(contract.ReadStates), addr).(bool)
|
return neogointernal.CallWithToken(Hash, "isBlocked", int(contract.ReadStates), addr).(bool)
|
||||||
|
|
|
@ -305,7 +305,7 @@ func AddNetworkFee(bc *core.Blockchain, tx *transaction.Transaction, signers ...
|
||||||
tx.NetworkFee += netFee
|
tx.NetworkFee += netFee
|
||||||
size += sizeDelta
|
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.
|
// NewUnsignedBlock creates a new unsigned block from txs.
|
||||||
|
|
|
@ -111,12 +111,6 @@ func (c *ContractReader) GetMaxNotValidBeforeDelta() (uint32, error) {
|
||||||
return uint32(ret), err
|
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
|
// LockDepositUntil creates and sends a transaction that extends the deposit lock
|
||||||
// time for the given account. The return result from the "lockDepositUntil"
|
// 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
|
// 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)
|
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
|
// 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
|
// 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
|
// "withdraw" method is checked to be true, so transaction fails (with FAULT
|
||||||
|
|
|
@ -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) {
|
func TestTxSenders(t *testing.T) {
|
||||||
ta := new(testAct)
|
ta := new(testAct)
|
||||||
ntr := New(ta)
|
ntr := New(ta)
|
||||||
|
@ -134,9 +114,6 @@ func TestTxSenders(t *testing.T) {
|
||||||
"SetMaxNotValidBeforeDelta": func() (util.Uint256, uint32, error) {
|
"SetMaxNotValidBeforeDelta": func() (util.Uint256, uint32, error) {
|
||||||
return ntr.SetMaxNotValidBeforeDelta(42)
|
return ntr.SetMaxNotValidBeforeDelta(42)
|
||||||
},
|
},
|
||||||
"SetNotaryServiceFeePerKey": func() (util.Uint256, uint32, error) {
|
|
||||||
return ntr.SetNotaryServiceFeePerKey(100500)
|
|
||||||
},
|
|
||||||
"Withdraw": func() (util.Uint256, uint32, error) {
|
"Withdraw": func() (util.Uint256, uint32, error) {
|
||||||
return ntr.Withdraw(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
|
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) {
|
"SetMaxNotValidBeforeDeltaUnsigned": func() (*transaction.Transaction, error) {
|
||||||
return ntr.SetMaxNotValidBeforeDeltaUnsigned(42)
|
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) {
|
"WithdrawTransaction": func() (*transaction.Transaction, error) {
|
||||||
return ntr.WithdrawTransaction(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
|
return ntr.WithdrawTransaction(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,6 +40,7 @@ const (
|
||||||
execFeeSetter = "setExecFeeFactor"
|
execFeeSetter = "setExecFeeFactor"
|
||||||
feePerByteSetter = "setFeePerByte"
|
feePerByteSetter = "setFeePerByte"
|
||||||
storagePriceSetter = "setStoragePrice"
|
storagePriceSetter = "setStoragePrice"
|
||||||
|
attributeFeeSetter = "setAttributeFee"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContractReader provides an interface to call read-only PolicyContract
|
// 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"))
|
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.
|
// IsBlocked checks if the given account is blocked in the PolicyContract.
|
||||||
func (c *ContractReader) IsBlocked(account util.Uint160) (bool, error) {
|
func (c *ContractReader) IsBlocked(account util.Uint160) (bool, error) {
|
||||||
return unwrap.Bool(c.invoker.Call(Hash, "isBlocked", account))
|
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)
|
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
|
// 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
|
// network (via `blockAccount` method), it fails (with FAULT state) if it's not
|
||||||
// successful. The returned values are transaction hash, its
|
// successful. The returned values are transaction hash, its
|
||||||
|
|
|
@ -58,6 +58,8 @@ func TestReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
_, err := pc.IsBlocked(util.Uint160{1, 2, 3})
|
_, err := pc.IsBlocked(util.Uint160{1, 2, 3})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
_, err = pc.GetAttributeFee(transaction.ConflictsT)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
ta.err = nil
|
ta.err = nil
|
||||||
ta.res = &result.Invoke{
|
ta.res = &result.Invoke{
|
||||||
|
@ -71,6 +73,9 @@ func TestReader(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, int64(42), val)
|
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{
|
ta.res = &result.Invoke{
|
||||||
State: "HALT",
|
State: "HALT",
|
||||||
Stack: []stackitem.Item{
|
Stack: []stackitem.Item{
|
||||||
|
@ -97,6 +102,8 @@ func TestIntSetters(t *testing.T) {
|
||||||
_, _, err := m(42)
|
_, _, err := m(42)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
_, _, err := pc.SetAttributeFee(transaction.OracleResponseT, 123)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
ta.err = nil
|
ta.err = nil
|
||||||
ta.txh = util.Uint256{1, 2, 3}
|
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.txh, h)
|
||||||
require.Equal(t, ta.vub, vub)
|
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) {
|
func TestUint160Setters(t *testing.T) {
|
||||||
|
|
|
@ -183,6 +183,10 @@ func TestClientPolicyContract(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, int64(100000), val)
|
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{})
|
ret, err := polizei.IsBlocked(util.Uint160{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.False(t, ret)
|
require.False(t, ret)
|
||||||
|
@ -212,14 +216,17 @@ func TestClientPolicyContract(t *testing.T) {
|
||||||
txstorage, err := polis.SetStoragePriceUnsigned(100500)
|
txstorage, err := polis.SetStoragePriceUnsigned(100500)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
txattr, err := polis.SetAttributeFeeUnsigned(transaction.NotaryAssistedT, 100500)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
txblock, err := polis.BlockAccountUnsigned(util.Uint160{1, 2, 3})
|
txblock, err := polis.BlockAccountUnsigned(util.Uint160{1, 2, 3})
|
||||||
require.NoError(t, err)
|
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)
|
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)
|
_, err = c.SubmitBlock(*bl)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -235,6 +242,10 @@ func TestClientPolicyContract(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, int64(100500), val)
|
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})
|
ret, err = polizei.IsBlocked(util.Uint160{1, 2, 3})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, ret)
|
require.True(t, ret)
|
||||||
|
@ -480,10 +491,6 @@ func TestClientNotary(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, uint32(140), maxNVBd)
|
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{{
|
commAct, err := actor.New(c, []actor.SignerAccount{{
|
||||||
Signer: transaction.Signer{
|
Signer: transaction.Signer{
|
||||||
Account: testchain.CommitteeScriptHash(),
|
Account: testchain.CommitteeScriptHash(),
|
||||||
|
@ -501,12 +508,9 @@ func TestClientNotary(t *testing.T) {
|
||||||
|
|
||||||
txNVB, err := notaComm.SetMaxNotValidBeforeDeltaUnsigned(210)
|
txNVB, err := notaComm.SetMaxNotValidBeforeDeltaUnsigned(210)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
txFee, err := notaComm.SetNotaryServiceFeePerKeyUnsigned(500_0000)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
txNVB.Scripts[0].InvocationScript = testchain.SignCommittee(txNVB)
|
txNVB.Scripts[0].InvocationScript = testchain.SignCommittee(txNVB)
|
||||||
txFee.Scripts[0].InvocationScript = testchain.SignCommittee(txFee)
|
bl := testchain.NewBlock(t, chain, 1, 0, txNVB)
|
||||||
bl := testchain.NewBlock(t, chain, 1, 0, txNVB, txFee)
|
|
||||||
_, err = c.SubmitBlock(*bl)
|
_, err = c.SubmitBlock(*bl)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -514,10 +518,6 @@ func TestClientNotary(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, uint32(210), maxNVBd)
|
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{{
|
privAct, err := actor.New(c, []actor.SignerAccount{{
|
||||||
Signer: transaction.Signer{
|
Signer: transaction.Signer{
|
||||||
Account: priv0Hash,
|
Account: priv0Hash,
|
||||||
|
@ -743,12 +743,13 @@ func TestCalculateNetworkFee(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.Init())
|
require.NoError(t, c.Init())
|
||||||
|
|
||||||
t.Run("ContractWithArgs", func(t *testing.T) {
|
|
||||||
check := func(t *testing.T, extraFee int64) {
|
|
||||||
h, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
h, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
priv := testchain.PrivateKeyByID(0)
|
priv := testchain.PrivateKeyByID(0)
|
||||||
acc0 := wallet.NewAccountFromPrivateKey(priv)
|
acc0 := wallet.NewAccountFromPrivateKey(priv)
|
||||||
|
|
||||||
|
t.Run("ContractWithArgs", func(t *testing.T) {
|
||||||
|
check := func(t *testing.T, extraFee int64) {
|
||||||
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
|
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tx.ValidUntilBlock = chain.BlockHeight() + 10
|
tx.ValidUntilBlock = chain.BlockHeight() + 10
|
||||||
|
@ -802,6 +803,62 @@ func TestCalculateNetworkFee(t *testing.T) {
|
||||||
check(t, -1)
|
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) {
|
func TestNotaryActor(t *testing.T) {
|
||||||
|
|
|
@ -65,6 +65,7 @@ type (
|
||||||
Ledger interface {
|
Ledger interface {
|
||||||
AddBlock(block *block.Block) error
|
AddBlock(block *block.Block) error
|
||||||
BlockHeight() uint32
|
BlockHeight() uint32
|
||||||
|
CalculateAttributesFee(tx *transaction.Transaction) int64
|
||||||
CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error)
|
CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error)
|
||||||
CurrentBlockHash() util.Uint256
|
CurrentBlockHash() util.Uint256
|
||||||
FeePerByte() int64
|
FeePerByte() int64
|
||||||
|
@ -89,7 +90,6 @@ type (
|
||||||
GetNatives() []state.NativeContract
|
GetNatives() []state.NativeContract
|
||||||
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
||||||
GetNotaryContractScriptHash() util.Uint160
|
GetNotaryContractScriptHash() util.Uint160
|
||||||
GetNotaryServiceFeePerKey() int64
|
|
||||||
GetStateModule() core.StateRoot
|
GetStateModule() core.StateRoot
|
||||||
GetStorageItem(id int32, key []byte) state.StorageItem
|
GetStorageItem(id int32, key []byte) state.StorageItem
|
||||||
GetTestHistoricVM(t trigger.Type, tx *transaction.Transaction, nextBlockHeight uint32) (*interop.Context, error)
|
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
|
netFee += gasConsumed
|
||||||
size += io.GetVarSize(w.VerificationScript) + io.GetVarSize(w.InvocationScript)
|
size += io.GetVarSize(w.VerificationScript) + io.GetVarSize(w.InvocationScript)
|
||||||
}
|
}
|
||||||
if s.chain.P2PSigExtensionsEnabled() {
|
netFee += int64(size)*s.chain.FeePerByte() + s.chain.CalculateAttributesFee(tx)
|
||||||
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
|
|
||||||
return result.NetworkFee{Value: netFee}, nil
|
return result.NetworkFee{Value: netFee}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ func initClearServerWithCustomConfig(t testing.TB, ccfg func(configuration *conf
|
||||||
}
|
}
|
||||||
|
|
||||||
func initClearServerWithInMemoryChain(t testing.TB) (*core.Blockchain, *Server, *httptest.Server) {
|
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) {
|
func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *httptest.Server) {
|
||||||
|
|
|
@ -87,7 +87,7 @@ const (
|
||||||
faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60"
|
faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60"
|
||||||
faultedTxBlock uint32 = 23
|
faultedTxBlock uint32 = 23
|
||||||
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
|
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
|
||||||
block20StateRootLE = "cc8315751c5b6edf39c14f1637bfa0595d6ca86b8ed4d41cb495d572b680504f"
|
block20StateRootLE = "858c873539d6d24a70f2be13f9dafc61aef2b63c2aa16bb440676de6e44e3cf1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in a new issue