mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-23 03:38:35 +00:00
core: add notifications to ManagmentContract
This commit is contained in:
parent
d34353aec2
commit
b1324db847
2 changed files with 52 additions and 9 deletions
|
@ -38,7 +38,10 @@ const StoragePrice = 100000
|
|||
const (
|
||||
prefixContract = 8
|
||||
|
||||
defaultMinimumDeploymentFee = 10_00000000
|
||||
defaultMinimumDeploymentFee = 10_00000000
|
||||
contractDeployNotificationName = "Deploy"
|
||||
contractUpdateNotificationName = "Update"
|
||||
contractDestroyNotificationName = "Destroy"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -68,17 +71,17 @@ func newManagement() *Management {
|
|||
desc = newDescriptor("deploy", smartcontract.ArrayType,
|
||||
manifest.NewParameter("script", smartcontract.ByteArrayType),
|
||||
manifest.NewParameter("manifest", smartcontract.ByteArrayType))
|
||||
md = newMethodAndPrice(m.deploy, 0, smartcontract.WriteStates)
|
||||
md = newMethodAndPrice(m.deploy, 0, smartcontract.WriteStates|smartcontract.AllowNotify)
|
||||
m.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("update", smartcontract.VoidType,
|
||||
manifest.NewParameter("script", smartcontract.ByteArrayType),
|
||||
manifest.NewParameter("manifest", smartcontract.ByteArrayType))
|
||||
md = newMethodAndPrice(m.update, 0, smartcontract.WriteStates)
|
||||
md = newMethodAndPrice(m.update, 0, smartcontract.WriteStates|smartcontract.AllowNotify)
|
||||
m.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("destroy", smartcontract.VoidType)
|
||||
md = newMethodAndPrice(m.destroy, 1000000, smartcontract.WriteStates)
|
||||
md = newMethodAndPrice(m.destroy, 1000000, smartcontract.WriteStates|smartcontract.AllowNotify)
|
||||
m.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("getMinimumDeploymentFee", smartcontract.IntegerType)
|
||||
|
@ -89,6 +92,11 @@ func newManagement() *Management {
|
|||
manifest.NewParameter("value", smartcontract.IntegerType))
|
||||
md = newMethodAndPrice(m.setMinimumDeploymentFee, 300_0000, smartcontract.WriteStates)
|
||||
m.AddMethod(md, desc)
|
||||
|
||||
hashParam := manifest.NewParameter("Hash", smartcontract.Hash160Type)
|
||||
m.AddEvent(contractDeployNotificationName, hashParam)
|
||||
m.AddEvent(contractUpdateNotificationName, hashParam)
|
||||
m.AddEvent(contractDestroyNotificationName, hashParam)
|
||||
return m
|
||||
}
|
||||
|
||||
|
@ -214,6 +222,7 @@ func (m *Management) deploy(ic *interop.Context, args []stackitem.Item) stackite
|
|||
panic(err)
|
||||
}
|
||||
callDeploy(ic, newcontract, false)
|
||||
m.emitNotification(ic, contractDeployNotificationName, newcontract.Hash)
|
||||
return contractToStack(newcontract)
|
||||
}
|
||||
|
||||
|
@ -225,7 +234,7 @@ func (m *Management) markUpdated(h util.Uint160) {
|
|||
}
|
||||
|
||||
// Deploy creates contract's hash/ID and saves new contract into the given DAO.
|
||||
// It doesn't run _deploy method.
|
||||
// It doesn't run _deploy method and doesn't emit notification.
|
||||
func (m *Management) Deploy(d dao.DAO, sender util.Uint160, neff *nef.File, manif *manifest.Manifest) (*state.Contract, error) {
|
||||
h := state.CreateContractHash(sender, neff.Script)
|
||||
key := makeContractKey(h)
|
||||
|
@ -269,11 +278,12 @@ func (m *Management) update(ic *interop.Context, args []stackitem.Item) stackite
|
|||
panic(err)
|
||||
}
|
||||
callDeploy(ic, contract, true)
|
||||
m.emitNotification(ic, contractUpdateNotificationName, contract.Hash)
|
||||
return stackitem.Null{}
|
||||
}
|
||||
|
||||
// Update updates contract's script and/or manifest in the given DAO.
|
||||
// It doesn't run _deploy method.
|
||||
// It doesn't run _deploy method and doesn't emit notification.
|
||||
func (m *Management) Update(d dao.DAO, hash util.Uint160, neff *nef.File, manif *manifest.Manifest) (*state.Contract, error) {
|
||||
contract, err := m.GetContract(d, hash)
|
||||
if err != nil {
|
||||
|
@ -308,10 +318,11 @@ func (m *Management) destroy(ic *interop.Context, sis []stackitem.Item) stackite
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.emitNotification(ic, contractDestroyNotificationName, hash)
|
||||
return stackitem.Null{}
|
||||
}
|
||||
|
||||
// Destroy drops given contract from DAO along with its storage.
|
||||
// Destroy drops given contract from DAO along with its storage. It doesn't emit notification.
|
||||
func (m *Management) Destroy(d dao.DAO, hash util.Uint160) error {
|
||||
contract, err := m.GetContract(d, hash)
|
||||
if err != nil {
|
||||
|
@ -502,3 +513,12 @@ func (m *Management) getNextContractID(d dao.DAO) (int32, error) {
|
|||
si.Value = bigint.ToPreallocatedBytes(id, si.Value)
|
||||
return ret, d.PutStorageItem(m.ContractID, keyNextAvailableID, si)
|
||||
}
|
||||
|
||||
func (m *Management) emitNotification(ic *interop.Context, name string, hash util.Uint160) {
|
||||
ne := state.NotificationEvent{
|
||||
ScriptHash: m.Hash,
|
||||
Name: name,
|
||||
Item: stackitem.NewArray([]stackitem.Item{addrToStackItem(&hash)}),
|
||||
}
|
||||
ic.Notifications = append(ic.Notifications, ne)
|
||||
}
|
||||
|
|
|
@ -159,7 +159,11 @@ func TestContractDeploy(t *testing.T) {
|
|||
require.Equal(t, 1, len(res.Stack))
|
||||
compareContractStates(t, cs1, res.Stack[0])
|
||||
}
|
||||
|
||||
require.Equal(t, aers[0].Events, []state.NotificationEvent{{
|
||||
ScriptHash: mgmtHash,
|
||||
Name: "Deploy",
|
||||
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(cs1.Hash.BytesBE())}),
|
||||
}})
|
||||
t.Run("_deploy called", func(t *testing.T) {
|
||||
res, err := invokeContractMethod(bc, 1_00000000, cs1.Hash, "getValue")
|
||||
require.NoError(t, err)
|
||||
|
@ -337,7 +341,11 @@ func TestContractUpdate(t *testing.T) {
|
|||
require.Equal(t, vm.HaltState, aers[1].VMState)
|
||||
require.Equal(t, 1, len(aers[1].Stack))
|
||||
compareContractStates(t, cs1, aers[1].Stack[0])
|
||||
|
||||
require.Equal(t, aers[0].Events, []state.NotificationEvent{{
|
||||
ScriptHash: mgmtHash,
|
||||
Name: "Update",
|
||||
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(cs1.Hash.BytesBE())}),
|
||||
}})
|
||||
t.Run("_deploy called", func(t *testing.T) {
|
||||
res, err := invokeContractMethod(bc, 1_00000000, cs1.Hash, "getValue")
|
||||
require.NoError(t, err)
|
||||
|
@ -358,6 +366,11 @@ func TestContractUpdate(t *testing.T) {
|
|||
res, err := invokeContractMethod(bc, 10_00000000, cs1.Hash, "update", nil, manif1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, res.VMState)
|
||||
require.Equal(t, res.Events, []state.NotificationEvent{{
|
||||
ScriptHash: mgmtHash,
|
||||
Name: "Update",
|
||||
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(cs1.Hash.BytesBE())}),
|
||||
}})
|
||||
t.Run("check contract", func(t *testing.T) {
|
||||
checkContractState(t, bc, cs1.Hash, cs1)
|
||||
})
|
||||
|
@ -377,6 +390,11 @@ func TestContractUpdate(t *testing.T) {
|
|||
res, err := invokeContractMethod(bc, 10_00000000, cs1.Hash, "update", nef1b, manif1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, res.VMState)
|
||||
require.Equal(t, res.Events, []state.NotificationEvent{{
|
||||
ScriptHash: mgmtHash,
|
||||
Name: "Update",
|
||||
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(cs1.Hash.BytesBE())}),
|
||||
}})
|
||||
t.Run("check contract", func(t *testing.T) {
|
||||
checkContractState(t, bc, cs1.Hash, cs1)
|
||||
})
|
||||
|
@ -432,6 +450,11 @@ func TestContractDestroy(t *testing.T) {
|
|||
res, err := invokeContractMethod(bc, 1_00000000, cs1.Hash, "destroy")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, res.VMState)
|
||||
require.Equal(t, res.Events, []state.NotificationEvent{{
|
||||
ScriptHash: mgmtHash,
|
||||
Name: "Destroy",
|
||||
Item: stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(cs1.Hash.BytesBE())}),
|
||||
}})
|
||||
t.Run("check contract", func(t *testing.T) {
|
||||
res, err := invokeContractMethod(bc, 1_00000000, mgmtHash, "getContract", cs1.Hash.BytesBE())
|
||||
require.NoError(t, err)
|
||||
|
|
Loading…
Reference in a new issue