t5 applog RPC difference C# vs neo-go #1505

Open
opened 2025-12-28 17:16:40 +00:00 by sami · 4 comments
Owner

Originally created by @ixje on GitHub (Apr 7, 2025).

Current Behavior

a stack with invalid stack items is returned in the applicationlog for tx 0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48

{
  "id": 1,
  "jsonrpc": "2.0",
  "result": {
    "txid": "0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48",
    "executions": [
      {
        "trigger": "Application",
        "vmstate": "HALT",
        "gasconsumed": "6312969",
        "stack": [
          "error: unserializable: nil",
          "error: unserializable: nil"
        ],
        "notifications": [],
        "exception": null,
        "invocations": null
      }
    ]
  }
}

Expected Behavior

like neo-cli, a stack with valid stack items

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "txid": "0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48",
    "executions": [
      {
        "trigger": "Application",
        "vmstate": "HALT",
        "exception": null,
        "gasconsumed": "6312969",
        "stack": [
          {
            "type": "Any"
          },
          {
            "type": "Any"
          }
        ],
        "notifications": []
      }
    ]
  }
}

Possible Solution

return a stack with valid stack items e.g. the NullStackitem like C# is doing.

Steps to Reproduce

curl --request POST \
  --url https://rpc.t5.n3.nspcc.ru:20331/ \
  --header 'content-type: application/json' \
  --data '{
  "jsonrpc": "2.0",
  "method": "getapplicationlog",
  "params": ["0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48"],
  "id": 1
}
'

Context

our indexer has a little loop as follows that now breaks because stackitem.ToJSONWithTypes fails on this output.

	var stackItemsJSON []json.RawMessage
	for _, item := range exec.Stack {
		res, err := stackitem.ToJSONWithTypes(item)
		if err != nil {
			return nil, err
		}
		stackItemsJSON = append(stackItemsJSON, res)
	}

Your Environment

  • Version of the product used: 0.108.1
  • Server setup and configuration files used: default testnet protocol file with SaveInvocations turned on.
Originally created by @ixje on GitHub (Apr 7, 2025). ## Current Behavior a `stack` with invalid stack items is returned in the applicationlog for tx `0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48` ```json { "id": 1, "jsonrpc": "2.0", "result": { "txid": "0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48", "executions": [ { "trigger": "Application", "vmstate": "HALT", "gasconsumed": "6312969", "stack": [ "error: unserializable: nil", "error: unserializable: nil" ], "notifications": [], "exception": null, "invocations": null } ] } } ``` ## Expected Behavior like neo-cli, a `stack` with valid stack items ```json { "jsonrpc": "2.0", "id": 1, "result": { "txid": "0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48", "executions": [ { "trigger": "Application", "vmstate": "HALT", "exception": null, "gasconsumed": "6312969", "stack": [ { "type": "Any" }, { "type": "Any" } ], "notifications": [] } ] } } ``` ## Possible Solution return a `stack` with valid stack items e.g. the NullStackitem like C# is doing. ## Steps to Reproduce ``` curl --request POST \ --url https://rpc.t5.n3.nspcc.ru:20331/ \ --header 'content-type: application/json' \ --data '{ "jsonrpc": "2.0", "method": "getapplicationlog", "params": ["0x0819175f7cd906f2eee8fbc825496acd11f0f0afcfcaec32bfbb71a7a52b6f48"], "id": 1 } ' ``` ## Context our indexer has a little loop as follows that now breaks because `stackitem.ToJSONWithTypes` fails on this output. ```go var stackItemsJSON []json.RawMessage for _, item := range exec.Stack { res, err := stackitem.ToJSONWithTypes(item) if err != nil { return nil, err } stackItemsJSON = append(stackItemsJSON, res) } ``` ## Your Environment * Version of the product used: 0.108.1 * Server setup and configuration files used: default testnet protocol file with `SaveInvocations` turned on.
Author
Owner

@roman-khimov commented on GitHub (Apr 7, 2025):

Needs to be checked. Null stack item shouldn't be a problem, maybe it's something different in which case this behavior can be valid, some items can't be serialized and an error should be returned in this case (in general it can be returned in exactly this way).

@roman-khimov commented on GitHub (Apr 7, 2025): Needs to be checked. `Null` stack item shouldn't be a problem, maybe it's something different in which case this behavior can be valid, some items can't be serialized and an error should be returned in this case (in general it _can_ be returned in exactly this way).
Author
Owner

@ixje commented on GitHub (Apr 7, 2025):

in general it can be returned in exactly this way

That sounds problematic to me. From the top of my head all stack items returned are JSON objects that have at least a type key. With iterator and null being to exceptions to not having a value key as well. This

"stack": [
          "error: unserializable: nil",
          "error: unserializable: nil"
        ],

doesn't even return JSON objects, just strings. At least neo-mamba and neon-js will error on this and it wouldn't surprise me if other SDKs consuming this data make the same assumption that stack is a list/array/slice of StackItems with the aforementioned keys.

@ixje commented on GitHub (Apr 7, 2025): > in general it _can_ be returned in exactly this way That sounds problematic to me. From the top of my head all stack items returned are JSON objects that have at least a `type` key. With `iterator` and `null` being to exceptions to not having a `value` key as well. This ``` "stack": [ "error: unserializable: nil", "error: unserializable: nil" ], ``` doesn't even return JSON objects, just strings. At least neo-mamba and neon-js will error on this and it wouldn't surprise me if other SDKs consuming this data make the same assumption that `stack` is a list/array/slice of `StackItem`s with the aforementioned keys.
Author
Owner

@roman-khimov commented on GitHub (Apr 7, 2025):

There is NeoGo specifics there, C# also can produce this output in some cases or at least this was the case some time ago. The problem is that when the item is invalid substituting it with a valid placeholder item can lead to incorrect result interpretation since you can't differentiate error case from real item.

@roman-khimov commented on GitHub (Apr 7, 2025): There is NeoGo specifics there, C# also can produce this output in some cases or at least this was the case some time ago. The problem is that when the item is invalid substituting it with a valid placeholder item can lead to incorrect result interpretation since you can't differentiate error case from real item.
Author
Owner
@roman-khimov commented on GitHub (Oct 20, 2025): Relevant links: https://github.com/neo-project/neo/blob/272af62a1d5a2ae4dce5e612e61a0339a28ef52c/src/Plugins/RpcServer/RpcServer.SmartContract.cs#L99-L108 https://github.com/neo-project/neo/blob/272af62a1d5a2ae4dce5e612e61a0339a28ef52c/src/RpcClient/Models/RpcInvokeResult.cs#L49-L57 https://github.com/neo-project/neo/blob/272af62a1d5a2ae4dce5e612e61a0339a28ef52c/src/Plugins/ApplicationLogs/LogReader.cs#L453-L460 Also https://github.com/neo-project/neo/blob/272af62a1d5a2ae4dce5e612e61a0339a28ef52c/src/Plugins/ApplicationLogs/LogReader.cs#L469-L482 Unfortunately, different choices are made in different places even though it's all about the same problem of stack JSON.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nspcc-dev/neo-go#1505
No description provided.