core: substitute bad notifications with error messages

Tesnet sync failed with:
Feb 07 00:04:19 nodoka neo-go[1747]: 2020-02-07T00:04:19.838+0300        WARN        blockQueue: failed adding block into the blockchain        {"error": "failed to store notifications: not supported", "blockHeight": 713984, "nextIndex": 713985}

because some (not so) smart contract emitted a notification with an
InteropItem inside.
This commit is contained in:
Roman Khimov 2020-02-07 12:17:39 +03:00
parent b805b1a71b
commit 7ccf7974b6

View file

@ -343,7 +343,17 @@ func (ic *interopContext) runtimeCheckWitness(v *vm.VM) error {
func (ic *interopContext) runtimeNotify(v *vm.VM) error {
// It can be just about anything.
e := v.Estack().Pop()
ne := state.NotificationEvent{ScriptHash: getContextScriptHash(v, 0), Item: e.Item()}
item := e.Item()
// But it has to be serializable, otherwise we either have some broken
// (recursive) structure inside or an interop item that can't be used
// outside of the interop subsystem anyway. I'd probably fail transactions
// that emit such broken notifications, but that might break compatibility
// with testnet/mainnet, so we're replacing these with error messages.
_, err := vm.SerializeItem(item)
if err != nil {
item = vm.NewByteArrayItem([]byte(fmt.Sprintf("bad notification: %v", err)))
}
ne := state.NotificationEvent{ScriptHash: getContextScriptHash(v, 0), Item: item}
ic.notifications = append(ic.notifications, ne)
return nil
}