From 7ccf7974b68b18d3050fd8dc6d4e993d899ab5df Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 7 Feb 2020 12:17:39 +0300 Subject: [PATCH] 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. --- pkg/core/interop_system.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 9d8c930a8..811f036ae 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -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 }