mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-03-13 09:18:34 +00:00
core: restrict the number of allowed SC notifications
Close #3490. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
e63cbe7c82
commit
2c8bd056fa
9 changed files with 84 additions and 27 deletions
|
@ -476,7 +476,7 @@ in development and can change in an incompatible way.
|
||||||
| `Basilisk` | Enables strict smart contract script check against a set of JMP instructions and against method boundaries enabled on contract deploy or update. Increases `stackitem.Integer` JSON parsing precision up to the maximum value supported by the NeoVM. Enables strict check for notifications emitted by a contract to precisely match the events specified in the contract manifest. | https://github.com/nspcc-dev/neo-go/pull/3056 <br> https://github.com/neo-project/neo/pull/2881 <br> https://github.com/nspcc-dev/neo-go/pull/3080 <br> https://github.com/neo-project/neo/pull/2883 <br> https://github.com/nspcc-dev/neo-go/pull/3085 <br> https://github.com/neo-project/neo/pull/2810 |
|
| `Basilisk` | Enables strict smart contract script check against a set of JMP instructions and against method boundaries enabled on contract deploy or update. Increases `stackitem.Integer` JSON parsing precision up to the maximum value supported by the NeoVM. Enables strict check for notifications emitted by a contract to precisely match the events specified in the contract manifest. | https://github.com/nspcc-dev/neo-go/pull/3056 <br> https://github.com/neo-project/neo/pull/2881 <br> https://github.com/nspcc-dev/neo-go/pull/3080 <br> https://github.com/neo-project/neo/pull/2883 <br> https://github.com/nspcc-dev/neo-go/pull/3085 <br> https://github.com/neo-project/neo/pull/2810 |
|
||||||
| `Cockatrice` | Introduces the ability to update native contracts. Includes a couple of new native smart contract APIs: `keccak256` of native CryptoLib contract and `getCommitteeAddress` of native NeoToken contract. | https://github.com/nspcc-dev/neo-go/pull/3402 <br> https://github.com/neo-project/neo/pull/2942 <br> https://github.com/nspcc-dev/neo-go/pull/3301 <br> https://github.com/neo-project/neo/pull/2925 <br> https://github.com/nspcc-dev/neo-go/pull/3362 <br> https://github.com/neo-project/neo/pull/3154 |
|
| `Cockatrice` | Introduces the ability to update native contracts. Includes a couple of new native smart contract APIs: `keccak256` of native CryptoLib contract and `getCommitteeAddress` of native NeoToken contract. | https://github.com/nspcc-dev/neo-go/pull/3402 <br> https://github.com/neo-project/neo/pull/2942 <br> https://github.com/nspcc-dev/neo-go/pull/3301 <br> https://github.com/neo-project/neo/pull/2925 <br> https://github.com/nspcc-dev/neo-go/pull/3362 <br> https://github.com/neo-project/neo/pull/3154 |
|
||||||
| `Domovoi` | Makes node use executing contract state for the contract call permissions check instead of the state stored in the native Management contract. In C# also makes System.Runtime.GetNotifications interop properly count stack references of notification parameters which prevents users from creating objects that exceed MaxStackSize constraint, but NeoGo has never had this bug, thus proper behaviour is preserved even before HFDomovoi. It results in the fact that some T5 testnet transactions have different ApplicationLogs compared to the C# node, but the node states match. | https://github.com/nspcc-dev/neo-go/pull/3476 <br> https://github.com/neo-project/neo/pull/3290 <br> https://github.com/nspcc-dev/neo-go/pull/3473 <br> https://github.com/neo-project/neo/pull/3290 <br> https://github.com/neo-project/neo/pull/3301 <br> https://github.com/nspcc-dev/neo-go/pull/3485 |
|
| `Domovoi` | Makes node use executing contract state for the contract call permissions check instead of the state stored in the native Management contract. In C# also makes System.Runtime.GetNotifications interop properly count stack references of notification parameters which prevents users from creating objects that exceed MaxStackSize constraint, but NeoGo has never had this bug, thus proper behaviour is preserved even before HFDomovoi. It results in the fact that some T5 testnet transactions have different ApplicationLogs compared to the C# node, but the node states match. | https://github.com/nspcc-dev/neo-go/pull/3476 <br> https://github.com/neo-project/neo/pull/3290 <br> https://github.com/nspcc-dev/neo-go/pull/3473 <br> https://github.com/neo-project/neo/pull/3290 <br> https://github.com/neo-project/neo/pull/3301 <br> https://github.com/nspcc-dev/neo-go/pull/3485 |
|
||||||
| `Echidna` | Introduces `Designation` event extension with `Old` and `New` roles data to native RoleManagement contract. Adds support for `base64UrlEncode` and `base64UrlDecode` methods to native StdLib contract. Extends the list of required call flags for `registerCandidate`, `unregisterCandidate`and `vote` methods of native NeoToken contract with AllowNotify flag. Enables `onNEP17Payment` method of NEO contract for candidate registration. | https://github.com/nspcc-dev/neo-go/pull/3554 <br> https://github.com/nspcc-dev/neo-go/pull/3761 <br> https://github.com/nspcc-dev/neo-go/pull/3554 <br> https://github.com/neo-project/neo/pull/3597 <br> https://github.com/nspcc-dev/neo-go/pull/3700 |
|
| `Echidna` | Introduces `Designation` event extension with `Old` and `New` roles data to native RoleManagement contract. Adds support for `base64UrlEncode` and `base64UrlDecode` methods to native StdLib contract. Extends the list of required call flags for `registerCandidate`, `unregisterCandidate`and `vote` methods of native NeoToken contract with AllowNotify flag. Enables `onNEP17Payment` method of NEO contract for candidate registration. Introduces constraint for maximum number of execution notifications. | https://github.com/nspcc-dev/neo-go/pull/3554 <br> https://github.com/nspcc-dev/neo-go/pull/3761 <br> https://github.com/nspcc-dev/neo-go/pull/3554 <br> https://github.com/neo-project/neo/pull/3597 <br> https://github.com/nspcc-dev/neo-go/pull/3700 <br> https://github.com/nspcc-dev/neo-go/pull/3640 <br> https://github.com/neo-project/neo/pull/3548 |
|
||||||
|
|
||||||
|
|
||||||
## DB compatibility
|
## DB compatibility
|
||||||
|
|
|
@ -44,7 +44,8 @@ const (
|
||||||
// match. See #3485 for details.
|
// match. See #3485 for details.
|
||||||
HFDomovoi // Domovoi
|
HFDomovoi // Domovoi
|
||||||
// HFEchidna represents hard-fork introduced in #3554 (ported from
|
// HFEchidna represents hard-fork introduced in #3554 (ported from
|
||||||
// https://github.com/neo-project/neo/pull/3454).
|
// https://github.com/neo-project/neo/pull/3454), #3640 (ported from
|
||||||
|
// https://github.com/neo-project/neo/pull/3548).
|
||||||
HFEchidna // Echidna
|
HFEchidna // Echidna
|
||||||
// hfLast denotes the end of hardforks enum. Consider adding new hardforks
|
// hfLast denotes the end of hardforks enum. Consider adding new hardforks
|
||||||
// before hfLast.
|
// before hfLast.
|
||||||
|
|
|
@ -35,6 +35,9 @@ const (
|
||||||
DefaultBaseExecFee = 30
|
DefaultBaseExecFee = 30
|
||||||
// ContextNonceDataLen is a length of [Context.NonceData] in bytes.
|
// ContextNonceDataLen is a length of [Context.NonceData] in bytes.
|
||||||
ContextNonceDataLen = 16
|
ContextNonceDataLen = 16
|
||||||
|
// MaxNotificationCount is the maximum number of notifications per single
|
||||||
|
// application execution.
|
||||||
|
MaxNotificationCount = 512
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ledger is the interface to Blockchain required for Context functionality.
|
// Ledger is the interface to Blockchain required for Context functionality.
|
||||||
|
@ -565,10 +568,18 @@ func (ic *Context) IsHardforkActivation(hf config.Hardfork) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNotification creates notification event and appends it to the notification list.
|
// AddNotification creates notification event and appends it to the notification list.
|
||||||
func (ic *Context) AddNotification(hash util.Uint160, name string, item *stackitem.Array) {
|
func (ic *Context) AddNotification(hash util.Uint160, name string, item *stackitem.Array) error {
|
||||||
|
if ic.IsHardforkEnabled(config.HFEchidna) {
|
||||||
|
// Do not check persisting triggers to avoid native persist failure. Do not check
|
||||||
|
// verification trigger since verification context is loaded with ReadOnly flag.
|
||||||
|
if ic.Trigger == trigger.Application && len(ic.Notifications) == MaxNotificationCount {
|
||||||
|
return fmt.Errorf("notification count shouldn't exceed %d", MaxNotificationCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
ic.Notifications = append(ic.Notifications, state.NotificationEvent{
|
ic.Notifications = append(ic.Notifications, state.NotificationEvent{
|
||||||
ScriptHash: hash,
|
ScriptHash: hash,
|
||||||
Name: name,
|
Name: name,
|
||||||
Item: item,
|
Item: item,
|
||||||
})
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,8 +114,7 @@ func Notify(ic *interop.Context) error {
|
||||||
if len(bytes) > MaxNotificationSize {
|
if len(bytes) > MaxNotificationSize {
|
||||||
return fmt.Errorf("notification size shouldn't exceed %d", MaxNotificationSize)
|
return fmt.Errorf("notification size shouldn't exceed %d", MaxNotificationSize)
|
||||||
}
|
}
|
||||||
ic.AddNotification(curHash, name, stackitem.DeepCopy(stackitem.NewArray(args), true).(*stackitem.Array))
|
return ic.AddNotification(curHash, name, stackitem.DeepCopy(stackitem.NewArray(args), true).(*stackitem.Array))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadScript takes a script and arguments from the stack and loads it into the VM.
|
// LoadScript takes a script and arguments from the stack and loads it into the VM.
|
||||||
|
|
|
@ -432,8 +432,8 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r noderoles.Role, pubs
|
||||||
ntf.Append(pubsToArray(old))
|
ntf.Append(pubsToArray(old))
|
||||||
ntf.Append(pubsToArray(pubs))
|
ntf.Append(pubsToArray(pubs))
|
||||||
}
|
}
|
||||||
ic.AddNotification(s.Hash, DesignationEventName, ntf)
|
|
||||||
return nil
|
return ic.AddNotification(s.Hash, DesignationEventName, ntf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) getRole(item stackitem.Item) (noderoles.Role, bool) {
|
func (s *Designate) getRole(item stackitem.Item) (noderoles.Role, bool) {
|
||||||
|
|
|
@ -372,7 +372,10 @@ func (m *Management) deployWithData(ic *interop.Context, args []stackitem.Item)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
m.callDeploy(ic, newcontract, args[2], false)
|
m.callDeploy(ic, newcontract, args[2], false)
|
||||||
m.emitNotification(ic, contractDeployNotificationName, newcontract.Hash)
|
err = m.emitNotification(ic, contractDeployNotificationName, newcontract.Hash)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
return contractToStack(newcontract)
|
return contractToStack(newcontract)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +447,10 @@ func (m *Management) updateWithData(ic *interop.Context, args []stackitem.Item)
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
m.callDeploy(ic, contract, args[2], true)
|
m.callDeploy(ic, contract, args[2], true)
|
||||||
m.emitNotification(ic, contractUpdateNotificationName, contract.Hash)
|
err = m.emitNotification(ic, contractUpdateNotificationName, contract.Hash)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
return stackitem.Null{}
|
return stackitem.Null{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +503,10 @@ func (m *Management) destroy(ic *interop.Context, sis []stackitem.Item) stackite
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
m.emitNotification(ic, contractDestroyNotificationName, hash)
|
err = m.emitNotification(ic, contractDestroyNotificationName, hash)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
return stackitem.Null{}
|
return stackitem.Null{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,7 +690,10 @@ func (m *Management) OnPersist(ic *interop.Context) error {
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
ntfName = contractUpdateNotificationName
|
ntfName = contractUpdateNotificationName
|
||||||
}
|
}
|
||||||
m.emitNotification(ic, ntfName, cs.Hash)
|
err = m.emitNotification(ic, ntfName, cs.Hash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -806,8 +818,8 @@ func (m *Management) getNextContractID(d *dao.Simple) (int32, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Management) emitNotification(ic *interop.Context, name string, hash util.Uint160) {
|
func (m *Management) emitNotification(ic *interop.Context, name string, hash util.Uint160) error {
|
||||||
ic.AddNotification(m.Hash, name, stackitem.NewArray([]stackitem.Item{addrToStackItem(&hash)}))
|
return ic.AddNotification(m.Hash, name, stackitem.NewArray([]stackitem.Item{addrToStackItem(&hash)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkScriptAndMethods(ic *interop.Context, script []byte, methods []manifest.Method) error {
|
func checkScriptAndMethods(ic *interop.Context, script []byte, methods []manifest.Method) error {
|
||||||
|
|
|
@ -479,9 +479,12 @@ func (n *NEO) OnPersist(ic *interop.Context) error {
|
||||||
ic.DAO.PutStorageItem(n.ID, prefixCommittee, cache.committee.Bytes(ic.DAO.GetItemCtx()))
|
ic.DAO.PutStorageItem(n.ID, prefixCommittee, cache.committee.Bytes(ic.DAO.GetItemCtx()))
|
||||||
|
|
||||||
if oldCommittee != nil {
|
if oldCommittee != nil {
|
||||||
ic.AddNotification(n.Hash, "CommitteeChanged", stackitem.NewArray([]stackitem.Item{
|
err := ic.AddNotification(n.Hash, "CommitteeChanged", stackitem.NewArray([]stackitem.Item{
|
||||||
oldCommittee, newCommittee,
|
oldCommittee, newCommittee,
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -883,7 +886,8 @@ func (n *NEO) onNEP17Payment(ic *interop.Context, args []stackitem.Item) stackit
|
||||||
return stackitem.Null{}
|
return stackitem.Null{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterCandidateInternal registers pub as a new candidate.
|
// RegisterCandidateInternal registers pub as a new candidate. This method must not be
|
||||||
|
// called outside of VM since it panics on critical errors.
|
||||||
func (n *NEO) RegisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error {
|
func (n *NEO) RegisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error {
|
||||||
var emitEvent = true
|
var emitEvent = true
|
||||||
|
|
||||||
|
@ -898,16 +902,23 @@ func (n *NEO) RegisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey
|
||||||
c.Registered = true
|
c.Registered = true
|
||||||
}
|
}
|
||||||
err := putConvertibleToDAO(n.ID, ic.DAO, key, c)
|
err := putConvertibleToDAO(n.ID, ic.DAO, key, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if emitEvent {
|
if emitEvent {
|
||||||
cache := ic.DAO.GetRWCache(n.ID).(*NeoCache)
|
cache := ic.DAO.GetRWCache(n.ID).(*NeoCache)
|
||||||
cache.votesChanged = true
|
cache.votesChanged = true
|
||||||
ic.AddNotification(n.Hash, "CandidateStateChanged", stackitem.NewArray([]stackitem.Item{
|
err = ic.AddNotification(n.Hash, "CandidateStateChanged", stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray(pub.Bytes()),
|
stackitem.NewByteArray(pub.Bytes()),
|
||||||
stackitem.NewBool(c.Registered),
|
stackitem.NewBool(c.Registered),
|
||||||
stackitem.NewBigInteger(&c.Votes),
|
stackitem.NewBigInteger(&c.Votes),
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
// Panic since it's a critical error that must abort execution.
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
return err
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NEO) unregisterCandidate(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
func (n *NEO) unregisterCandidate(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
|
@ -922,7 +933,8 @@ func (n *NEO) unregisterCandidate(ic *interop.Context, args []stackitem.Item) st
|
||||||
return stackitem.NewBool(err == nil)
|
return stackitem.NewBool(err == nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnregisterCandidateInternal unregisters pub as a candidate.
|
// UnregisterCandidateInternal unregisters pub as a candidate. This method must not be
|
||||||
|
// called outside of VM since it panics on critical errors.
|
||||||
func (n *NEO) UnregisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error {
|
func (n *NEO) UnregisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -942,14 +954,21 @@ func (n *NEO) UnregisterCandidateInternal(ic *interop.Context, pub *keys.PublicK
|
||||||
if !ok {
|
if !ok {
|
||||||
err = putConvertibleToDAO(n.ID, ic.DAO, key, c)
|
err = putConvertibleToDAO(n.ID, ic.DAO, key, c)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if emitEvent {
|
if emitEvent {
|
||||||
ic.AddNotification(n.Hash, "CandidateStateChanged", stackitem.NewArray([]stackitem.Item{
|
err := ic.AddNotification(n.Hash, "CandidateStateChanged", stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray(pub.Bytes()),
|
stackitem.NewByteArray(pub.Bytes()),
|
||||||
stackitem.NewBool(c.Registered),
|
stackitem.NewBool(c.Registered),
|
||||||
stackitem.NewBigInteger(&c.Votes),
|
stackitem.NewBigInteger(&c.Votes),
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
// Panic since it's a critical error that must abort execution.
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
return err
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
|
@ -962,7 +981,8 @@ func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
return stackitem.NewBool(err == nil)
|
return stackitem.NewBool(err == nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VoteInternal votes from account h for validarors specified in pubs.
|
// VoteInternal votes from account h for validarors specified in pubs. This method
|
||||||
|
// must not be called outside of VM since it panics on critical errors.
|
||||||
func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.PublicKey) error {
|
func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.PublicKey) error {
|
||||||
ok, err := runtime.CheckHashedWitness(ic, h)
|
ok, err := runtime.CheckHashedWitness(ic, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1024,12 +1044,16 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public
|
||||||
}
|
}
|
||||||
ic.DAO.PutStorageItem(n.ID, key, acc.Bytes(ic.DAO.GetItemCtx()))
|
ic.DAO.PutStorageItem(n.ID, key, acc.Bytes(ic.DAO.GetItemCtx()))
|
||||||
|
|
||||||
ic.AddNotification(n.Hash, "Vote", stackitem.NewArray([]stackitem.Item{
|
err = ic.AddNotification(n.Hash, "Vote", stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray(h.BytesBE()),
|
stackitem.NewByteArray(h.BytesBE()),
|
||||||
keyToStackItem(oldVote),
|
keyToStackItem(oldVote),
|
||||||
keyToStackItem(pub),
|
keyToStackItem(pub),
|
||||||
stackitem.NewBigInteger(&acc.Balance),
|
stackitem.NewBigInteger(&acc.Balance),
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
// Panic since it's a critical error that must abort execution.
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
if newGas != nil { // Can be if it was already distributed in the same block.
|
if newGas != nil { // Can be if it was already distributed in the same block.
|
||||||
n.GAS.mint(ic, h, newGas, true)
|
n.GAS.mint(ic, h, newGas, true)
|
||||||
|
|
|
@ -146,7 +146,11 @@ func (c *nep17TokenNative) postTransfer(ic *interop.Context, from, to *util.Uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
c.emitTransfer(ic, from, to, amount)
|
err := c.emitTransfer(ic, from, to, amount)
|
||||||
|
if err != nil {
|
||||||
|
skipPostCalls = true
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
if to == nil || !callOnPayment {
|
if to == nil || !callOnPayment {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -170,8 +174,8 @@ func (c *nep17TokenNative) postTransfer(ic *interop.Context, from, to *util.Uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nep17TokenNative) emitTransfer(ic *interop.Context, from, to *util.Uint160, amount *big.Int) {
|
func (c *nep17TokenNative) emitTransfer(ic *interop.Context, from, to *util.Uint160, amount *big.Int) error {
|
||||||
ic.AddNotification(c.Hash, "Transfer", stackitem.NewArray([]stackitem.Item{
|
return ic.AddNotification(c.Hash, "Transfer", stackitem.NewArray([]stackitem.Item{
|
||||||
addrToStackItem(from),
|
addrToStackItem(from),
|
||||||
addrToStackItem(to),
|
addrToStackItem(to),
|
||||||
stackitem.NewBigInteger(amount),
|
stackitem.NewBigInteger(amount),
|
||||||
|
|
|
@ -316,10 +316,13 @@ func (o *Oracle) FinishInternal(ic *interop.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrRequestNotFound
|
return ErrRequestNotFound
|
||||||
}
|
}
|
||||||
ic.AddNotification(o.Hash, "OracleResponse", stackitem.NewArray([]stackitem.Item{
|
err = ic.AddNotification(o.Hash, "OracleResponse", stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.Make(resp.ID),
|
stackitem.Make(resp.ID),
|
||||||
stackitem.Make(req.OriginalTxID.BytesBE()),
|
stackitem.Make(req.OriginalTxID.BytesBE()),
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
origTx, _, err := ic.DAO.GetTransaction(req.OriginalTxID)
|
origTx, _, err := ic.DAO.GetTransaction(req.OriginalTxID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -422,12 +425,15 @@ func (o *Oracle) RequestInternal(ic *interop.Context, url string, filter *string
|
||||||
} else {
|
} else {
|
||||||
filterNotif = stackitem.Null{}
|
filterNotif = stackitem.Null{}
|
||||||
}
|
}
|
||||||
ic.AddNotification(o.Hash, "OracleRequest", stackitem.NewArray([]stackitem.Item{
|
err = ic.AddNotification(o.Hash, "OracleRequest", stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.Make(id),
|
stackitem.Make(id),
|
||||||
stackitem.Make(ic.VM.GetCallingScriptHash().BytesBE()),
|
stackitem.Make(ic.VM.GetCallingScriptHash().BytesBE()),
|
||||||
stackitem.Make(url),
|
stackitem.Make(url),
|
||||||
filterNotif,
|
filterNotif,
|
||||||
}))
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
req := &state.OracleRequest{
|
req := &state.OracleRequest{
|
||||||
OriginalTxID: o.getOriginalTxID(ic.DAO, ic.Tx),
|
OriginalTxID: o.getOriginalTxID(ic.DAO, ic.Tx),
|
||||||
GasForResponse: gas.Uint64(),
|
GasForResponse: gas.Uint64(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue