@agoric/cosmos 0.34.2-orchestration-dev-096c4e8.0 → 0.34.2-other-dev-3eb1a1d.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 (90) hide show
  1. package/MAINTAINERS.md +3 -0
  2. package/Makefile +38 -34
  3. package/ante/ante.go +1 -4
  4. package/ante/inbound_test.go +2 -2
  5. package/app/app.go +198 -137
  6. package/app/upgrade.go +248 -0
  7. package/cmd/agd/agvm.go +3 -3
  8. package/cmd/agd/find_binary.go +2 -2
  9. package/cmd/agd/main.go +9 -10
  10. package/cmd/libdaemon/main.go +13 -13
  11. package/daemon/cmd/root.go +235 -92
  12. package/daemon/cmd/root_test.go +189 -1
  13. package/daemon/main.go +3 -2
  14. package/git-revision.txt +1 -1
  15. package/go.mod +14 -11
  16. package/go.sum +20 -19
  17. package/index.cjs +1 -1
  18. package/package.json +4 -3
  19. package/proto/agoric/swingset/genesis.proto +4 -0
  20. package/proto/agoric/swingset/swingset.proto +26 -1
  21. package/proto/agoric/vbank/vbank.proto +7 -0
  22. package/proto/agoric/vtransfer/genesis.proto +18 -0
  23. package/scripts/protocgen.sh +7 -8
  24. package/types/kv_entry_helpers.go +42 -0
  25. package/upgradegaia.sh +8 -8
  26. package/util/util.go +21 -0
  27. package/vm/action.go +1 -1
  28. package/vm/client.go +15 -13
  29. package/vm/client_test.go +34 -36
  30. package/vm/controller.go +3 -38
  31. package/vm/core_proposals.go +22 -2
  32. package/vm/proto_json.go +38 -0
  33. package/vm/proto_json_test.go +103 -0
  34. package/vm/server.go +106 -5
  35. package/x/swingset/alias.go +2 -0
  36. package/x/swingset/config.go +234 -0
  37. package/x/swingset/genesis.go +178 -40
  38. package/x/swingset/keeper/extension_snapshotter.go +2 -2
  39. package/x/swingset/keeper/keeper.go +24 -27
  40. package/x/swingset/keeper/swing_store_exports_handler.go +14 -3
  41. package/x/swingset/keeper/test_utils.go +16 -0
  42. package/x/swingset/module.go +24 -9
  43. package/x/swingset/testing/queue.go +17 -0
  44. package/x/swingset/types/default-params.go +31 -5
  45. package/x/swingset/types/expected_keepers.go +2 -2
  46. package/x/swingset/types/genesis.pb.go +78 -25
  47. package/x/swingset/types/msgs.go +53 -12
  48. package/x/swingset/types/params.go +53 -43
  49. package/x/swingset/types/params_test.go +75 -9
  50. package/x/swingset/types/swingset.pb.go +387 -57
  51. package/x/vbank/README.md +6 -1
  52. package/x/vbank/genesis.go +0 -2
  53. package/x/vbank/keeper/keeper.go +4 -9
  54. package/x/vbank/keeper/migrations.go +30 -0
  55. package/x/vbank/module.go +8 -7
  56. package/x/vbank/types/key.go +3 -3
  57. package/x/vbank/types/msgs.go +0 -12
  58. package/x/vbank/types/params.go +43 -2
  59. package/x/vbank/types/vbank.pb.go +105 -36
  60. package/x/vbank/vbank.go +8 -13
  61. package/x/vbank/vbank_test.go +14 -9
  62. package/x/vibc/alias.go +1 -1
  63. package/x/vibc/module.go +2 -7
  64. package/x/vibc/types/ibc_module.go +9 -3
  65. package/x/vibc/types/receiver.go +17 -7
  66. package/x/vlocalchain/handler.go +2 -1
  67. package/x/vlocalchain/keeper/keeper.go +24 -8
  68. package/x/vlocalchain/keeper/keeper_test.go +65 -1
  69. package/x/vlocalchain/types/expected_keepers.go +12 -0
  70. package/x/vlocalchain/vlocalchain.go +27 -22
  71. package/x/vlocalchain/vlocalchain_test.go +163 -8
  72. package/x/vstorage/keeper/grpc_query.go +0 -1
  73. package/x/vstorage/keeper/keeper.go +9 -17
  74. package/x/vstorage/module.go +0 -5
  75. package/x/vstorage/testing/queue.go +28 -0
  76. package/x/vtransfer/alias.go +13 -0
  77. package/x/vtransfer/genesis.go +39 -0
  78. package/x/vtransfer/genesis_test.go +12 -0
  79. package/x/vtransfer/handler.go +20 -0
  80. package/x/vtransfer/ibc_middleware.go +186 -0
  81. package/x/vtransfer/ibc_middleware_test.go +449 -0
  82. package/x/vtransfer/keeper/keeper.go +282 -0
  83. package/x/vtransfer/module.go +124 -0
  84. package/x/vtransfer/types/baseaddr.go +156 -0
  85. package/x/vtransfer/types/baseaddr_test.go +167 -0
  86. package/x/vtransfer/types/expected_keepers.go +38 -0
  87. package/x/vtransfer/types/genesis.pb.go +328 -0
  88. package/x/vtransfer/types/key.go +9 -0
  89. package/x/vtransfer/types/msgs.go +9 -0
  90. package/ante/fee.go +0 -97
package/vm/client_test.go CHANGED
@@ -11,30 +11,28 @@ import (
11
11
  "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
12
12
  )
13
13
 
14
- type Sender func(ctx context.Context, needReply bool, str string) (string, error)
15
-
16
14
  type errorWrapper struct {
17
15
  Error string `json:"error"`
18
16
  }
19
17
 
20
18
  // ConnectVMClientCodec creates an RPC client codec and a sender to the
21
19
  // in-process implementation of the VM.
22
- func ConnectVMClientCodec(ctx context.Context, nodePort int, sendFunc func(int, int, string)) (*vm.ClientCodec, Sender) {
23
- vmClientCodec := vm.NewClientCodec(context.Background(), sendFunc)
20
+ func ConnectVMClientCodec(ctx context.Context, nodePort int, sendFunc func(int, int, string)) (*vm.ClientCodec, vm.Sender) {
21
+ vmClientCodec := vm.NewClientCodec(ctx, sendFunc)
24
22
  vmClient := rpc.NewClientWithCodec(vmClientCodec)
25
23
 
26
- sendToNode := func(ctx context.Context, needReply bool, str string) (string, error) {
27
- if str == "shutdown" {
24
+ sendToNode := func(ctx context.Context, needReply bool, jsonRequest string) (jsonReply string, err error) {
25
+ if jsonRequest == "shutdown" {
28
26
  return "", vmClientCodec.Close()
29
27
  }
30
28
 
31
29
  msg := vm.Message{
32
- Port: nodePort,
30
+ Port: nodePort,
33
31
  NeedsReply: needReply,
34
- Data: str,
32
+ Data: jsonRequest,
35
33
  }
36
34
  var reply string
37
- err := vmClient.Call(vm.ReceiveMessageMethod, msg, &reply)
35
+ err = vmClient.Call(vm.ReceiveMessageMethod, msg, &reply)
38
36
  return reply, err
39
37
  }
40
38
 
@@ -42,34 +40,35 @@ func ConnectVMClientCodec(ctx context.Context, nodePort int, sendFunc func(int,
42
40
  }
43
41
 
44
42
  type Fixture struct {
45
- SendToNode Sender
46
- SendToGo func (port int, msgStr string) string
47
- ReplyToGo func (replyPort int, isError bool, respStr string) int
43
+ SendToNode vm.Sender
44
+ SendToGo func(port int, msgStr string) string
45
+ ReplyToGo func(replyPort int, isError bool, respStr string) int
48
46
  }
49
47
 
50
- func NewFixture(t *testing.T) (*Fixture) {
48
+ func NewFixture(t *testing.T) *Fixture {
51
49
  nodePort := 42
52
50
 
53
51
  f := &Fixture{}
52
+ agdServer := vm.NewAgdServer()
54
53
 
55
54
  sendFunc := func(port int, reply int, str string) {
56
55
  switch str {
57
- case "ping":
58
- time.AfterFunc(100*time.Millisecond, func() {
59
- fmt.Printf("sendFunc: port=%d, reply=%d, str=%s\n", port, reply, str)
60
- if reply != 0 {
61
- f.ReplyToGo(reply, false, "pong")
62
- }
63
- })
64
- case "wait":
65
- time.AfterFunc(300*time.Millisecond, func() {
66
- fmt.Printf("sendFunc: port=%d, reply=%d, str=%s\n", port, reply, str)
67
- if reply != 0 {
68
- f.ReplyToGo(reply, false, "done-waiting")
69
- }
70
- })
71
- default:
72
- t.Errorf("Unexpected message %s", 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)
73
72
  }
74
73
  }
75
74
 
@@ -78,23 +77,22 @@ func NewFixture(t *testing.T) (*Fixture) {
78
77
  int(nodePort),
79
78
  sendFunc,
80
79
  )
81
- agdServer := vm.NewAgdServer()
82
80
 
83
81
  f.SendToNode = sendToNode
84
- f.SendToGo = func (port int, msgStr string) string {
82
+ f.SendToGo = func(port int, msgStr string) string {
85
83
  fmt.Println("Send to Go", msgStr)
86
84
  var respStr string
87
85
  message := &vm.Message{
88
- Port: int(port),
86
+ Port: int(port),
89
87
  NeedsReply: true,
90
- Data: msgStr,
88
+ Data: msgStr,
91
89
  }
92
-
90
+
93
91
  err := agdServer.ReceiveMessage(message, &respStr)
94
92
  if err == nil {
95
93
  return respStr
96
94
  }
97
-
95
+
98
96
  // fmt.Fprintln(os.Stderr, "Cannot receive from controller", err)
99
97
  errResp := errorWrapper{
100
98
  Error: err.Error(),
@@ -106,7 +104,7 @@ func NewFixture(t *testing.T) (*Fixture) {
106
104
  return string(respBytes)
107
105
  }
108
106
 
109
- f.ReplyToGo = func (replyPort int, isError bool, respStr string) int {
107
+ f.ReplyToGo = func(replyPort int, isError bool, respStr string) int {
110
108
  if err := vmClientCodec.Receive(replyPort, isError, respStr); err != nil {
111
109
  return 1
112
110
  }
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,20 +24,10 @@ 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
31
  type protectedPortHandler struct {
39
32
  inner PortHandler
40
33
  }
@@ -54,31 +47,3 @@ func (h protectedPortHandler) Receive(ctx context.Context, str string) (ret stri
54
47
  func NewProtectedPortHandler(inner PortHandler) PortHandler {
55
48
  return protectedPortHandler{inner}
56
49
  }
57
-
58
- func SetControllerContext(ctx sdk.Context) func() {
59
- // We are only called by the controller, so we assume that it is billing its
60
- // own meter usage.
61
- controllerContext = sdk.WrapSDKContext(ctx.WithGasMeter(sdk.NewInfiniteGasMeter()))
62
- return func() {
63
- controllerContext = wrappedEmptySDKContext
64
- }
65
- }
66
-
67
- func GetPort(name string) int {
68
- return nameToPort[name]
69
- }
70
-
71
- func RegisterPortHandler(name string, portHandler PortHandler) int {
72
- lastPort++
73
- portToHandler[lastPort] = NewProtectedPortHandler(portHandler)
74
- portToName[lastPort] = name
75
- nameToPort[name] = lastPort
76
- return lastPort
77
- }
78
- func UnregisterPortHandler(portNum int) error {
79
- delete(portToHandler, portNum)
80
- name := portToName[portNum]
81
- delete(portToName, portNum)
82
- delete(nameToPort, name)
83
- return nil
84
- }
@@ -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
  }
@@ -0,0 +1,38 @@
1
+ package vm
2
+
3
+ import (
4
+ "encoding/json"
5
+
6
+ "github.com/gogo/protobuf/jsonpb"
7
+ "github.com/gogo/protobuf/proto"
8
+ )
9
+
10
+ // We need jsonpb for its access to the global registry.
11
+ var marshaller = jsonpb.Marshaler{EmitDefaults: true}
12
+
13
+ func ProtoJSONMarshal(val interface{}) ([]byte, error) {
14
+ if pm, ok := val.(proto.Message); ok {
15
+ var s string
16
+ s, err := marshaller.MarshalToString(pm)
17
+ return []byte(s), err
18
+ }
19
+
20
+ // Marshal a non-proto value to JSON.
21
+ return json.Marshal(val)
22
+ }
23
+
24
+ // ProtoJSONMarshalSlice marshals a slice of proto messages and non-proto values to
25
+ // a single JSON byte slice.
26
+ func ProtoJSONMarshalSlice(vals []interface{}) ([]byte, error) {
27
+ var err error
28
+ jsonSlice := make([]json.RawMessage, len(vals))
29
+ for i, val := range vals {
30
+ jsonSlice[i], err = ProtoJSONMarshal(val)
31
+ if err != nil {
32
+ return nil, err
33
+ }
34
+ }
35
+
36
+ // Marshal the JSON array to a single JSON byte slice.
37
+ return json.Marshal(jsonSlice)
38
+ }
@@ -0,0 +1,103 @@
1
+ package vm_test
2
+
3
+ import (
4
+ "bytes"
5
+ "strings"
6
+ "testing"
7
+
8
+ "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
9
+
10
+ sdk "github.com/cosmos/cosmos-sdk/types"
11
+
12
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
13
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
14
+ )
15
+
16
+ func TestProtoJSONMarshal(t *testing.T) {
17
+ accAddr, err := sdk.AccAddressFromHexUnsafe("0123456789")
18
+ if err != nil {
19
+ panic(err)
20
+ }
21
+ valAddr, err := sdk.ValAddressFromHex("9876543210")
22
+ if err != nil {
23
+ panic(err)
24
+ }
25
+ coin := sdk.NewInt64Coin("uatom", 1234567)
26
+
27
+ testCases := []struct {
28
+ name string
29
+ create func() interface{}
30
+ expected string
31
+ }{
32
+ {
33
+ "nil",
34
+ func() interface{} {
35
+ return nil
36
+ },
37
+ `null`,
38
+ },
39
+ {
40
+ "primitive number",
41
+ func() interface{} {
42
+ return 12345
43
+ },
44
+ `12345`,
45
+ },
46
+ {
47
+ "MsgDelegate",
48
+ func() interface{} {
49
+ return stakingtypes.NewMsgDelegate(accAddr, valAddr, coin)
50
+ },
51
+ `{"delegatorAddress":"cosmos1qy352eufjjmc9c","validatorAddress":"cosmosvaloper1npm9gvss52mlmk","amount":{"denom":"uatom","amount":"1234567"}}`,
52
+ },
53
+ {
54
+ "QueryDenomOwnersResponse",
55
+ func() interface{} {
56
+ return &banktypes.QueryDenomOwnersResponse{
57
+ DenomOwners: []*banktypes.DenomOwner{
58
+ {
59
+ Address: accAddr.String(),
60
+ Balance: coin,
61
+ },
62
+ {
63
+ Address: valAddr.String(),
64
+ Balance: coin.Add(coin),
65
+ },
66
+ },
67
+ }
68
+ },
69
+ `{"denomOwners":[{"address":"cosmos1qy352eufjjmc9c","balance":{"denom":"uatom","amount":"1234567"}},{"address":"cosmosvaloper1npm9gvss52mlmk","balance":{"denom":"uatom","amount":"2469134"}}],"pagination":null}`,
70
+ },
71
+ }
72
+
73
+ for _, tc := range testCases {
74
+ t.Run(tc.name, func(t *testing.T) {
75
+ val := tc.create()
76
+ bz, err := vm.ProtoJSONMarshal(val)
77
+ if err != nil {
78
+ t.Errorf("ProtoJSONMarshal of %q failed %v", val, err)
79
+ }
80
+ if !bytes.Equal(bz, []byte(tc.expected)) {
81
+ t.Errorf("ProtoJSONMarshal of %q returned %q, expected %q", val, string(bz), tc.expected)
82
+ }
83
+ })
84
+ }
85
+
86
+ t.Run("all in a slice", func(t *testing.T) {
87
+ vals := make([]interface{}, len(testCases))
88
+ expectedJson := make([]string, len(testCases))
89
+ for i, tc := range testCases {
90
+ vals[i] = tc.create()
91
+ expectedJson[i] = tc.expected
92
+ }
93
+ bz, err := vm.ProtoJSONMarshalSlice(vals)
94
+ if err != nil {
95
+ t.Errorf("ProtoJSONMarshalSlice of %q failed %v", vals, err)
96
+ }
97
+
98
+ expected := "[" + strings.Join(expectedJson, ",") + "]"
99
+ if !bytes.Equal(bz, []byte(expected)) {
100
+ t.Errorf("ProtoJSONMarshalSlice of %q returned %q, expected %q", vals, string(bz), expected)
101
+ }
102
+ })
103
+ }
package/vm/server.go CHANGED
@@ -1,23 +1,124 @@
1
1
  package vm
2
2
 
3
3
  import (
4
+ "context"
4
5
  "fmt"
6
+ "sync"
7
+
8
+ sdk "github.com/cosmos/cosmos-sdk/types"
5
9
  )
6
10
 
7
- type AgdServer struct{}
11
+ // AgdServer manages communication from the VM to the ABCI app. The structure
12
+ // is mutable and the mutex must be held to read or write any field.
13
+ type AgdServer struct {
14
+ currentCtx context.Context
15
+ mtx sync.Mutex
16
+ // zero is an out-of-bounds port number
17
+ lastPort int
18
+ // portToHandler[i] is nonzero iff portToName[i] is nonempty
19
+ portToHandler map[int]PortHandler
20
+ // portToName[nameToPort[s]] == s && nameToPort[portToName[i]] == i for all i, s
21
+ portToName map[int]string
22
+ nameToPort map[string]int
23
+ }
24
+
25
+ var wrappedEmptySDKContext = sdk.WrapSDKContext(
26
+ sdk.Context{}.WithContext(context.Background()),
27
+ )
8
28
 
29
+ // NewAgdServer returns a pointer to a new AgdServer with empty context and port
30
+ // mappings.
9
31
  func NewAgdServer() *AgdServer {
10
- return &AgdServer{}
32
+ return &AgdServer{
33
+ currentCtx: wrappedEmptySDKContext,
34
+ mtx: sync.Mutex{},
35
+ portToHandler: make(map[int]PortHandler),
36
+ portToName: make(map[int]string),
37
+ nameToPort: make(map[string]int),
38
+ }
39
+ }
40
+
41
+ // SetControllerContext sets the context to the given argument and returns a function
42
+ // which will reset the context to an empty context (not the old context).
43
+ func (s *AgdServer) SetControllerContext(ctx sdk.Context) func() {
44
+ // We are only called by the controller, so we assume that it is billing its
45
+ // own meter usage.
46
+ s.mtx.Lock()
47
+ defer s.mtx.Unlock()
48
+ s.currentCtx = sdk.WrapSDKContext(ctx.WithGasMeter(sdk.NewInfiniteGasMeter()))
49
+ return func() {
50
+ s.mtx.Lock()
51
+ defer s.mtx.Unlock()
52
+ s.currentCtx = wrappedEmptySDKContext
53
+ }
54
+ }
55
+
56
+ // getContextAndHandler returns the current context and the handler for the
57
+ // given port number.
58
+ func (s *AgdServer) getContextAndHandler(port int) (context.Context, PortHandler) {
59
+ s.mtx.Lock()
60
+ defer s.mtx.Unlock()
61
+ ctx := s.currentCtx
62
+ handler := s.portToHandler[port]
63
+ return ctx, handler
11
64
  }
12
65
 
13
66
  // ReceiveMessage is the method the VM calls in order to have agd receive a
14
67
  // Message.
15
- func (s AgdServer) ReceiveMessage(msg *Message, reply *string) error {
16
- handler := portToHandler[msg.Port]
68
+ func (s *AgdServer) ReceiveMessage(msg *Message, reply *string) error {
69
+ ctx, handler := s.getContextAndHandler(msg.Port)
17
70
  if handler == nil {
18
71
  return fmt.Errorf("unregistered port %d", msg.Port)
19
72
  }
20
- resp, err := handler.Receive(controllerContext, msg.Data)
73
+ resp, err := handler.Receive(ctx, msg.Data)
21
74
  *reply = resp
22
75
  return err
23
76
  }
77
+
78
+ // GetPort returns the port number for the given port name, or 0 if the name is
79
+ // not registered.
80
+ func (s *AgdServer) GetPort(name string) int {
81
+ s.mtx.Lock()
82
+ defer s.mtx.Unlock()
83
+ return s.nameToPort[name]
84
+ }
85
+
86
+ // MustRegisterPortHandler attempts to RegisterPortHandler, panicing on error.
87
+ func (s *AgdServer) MustRegisterPortHandler(name string, portHandler PortHandler) int {
88
+ port, err := s.RegisterPortHandler(name, portHandler)
89
+ if err != nil {
90
+ panic(err)
91
+ }
92
+ return port
93
+ }
94
+
95
+ // RegisterPortHandler registers the handler to a new port number, then maps the name to it,
96
+ // returning the port number. If the name was previously in use, an error is returned.
97
+ func (s *AgdServer) RegisterPortHandler(name string, portHandler PortHandler) (int, error) {
98
+ s.mtx.Lock()
99
+ defer s.mtx.Unlock()
100
+ if _, ok := s.nameToPort[name]; ok {
101
+ return 0, fmt.Errorf("name %s already in use", name)
102
+ }
103
+ s.lastPort++
104
+ s.portToHandler[s.lastPort] = NewProtectedPortHandler(portHandler)
105
+ s.portToName[s.lastPort] = name
106
+ s.nameToPort[name] = s.lastPort
107
+ return s.lastPort, nil
108
+ }
109
+
110
+ // UnregisterPortHandler unregisters the handler and name mappings for this port
111
+ // number, and the reverse mapping for its name, if any of these exist. If
112
+ // portNum is not registered, return an error.
113
+ func (s *AgdServer) UnregisterPortHandler(portNum int) error {
114
+ s.mtx.Lock()
115
+ defer s.mtx.Unlock()
116
+ if s.portToHandler[portNum] == nil {
117
+ return fmt.Errorf("port %d not registered", portNum)
118
+ }
119
+ delete(s.portToHandler, portNum)
120
+ name := s.portToName[portNum]
121
+ delete(s.portToName, portNum)
122
+ delete(s.nameToPort, name)
123
+ return nil
124
+ }
@@ -24,6 +24,8 @@ type (
24
24
  Keeper = keeper.Keeper
25
25
  SwingStoreExportsHandler = keeper.SwingStoreExportsHandler
26
26
  ExtensionSnapshotter = keeper.ExtensionSnapshotter
27
+ ActionContext = types.ActionContext
28
+ InboundQueueRecord = types.InboundQueueRecord
27
29
  Egress = types.Egress
28
30
  MsgDeliverInbound = types.MsgDeliverInbound
29
31
  MsgProvision = types.MsgProvision