@agoric/cosmos 0.35.0-upgrade-14-dev-c8f9e7b.0 → 0.35.0-upgrade-16a-dev-fb592e4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +121 -77
  2. package/MAINTAINERS.md +3 -0
  3. package/Makefile +36 -26
  4. package/ante/ante.go +7 -9
  5. package/ante/inbound_test.go +3 -2
  6. package/ante/vm_admission.go +2 -1
  7. package/app/app.go +212 -140
  8. package/app/upgrade.go +76 -0
  9. package/cmd/agd/agvm.go +42 -0
  10. package/cmd/agd/main.go +130 -11
  11. package/cmd/libdaemon/main.go +64 -53
  12. package/cmd/libdaemon/main_test.go +2 -1
  13. package/daemon/cmd/root.go +171 -74
  14. package/daemon/cmd/root_test.go +189 -1
  15. package/daemon/main.go +4 -2
  16. package/e2e_test/Makefile +29 -0
  17. package/e2e_test/README.md +100 -0
  18. package/e2e_test/go.mod +217 -0
  19. package/e2e_test/go.sum +1323 -0
  20. package/e2e_test/ibc_conformance_test.go +56 -0
  21. package/e2e_test/pfm_test.go +613 -0
  22. package/e2e_test/util.go +271 -0
  23. package/git-revision.txt +1 -1
  24. package/go.mod +22 -11
  25. package/go.sum +17 -13
  26. package/package.json +9 -5
  27. package/proto/agoric/swingset/genesis.proto +4 -0
  28. package/proto/agoric/swingset/swingset.proto +1 -1
  29. package/proto/agoric/vlocalchain/.clang-format +7 -0
  30. package/proto/agoric/vlocalchain/vlocalchain.proto +31 -0
  31. package/proto/agoric/vtransfer/genesis.proto +18 -0
  32. package/scripts/protocgen.sh +7 -8
  33. package/types/kv_entry_helpers.go +42 -0
  34. package/upgradegaia.sh +8 -8
  35. package/vm/action.go +5 -4
  36. package/vm/action_test.go +31 -11
  37. package/vm/client.go +113 -0
  38. package/vm/client_test.go +182 -0
  39. package/vm/controller.go +17 -40
  40. package/vm/core_proposals.go +22 -2
  41. package/vm/jsonrpcconn/jsonrpcconn.go +160 -0
  42. package/vm/jsonrpcconn/jsonrpcconn_test.go +126 -0
  43. package/vm/proto_json.go +38 -0
  44. package/vm/proto_json_test.go +103 -0
  45. package/vm/server.go +124 -0
  46. package/x/swingset/abci.go +10 -10
  47. package/x/swingset/alias.go +2 -0
  48. package/x/swingset/client/cli/tx.go +4 -0
  49. package/x/swingset/genesis.go +84 -24
  50. package/x/swingset/handler.go +2 -1
  51. package/x/swingset/keeper/extension_snapshotter.go +2 -2
  52. package/x/swingset/keeper/keeper.go +13 -25
  53. package/x/swingset/keeper/msg_server.go +18 -18
  54. package/x/swingset/keeper/proposal.go +3 -3
  55. package/x/swingset/keeper/querier.go +12 -11
  56. package/x/swingset/keeper/swing_store_exports_handler.go +21 -6
  57. package/x/swingset/keeper/test_utils.go +16 -0
  58. package/x/swingset/module.go +7 -7
  59. package/x/swingset/proposal_handler.go +2 -1
  60. package/x/swingset/testing/queue.go +17 -0
  61. package/x/swingset/types/default-params.go +1 -1
  62. package/x/swingset/types/expected_keepers.go +3 -2
  63. package/x/swingset/types/genesis.pb.go +78 -25
  64. package/x/swingset/types/msgs.go +44 -24
  65. package/x/swingset/types/params.go +2 -1
  66. package/x/swingset/types/proposal.go +5 -4
  67. package/x/swingset/types/swingset.pb.go +1 -1
  68. package/x/vbank/genesis.go +0 -2
  69. package/x/vbank/handler.go +2 -1
  70. package/x/vbank/keeper/querier.go +4 -3
  71. package/x/vbank/module.go +0 -5
  72. package/x/vbank/types/msgs.go +0 -12
  73. package/x/vbank/vbank.go +9 -9
  74. package/x/vbank/vbank_test.go +2 -2
  75. package/x/vibc/alias.go +3 -0
  76. package/x/vibc/handler.go +16 -9
  77. package/x/vibc/keeper/keeper.go +102 -65
  78. package/x/vibc/keeper/triggers.go +101 -0
  79. package/x/vibc/module.go +5 -8
  80. package/x/vibc/types/expected_keepers.go +13 -0
  81. package/x/vibc/types/ibc_module.go +336 -0
  82. package/x/vibc/types/receiver.go +170 -0
  83. package/x/vlocalchain/alias.go +19 -0
  84. package/x/vlocalchain/handler.go +21 -0
  85. package/x/vlocalchain/keeper/keeper.go +279 -0
  86. package/x/vlocalchain/keeper/keeper_test.go +97 -0
  87. package/x/vlocalchain/types/codec.go +34 -0
  88. package/x/vlocalchain/types/key.go +27 -0
  89. package/x/vlocalchain/types/msgs.go +16 -0
  90. package/x/vlocalchain/types/vlocalchain.pb.go +1072 -0
  91. package/x/vlocalchain/vlocalchain.go +114 -0
  92. package/x/vlocalchain/vlocalchain_test.go +434 -0
  93. package/x/vstorage/handler.go +2 -1
  94. package/x/vstorage/keeper/grpc_query.go +0 -1
  95. package/x/vstorage/keeper/keeper.go +13 -20
  96. package/x/vstorage/keeper/querier.go +6 -5
  97. package/x/vstorage/keeper/querier_test.go +4 -3
  98. package/x/vstorage/module.go +0 -5
  99. package/x/vstorage/testing/queue.go +27 -0
  100. package/x/vtransfer/alias.go +13 -0
  101. package/x/vtransfer/genesis.go +39 -0
  102. package/x/vtransfer/genesis_test.go +12 -0
  103. package/x/vtransfer/handler.go +20 -0
  104. package/x/vtransfer/ibc_middleware.go +186 -0
  105. package/x/vtransfer/ibc_middleware_test.go +448 -0
  106. package/x/vtransfer/keeper/keeper.go +281 -0
  107. package/x/vtransfer/module.go +124 -0
  108. package/x/vtransfer/types/expected_keepers.go +38 -0
  109. package/x/vtransfer/types/genesis.pb.go +327 -0
  110. package/x/vtransfer/types/key.go +9 -0
  111. package/x/vtransfer/types/msgs.go +9 -0
  112. package/ante/fee.go +0 -96
  113. package/proto/agoric/lien/genesis.proto +0 -25
  114. package/proto/agoric/lien/lien.proto +0 -25
  115. package/x/lien/alias.go +0 -17
  116. package/x/lien/genesis.go +0 -58
  117. package/x/lien/genesis_test.go +0 -101
  118. package/x/lien/keeper/account.go +0 -290
  119. package/x/lien/keeper/keeper.go +0 -255
  120. package/x/lien/keeper/keeper_test.go +0 -623
  121. package/x/lien/lien.go +0 -205
  122. package/x/lien/lien_test.go +0 -533
  123. package/x/lien/module.go +0 -115
  124. package/x/lien/spec/01_concepts.md +0 -146
  125. package/x/lien/spec/02_messages.md +0 -96
  126. package/x/lien/types/accountkeeper.go +0 -81
  127. package/x/lien/types/accountstate.go +0 -27
  128. package/x/lien/types/expected_keepers.go +0 -18
  129. package/x/lien/types/genesis.pb.go +0 -567
  130. package/x/lien/types/key.go +0 -25
  131. package/x/lien/types/lien.pb.go +0 -403
  132. package/x/vibc/ibc.go +0 -394
  133. /package/{src/index.cjs → index.cjs} +0 -0
package/upgradegaia.sh CHANGED
@@ -8,8 +8,8 @@
8
8
  set -ueo pipefail
9
9
 
10
10
  test $# -eq 2 || {
11
- echo "Usage: $0 <FROM_BRANCH> <TO_BRANCH>" 1>&2
12
- exit 1
11
+ echo "Usage: $0 <FROM_BRANCH> <TO_BRANCH>" 1>&2
12
+ exit 1
13
13
  }
14
14
 
15
15
  FROM_BRANCH="$1"
@@ -23,8 +23,8 @@ for tag in "$FROM_BRANCH" "$TO_BRANCH"; do
23
23
  qtag=${tag//\//_}
24
24
  for root in Makefile app cmd/gaiad; do
25
25
  case "$root" in
26
- Makefile) echo "$root" ;;
27
- *) git ls-tree --name-only --full-tree -r "$tag:$root" | sed -e "s!^!$root/!" ;;
26
+ Makefile) echo "$root" ;;
27
+ *) git ls-tree --name-only --full-tree -r "$tag:$root" | sed -e "s!^!$root/!" ;;
28
28
  esac
29
29
  done | while read -r src; do
30
30
  # echo "$src"
@@ -36,12 +36,12 @@ for tag in "$FROM_BRANCH" "$TO_BRANCH"; do
36
36
  done
37
37
 
38
38
  echo "Compute 3-way diffs between Gaia and us"
39
- (cd "$tmp/${FROM_BRANCH//\//_}" && find . -type f -print) | \
40
- while read -r src; do
39
+ (cd "$tmp/${FROM_BRANCH//\//_}" && find . -type f -print) \
40
+ | while read -r src; do
41
41
  # echo "$src"
42
42
  case "$src" in
43
- ./cmd/gaiad/*) our=${src//cmd\/gaiad/daemon} ;;
44
- *) our=$src ;;
43
+ ./cmd/gaiad/*) our=${src//cmd\/gaiad/daemon} ;;
44
+ *) our=$src ;;
45
45
  esac
46
46
 
47
47
  new="$tmp/diff3/$our"
package/vm/action.go CHANGED
@@ -18,7 +18,7 @@ var (
18
18
  type Jsonable interface{}
19
19
 
20
20
  type Action interface {
21
- GetActionHeader() ActionHeader
21
+ GetActionHeader() *ActionHeader
22
22
  }
23
23
 
24
24
  // ActionPusher enqueues data for later consumption by the controller.
@@ -27,14 +27,14 @@ type ActionPusher func(ctx sdk.Context, action Action) error
27
27
  // ActionHeader should be embedded in all actions. It is populated by PopulateAction.
28
28
  type ActionHeader struct {
29
29
  // Type defaults to the `actionType:"..."` tag of the embedder's ActionHeader field.
30
- Type string `json:"type"`
30
+ Type string `json:"type,omitempty"`
31
31
  // BlockHeight defaults to sdk.Context.BlockHeight().
32
32
  BlockHeight int64 `json:"blockHeight,omitempty"`
33
33
  // BlockTime defaults to sdk.Context.BlockTime().Unix().
34
34
  BlockTime int64 `json:"blockTime,omitempty"`
35
35
  }
36
36
 
37
- func (ah ActionHeader) GetActionHeader() ActionHeader {
37
+ func (ah *ActionHeader) GetActionHeader() *ActionHeader {
38
38
  return ah
39
39
  }
40
40
 
@@ -129,5 +129,6 @@ func PopulateAction(ctx sdk.Context, action Action) Action {
129
129
  }
130
130
  }
131
131
  }
132
- return newActionDesc.Interface().(Action)
132
+
133
+ return newActionDescPtr.Interface().(Action)
133
134
  }
package/vm/action_test.go CHANGED
@@ -10,9 +10,11 @@ import (
10
10
  )
11
11
 
12
12
  var (
13
- _ vm.Action = &Trivial{}
13
+ _ vm.Action = Defaults{}
14
14
  _ vm.Action = &Defaults{}
15
+ _ vm.Action = dataAction{}
15
16
  _ vm.Action = &dataAction{}
17
+ _ vm.Action = &Trivial{}
16
18
  )
17
19
 
18
20
  type Trivial struct {
@@ -29,8 +31,8 @@ type Defaults struct {
29
31
  Any interface{}
30
32
  }
31
33
 
32
- func (d Defaults) GetActionHeader() vm.ActionHeader {
33
- return vm.ActionHeader{}
34
+ func (d Defaults) GetActionHeader() *vm.ActionHeader {
35
+ return &vm.ActionHeader{}
34
36
  }
35
37
 
36
38
  type dataAction struct {
@@ -52,6 +54,10 @@ func TestActionContext(t *testing.T) {
52
54
  &Trivial{Abc: 123, def: "zot"},
53
55
  &Trivial{Abc: 123, def: "zot"},
54
56
  },
57
+ {"not a pointer", emptyCtx,
58
+ &Trivial{Abc: 123, def: "zot"},
59
+ Trivial{Abc: 123, def: "zot"},
60
+ },
55
61
  {"block height",
56
62
  emptyCtx.WithBlockHeight(998),
57
63
  &Trivial{Abc: 123, def: "zot"},
@@ -67,6 +73,20 @@ func TestActionContext(t *testing.T) {
67
73
  &Defaults{},
68
74
  &Defaults{"abc", 123, 4.56, true, nil},
69
75
  },
76
+ {"data action no pointer",
77
+ emptyCtx,
78
+ dataAction{},
79
+ dataAction{
80
+ ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION"},
81
+ },
82
+ },
83
+ {"data action pointer",
84
+ emptyCtx,
85
+ &dataAction{},
86
+ &dataAction{
87
+ ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION"},
88
+ },
89
+ },
70
90
  {"data action defaults",
71
91
  emptyCtx.WithBlockHeight(998).WithBlockTime(time.UnixMicro(1_000_000)),
72
92
  &dataAction{Data: []byte("hello")},
@@ -75,30 +95,30 @@ func TestActionContext(t *testing.T) {
75
95
  },
76
96
  {"data action override Type",
77
97
  emptyCtx.WithBlockHeight(998).WithBlockTime(time.UnixMicro(1_000_000)),
78
- &dataAction{Data: []byte("hello2"),
98
+ dataAction{Data: []byte("hello2"),
79
99
  ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION2"}},
80
- &dataAction{Data: []byte("hello2"),
100
+ dataAction{Data: []byte("hello2"),
81
101
  ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION2", BlockHeight: 998, BlockTime: 1}},
82
102
  },
83
103
  {"data action override BlockHeight",
84
104
  emptyCtx.WithBlockHeight(998).WithBlockTime(time.UnixMicro(1_000_000)),
85
- &dataAction{Data: []byte("hello2"),
105
+ dataAction{Data: []byte("hello2"),
86
106
  ActionHeader: &vm.ActionHeader{BlockHeight: 999}},
87
- &dataAction{Data: []byte("hello2"),
107
+ dataAction{Data: []byte("hello2"),
88
108
  ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION", BlockHeight: 999, BlockTime: 1}},
89
109
  },
90
110
  {"data action override BlockTime",
91
111
  emptyCtx.WithBlockHeight(998).WithBlockTime(time.UnixMicro(1_000_000)),
92
- &dataAction{Data: []byte("hello2"),
112
+ dataAction{Data: []byte("hello2"),
93
113
  ActionHeader: &vm.ActionHeader{BlockTime: 2}},
94
- &dataAction{Data: []byte("hello2"),
114
+ dataAction{Data: []byte("hello2"),
95
115
  ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION", BlockHeight: 998, BlockTime: 2}},
96
116
  },
97
117
  {"data action override all defaults",
98
118
  emptyCtx.WithBlockHeight(998).WithBlockTime(time.UnixMicro(1_000_000)),
99
- &dataAction{Data: []byte("hello2"),
119
+ dataAction{Data: []byte("hello2"),
100
120
  ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION2", BlockHeight: 999, BlockTime: 2}},
101
- &dataAction{Data: []byte("hello2"),
121
+ dataAction{Data: []byte("hello2"),
102
122
  ActionHeader: &vm.ActionHeader{Type: "DATA_ACTION2", BlockHeight: 999, BlockTime: 2}},
103
123
  },
104
124
  }
package/vm/client.go ADDED
@@ -0,0 +1,113 @@
1
+ package vm
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+ "net/rpc"
7
+ )
8
+
9
+ // ReceiveMessageMethod is the name of the method we call in order to have the
10
+ // VM receive a Message.
11
+ const ReceiveMessageMethod = "agvm.ReceiveMessage"
12
+
13
+ // Message is what we send to the VM.
14
+ type Message struct {
15
+ Port int
16
+ Data string
17
+ NeedsReply bool
18
+ }
19
+
20
+ // ClientCodec implements rpc.ClientCodec.
21
+ var _ rpc.ClientCodec = (*ClientCodec)(nil)
22
+
23
+ // ClientCodec implements a net/rpc ClientCodec for the "bridge" between the Go
24
+ // runtime and the VM in the single-process dual-runtime configuration.
25
+ //
26
+ // We expect to call it via the legacy API with signature:
27
+ // sendToController func(needsReply bool, msg string) (string, error)
28
+ // where msg and the returned string are JSON-encoded values.
29
+ //
30
+ // Note that the net/rpc framework cannot express a call that does not expect a
31
+ // response, so we'll note such calls by sending with a reply port of 0 and
32
+ // having the WriteRequest() method fabricate a Receive() call to clear the rpc
33
+ // state.
34
+ type ClientCodec struct {
35
+ ctx context.Context
36
+ send func(port, rPort int, msg string)
37
+ outbound map[int]rpc.Request
38
+ inbound chan *rpc.Response
39
+ replies map[uint64]string
40
+ replyToRead uint64
41
+ }
42
+
43
+ // NewClientCodec creates a new ClientCodec.
44
+ func NewClientCodec(ctx context.Context, send func(int, int, string)) *ClientCodec {
45
+ return &ClientCodec{
46
+ ctx: ctx,
47
+ send: send,
48
+ outbound: make(map[int]rpc.Request),
49
+ inbound: make(chan *rpc.Response),
50
+ replies: make(map[uint64]string),
51
+ }
52
+ }
53
+
54
+ // WriteRequest sends a request to the VM.
55
+ func (cc *ClientCodec) WriteRequest(r *rpc.Request, body interface{}) error {
56
+ if r.ServiceMethod != ReceiveMessageMethod {
57
+ return fmt.Errorf("unknown method %s", r.ServiceMethod)
58
+ }
59
+
60
+ msg, ok := body.(Message)
61
+ if !ok {
62
+ return fmt.Errorf("body %T is not a Message", body)
63
+ }
64
+ rPort := int(r.Seq + 1) // rPort is 1-indexed to indicate it's required
65
+ cc.outbound[rPort] = *r
66
+ var senderReplyPort int
67
+ if msg.NeedsReply {
68
+ senderReplyPort = rPort
69
+ }
70
+ cc.send(msg.Port, senderReplyPort, msg.Data)
71
+ if !msg.NeedsReply {
72
+ return cc.Receive(rPort, false, "<no-reply-requested>")
73
+ }
74
+ return nil
75
+ }
76
+
77
+ // ReadResponseHeader decodes a response header from the VM.
78
+ func (cc *ClientCodec) ReadResponseHeader(r *rpc.Response) error {
79
+ resp := <-cc.inbound
80
+ *r = *resp
81
+ cc.replyToRead = r.Seq
82
+ return nil
83
+ }
84
+
85
+ // ReadResponseBody decodes a response body (currently just string) from the VM.
86
+ func (cc *ClientCodec) ReadResponseBody(body interface{}) error {
87
+ if body != nil {
88
+ *body.(*string) = cc.replies[cc.replyToRead]
89
+ }
90
+ delete(cc.replies, cc.replyToRead)
91
+ return nil
92
+ }
93
+
94
+ // Receive is called by the VM to send a response to the client.
95
+ func (cc *ClientCodec) Receive(rPort int, isError bool, data string) error {
96
+ outb := cc.outbound[rPort]
97
+ delete(cc.outbound, rPort)
98
+ resp := &rpc.Response{
99
+ ServiceMethod: outb.ServiceMethod,
100
+ Seq: outb.Seq,
101
+ }
102
+ if isError {
103
+ resp.Error = data
104
+ } else {
105
+ cc.replies[resp.Seq] = data
106
+ }
107
+ cc.inbound <- resp
108
+ return nil
109
+ }
110
+
111
+ func (cc *ClientCodec) Close() error {
112
+ return nil
113
+ }
@@ -0,0 +1,182 @@
1
+ package vm_test
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "fmt"
7
+ "net/rpc"
8
+ "testing"
9
+ "time"
10
+
11
+ "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
12
+ )
13
+
14
+ type errorWrapper struct {
15
+ Error string `json:"error"`
16
+ }
17
+
18
+ // ConnectVMClientCodec creates an RPC client codec and a sender to the
19
+ // in-process implementation of the VM.
20
+ func ConnectVMClientCodec(ctx context.Context, nodePort int, sendFunc func(int, int, string)) (*vm.ClientCodec, vm.Sender) {
21
+ vmClientCodec := vm.NewClientCodec(ctx, sendFunc)
22
+ vmClient := rpc.NewClientWithCodec(vmClientCodec)
23
+
24
+ sendToNode := func(ctx context.Context, needReply bool, jsonRequest string) (jsonReply string, err error) {
25
+ if jsonRequest == "shutdown" {
26
+ return "", vmClientCodec.Close()
27
+ }
28
+
29
+ msg := vm.Message{
30
+ Port: nodePort,
31
+ NeedsReply: needReply,
32
+ Data: jsonRequest,
33
+ }
34
+ var reply string
35
+ err = vmClient.Call(vm.ReceiveMessageMethod, msg, &reply)
36
+ return reply, err
37
+ }
38
+
39
+ return vmClientCodec, sendToNode
40
+ }
41
+
42
+ type Fixture struct {
43
+ SendToNode vm.Sender
44
+ SendToGo func(port int, msgStr string) string
45
+ ReplyToGo func(replyPort int, isError bool, respStr string) int
46
+ }
47
+
48
+ func NewFixture(t *testing.T) *Fixture {
49
+ nodePort := 42
50
+
51
+ f := &Fixture{}
52
+ agdServer := vm.NewAgdServer()
53
+
54
+ sendFunc := func(port int, reply int, str string) {
55
+ switch str {
56
+ case "ping":
57
+ time.AfterFunc(100*time.Millisecond, func() {
58
+ fmt.Printf("sendFunc: port=%d, reply=%d, str=%s\n", port, reply, str)
59
+ if reply != 0 {
60
+ f.ReplyToGo(reply, false, "pong")
61
+ }
62
+ })
63
+ case "wait":
64
+ time.AfterFunc(300*time.Millisecond, func() {
65
+ fmt.Printf("sendFunc: port=%d, reply=%d, str=%s\n", port, reply, str)
66
+ if reply != 0 {
67
+ f.ReplyToGo(reply, false, "done-waiting")
68
+ }
69
+ })
70
+ default:
71
+ t.Errorf("Unexpected message %s", str)
72
+ }
73
+ }
74
+
75
+ vmClientCodec, sendToNode := ConnectVMClientCodec(
76
+ context.Background(),
77
+ int(nodePort),
78
+ sendFunc,
79
+ )
80
+
81
+ f.SendToNode = sendToNode
82
+ f.SendToGo = func(port int, msgStr string) string {
83
+ fmt.Println("Send to Go", msgStr)
84
+ var respStr string
85
+ message := &vm.Message{
86
+ Port: int(port),
87
+ NeedsReply: true,
88
+ Data: msgStr,
89
+ }
90
+
91
+ err := agdServer.ReceiveMessage(message, &respStr)
92
+ if err == nil {
93
+ return respStr
94
+ }
95
+
96
+ // fmt.Fprintln(os.Stderr, "Cannot receive from controller", err)
97
+ errResp := errorWrapper{
98
+ Error: err.Error(),
99
+ }
100
+ respBytes, err := json.Marshal(&errResp)
101
+ if err != nil {
102
+ panic(err)
103
+ }
104
+ return string(respBytes)
105
+ }
106
+
107
+ f.ReplyToGo = func(replyPort int, isError bool, respStr string) int {
108
+ if err := vmClientCodec.Receive(replyPort, isError, respStr); err != nil {
109
+ return 1
110
+ }
111
+ return 0
112
+ }
113
+
114
+ return f
115
+ }
116
+
117
+ func TestClient_oneOutbound(t *testing.T) {
118
+ f := NewFixture(t)
119
+
120
+ // Try one blocking call.
121
+ ret, err := f.SendToNode(context.Background(), true, "ping")
122
+ if err != nil {
123
+ t.Error(err)
124
+ }
125
+ if ret != "pong" {
126
+ t.Errorf("ping want pong, got %s", ret)
127
+ }
128
+ }
129
+
130
+ func TestClient_ShortBg(t *testing.T) {
131
+
132
+ f := NewFixture(t)
133
+
134
+ // Try a short background call with a long overlapping call.
135
+ done := make(chan struct{})
136
+ go func() {
137
+ defer close(done)
138
+ ret, err := f.SendToNode(context.Background(), true, "ping")
139
+ if err != nil {
140
+ t.Error(err)
141
+ }
142
+ if ret != "pong" {
143
+ t.Errorf("ping want pong, got %s", ret)
144
+ }
145
+ }()
146
+
147
+ ret, err := f.SendToNode(context.Background(), true, "wait")
148
+ if err != nil {
149
+ t.Error(err)
150
+ }
151
+ if ret != "done-waiting" {
152
+ t.Errorf("wait want done-waiting, got %s", ret)
153
+ }
154
+ <-done
155
+ }
156
+
157
+ func TestClient_LongBg(t *testing.T) {
158
+
159
+ f := NewFixture(t)
160
+
161
+ // Try a long background call with a short overlapping call.
162
+ done := make(chan struct{})
163
+ go func() {
164
+ defer close(done)
165
+ ret, err := f.SendToNode(context.Background(), true, "wait")
166
+ if err != nil {
167
+ t.Error(err)
168
+ }
169
+ if ret != "done-waiting" {
170
+ t.Errorf("ping want done-waiting, got %s", ret)
171
+ }
172
+ }()
173
+
174
+ ret, err := f.SendToNode(context.Background(), true, "ping")
175
+ if err != nil {
176
+ t.Error(err)
177
+ }
178
+ if ret != "pong" {
179
+ t.Errorf("wait want pong, got %s", ret)
180
+ }
181
+ <-done
182
+ }
package/vm/controller.go CHANGED
@@ -7,6 +7,9 @@ import (
7
7
  sdk "github.com/cosmos/cosmos-sdk/types"
8
8
  )
9
9
 
10
+ // Sender makes a request of our associated VM.
11
+ type Sender func(ctx context.Context, needReply bool, jsonRequest string) (jsonReply string, err error)
12
+
10
13
  type ControllerAdmissionMsg interface {
11
14
  sdk.Msg
12
15
  CheckAdmissibility(sdk.Context, interface{}) error
@@ -21,52 +24,26 @@ type ControllerAdmissionMsg interface {
21
24
  IsHighPriority(sdk.Context, interface{}) (bool, error)
22
25
  }
23
26
 
24
- var wrappedEmptySDKContext = sdk.WrapSDKContext(
25
- sdk.Context{}.WithContext(context.Background()),
26
- )
27
- var controllerContext context.Context = wrappedEmptySDKContext
28
-
29
27
  type PortHandler interface {
30
28
  Receive(context.Context, string) (string, error)
31
29
  }
32
30
 
33
- var portToHandler = make(map[int]PortHandler)
34
- var portToName = make(map[int]string)
35
- var nameToPort = make(map[string]int)
36
- var lastPort = 0
37
-
38
- func SetControllerContext(ctx sdk.Context) func() {
39
- // We are only called by the controller, so we assume that it is billing its
40
- // own meter usage.
41
- controllerContext = sdk.WrapSDKContext(ctx.WithGasMeter(sdk.NewInfiniteGasMeter()))
42
- return func() {
43
- controllerContext = wrappedEmptySDKContext
44
- }
31
+ type protectedPortHandler struct {
32
+ inner PortHandler
45
33
  }
46
34
 
47
- func GetPort(name string) int {
48
- return nameToPort[name]
49
- }
50
-
51
- func RegisterPortHandler(name string, portHandler PortHandler) int {
52
- lastPort++
53
- portToHandler[lastPort] = portHandler
54
- portToName[lastPort] = name
55
- nameToPort[name] = lastPort
56
- return lastPort
57
- }
58
- func UnregisterPortHandler(portNum int) error {
59
- delete(portToHandler, portNum)
60
- name := portToName[portNum]
61
- delete(portToName, portNum)
62
- delete(nameToPort, name)
63
- return nil
35
+ func (h protectedPortHandler) Receive(ctx context.Context, str string) (ret string, err error) {
36
+ defer func() {
37
+ if r := recover(); r != nil {
38
+ // Propagate just the string, not the error stack or we will invite
39
+ // nondeterminism.
40
+ err = fmt.Errorf("panic: %s", r)
41
+ }
42
+ }()
43
+ ret, err = h.inner.Receive(ctx, str)
44
+ return
64
45
  }
65
46
 
66
- func ReceiveFromController(portNum int, msg string) (string, error) {
67
- handler := portToHandler[portNum]
68
- if handler == nil {
69
- return "", fmt.Errorf("unregistered port %d", portNum)
70
- }
71
- return handler.Receive(controllerContext, msg)
47
+ func NewProtectedPortHandler(inner PortHandler) PortHandler {
48
+ return protectedPortHandler{inner}
72
49
  }
@@ -1,5 +1,10 @@
1
1
  package vm
2
2
 
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ )
7
+
3
8
  // CoreProposalStep is a set of core proposal configs which are executed
4
9
  // concurrently
5
10
  type CoreProposalStep []Jsonable
@@ -11,12 +16,27 @@ type CoreProposals struct {
11
16
  Steps []CoreProposalStep `json:"steps"`
12
17
  }
13
18
 
19
+ type ArbitraryCoreProposal struct {
20
+ Json json.RawMessage
21
+ }
22
+
23
+ func NewArbitraryCoreProposal(jsonStr string) *ArbitraryCoreProposal {
24
+ return &ArbitraryCoreProposal{Json: []byte(jsonStr)}
25
+ }
26
+
14
27
  // CoreProposalStepForModules generates a single core proposal step from
15
28
  // the given modules, which will be executed concurrently during that step
16
- func CoreProposalStepForModules(modules ...string) CoreProposalStep {
29
+ func CoreProposalStepForModules(modules ...Jsonable) CoreProposalStep {
17
30
  step := make([]Jsonable, len(modules))
18
31
  for i := range modules {
19
- step[i] = modules[i]
32
+ switch m := modules[i].(type) {
33
+ case ArbitraryCoreProposal:
34
+ step[i] = m.Json
35
+ case string:
36
+ step[i] = m
37
+ default:
38
+ panic(fmt.Errorf("unexpected step type %T", m))
39
+ }
20
40
  }
21
41
  return step
22
42
  }