From ccc6d5b789bbb6a267135b05047db8b85adc74c7 Mon Sep 17 00:00:00 2001 From: Blake <104744707+r3v4s@users.noreply.github.com> Date: Wed, 15 May 2024 18:35:23 +0900 Subject: [PATCH] feat: add separator to rpc `block_results` to identify msg & response pair (#2063) related to #2055 I'm opening this pr to get some ideas. Currently, keeper does make response data with `\n` as separator to separate number of responses for single function. https://github.com/gnolang/gno/blob/80575054429e07c221f1453104dd0ad29e33291c/gno.land/pkg/sdk/vm/keeper.go#L307-L312 If single function returns 2 string, response may look like this ```text ("1" string) ("2" string) ``` However as describe in #2055, response for single tx with multi-msg really doesn't separate response values. So this pr adds `\n\n` as a separator for every function. ### sample contract ```go package returns func FuncNo() {} func Func2() (string, uint64) { return "asd", 123 } func Func3() (int64, string, uint64) { return -1, "hmm", 78978 } ``` ### call with multi-msg ```javascript await adena.DoContract({ messages: [ { "type": "/vm.m_call", "value": { "caller": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "send": "", "pkg_path": "gno.land/r/r3v4/returns", "func": "FuncNo", "args": [] } }, { "type": "/vm.m_call", "value": { "caller": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "send": "", "pkg_path": "gno.land/r/r3v4/returns", "func": "Func2", "args": [] } }, { "type": "/vm.m_call", "value": { "caller": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "send": "", "pkg_path": "gno.land/r/r3v4/returns", "func": "FuncNo", "args": [] } }, { "type": "/vm.m_call", "value": { "caller": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "send": "", "pkg_path": "gno.land/r/r3v4/returns", "func": "Func3", "args": [] } }, { "type": "/vm.m_call", "value": { "caller": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", "send": "", "pkg_path": "gno.land/r/r3v4/returns", "func": "FuncNo", "args": [] } } ], gasFee: 1, gasWanted: 2000000 }); ``` ### block_results from rpc with b64 encoded ``` KCJhc2QiIHN0cmluZykKKDEyMyB1aW50NjQpKC0xIGludDY0KQooImhtbSIgc3RyaW5nKQooNzg5NzggdWludDY0KQ ``` ### b64 decoded ``` ("asd" string) (123 uint64)(-1 int64) ("hmm" string) (78978 uint64) ``` two problem exists with above response 1. It needs to do something about function that doesn't return any value 2. It needs to divide results string for each function ### in this pr response b64 encoded ``` CgooImFzZCIgc3RyaW5nKQooMTIzIHVpbnQ2NCkKCgoKKC0xIGludDY0KQooImhtbSIgc3RyaW5nKQooNzg5NzggdWludDY0KQoKCgo ``` ### decode b64 and divide by '\n\n' ![image](https://github.com/gnolang/gno/assets/104744707/cf4ee0b8-a0d3-4fb8-aa59-68c814f8ef5b) From now, we know... 1. tx had 5 messages 2. first, third and fifth msg function doesn't return anything 3. second msg function return 2 values 4. fourth msg function return 3 values --- gno.land/pkg/gnoclient/integration_test.go | 4 ++-- gno.land/pkg/sdk/vm/keeper.go | 1 + gno.land/pkg/sdk/vm/keeper_test.go | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/gno.land/pkg/gnoclient/integration_test.go b/gno.land/pkg/gnoclient/integration_test.go index 985ec0f8d53..bd8079517d8 100644 --- a/gno.land/pkg/gnoclient/integration_test.go +++ b/gno.land/pkg/gnoclient/integration_test.go @@ -54,7 +54,7 @@ func TestCallSingle_Integration(t *testing.T) { // Execute call res, err := client.Call(baseCfg, msg) - expected := "(\"hi test argument\" string)" + expected := "(\"hi test argument\" string)\n\n" got := string(res.DeliverTx.Data) assert.Nil(t, err) @@ -103,7 +103,7 @@ func TestCallMultiple_Integration(t *testing.T) { Send: "", } - expected := "(\"it works!\" string)(\"hi test argument\" string)" + expected := "(\"it works!\" string)\n\n(\"hi test argument\" string)\n\n" // Execute call res, err := client.Call(baseCfg, msg1, msg2) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index e7757235020..ef260bd3c42 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -315,6 +315,7 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { res += "\n" } } + res += "\n\n" // use `\n\n` as separator to separate results for single tx with multi msgs return res, nil // TODO pay for gas? TODO see context? } diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 9d74a855a61..bd6f7ad88d1 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -92,7 +92,7 @@ func Echo(msg string) string { msg2 := NewMsgCall(addr, coins, pkgPath, "Echo", []string{"hello world"}) res, err := env.vmk.Call(ctx, msg2) assert.NoError(t, err) - assert.Equal(t, `("echo:hello world" string)`, res) + assert.Equal(t, `("echo:hello world" string)`+"\n\n", res) // t.Log("result:", res) } @@ -235,7 +235,7 @@ func Echo(msg string) string { msg2 := NewMsgCall(addr, coins, pkgPath, "Echo", []string{"hello world"}) res, err := env.vmk.Call(ctx, msg2) assert.NoError(t, err) - assert.Equal(t, `("echo:hello world" string)`, res) + assert.Equal(t, `("echo:hello world" string)`+"\n\n", res) } // Sending too much realm package coins fails. @@ -331,7 +331,7 @@ func GetAdmin() string { coins := std.MustParseCoins("") msg2 := NewMsgCall(addr, coins, pkgPath, "GetAdmin", []string{}) res, err := env.vmk.Call(ctx, msg2) - addrString := fmt.Sprintf("(\"%s\" string)", addr.String()) + addrString := fmt.Sprintf("(\"%s\" string)\n\n", addr.String()) assert.NoError(t, err) assert.Equal(t, addrString, res) }