@agoric/cosmos 0.34.2-dev-ecf2d8e.0 → 0.35.0-other-dev-70beeb7.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 (40) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/app/app.go +103 -14
  3. package/app/const.go +6 -0
  4. package/cmd/agd/main.go +11 -133
  5. package/cmd/libdaemon/main.go +53 -67
  6. package/daemon/cmd/root.go +24 -55
  7. package/daemon/main.go +1 -3
  8. package/git-revision.txt +1 -1
  9. package/package.json +3 -3
  10. package/proto/agoric/vstorage/query.proto +1 -53
  11. package/vm/controller.go +18 -8
  12. package/x/lien/lien.go +4 -6
  13. package/x/lien/lien_test.go +15 -19
  14. package/x/swingset/abci.go +2 -3
  15. package/x/swingset/swingset.go +2 -4
  16. package/x/swingset/types/default-params.go +1 -1
  17. package/x/swingset/types/msgs.pb.go +16 -16
  18. package/x/vbank/vbank.go +10 -11
  19. package/x/vbank/vbank_test.go +5 -5
  20. package/x/vibc/ibc.go +11 -12
  21. package/x/vibc/keeper/keeper.go +15 -1
  22. package/x/vibc/types/expected_keepers.go +1 -2
  23. package/x/vstorage/keeper/grpc_query.go +0 -221
  24. package/x/vstorage/keeper/querier.go +11 -31
  25. package/x/vstorage/types/path_keys.go +10 -22
  26. package/x/vstorage/types/path_keys_test.go +18 -84
  27. package/x/vstorage/types/query.pb.go +36 -646
  28. package/x/vstorage/types/query.pb.gw.go +0 -119
  29. package/x/vstorage/vstorage.go +15 -16
  30. package/x/vstorage/vstorage_test.go +4 -4
  31. package/cmd/agd/agvm.go +0 -42
  32. package/vm/client.go +0 -113
  33. package/vm/client_test.go +0 -184
  34. package/vm/jsonrpcconn/jsonrpcconn.go +0 -160
  35. package/vm/jsonrpcconn/jsonrpcconn_test.go +0 -126
  36. package/vm/server.go +0 -23
  37. package/x/vstorage/README.md +0 -95
  38. package/x/vstorage/capdata/capdata.go +0 -298
  39. package/x/vstorage/capdata/capdata_test.go +0 -352
  40. package/x/vstorage/keeper/keeper_grpc_test.go +0 -300
@@ -284,7 +284,7 @@ func Test_Receive_GetBalance(t *testing.T) {
284
284
  }}
285
285
  keeper, ctx := makeTestKit(nil, bank)
286
286
  ch := NewPortHandler(AppModule{}, keeper)
287
- ctlCtx := sdk.WrapSDKContext(ctx)
287
+ ctlCtx := &vm.ControllerContext{Context: ctx}
288
288
 
289
289
  ret, err := ch.Receive(ctlCtx, `{
290
290
  "type": "VBANK_GET_BALANCE",
@@ -312,7 +312,7 @@ func Test_Receive_Give(t *testing.T) {
312
312
  }}
313
313
  keeper, ctx := makeTestKit(nil, bank)
314
314
  ch := NewPortHandler(AppModule{}, keeper)
315
- ctlCtx := sdk.WrapSDKContext(ctx)
315
+ ctlCtx := &vm.ControllerContext{Context: ctx}
316
316
 
317
317
  ret, err := ch.Receive(ctlCtx, `{
318
318
  "type": "VBANK_GIVE",
@@ -349,7 +349,7 @@ func Test_Receive_GiveToRewardDistributor(t *testing.T) {
349
349
  bank := &mockBank{}
350
350
  keeper, ctx := makeTestKit(nil, bank)
351
351
  ch := NewPortHandler(AppModule{}, keeper)
352
- ctlCtx := sdk.WrapSDKContext(ctx)
352
+ ctlCtx := &vm.ControllerContext{Context: ctx}
353
353
 
354
354
  tests := []struct {
355
355
  name string
@@ -474,7 +474,7 @@ func Test_Receive_Grab(t *testing.T) {
474
474
  }}
475
475
  keeper, ctx := makeTestKit(nil, bank)
476
476
  ch := NewPortHandler(AppModule{}, keeper)
477
- ctlCtx := sdk.WrapSDKContext(ctx)
477
+ ctlCtx := &vm.ControllerContext{Context: ctx}
478
478
 
479
479
  ret, err := ch.Receive(ctlCtx, `{
480
480
  "type": "VBANK_GRAB",
@@ -787,7 +787,7 @@ func Test_Module_Account(t *testing.T) {
787
787
  keeper, ctx := makeTestKit(acct, nil)
788
788
  am := AppModule{keeper: keeper}
789
789
  ch := NewPortHandler(am, keeper)
790
- ctlCtx := sdk.WrapSDKContext(ctx)
790
+ ctlCtx := &vm.ControllerContext{Context: ctx}
791
791
 
792
792
  mod1 := "vbank/reserve"
793
793
  ret, err := ch.Receive(ctlCtx, `{
package/x/vibc/ibc.go CHANGED
@@ -1,7 +1,6 @@
1
1
  package vibc
2
2
 
3
3
  import (
4
- "context"
5
4
  "encoding/json"
6
5
  "fmt"
7
6
 
@@ -64,9 +63,8 @@ func NewIBCModule(keeper Keeper) IBCModule {
64
63
  }
65
64
  }
66
65
 
67
- func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err error) {
66
+ func (ch IBCModule) Receive(ctx *vm.ControllerContext, str string) (ret string, err error) {
68
67
  // fmt.Println("ibc.go downcall", str)
69
- ctx := sdk.UnwrapSDKContext(cctx)
70
68
  keeper := ch.keeper
71
69
 
72
70
  msg := new(portMessage)
@@ -82,7 +80,7 @@ func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err e
82
80
  switch msg.Method {
83
81
  case "sendPacket":
84
82
  seq, ok := keeper.GetNextSequenceSend(
85
- ctx,
83
+ ctx.Context,
86
84
  msg.Packet.SourcePort,
87
85
  msg.Packet.SourceChannel,
88
86
  )
@@ -93,7 +91,7 @@ func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err e
93
91
  timeoutTimestamp := msg.Packet.TimeoutTimestamp
94
92
  if msg.Packet.TimeoutHeight.IsZero() && msg.Packet.TimeoutTimestamp == 0 {
95
93
  // Use the relative timeout if no absolute timeout is specifiied.
96
- timeoutTimestamp = uint64(ctx.BlockTime().UnixNano()) + msg.RelativeTimeoutNs
94
+ timeoutTimestamp = uint64(ctx.Context.BlockTime().UnixNano()) + msg.RelativeTimeoutNs
97
95
  }
98
96
 
99
97
  packet := channeltypes.NewPacket(
@@ -102,7 +100,7 @@ func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err e
102
100
  msg.Packet.DestinationPort, msg.Packet.DestinationChannel,
103
101
  msg.Packet.TimeoutHeight, timeoutTimestamp,
104
102
  )
105
- err = keeper.SendPacket(ctx, packet)
103
+ err = keeper.SendPacket(ctx.Context, packet)
106
104
  if err == nil {
107
105
  bytes, err := json.Marshal(&packet)
108
106
  if err == nil {
@@ -111,14 +109,14 @@ func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err e
111
109
  }
112
110
 
113
111
  case "receiveExecuted":
114
- err = keeper.WriteAcknowledgement(ctx, msg.Packet, msg.Ack)
112
+ err = keeper.WriteAcknowledgement(ctx.Context, msg.Packet, msg.Ack)
115
113
  if err == nil {
116
114
  ret = "true"
117
115
  }
118
116
 
119
117
  case "startChannelOpenInit":
120
118
  err = keeper.ChanOpenInit(
121
- ctx, stringToOrder(msg.Order), msg.Hops,
119
+ ctx.Context, stringToOrder(msg.Order), msg.Hops,
122
120
  msg.Packet.SourcePort,
123
121
  msg.Packet.DestinationPort,
124
122
  msg.Version,
@@ -128,19 +126,19 @@ func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err e
128
126
  }
129
127
 
130
128
  case "startChannelCloseInit":
131
- err = keeper.ChanCloseInit(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
129
+ err = keeper.ChanCloseInit(ctx.Context, msg.Packet.SourcePort, msg.Packet.SourceChannel)
132
130
  if err == nil {
133
131
  ret = "true"
134
132
  }
135
133
 
136
134
  case "bindPort":
137
- err = keeper.BindPort(ctx, msg.Packet.SourcePort)
135
+ err = keeper.BindPort(ctx.Context, msg.Packet.SourcePort)
138
136
  if err == nil {
139
137
  ret = "true"
140
138
  }
141
139
 
142
140
  case "timeoutExecuted":
143
- err = keeper.TimeoutExecuted(ctx, msg.Packet)
141
+ err = keeper.TimeoutExecuted(ctx.Context, msg.Packet)
144
142
  if err == nil {
145
143
  ret = "true"
146
144
  }
@@ -230,6 +228,7 @@ type channelOpenAckEvent struct {
230
228
  Event string `json:"event"` // channelOpenAck
231
229
  PortID string `json:"portID"`
232
230
  ChannelID string `json:"channelID"`
231
+ CounterpartyChannelID string `json:"counterpartyChannelID"`
233
232
  CounterpartyVersion string `json:"counterpartyVersion"`
234
233
  Counterparty channeltypes.Counterparty `json:"counterparty"`
235
234
  ConnectionHops []string `json:"connectionHops"`
@@ -248,12 +247,12 @@ func (im IBCModule) OnChanOpenAck(
248
247
  // returns an empty channel object that we can still use without crashing.
249
248
  channel, _ := im.keeper.GetChannel(ctx, portID, channelID)
250
249
 
251
- channel.Counterparty.ChannelId = counterpartyChannelID
252
250
  event := channelOpenAckEvent{
253
251
  Type: "IBC_EVENT",
254
252
  Event: "channelOpenAck",
255
253
  PortID: portID,
256
254
  ChannelID: channelID,
255
+ CounterpartyChannelID: counterpartyChannelID,
257
256
  CounterpartyVersion: counterpartyVersion,
258
257
  Counterparty: channel.Counterparty,
259
258
  ConnectionHops: channel.ConnectionHops,
@@ -92,7 +92,13 @@ func (k Keeper) ChanOpenInit(ctx sdk.Context, order channeltypes.Order, connecti
92
92
  return err
93
93
  }
94
94
 
95
- k.channelKeeper.WriteOpenInitChannel(ctx, portID, channelID, order, connectionHops, counterparty, version)
95
+ // We need to emit a channel event to notify the relayer.
96
+ ctx.EventManager().EmitEvents(sdk.Events{
97
+ sdk.NewEvent(
98
+ sdk.EventTypeMessage,
99
+ sdk.NewAttribute(sdk.AttributeKeyModule, channeltypes.AttributeValueCategory),
100
+ ),
101
+ })
96
102
  return nil
97
103
  }
98
104
 
@@ -151,6 +157,14 @@ func (k Keeper) ChanCloseInit(ctx sdk.Context, portID, channelID string) error {
151
157
  if err != nil {
152
158
  return err
153
159
  }
160
+
161
+ // We need to emit a channel event to notify the relayer.
162
+ ctx.EventManager().EmitEvents(sdk.Events{
163
+ sdk.NewEvent(
164
+ sdk.EventTypeMessage,
165
+ sdk.NewAttribute(sdk.AttributeKeyModule, channeltypes.AttributeValueCategory),
166
+ ),
167
+ })
154
168
  return nil
155
169
  }
156
170
 
@@ -16,8 +16,7 @@ type ChannelKeeper interface {
16
16
  WriteAcknowledgement(ctx sdk.Context, channelCap *capability.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error
17
17
  ChanOpenInit(ctx sdk.Context, order channel.Order, connectionHops []string, portID string,
18
18
  portCap *capability.Capability, counterparty channel.Counterparty, version string) (string, *capability.Capability, error)
19
- WriteOpenInitChannel(ctx sdk.Context, portID, channelID string, order channel.Order,
20
- connectionHops []string, counterparty channel.Counterparty, version string)
19
+
21
20
  ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capability.Capability) error
22
21
  TimeoutExecuted(ctx sdk.Context, channelCap *capability.Capability, packet ibcexported.PacketI) error
23
22
  }
@@ -2,14 +2,10 @@ package keeper
2
2
 
3
3
  import (
4
4
  "context"
5
- "encoding/json"
6
- "fmt"
7
- "strings"
8
5
 
9
6
  "google.golang.org/grpc/codes"
10
7
  "google.golang.org/grpc/status"
11
8
 
12
- "github.com/Agoric/agoric-sdk/golang/cosmos/x/vstorage/capdata"
13
9
  "github.com/Agoric/agoric-sdk/golang/cosmos/x/vstorage/types"
14
10
  sdk "github.com/cosmos/cosmos-sdk/types"
15
11
  )
@@ -21,11 +17,6 @@ type Querier struct {
21
17
 
22
18
  var _ types.QueryServer = Querier{}
23
19
 
24
- // ===================================================================
25
- // /agoric.vstorage.Query/Data
26
- // ===================================================================
27
-
28
- // /agoric.vstorage.Query/Data returns data for a specified path.
29
20
  func (k Querier) Data(c context.Context, req *types.QueryDataRequest) (*types.QueryDataResponse, error) {
30
21
  if req == nil {
31
22
  return nil, status.Error(codes.InvalidArgument, "empty request")
@@ -39,218 +30,6 @@ func (k Querier) Data(c context.Context, req *types.QueryDataRequest) (*types.Qu
39
30
  }, nil
40
31
  }
41
32
 
42
- // ===================================================================
43
- // /agoric.vstorage.Query/CapData
44
- // ===================================================================
45
-
46
- const (
47
- // Media types.
48
- JSONLines = "JSON Lines"
49
-
50
- // CapData transformation formats.
51
- FormatCapDataFlat = "flat"
52
-
53
- // CapData remotable value formats.
54
- FormatRemotableAsObject = "object"
55
- FormatRemotableAsString = "string"
56
- )
57
-
58
- var capDataResponseMediaTypes = map[string]string{
59
- JSONLines: JSONLines,
60
- // Default to JSON Lines.
61
- "": JSONLines,
62
- }
63
- var capDataTransformationFormats = map[string]string{
64
- FormatCapDataFlat: FormatCapDataFlat,
65
- // Default to no transformation.
66
- "": "",
67
- }
68
- var capDataRemotableValueFormats = map[string]string{
69
- FormatRemotableAsObject: FormatRemotableAsObject,
70
- FormatRemotableAsString: FormatRemotableAsString,
71
- // No default because both formats are lossy.
72
- }
73
-
74
- // flatten converts data into a flat structure in which each deep leaf entry is replaced with
75
- // a top-level entry having the same value but a key generated by joining the keys on its path
76
- // with separating dashes.
77
- // For example,
78
- // ```
79
- // { "contacts": [
80
- //
81
- // { "name": "Alice", "email": "a@example.com" },
82
- // { "name": "Bob", "email": "b@example.com" }
83
- //
84
- // ] }
85
- // ```
86
- // becomes
87
- // ```
88
- //
89
- // {
90
- // "contacts-0-name": "Alice",
91
- // "contacts-0-email": "a@example.com",
92
- // "contacts-1-name": "Bob",
93
- // "contacts-1-email": "b@example.com"
94
- // }
95
- //
96
- // ```
97
- // cf. https://github.com/Agoric/agoric-sdk/blob/6e5b422b80e47c4dac151404f43faea5ab41e9b0/scripts/get-flattened-publication.sh
98
- func flatten(input interface{}, output map[string]interface{}, key string, top bool) error {
99
- // Act on the raw representation of a Remotable.
100
- if remotable, ok := input.(*capdata.CapdataRemotable); ok {
101
- var replacement interface{}
102
- repr, err := capdata.JsonMarshal(remotable)
103
- if err == nil {
104
- err = json.Unmarshal(repr, &replacement)
105
- }
106
- if err != nil {
107
- return err
108
- }
109
- input = replacement
110
- }
111
-
112
- childKeyPrefix := key
113
- if !top {
114
- childKeyPrefix = childKeyPrefix + "-"
115
- }
116
- if arr, ok := input.([]interface{}); ok {
117
- for i, v := range arr {
118
- if err := flatten(v, output, childKeyPrefix+fmt.Sprintf("%d", i), false); err != nil {
119
- return err
120
- }
121
- }
122
- } else if obj, ok := input.(map[string]interface{}); ok {
123
- for k, v := range obj {
124
- if err := flatten(v, output, childKeyPrefix+k, false); err != nil {
125
- return err
126
- }
127
- }
128
- } else {
129
- if _, has := output[key]; has {
130
- return fmt.Errorf("key conflict: %q", key)
131
- }
132
- output[key] = input
133
- }
134
- return nil
135
- }
136
-
137
- // capdataBigintToDigits represents a bigint as a string consisting of
138
- // an optional "-" followed by a sequence of digits with no extraneous zeroes
139
- // (e.g., "0" or "-40").
140
- func capdataBigintToDigits(bigint *capdata.CapdataBigint) interface{} {
141
- return bigint.Normalized
142
- }
143
-
144
- // capdataRemotableToString represents a Remotable as a bracketed string
145
- // containing its alleged name and id from `slots`
146
- // (e.g., "[Alleged: IST brand <board007>]").
147
- func capdataRemotableToString(r *capdata.CapdataRemotable) interface{} {
148
- iface := "Remotable"
149
- if r.Iface != nil || *r.Iface != "" {
150
- iface = *r.Iface
151
- }
152
- return fmt.Sprintf("[%s <%s>]", iface, r.Id)
153
- }
154
-
155
- // capdataRemotableToObject represents a Remotable as an object containing
156
- // its id from `slots` and its alleged name minus any "Alleged:" prefix
157
- // (e.g., `{ "id": "board007", "allegedName": "IST brand" }`).
158
- func capdataRemotableToObject(r *capdata.CapdataRemotable) interface{} {
159
- iface := "Remotable"
160
- if r.Iface != nil || *r.Iface != "" {
161
- iface = *r.Iface
162
- iface, _ = strings.CutPrefix(iface, "Alleged: ")
163
- }
164
- return map[string]interface{}{"id": r.Id, "allegedName": iface}
165
- }
166
-
167
- // /agoric.vstorage.Query/CapData returns data for a specified path,
168
- // interpreted as CapData in a StreamCell (auto-promoting isolated CapData
169
- // into a single-item StreamCell) and transformed as specified.
170
- func (k Querier) CapData(c context.Context, req *types.QueryCapDataRequest) (*types.QueryCapDataResponse, error) {
171
- if req == nil {
172
- return nil, status.Error(codes.InvalidArgument, "empty request")
173
- }
174
- ctx := sdk.UnwrapSDKContext(c)
175
-
176
- valueTransformations := capdata.CapdataValueTransformations{
177
- Bigint: capdataBigintToDigits,
178
- }
179
-
180
- // A response Value is "<prefix><separator-joined items><suffix>".
181
- prefix, separator, suffix := "", "\n", ""
182
-
183
- // Read options.
184
- mediaType, ok := capDataResponseMediaTypes[req.MediaType]
185
- if !ok {
186
- return nil, status.Error(codes.InvalidArgument, "invalid media_type")
187
- }
188
- transformation, ok := capDataTransformationFormats[req.ItemFormat]
189
- if !ok {
190
- return nil, status.Error(codes.InvalidArgument, "invalid item_format")
191
- }
192
- switch remotableFormat, ok := capDataRemotableValueFormats[req.RemotableValueFormat]; {
193
- case !ok:
194
- return nil, status.Error(codes.InvalidArgument, "invalid remotable_value_format")
195
- case remotableFormat == FormatRemotableAsObject:
196
- valueTransformations.Remotable = capdataRemotableToObject
197
- case remotableFormat == FormatRemotableAsString:
198
- valueTransformations.Remotable = capdataRemotableToString
199
- }
200
-
201
- // Read data, auto-upgrading a standalone value to a single-value StreamCell.
202
- entry := k.GetEntry(ctx, req.Path)
203
- if !entry.HasValue() {
204
- return nil, status.Error(codes.FailedPrecondition, "no data")
205
- }
206
- value := entry.StringValue()
207
- var cell StreamCell
208
- _ = json.Unmarshal([]byte(value), &cell)
209
- if cell.BlockHeight == "" {
210
- cell = StreamCell{Values: []string{value}}
211
- }
212
-
213
- // Format each StreamCell value.
214
- responseItems := make([]string, len(cell.Values))
215
- for i, capDataJson := range cell.Values {
216
- item, err := capdata.DecodeSerializedCapdata(capDataJson, valueTransformations)
217
- if err != nil {
218
- return nil, status.Error(codes.FailedPrecondition, err.Error())
219
- }
220
- if transformation == FormatCapDataFlat {
221
- flattened := map[string]interface{}{}
222
- if err := flatten(item, flattened, "", true); err != nil {
223
- return nil, status.Error(codes.Internal, err.Error())
224
- }
225
- // Replace the item, unless it was a scalar that "flattened" to `{ "": ... }`.
226
- if _, singleton := flattened[""]; !singleton {
227
- item = flattened
228
- }
229
- }
230
- switch mediaType {
231
- case JSONLines:
232
- jsonText, err := capdata.JsonMarshal(item)
233
- if err != nil {
234
- return nil, status.Error(codes.Internal, err.Error())
235
- }
236
- responseItems[i] = string(jsonText)
237
- }
238
- }
239
-
240
- return &types.QueryCapDataResponse{
241
- BlockHeight: cell.BlockHeight,
242
- Value: prefix + strings.Join(responseItems, separator) + suffix,
243
- }, nil
244
- }
245
-
246
- // ===================================================================
247
- // /agoric.vstorage.Query/Children
248
- // ===================================================================
249
-
250
- // /agoric.vstorage.Query/Children returns the list of path segments
251
- // that exist immediately underneath a specified path, including
252
- // those corresponding with "empty non-terminals" having children
253
- // but no data of their own.
254
33
  func (k Querier) Children(c context.Context, req *types.QueryChildrenRequest) (*types.QueryChildrenResponse, error) {
255
34
  if req == nil {
256
35
  return nil, status.Error(codes.InvalidArgument, "empty request")
@@ -1,6 +1,8 @@
1
1
  package keeper
2
2
 
3
3
  import (
4
+ "strings"
5
+
4
6
  abci "github.com/tendermint/tendermint/abci/types"
5
7
 
6
8
  "github.com/cosmos/cosmos-sdk/codec"
@@ -16,36 +18,14 @@ const (
16
18
  QueryChildren = "children"
17
19
  )
18
20
 
19
- // getVstorageEntryPath validates that a request URL path represents a valid
20
- // entry path with no extra data, and returns the path of that vstorage entry.
21
- func getVstorageEntryPath(urlPathSegments []string) (string, error) {
22
- if len(urlPathSegments) != 1 || types.ValidatePath(urlPathSegments[0]) != nil {
23
- return "", sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid vstorage entry path")
24
- }
25
- return urlPathSegments[0], nil
26
- }
27
-
28
- // NewQuerier returns the function for handling queries routed to this module.
29
- // It performs its own routing based on the first slash-separated URL path
30
- // segment (e.g., URL path `/data/foo.bar` is a request for the value associated
31
- // with vstorage path "foo.bar", and `/children/foo.bar` is a request for the
32
- // child path segments immediately underneath vstorage path "foo.bar" which may
33
- // be used to extend it to a vstorage path such as "foo.bar.baz").
21
+ // NewQuerier is the module level router for state queries
34
22
  func NewQuerier(keeper Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier {
35
- return func(ctx sdk.Context, urlPathSegments []string, req abci.RequestQuery) (res []byte, err error) {
36
- switch urlPathSegments[0] {
23
+ return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err error) {
24
+ switch path[0] {
37
25
  case QueryData:
38
- entryPath, entryPathErr := getVstorageEntryPath(urlPathSegments[1:])
39
- if entryPathErr != nil {
40
- return nil, entryPathErr
41
- }
42
- return queryData(ctx, entryPath, req, keeper, legacyQuerierCdc)
26
+ return queryData(ctx, strings.Join(path[1:], "/"), req, keeper, legacyQuerierCdc)
43
27
  case QueryChildren:
44
- entryPath, entryPathErr := getVstorageEntryPath(urlPathSegments[1:])
45
- if entryPathErr != nil {
46
- return nil, entryPathErr
47
- }
48
- return queryChildren(ctx, entryPath, req, keeper, legacyQuerierCdc)
28
+ return queryChildren(ctx, strings.Join(path[1:], "/"), req, keeper, legacyQuerierCdc)
49
29
  default:
50
30
  return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown vstorage query endpoint")
51
31
  }
@@ -56,12 +36,12 @@ func NewQuerier(keeper Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier
56
36
  func queryData(ctx sdk.Context, path string, req abci.RequestQuery, keeper Keeper, legacyQuerierCdc *codec.LegacyAmino) (res []byte, err error) {
57
37
  entry := keeper.GetEntry(ctx, path)
58
38
  if !entry.HasValue() {
59
- return nil, sdkerrors.Wrap(sdkerrors.ErrNotFound, "no data for vstorage path")
39
+ return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "could not get vstorage path")
60
40
  }
61
41
 
62
- bz, marshalErr := codec.MarshalJSONIndent(legacyQuerierCdc, types.Data{Value: entry.StringValue()})
63
- if marshalErr != nil {
64
- return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, marshalErr.Error())
42
+ bz, err2 := codec.MarshalJSONIndent(legacyQuerierCdc, types.Data{Value: entry.StringValue()})
43
+ if err2 != nil {
44
+ return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err2.Error())
65
45
  }
66
46
 
67
47
  return bz, nil
@@ -7,17 +7,9 @@ import (
7
7
  "strings"
8
8
  )
9
9
 
10
- // - A "path" is a sequence of zero or more dot-separated nonempty segments
11
- // using a restricted alphabet of ASCII alphanumerics plus underscore and dash,
12
- // consistent with packages/internal/src/lib-chainStorage.js but not currently
13
- // enforcing a length restriction on path segments.
14
- // So `""`, `"foo"`, and `"foo.bar__baz.qux--quux"` are paths but `"."`,
15
- // `"foo/bar"`, `"fo\to"`, and `"foö"` are not.
16
- // This alphabet might be expanded in the future, but such expansion SHOULD NOT
17
- // include control characters (including those that are not ASCII, such as
18
- // U+202E RIGHT-TO-LEFT OVERRIDE), slash `/` (which separates ABCI request path
19
- // segments in e.g. `custom/vstorage/data/foo`), or backslash `\` (which should
20
- // be reserved for adding escape sequences).
10
+ // - A "path" is a sequence of zero or more dot-separated nonempty strings of
11
+ // 7-bit non-nul, non-dot ASCII characters. So `""`, `"foo"`, and
12
+ // `"foo.bar.baz"` are paths but `"."`, "foo.", and "fo\0o" are not.
21
13
  //
22
14
  // - An encoded key for a path is the path prefixed with its length (in ASCII
23
15
  // digits), separated by nul, followed by the path with dots replaced with nul.
@@ -50,26 +42,22 @@ func EncodedKeyToPath(key []byte) string {
50
42
  return string(pathBytes)
51
43
  }
52
44
 
53
- var pathSegmentPattern = `[a-zA-Z0-9_-]+`
54
- var pathSeparatorPattern = `\` + PathSeparator
55
- var pathPattern = fmt.Sprintf(`^$|^%[1]s(%[2]s%[1]s)*$`, pathSegmentPattern, pathSeparatorPattern)
56
- var pathMatcher = regexp.MustCompile(pathPattern)
45
+ var pathPattern = regexp.MustCompile(`[-a-zA-Z0-9_` + PathSeparator + `]*`)
57
46
 
58
47
  func ValidatePath(path string) error {
59
- if pathMatcher.MatchString(path) {
60
- return nil
48
+ if !pathPattern.MatchString(path) {
49
+ return fmt.Errorf("path %q contains invalid characters", path)
50
+ }
51
+ if strings.Contains(path, PathSeparator+PathSeparator) {
52
+ return fmt.Errorf("path %q contains doubled separators", path)
61
53
  }
62
- // Rescan the string to give a useful error message.
63
54
  if strings.HasPrefix(path, PathSeparator) {
64
55
  return fmt.Errorf("path %q starts with separator", path)
65
56
  }
66
57
  if strings.HasSuffix(path, PathSeparator) {
67
58
  return fmt.Errorf("path %q ends with separator", path)
68
59
  }
69
- if strings.Contains(path, PathSeparator+PathSeparator) {
70
- return fmt.Errorf("path %q contains doubled separators", path)
71
- }
72
- return fmt.Errorf("path %q contains invalid characters", path)
60
+ return nil
73
61
  }
74
62
 
75
63
  // PathToEncodedKey converts a path to a byte slice key
@@ -2,106 +2,40 @@ package types
2
2
 
3
3
  import (
4
4
  "bytes"
5
- "fmt"
6
- "strings"
7
5
  "testing"
8
6
  )
9
7
 
10
8
  func Test_Key_Encoding(t *testing.T) {
11
9
  tests := []struct {
12
- name string
13
- path string
14
- key []byte
15
- errContains string
10
+ name string
11
+ childStr string
12
+ key []byte
16
13
  }{
17
14
  {
18
- name: "empty path",
19
- path: "",
20
- key: []byte("0\x00"),
15
+ name: "empty key is prefixed",
16
+ childStr: "",
17
+ key: []byte("0\x00"),
21
18
  },
22
19
  {
23
- name: "single-segment path",
24
- path: "some",
25
- key: []byte("1\x00some"),
20
+ name: "some key string",
21
+ childStr: "some",
22
+ key: []byte("1\x00some"),
26
23
  },
27
24
  {
28
- name: "multi-segment path",
29
- path: "some.child.grandchild",
30
- key: []byte("3\x00some\x00child\x00grandchild"),
31
- },
32
- {
33
- name: "non-letters",
34
- path: "-_0_-",
35
- key: []byte("1\x00-_0_-"),
36
- },
37
- {
38
- name: "lone dot",
39
- path: ".",
40
- errContains: "starts with separator",
41
- },
42
- {
43
- name: "starts with dot",
44
- path: ".foo",
45
- errContains: "starts with separator",
46
- },
47
- {
48
- name: "ends with dot",
49
- path: "foo.",
50
- errContains: "ends with separator",
51
- },
52
- {
53
- name: "empty path segment",
54
- path: "foo..bar",
55
- errContains: "doubled separators",
56
- },
57
- {
58
- name: "invalid path character U+0000 NUL",
59
- path: "foo\x00bar",
60
- errContains: "invalid character",
61
- },
62
- {
63
- name: "invalid path character U+002F SOLIDUS",
64
- path: "foo/bar",
65
- errContains: "invalid character",
66
- },
67
- {
68
- name: "invalid path character U+005C REVERSE SOLIDUS",
69
- path: "foo\\bar",
70
- errContains: "invalid character",
71
- },
72
- {
73
- name: "invalid path character U+007C VERTICAL LINE",
74
- path: "foo|bar",
75
- errContains: "invalid character",
25
+ name: "dot-separated",
26
+ childStr: "some.child.grandchild",
27
+ key: []byte("3\x00some\x00child\x00grandchild"),
76
28
  },
77
29
  }
78
30
 
79
31
  for _, tt := range tests {
80
- if tt.key != nil {
81
- t.Run(tt.name, func(t *testing.T) {
82
- if key := PathToEncodedKey(tt.path); !bytes.Equal(key, tt.key) {
83
- t.Errorf("pathToKey(%q) = []byte(%q), want []byte(%q)", tt.path, key, tt.key)
84
- }
85
- if path := EncodedKeyToPath(tt.key); path != tt.path {
86
- t.Errorf("keyToPath([]byte(%q)) = %q, want %q", tt.key, path, tt.path)
87
- }
88
- })
89
- continue
90
- }
91
- expect := tt.errContains
92
32
  t.Run(tt.name, func(t *testing.T) {
93
- var key []byte
94
- defer func() {
95
- if err := recover(); err != nil {
96
- errStr := fmt.Sprintf("%v", err)
97
- if !strings.Contains(errStr, expect) {
98
- t.Errorf("pathToKey(%q) = error %q, want error %v", tt.path, errStr, expect)
99
- }
100
- } else {
101
- t.Errorf("pathToKey(%q) = []byte(%q), want error %v", tt.path, key, expect)
102
- }
103
- }()
104
- key = PathToEncodedKey(tt.path)
33
+ if key := PathToEncodedKey(tt.childStr); !bytes.Equal(key, tt.key) {
34
+ t.Errorf("pathToKey(%q) = %v, want %v", tt.childStr, key, tt.key)
35
+ }
36
+ if childStr := EncodedKeyToPath(tt.key); childStr != tt.childStr {
37
+ t.Errorf("keyToString(%v) = %q, want %q", tt.key, childStr, tt.childStr)
38
+ }
105
39
  })
106
40
  }
107
41
  }