2021-12-09 17:12:15 +00:00
package native_test
import (
"bytes"
"encoding/json"
"fmt"
"testing"
2022-03-15 16:16:39 +00:00
"github.com/nspcc-dev/neo-go/internal/contracts"
2021-12-09 17:12:15 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
"github.com/nspcc-dev/neo-go/pkg/core/state"
2022-03-15 16:16:39 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/storage"
2021-12-09 17:12:15 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
"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"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
2022-04-19 14:12:03 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/vm"
2021-12-09 17:12:15 +00:00
"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"
"github.com/stretchr/testify/require"
)
func newManagementClient ( t * testing . T ) * neotest . ContractInvoker {
return newNativeClient ( t , nativenames . Management )
}
func TestManagement_MinimumDeploymentFee ( t * testing . T ) {
testGetSet ( t , newManagementClient ( t ) , "MinimumDeploymentFee" , 10_00000000 , 0 , 0 )
}
2022-04-19 14:12:03 +00:00
func TestManagement_MinimumDeploymentFeeCache ( t * testing . T ) {
c := newManagementClient ( t )
testGetSetCache ( t , c , "MinimumDeploymentFee" , 10_00000000 )
}
func TestManagement_ContractCache ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . Committee . ScriptHash ( ) )
manifestBytes , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nefBytes , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
// Deploy contract, abort the transaction and check that Management cache wasn't persisted
// for FAULTed tx at the same block.
w := io . NewBufBinWriter ( )
emit . AppCall ( w . BinWriter , managementInvoker . Hash , "deploy" , callflag . All , nefBytes , manifestBytes )
emit . Opcodes ( w . BinWriter , opcode . ABORT )
tx1 := managementInvoker . PrepareInvocation ( t , w . Bytes ( ) , managementInvoker . Signers )
tx2 := managementInvoker . PrepareInvoke ( t , "getContract" , cs1 . Hash . BytesBE ( ) )
managementInvoker . AddNewBlock ( t , tx1 , tx2 )
managementInvoker . CheckFault ( t , tx1 . Hash ( ) , "ABORT" )
managementInvoker . CheckHalt ( t , tx2 . Hash ( ) , stackitem . Null { } )
// Deploy the contract and check that cache was persisted for HALTed transaction at the same block.
tx1 = managementInvoker . PrepareInvoke ( t , "deploy" , nefBytes , manifestBytes )
tx2 = managementInvoker . PrepareInvoke ( t , "getContract" , cs1 . Hash . BytesBE ( ) )
managementInvoker . AddNewBlock ( t , tx1 , tx2 )
managementInvoker . CheckHalt ( t , tx1 . Hash ( ) )
aer , err := managementInvoker . Chain . GetAppExecResults ( tx2 . Hash ( ) , trigger . Application )
require . NoError ( t , err )
require . Equal ( t , vm . HaltState , aer [ 0 ] . VMState , aer [ 0 ] . FaultException )
require . NotEqual ( t , stackitem . Null { } , aer [ 0 ] . Stack )
}
2021-12-09 17:12:15 +00:00
func TestManagement_ContractDeploy ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . Committee . ScriptHash ( ) )
2021-12-09 17:12:15 +00:00
manifestBytes , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nefBytes , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
t . Run ( "no NEF" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "no valid NEF provided" , "deploy" , nil , manifestBytes )
} )
t . Run ( "no manifest" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "no valid manifest provided" , "deploy" , nefBytes , nil )
} )
t . Run ( "int for NEF" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid NEF file" , "deploy" , int64 ( 1 ) , manifestBytes )
} )
t . Run ( "zero-length NEF" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid NEF file" , "deploy" , [ ] byte { } , manifestBytes )
} )
t . Run ( "array for NEF" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid NEF file" , "deploy" , [ ] interface { } { int64 ( 1 ) } , manifestBytes )
} )
t . Run ( "bad script in NEF" , func ( t * testing . T ) {
nf , err := nef . FileFromBytes ( nefBytes ) // make a full copy
require . NoError ( t , err )
nf . Script [ 0 ] = 0xff
nf . CalculateChecksum ( )
nefBad , err := nf . Bytes ( )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "invalid NEF file" , "deploy" , nefBad , manifestBytes )
} )
t . Run ( "int for manifest" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid manifest" , "deploy" , nefBytes , int64 ( 1 ) )
} )
t . Run ( "zero-length manifest" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid manifest" , "deploy" , nefBytes , [ ] byte { } )
} )
t . Run ( "array for manifest" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid manifest" , "deploy" , nefBytes , [ ] interface { } { int64 ( 1 ) } )
} )
t . Run ( "non-utf8 manifest" , func ( t * testing . T ) {
manifestBad := bytes . Replace ( manifestBytes , [ ] byte ( "TestMain" ) , [ ] byte ( "\xff\xfe\xfd" ) , 1 ) // Replace name.
managementInvoker . InvokeFail ( t , "manifest is not UTF-8 compliant" , "deploy" , nefBytes , manifestBad )
} )
t . Run ( "invalid manifest" , func ( t * testing . T ) {
pkey , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
badManifest := cs1 . Manifest
badManifest . Groups = [ ] manifest . Group { { PublicKey : pkey . PublicKey ( ) , Signature : make ( [ ] byte , 64 ) } }
manifB , err := json . Marshal ( & badManifest )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "invalid manifest" , "deploy" , nefBytes , manifB )
} )
t . Run ( "bad methods in manifest 1" , func ( t * testing . T ) {
badManifest := cs1 . Manifest
badManifest . ABI . Methods = make ( [ ] manifest . Method , len ( cs1 . Manifest . ABI . Methods ) )
copy ( badManifest . ABI . Methods , cs1 . Manifest . ABI . Methods )
core: adjust contract script check on deploy
Reference implementation doesn't panic if the method offset is out of
the contract script bounds, see:
https://github.com/neo-project/neo/blob/736c346b9d8b1404f10023eeecb3a8e92ae0c542/src/neo/SmartContract/Helper.cs#L82
and
https://github.com/neo-project/neo-vm/blob/a65487fa56be3eccb2c1dbfec5dcdd71b8a05fde/src/Neo.VM/Script.cs#L146.
This commit fixes T5 statediff at block #125000. Neo-go node FAULTed the
deploying transaction:
```
{
"version" : 0,
"sysfee" : "1000106065",
"validuntilblock" : 130758,
"script" : "DdMDeyJuYW1lIjoiTmVwMTdUb2tlbiIsImdyb3VwcyI6W10sImZlYXR1cmVzIjp7fSwic3VwcG9ydGVkc3RhbmRhcmRzIjpbIk5FUC0xNyJdLCJhYmkiOnsibWV0aG9kcyI6W3sibmFtZSI6InN5bWJvbCIsInBhcmFtZXRlcnMiOltdLCJyZXR1cm50eXBlIjoiU3RyaW5nIiwib2Zmc2V0IjoyMiwic2FmZSI6dHJ1ZX0seyJuYW1lIjoiZGVjaW1hbHMiLCJwYXJhbWV0ZXJzIjpbXSwicmV0dXJudHlwZSI6IkludGVnZXIiLCJvZmZzZXQiOjIyLCJzYWZlIjp0cnVlfSx7Im5hbWUiOiJ0b3RhbFN1cHBseSIsInBhcmFtZXRlcnMiOltdLCJyZXR1cm50eXBlIjoiSW50ZWdlciIsIm9mZnNldCI6MjIsInNhZmUiOnRydWV9LHsibmFtZSI6ImJhbGFuY2VPZiIsInBhcmFtZXRlcnMiOlt7Im5hbWUiOiJvd25lciIsInR5cGUiOiJIYXNoMTYwIn1dLCJyZXR1cm50eXBlIjoiSW50ZWdlciIsIm9mZnNldCI6MjIsInNhZmUiOnRydWV9LHsibmFtZSI6InRyYW5zZmVyIiwicGFyYW1ldGVycyI6W3sibmFtZSI6ImZyb20iLCJ0eXBlIjoiSGFzaDE2MCJ9LHsibmFtZSI6InRvIiwidHlwZSI6Ikhhc2gxNjAifSx7Im5hbWUiOiJhbW91bnQiLCJ0eXBlIjoiSW50ZWdlciJ9LHsibmFtZSI6ImRhdGEiLCJ0eXBlIjoiQW55In1dLCJyZXR1cm50eXBlIjoiQm9vbGVhbiIsIm9mZnNldCI6MjIsInNhZmUiOmZhbHNlfV0sImV2ZW50cyI6W3sibmFtZSI6IlRyYW5zZmVyIiwicGFyYW1ldGVycyI6W3sibmFtZSI6ImZyb20iLCJ0eXBlIjoiSGFzaDE2MCJ9LHsibmFtZSI6InRvIiwidHlwZSI6Ikhhc2gxNjAifSx7Im5hbWUiOiJhbW91bnQiLCJ0eXBlIjoiSW50ZWdlciJ9XX1dfSwicGVybWlzc2lvbnMiOlt7ImNvbnRyYWN0IjoiKiIsIm1ldGhvZHMiOiIqIn1dLCJ0cnVzdHMiOltdLCJleHRyYSI6eyJlbWFpbCI6ImRldmVsb3BlckBuZW8ub3JnIiwiYXV0aG9yIjoibGF6eW5vZGUiLCJkZXNjcmlwdGlvbiI6IkEgU2ltcGxlIE5lcC0xNyBDb250cmFjdCJ9fQyyTkVGM25lb21sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOaHR0cHM6Ly9naXRodWIuY29tL2xhenlub2RlL25lb21sL2Jsb2IvZGV2L2V4YW1wbGVzL2EuZnVuY3Rpb24uc2ltcGxlbmVwMTcueG1sAAAAABYMBU5lb01MQBhAAgDh9QVAATkFQBFAkA456BLAHwwGZGVwbG95DBT9o/pDRupTKiWPxJfdrdtkN8n9/0FifVtS",
"hash" : "0x40302bcf2021f63a1c24f6009e154c3200f73ad2fe1462d7d599145823dbfa7e",
"witnesses" : [
{
"verification" : "DCECExn08eznGBdguHbcwI+R2//EtVdDx4qf6CeizHqOJgBBVuezJw==",
"invocation" : "DEBtoq+T9NrammQjuYnifco7KHCTk2v+woEJqJCUMr9IscS7PaZaN3FNzSt11yUglIi3T0CJ17KwArBOBvJ8kwq2"
}
],
"attributes" : [],
"signers" : [
{
"scopes" : "None",
"account" : "0x13a192c56738900f9918d7f1ec07d9d8c278b804"
}
],
"size" : 1360,
"nonce" : 1829882407,
"sender" : "NLLvsqs7AyBNmQT6NThUxYWDFwV5b1evaK",
"netfee" : "234352"
}
```
Transaction script contains malformed contract manifest (all methods
offsets are set to be 22, while the contract script lenght is 22):
```
{
"name" : "Nep17Token",
"groups" : [],
"extra" : {
"description" : "A Simple Nep-17 Contract",
"email" : "developer@neo.org",
"author" : "lazynode"
},
"permissions" : [
{
"contract" : "*",
"methods" : "*"
}
],
"features" : {},
"supportedstandards" : [
"NEP-17"
],
"abi" : {
"events" : [
{
"parameters" : [
{
"name" : "from",
"type" : "Hash160"
},
{
"type" : "Hash160",
"name" : "to"
},
{
"name" : "amount",
"type" : "Integer"
}
],
"name" : "Transfer"
}
],
"methods" : [
{
"safe" : true,
"offset" : 22,
"name" : "symbol",
"returntype" : "String",
"parameters" : []
},
{
"returntype" : "Integer",
"parameters" : [],
"safe" : true,
"offset" : 22,
"name" : "decimals"
},
{
"parameters" : [],
"returntype" : "Integer",
"name" : "totalSupply",
"safe" : true,
"offset" : 22
},
{
"parameters" : [
{
"name" : "owner",
"type" : "Hash160"
}
],
"returntype" : "Integer",
"name" : "balanceOf",
"offset" : 22,
"safe" : true
},
{
"name" : "transfer",
"offset" : 22,
"safe" : false,
"parameters" : [
{
"type" : "Hash160",
"name" : "from"
},
{
"name" : "to",
"type" : "Hash160"
},
{
"name" : "amount",
"type" : "Integer"
},
{
"name" : "data",
"type" : "Any"
}
],
"returntype" : "Boolean"
}
]
},
"trusts" : []
}
```
2022-06-02 06:00:59 +00:00
badManifest . ABI . Methods [ 0 ] . Offset = 100500 // out of bounds, but it's OK, this method will not be checked then.
2021-12-09 17:12:15 +00:00
manifB , err := json . Marshal ( & badManifest )
require . NoError ( t , err )
core: adjust contract script check on deploy
Reference implementation doesn't panic if the method offset is out of
the contract script bounds, see:
https://github.com/neo-project/neo/blob/736c346b9d8b1404f10023eeecb3a8e92ae0c542/src/neo/SmartContract/Helper.cs#L82
and
https://github.com/neo-project/neo-vm/blob/a65487fa56be3eccb2c1dbfec5dcdd71b8a05fde/src/Neo.VM/Script.cs#L146.
This commit fixes T5 statediff at block #125000. Neo-go node FAULTed the
deploying transaction:
```
{
"version" : 0,
"sysfee" : "1000106065",
"validuntilblock" : 130758,
"script" : "DdMDeyJuYW1lIjoiTmVwMTdUb2tlbiIsImdyb3VwcyI6W10sImZlYXR1cmVzIjp7fSwic3VwcG9ydGVkc3RhbmRhcmRzIjpbIk5FUC0xNyJdLCJhYmkiOnsibWV0aG9kcyI6W3sibmFtZSI6InN5bWJvbCIsInBhcmFtZXRlcnMiOltdLCJyZXR1cm50eXBlIjoiU3RyaW5nIiwib2Zmc2V0IjoyMiwic2FmZSI6dHJ1ZX0seyJuYW1lIjoiZGVjaW1hbHMiLCJwYXJhbWV0ZXJzIjpbXSwicmV0dXJudHlwZSI6IkludGVnZXIiLCJvZmZzZXQiOjIyLCJzYWZlIjp0cnVlfSx7Im5hbWUiOiJ0b3RhbFN1cHBseSIsInBhcmFtZXRlcnMiOltdLCJyZXR1cm50eXBlIjoiSW50ZWdlciIsIm9mZnNldCI6MjIsInNhZmUiOnRydWV9LHsibmFtZSI6ImJhbGFuY2VPZiIsInBhcmFtZXRlcnMiOlt7Im5hbWUiOiJvd25lciIsInR5cGUiOiJIYXNoMTYwIn1dLCJyZXR1cm50eXBlIjoiSW50ZWdlciIsIm9mZnNldCI6MjIsInNhZmUiOnRydWV9LHsibmFtZSI6InRyYW5zZmVyIiwicGFyYW1ldGVycyI6W3sibmFtZSI6ImZyb20iLCJ0eXBlIjoiSGFzaDE2MCJ9LHsibmFtZSI6InRvIiwidHlwZSI6Ikhhc2gxNjAifSx7Im5hbWUiOiJhbW91bnQiLCJ0eXBlIjoiSW50ZWdlciJ9LHsibmFtZSI6ImRhdGEiLCJ0eXBlIjoiQW55In1dLCJyZXR1cm50eXBlIjoiQm9vbGVhbiIsIm9mZnNldCI6MjIsInNhZmUiOmZhbHNlfV0sImV2ZW50cyI6W3sibmFtZSI6IlRyYW5zZmVyIiwicGFyYW1ldGVycyI6W3sibmFtZSI6ImZyb20iLCJ0eXBlIjoiSGFzaDE2MCJ9LHsibmFtZSI6InRvIiwidHlwZSI6Ikhhc2gxNjAifSx7Im5hbWUiOiJhbW91bnQiLCJ0eXBlIjoiSW50ZWdlciJ9XX1dfSwicGVybWlzc2lvbnMiOlt7ImNvbnRyYWN0IjoiKiIsIm1ldGhvZHMiOiIqIn1dLCJ0cnVzdHMiOltdLCJleHRyYSI6eyJlbWFpbCI6ImRldmVsb3BlckBuZW8ub3JnIiwiYXV0aG9yIjoibGF6eW5vZGUiLCJkZXNjcmlwdGlvbiI6IkEgU2ltcGxlIE5lcC0xNyBDb250cmFjdCJ9fQyyTkVGM25lb21sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOaHR0cHM6Ly9naXRodWIuY29tL2xhenlub2RlL25lb21sL2Jsb2IvZGV2L2V4YW1wbGVzL2EuZnVuY3Rpb24uc2ltcGxlbmVwMTcueG1sAAAAABYMBU5lb01MQBhAAgDh9QVAATkFQBFAkA456BLAHwwGZGVwbG95DBT9o/pDRupTKiWPxJfdrdtkN8n9/0FifVtS",
"hash" : "0x40302bcf2021f63a1c24f6009e154c3200f73ad2fe1462d7d599145823dbfa7e",
"witnesses" : [
{
"verification" : "DCECExn08eznGBdguHbcwI+R2//EtVdDx4qf6CeizHqOJgBBVuezJw==",
"invocation" : "DEBtoq+T9NrammQjuYnifco7KHCTk2v+woEJqJCUMr9IscS7PaZaN3FNzSt11yUglIi3T0CJ17KwArBOBvJ8kwq2"
}
],
"attributes" : [],
"signers" : [
{
"scopes" : "None",
"account" : "0x13a192c56738900f9918d7f1ec07d9d8c278b804"
}
],
"size" : 1360,
"nonce" : 1829882407,
"sender" : "NLLvsqs7AyBNmQT6NThUxYWDFwV5b1evaK",
"netfee" : "234352"
}
```
Transaction script contains malformed contract manifest (all methods
offsets are set to be 22, while the contract script lenght is 22):
```
{
"name" : "Nep17Token",
"groups" : [],
"extra" : {
"description" : "A Simple Nep-17 Contract",
"email" : "developer@neo.org",
"author" : "lazynode"
},
"permissions" : [
{
"contract" : "*",
"methods" : "*"
}
],
"features" : {},
"supportedstandards" : [
"NEP-17"
],
"abi" : {
"events" : [
{
"parameters" : [
{
"name" : "from",
"type" : "Hash160"
},
{
"type" : "Hash160",
"name" : "to"
},
{
"name" : "amount",
"type" : "Integer"
}
],
"name" : "Transfer"
}
],
"methods" : [
{
"safe" : true,
"offset" : 22,
"name" : "symbol",
"returntype" : "String",
"parameters" : []
},
{
"returntype" : "Integer",
"parameters" : [],
"safe" : true,
"offset" : 22,
"name" : "decimals"
},
{
"parameters" : [],
"returntype" : "Integer",
"name" : "totalSupply",
"safe" : true,
"offset" : 22
},
{
"parameters" : [
{
"name" : "owner",
"type" : "Hash160"
}
],
"returntype" : "Integer",
"name" : "balanceOf",
"offset" : 22,
"safe" : true
},
{
"name" : "transfer",
"offset" : 22,
"safe" : false,
"parameters" : [
{
"type" : "Hash160",
"name" : "from"
},
{
"name" : "to",
"type" : "Hash160"
},
{
"name" : "amount",
"type" : "Integer"
},
{
"name" : "data",
"type" : "Any"
}
],
"returntype" : "Boolean"
}
]
},
"trusts" : []
}
```
2022-06-02 06:00:59 +00:00
tx := c . PrepareInvokeNoSign ( t , "deploy" , nefBytes , manifB )
tx . Signers = [ ] transaction . Signer { { } } // Need dummy signer to deploy.
b := c . NewUnsignedBlock ( t , tx )
ic := c . Chain . GetTestVM ( trigger . Application , tx , b )
t . Cleanup ( ic . Finalize )
2021-12-09 17:12:15 +00:00
core: adjust contract script check on deploy
Reference implementation doesn't panic if the method offset is out of
the contract script bounds, see:
https://github.com/neo-project/neo/blob/736c346b9d8b1404f10023eeecb3a8e92ae0c542/src/neo/SmartContract/Helper.cs#L82
and
https://github.com/neo-project/neo-vm/blob/a65487fa56be3eccb2c1dbfec5dcdd71b8a05fde/src/Neo.VM/Script.cs#L146.
This commit fixes T5 statediff at block #125000. Neo-go node FAULTed the
deploying transaction:
```
{
"version" : 0,
"sysfee" : "1000106065",
"validuntilblock" : 130758,
"script" : "DdMDeyJuYW1lIjoiTmVwMTdUb2tlbiIsImdyb3VwcyI6W10sImZlYXR1cmVzIjp7fSwic3VwcG9ydGVkc3RhbmRhcmRzIjpbIk5FUC0xNyJdLCJhYmkiOnsibWV0aG9kcyI6W3sibmFtZSI6InN5bWJvbCIsInBhcmFtZXRlcnMiOltdLCJyZXR1cm50eXBlIjoiU3RyaW5nIiwib2Zmc2V0IjoyMiwic2FmZSI6dHJ1ZX0seyJuYW1lIjoiZGVjaW1hbHMiLCJwYXJhbWV0ZXJzIjpbXSwicmV0dXJudHlwZSI6IkludGVnZXIiLCJvZmZzZXQiOjIyLCJzYWZlIjp0cnVlfSx7Im5hbWUiOiJ0b3RhbFN1cHBseSIsInBhcmFtZXRlcnMiOltdLCJyZXR1cm50eXBlIjoiSW50ZWdlciIsIm9mZnNldCI6MjIsInNhZmUiOnRydWV9LHsibmFtZSI6ImJhbGFuY2VPZiIsInBhcmFtZXRlcnMiOlt7Im5hbWUiOiJvd25lciIsInR5cGUiOiJIYXNoMTYwIn1dLCJyZXR1cm50eXBlIjoiSW50ZWdlciIsIm9mZnNldCI6MjIsInNhZmUiOnRydWV9LHsibmFtZSI6InRyYW5zZmVyIiwicGFyYW1ldGVycyI6W3sibmFtZSI6ImZyb20iLCJ0eXBlIjoiSGFzaDE2MCJ9LHsibmFtZSI6InRvIiwidHlwZSI6Ikhhc2gxNjAifSx7Im5hbWUiOiJhbW91bnQiLCJ0eXBlIjoiSW50ZWdlciJ9LHsibmFtZSI6ImRhdGEiLCJ0eXBlIjoiQW55In1dLCJyZXR1cm50eXBlIjoiQm9vbGVhbiIsIm9mZnNldCI6MjIsInNhZmUiOmZhbHNlfV0sImV2ZW50cyI6W3sibmFtZSI6IlRyYW5zZmVyIiwicGFyYW1ldGVycyI6W3sibmFtZSI6ImZyb20iLCJ0eXBlIjoiSGFzaDE2MCJ9LHsibmFtZSI6InRvIiwidHlwZSI6Ikhhc2gxNjAifSx7Im5hbWUiOiJhbW91bnQiLCJ0eXBlIjoiSW50ZWdlciJ9XX1dfSwicGVybWlzc2lvbnMiOlt7ImNvbnRyYWN0IjoiKiIsIm1ldGhvZHMiOiIqIn1dLCJ0cnVzdHMiOltdLCJleHRyYSI6eyJlbWFpbCI6ImRldmVsb3BlckBuZW8ub3JnIiwiYXV0aG9yIjoibGF6eW5vZGUiLCJkZXNjcmlwdGlvbiI6IkEgU2ltcGxlIE5lcC0xNyBDb250cmFjdCJ9fQyyTkVGM25lb21sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOaHR0cHM6Ly9naXRodWIuY29tL2xhenlub2RlL25lb21sL2Jsb2IvZGV2L2V4YW1wbGVzL2EuZnVuY3Rpb24uc2ltcGxlbmVwMTcueG1sAAAAABYMBU5lb01MQBhAAgDh9QVAATkFQBFAkA456BLAHwwGZGVwbG95DBT9o/pDRupTKiWPxJfdrdtkN8n9/0FifVtS",
"hash" : "0x40302bcf2021f63a1c24f6009e154c3200f73ad2fe1462d7d599145823dbfa7e",
"witnesses" : [
{
"verification" : "DCECExn08eznGBdguHbcwI+R2//EtVdDx4qf6CeizHqOJgBBVuezJw==",
"invocation" : "DEBtoq+T9NrammQjuYnifco7KHCTk2v+woEJqJCUMr9IscS7PaZaN3FNzSt11yUglIi3T0CJ17KwArBOBvJ8kwq2"
}
],
"attributes" : [],
"signers" : [
{
"scopes" : "None",
"account" : "0x13a192c56738900f9918d7f1ec07d9d8c278b804"
}
],
"size" : 1360,
"nonce" : 1829882407,
"sender" : "NLLvsqs7AyBNmQT6NThUxYWDFwV5b1evaK",
"netfee" : "234352"
}
```
Transaction script contains malformed contract manifest (all methods
offsets are set to be 22, while the contract script lenght is 22):
```
{
"name" : "Nep17Token",
"groups" : [],
"extra" : {
"description" : "A Simple Nep-17 Contract",
"email" : "developer@neo.org",
"author" : "lazynode"
},
"permissions" : [
{
"contract" : "*",
"methods" : "*"
}
],
"features" : {},
"supportedstandards" : [
"NEP-17"
],
"abi" : {
"events" : [
{
"parameters" : [
{
"name" : "from",
"type" : "Hash160"
},
{
"type" : "Hash160",
"name" : "to"
},
{
"name" : "amount",
"type" : "Integer"
}
],
"name" : "Transfer"
}
],
"methods" : [
{
"safe" : true,
"offset" : 22,
"name" : "symbol",
"returntype" : "String",
"parameters" : []
},
{
"returntype" : "Integer",
"parameters" : [],
"safe" : true,
"offset" : 22,
"name" : "decimals"
},
{
"parameters" : [],
"returntype" : "Integer",
"name" : "totalSupply",
"safe" : true,
"offset" : 22
},
{
"parameters" : [
{
"name" : "owner",
"type" : "Hash160"
}
],
"returntype" : "Integer",
"name" : "balanceOf",
"offset" : 22,
"safe" : true
},
{
"name" : "transfer",
"offset" : 22,
"safe" : false,
"parameters" : [
{
"type" : "Hash160",
"name" : "from"
},
{
"name" : "to",
"type" : "Hash160"
},
{
"name" : "amount",
"type" : "Integer"
},
{
"name" : "data",
"type" : "Any"
}
],
"returntype" : "Boolean"
}
]
},
"trusts" : []
}
```
2022-06-02 06:00:59 +00:00
ic . VM . LoadWithFlags ( tx . Script , callflag . All )
err = ic . VM . Run ( )
require . NoError ( t , err )
} )
2021-12-09 17:12:15 +00:00
t . Run ( "bad methods in manifest 2" , func ( t * testing . T ) {
var badManifest = cs1 . Manifest
badManifest . ABI . Methods = make ( [ ] manifest . Method , len ( cs1 . Manifest . ABI . Methods ) )
copy ( badManifest . ABI . Methods , cs1 . Manifest . ABI . Methods )
badManifest . ABI . Methods [ 0 ] . Offset = len ( cs1 . NEF . Script ) - 2 // Ends with `CALLT(X,X);RET`.
manifB , err := json . Marshal ( badManifest )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "some methods point to wrong offsets (not to instruction boundary)" , "deploy" , nefBytes , manifB )
} )
2022-06-02 09:09:34 +00:00
t . Run ( "duplicated methods in manifest 1" , func ( t * testing . T ) {
badManifest := cs1 . Manifest
badManifest . ABI . Methods = make ( [ ] manifest . Method , len ( cs1 . Manifest . ABI . Methods ) )
copy ( badManifest . ABI . Methods , cs1 . Manifest . ABI . Methods )
badManifest . ABI . Methods [ 0 ] = badManifest . ABI . Methods [ 1 ] // duplicates
manifB , err := json . Marshal ( & badManifest )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "duplicate method specifications" , "deploy" , nefBytes , manifB )
} )
t . Run ( "duplicated events in manifest 1" , func ( t * testing . T ) {
badManifest := cs1 . Manifest
badManifest . ABI . Methods = make ( [ ] manifest . Method , len ( cs1 . Manifest . ABI . Methods ) )
copy ( badManifest . ABI . Methods , cs1 . Manifest . ABI . Methods )
badManifest . ABI . Events = [ ] manifest . Event { { Name : "event" } , { Name : "event" } } // duplicates
manifB , err := json . Marshal ( & badManifest )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "duplicate event names" , "deploy" , nefBytes , manifB )
} )
2021-12-09 17:12:15 +00:00
t . Run ( "not enough GAS" , func ( t * testing . T ) {
tx := managementInvoker . NewUnsignedTx ( t , managementInvoker . Hash , "deploy" , nefBytes , manifestBytes )
managementInvoker . SignTx ( t , tx , 1_0000_0000 , managementInvoker . Signers ... )
managementInvoker . AddNewBlock ( t , tx )
managementInvoker . CheckFault ( t , tx . Hash ( ) , "gas limit exceeded" )
} )
si , err := cs1 . ToStackItem ( )
require . NoError ( t , err )
t . Run ( "positive" , func ( t * testing . T ) {
tx1 := managementInvoker . PrepareInvoke ( t , "deploy" , nefBytes , manifestBytes )
tx2 := managementInvoker . PrepareInvoke ( t , "getContract" , cs1 . Hash . BytesBE ( ) )
managementInvoker . AddNewBlock ( t , tx1 , tx2 )
managementInvoker . CheckHalt ( t , tx1 . Hash ( ) , si )
managementInvoker . CheckHalt ( t , tx2 . Hash ( ) , si )
managementInvoker . CheckTxNotificationEvent ( t , tx1 . Hash ( ) , 0 , state . NotificationEvent {
ScriptHash : c . NativeHash ( t , nativenames . Management ) ,
Name : "Deploy" ,
Item : stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewByteArray ( cs1 . Hash . BytesBE ( ) ) } ) ,
} )
t . Run ( "_deploy called" , func ( t * testing . T ) {
helperInvoker := c . Executor . CommitteeInvoker ( cs1 . Hash )
expected := stackitem . NewArray ( [ ] stackitem . Item { stackitem . Make ( "create" ) , stackitem . Null { } } )
expectedBytes , err := stackitem . Serialize ( expected )
require . NoError ( t , err )
helperInvoker . Invoke ( t , stackitem . NewByteArray ( expectedBytes ) , "getValue" )
} )
t . Run ( "get after deploy" , func ( t * testing . T ) {
managementInvoker . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
t . Run ( "get after restore" , func ( t * testing . T ) {
w := io . NewBufBinWriter ( )
require . NoError ( t , chaindump . Dump ( c . Executor . Chain , w . BinWriter , 0 , c . Executor . Chain . BlockHeight ( ) + 1 ) )
require . NoError ( t , w . Err )
r := io . NewBinReaderFromBuf ( w . Bytes ( ) )
bc2 , acc := chain . NewSingle ( t )
e2 := neotest . NewExecutor ( t , bc2 , acc , acc )
managementInvoker2 := e2 . CommitteeInvoker ( e2 . NativeHash ( t , nativenames . Management ) )
require . NoError ( t , chaindump . Restore ( bc2 , r , 0 , c . Executor . Chain . BlockHeight ( ) + 1 , nil ) )
require . NoError ( t , r . Err )
managementInvoker2 . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
} )
t . Run ( "contract already exists" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "contract already exists" , "deploy" , nefBytes , manifestBytes )
} )
t . Run ( "failed _deploy" , func ( t * testing . T ) {
deployScript := [ ] byte { byte ( opcode . ABORT ) }
m := manifest . NewManifest ( "TestDeployAbort" )
m . ABI . Methods = [ ] manifest . Method {
{
Name : manifest . MethodDeploy ,
Offset : 0 ,
Parameters : [ ] manifest . Parameter {
manifest . NewParameter ( "data" , smartcontract . AnyType ) ,
manifest . NewParameter ( "isUpdate" , smartcontract . BoolType ) ,
} ,
ReturnType : smartcontract . VoidType ,
} ,
}
nefD , err := nef . NewFile ( deployScript )
require . NoError ( t , err )
nefDb , err := nefD . Bytes ( )
require . NoError ( t , err )
manifD , err := json . Marshal ( m )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "ABORT" , "deploy" , nefDb , manifD )
t . Run ( "get after failed deploy" , func ( t * testing . T ) {
h := state . CreateContractHash ( c . CommitteeHash , nefD . Checksum , m . Name )
managementInvoker . Invoke ( t , stackitem . Null { } , "getContract" , h . BytesBE ( ) )
} )
} )
t . Run ( "bad _deploy" , func ( t * testing . T ) { // invalid _deploy signature
deployScript := [ ] byte { byte ( opcode . RET ) }
m := manifest . NewManifest ( "TestBadDeploy" )
m . ABI . Methods = [ ] manifest . Method {
{
Name : manifest . MethodDeploy ,
Offset : 0 ,
Parameters : [ ] manifest . Parameter {
manifest . NewParameter ( "data" , smartcontract . AnyType ) ,
manifest . NewParameter ( "isUpdate" , smartcontract . BoolType ) ,
} ,
ReturnType : smartcontract . ArrayType ,
} ,
}
nefD , err := nef . NewFile ( deployScript )
require . NoError ( t , err )
nefDb , err := nefD . Bytes ( )
require . NoError ( t , err )
manifD , err := json . Marshal ( m )
require . NoError ( t , err )
managementInvoker . InvokeFail ( t , "invalid return values count: expected 0, got 2" , "deploy" , nefDb , manifD )
t . Run ( "get after bad _deploy" , func ( t * testing . T ) {
h := state . CreateContractHash ( c . CommitteeHash , nefD . Checksum , m . Name )
managementInvoker . Invoke ( t , stackitem . Null { } , "getContract" , h . BytesBE ( ) )
} )
} )
}
func TestManagement_StartFromHeight ( t * testing . T ) {
// Create database to be able to start another chain from the same height later.
ldbDir := t . TempDir ( )
dbConfig := storage . DBConfiguration {
Type : "leveldb" ,
LevelDBOptions : storage . LevelDBOptions {
DataDirectoryPath : ldbDir ,
} ,
}
newLevelStore , err := storage . NewLevelDBStore ( dbConfig . LevelDBOptions )
require . Nil ( t , err , "NewLevelDBStore error" )
// Create blockchain and put contract state to it.
bc , acc := chain . NewSingleWithCustomConfigAndStore ( t , nil , newLevelStore , false )
go bc . Run ( )
e := neotest . NewExecutor ( t , bc , acc , acc )
c := e . CommitteeInvoker ( e . NativeHash ( t , nativenames . Management ) )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . CommitteeHash )
2021-12-09 17:12:15 +00:00
manifestBytes , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nefBytes , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
si , err := cs1 . ToStackItem ( )
require . NoError ( t , err )
managementInvoker . Invoke ( t , si , "deploy" , nefBytes , manifestBytes )
managementInvoker . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
// Close current blockchain and start the new one from the same height with the same db.
bc . Close ( )
newLevelStore , err = storage . NewLevelDBStore ( dbConfig . LevelDBOptions )
require . NoError ( t , err )
bc2 , acc := chain . NewSingleWithCustomConfigAndStore ( t , nil , newLevelStore , true )
e2 := neotest . NewExecutor ( t , bc2 , acc , acc )
managementInvoker2 := e2 . CommitteeInvoker ( e2 . NativeHash ( t , nativenames . Management ) )
// Check that initialisation of native Management was correctly performed.
managementInvoker2 . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
}
func TestManagement_DeployManifestOverflow ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . CommitteeHash )
2021-12-09 17:12:15 +00:00
manif1 , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nef1 , err := nef . NewFile ( cs1 . NEF . Script )
require . NoError ( t , err )
nef1b , err := nef1 . Bytes ( )
require . NoError ( t , err )
w := io . NewBufBinWriter ( )
emit . Bytes ( w . BinWriter , manif1 )
emit . Int ( w . BinWriter , manifest . MaxManifestSize )
emit . Opcodes ( w . BinWriter , opcode . NEWBUFFER , opcode . CAT )
emit . Bytes ( w . BinWriter , nef1b )
emit . Int ( w . BinWriter , 2 )
emit . Opcodes ( w . BinWriter , opcode . PACK )
emit . AppCallNoArgs ( w . BinWriter , managementInvoker . Hash , "deploy" , callflag . All )
require . NoError ( t , w . Err )
script := w . Bytes ( )
tx := transaction . New ( script , 0 )
tx . ValidUntilBlock = managementInvoker . Chain . BlockHeight ( ) + 1
managementInvoker . SignTx ( t , tx , 100_0000_0000 , managementInvoker . Signers ... )
managementInvoker . AddNewBlock ( t , tx )
managementInvoker . CheckFault ( t , tx . Hash ( ) , fmt . Sprintf ( "invalid manifest: len is %d (max %d)" , manifest . MaxManifestSize + len ( manif1 ) , manifest . MaxManifestSize ) )
}
func TestManagement_ContractDeployAndUpdateWithParameter ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . CommitteeHash )
2021-12-09 17:12:15 +00:00
cs1 . Manifest . Permissions = [ ] manifest . Permission { * manifest . NewPermission ( manifest . PermissionWildcard ) }
cs1 . ID = 1
cs1 . Hash = state . CreateContractHash ( c . CommitteeHash , cs1 . NEF . Checksum , cs1 . Manifest . Name )
manif1 , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nef1b , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
si , err := cs1 . ToStackItem ( )
require . NoError ( t , err )
managementInvoker . Invoke ( t , si , "deploy" , nef1b , manif1 )
helperInvoker := c . Executor . CommitteeInvoker ( cs1 . Hash )
t . Run ( "_deploy called" , func ( t * testing . T ) {
expected := stackitem . NewArray ( [ ] stackitem . Item { stackitem . Make ( "create" ) , stackitem . Null { } } )
expectedBytes , err := stackitem . Serialize ( expected )
require . NoError ( t , err )
helperInvoker . Invoke ( t , stackitem . NewByteArray ( expectedBytes ) , "getValue" )
} )
cs1 . NEF . Script = append ( cs1 . NEF . Script , byte ( opcode . RET ) )
cs1 . NEF . Checksum = cs1 . NEF . CalculateChecksum ( )
nef1b , err = cs1 . NEF . Bytes ( )
require . NoError ( t , err )
cs1 . UpdateCounter ++
helperInvoker . Invoke ( t , stackitem . Null { } , "update" , nef1b , nil , "new data" )
t . Run ( "_deploy called" , func ( t * testing . T ) {
expected := stackitem . NewArray ( [ ] stackitem . Item { stackitem . Make ( "update" ) , stackitem . Make ( "new data" ) } )
expectedBytes , err := stackitem . Serialize ( expected )
require . NoError ( t , err )
helperInvoker . Invoke ( t , stackitem . NewByteArray ( expectedBytes ) , "getValue" )
} )
}
func TestManagement_ContractUpdate ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . CommitteeHash )
2021-12-09 17:12:15 +00:00
// Allow calling management contract.
cs1 . Manifest . Permissions = [ ] manifest . Permission { * manifest . NewPermission ( manifest . PermissionWildcard ) }
manifestBytes , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nefBytes , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
si , err := cs1 . ToStackItem ( )
require . NoError ( t , err )
managementInvoker . Invoke ( t , si , "deploy" , nefBytes , manifestBytes )
helperInvoker := c . Executor . CommitteeInvoker ( cs1 . Hash )
t . Run ( "unknown contract" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "contract doesn't exist" , "update" , nefBytes , manifestBytes )
} )
t . Run ( "zero-length NEF" , func ( t * testing . T ) {
helperInvoker . InvokeFail ( t , "invalid NEF file: empty" , "update" , [ ] byte { } , manifestBytes )
} )
t . Run ( "zero-length manifest" , func ( t * testing . T ) {
helperInvoker . InvokeFail ( t , "invalid manifest: empty" , "update" , nefBytes , [ ] byte { } )
} )
t . Run ( "no real params" , func ( t * testing . T ) {
helperInvoker . InvokeFail ( t , "both NEF and manifest are nil" , "update" , nil , nil )
} )
t . Run ( "invalid manifest" , func ( t * testing . T ) {
pkey , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
var badManifest = cs1 . Manifest
badManifest . Groups = [ ] manifest . Group { { PublicKey : pkey . PublicKey ( ) , Signature : make ( [ ] byte , 64 ) } }
manifB , err := json . Marshal ( badManifest )
require . NoError ( t , err )
helperInvoker . InvokeFail ( t , "invalid manifest: incorrect group signature" , "update" , nefBytes , manifB )
} )
t . Run ( "manifest and script mismatch" , func ( t * testing . T ) {
nf , err := nef . FileFromBytes ( nefBytes ) // Make a full copy.
require . NoError ( t , err )
nf . Script = append ( nf . Script , byte ( opcode . RET ) )
copy ( nf . Script [ 1 : ] , nf . Script ) // Now all method offsets are wrong.
nf . Script [ 0 ] = byte ( opcode . RET ) // Even though the script is correct.
nf . CalculateChecksum ( )
nefnew , err := nf . Bytes ( )
require . NoError ( t , err )
helperInvoker . InvokeFail ( t , "invalid NEF file: checksum verification failure" , "update" , nefnew , manifestBytes )
} )
t . Run ( "change name" , func ( t * testing . T ) {
var badManifest = cs1 . Manifest
badManifest . Name += "tail"
manifB , err := json . Marshal ( badManifest )
require . NoError ( t , err )
helperInvoker . InvokeFail ( t , "contract name can't be changed" , "update" , nefBytes , manifB )
} )
cs1 . NEF . Script = append ( cs1 . NEF . Script , byte ( opcode . RET ) )
cs1 . NEF . Checksum = cs1 . NEF . CalculateChecksum ( )
nefBytes , err = cs1 . NEF . Bytes ( )
require . NoError ( t , err )
cs1 . UpdateCounter ++
si , err = cs1 . ToStackItem ( )
require . NoError ( t , err )
t . Run ( "update script, positive" , func ( t * testing . T ) {
tx1 := helperInvoker . PrepareInvoke ( t , "update" , nefBytes , nil )
tx2 := managementInvoker . PrepareInvoke ( t , "getContract" , cs1 . Hash . BytesBE ( ) )
managementInvoker . AddNewBlock ( t , tx1 , tx2 )
managementInvoker . CheckHalt ( t , tx1 . Hash ( ) , stackitem . Null { } )
managementInvoker . CheckHalt ( t , tx2 . Hash ( ) , si )
managementInvoker . CheckTxNotificationEvent ( t , tx1 . Hash ( ) , 0 , state . NotificationEvent {
ScriptHash : c . NativeHash ( t , nativenames . Management ) ,
Name : "Update" ,
Item : stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewByteArray ( cs1 . Hash . BytesBE ( ) ) } ) ,
} )
t . Run ( "_deploy called" , func ( t * testing . T ) {
helperInvoker := c . Executor . CommitteeInvoker ( cs1 . Hash )
expected := stackitem . NewArray ( [ ] stackitem . Item { stackitem . Make ( "update" ) , stackitem . Null { } } )
expectedBytes , err := stackitem . Serialize ( expected )
require . NoError ( t , err )
helperInvoker . Invoke ( t , stackitem . NewByteArray ( expectedBytes ) , "getValue" )
} )
t . Run ( "check contract" , func ( t * testing . T ) {
managementInvoker . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
} )
cs1 . Manifest . Extra = [ ] byte ( ` "update me" ` )
manifestBytes , err = json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
cs1 . UpdateCounter ++
si , err = cs1 . ToStackItem ( )
require . NoError ( t , err )
t . Run ( "update manifest, positive" , func ( t * testing . T ) {
updHash := helperInvoker . Invoke ( t , stackitem . Null { } , "update" , nil , manifestBytes )
helperInvoker . CheckTxNotificationEvent ( t , updHash , 0 , state . NotificationEvent {
ScriptHash : helperInvoker . NativeHash ( t , nativenames . Management ) ,
Name : "Update" ,
Item : stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewByteArray ( cs1 . Hash . BytesBE ( ) ) } ) ,
} )
t . Run ( "check contract" , func ( t * testing . T ) {
managementInvoker . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
} )
cs1 . NEF . Script = append ( cs1 . NEF . Script , byte ( opcode . ABORT ) )
cs1 . NEF . Checksum = cs1 . NEF . CalculateChecksum ( )
nefBytes , err = cs1 . NEF . Bytes ( )
require . NoError ( t , err )
cs1 . Manifest . Extra = [ ] byte ( ` "update me once more" ` )
manifestBytes , err = json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
cs1 . UpdateCounter ++
si , err = cs1 . ToStackItem ( )
require . NoError ( t , err )
t . Run ( "update both script and manifest" , func ( t * testing . T ) {
updHash := helperInvoker . Invoke ( t , stackitem . Null { } , "update" , nefBytes , manifestBytes )
helperInvoker . CheckTxNotificationEvent ( t , updHash , 0 , state . NotificationEvent {
ScriptHash : helperInvoker . NativeHash ( t , nativenames . Management ) ,
Name : "Update" ,
Item : stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewByteArray ( cs1 . Hash . BytesBE ( ) ) } ) ,
} )
t . Run ( "check contract" , func ( t * testing . T ) {
managementInvoker . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
} )
}
func TestManagement_GetContract ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . CommitteeHash )
2021-12-09 17:12:15 +00:00
manifestBytes , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nefBytes , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
si , err := cs1 . ToStackItem ( )
require . NoError ( t , err )
managementInvoker . Invoke ( t , si , "deploy" , nefBytes , manifestBytes )
t . Run ( "bad parameter type" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "invalid conversion: Array/ByteString" , "getContract" , [ ] interface { } { int64 ( 1 ) } )
} )
t . Run ( "not a hash" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "expected byte size of 20 got 3" , "getContract" , [ ] byte { 1 , 2 , 3 } )
} )
t . Run ( "positive" , func ( t * testing . T ) {
managementInvoker . Invoke ( t , si , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
}
func TestManagement_ContractDestroy ( t * testing . T ) {
c := newManagementClient ( t )
managementInvoker := c . WithSigners ( c . Committee )
2022-03-15 16:16:39 +00:00
cs1 , _ := contracts . GetTestContractState ( t , pathToInternalContracts , 1 , 2 , c . CommitteeHash )
2021-12-09 17:12:15 +00:00
// Allow calling management contract.
cs1 . Manifest . Permissions = [ ] manifest . Permission { * manifest . NewPermission ( manifest . PermissionWildcard ) }
manifestBytes , err := json . Marshal ( cs1 . Manifest )
require . NoError ( t , err )
nefBytes , err := cs1 . NEF . Bytes ( )
require . NoError ( t , err )
si , err := cs1 . ToStackItem ( )
require . NoError ( t , err )
managementInvoker . Invoke ( t , si , "deploy" , nefBytes , manifestBytes )
helperInvoker := c . Executor . CommitteeInvoker ( cs1 . Hash )
t . Run ( "no contract" , func ( t * testing . T ) {
managementInvoker . InvokeFail ( t , "key not found" , "destroy" )
} )
t . Run ( "positive" , func ( t * testing . T ) {
dstrHash := helperInvoker . Invoke ( t , stackitem . Null { } , "destroy" )
helperInvoker . CheckTxNotificationEvent ( t , dstrHash , 0 , state . NotificationEvent {
ScriptHash : helperInvoker . NativeHash ( t , nativenames . Management ) ,
Name : "Destroy" ,
Item : stackitem . NewArray ( [ ] stackitem . Item { stackitem . NewByteArray ( cs1 . Hash . BytesBE ( ) ) } ) ,
} )
t . Run ( "check contract" , func ( t * testing . T ) {
managementInvoker . Invoke ( t , stackitem . Null { } , "getContract" , cs1 . Hash . BytesBE ( ) )
} )
2022-05-04 10:27:41 +00:00
// deploy after destroy should fail
managementInvoker . InvokeFail ( t , fmt . Sprintf ( "the contract %s has been blocked" , cs1 . Hash . StringLE ( ) ) , "deploy" , nefBytes , manifestBytes )
2021-12-09 17:12:15 +00:00
} )
}