@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.
- package/CHANGELOG.md +45 -0
- package/app/app.go +103 -14
- package/app/const.go +6 -0
- package/cmd/agd/main.go +11 -133
- package/cmd/libdaemon/main.go +53 -67
- package/daemon/cmd/root.go +24 -55
- package/daemon/main.go +1 -3
- package/git-revision.txt +1 -1
- package/package.json +3 -3
- package/proto/agoric/vstorage/query.proto +1 -53
- package/vm/controller.go +18 -8
- package/x/lien/lien.go +4 -6
- package/x/lien/lien_test.go +15 -19
- package/x/swingset/abci.go +2 -3
- package/x/swingset/swingset.go +2 -4
- package/x/swingset/types/default-params.go +1 -1
- package/x/swingset/types/msgs.pb.go +16 -16
- package/x/vbank/vbank.go +10 -11
- package/x/vbank/vbank_test.go +5 -5
- package/x/vibc/ibc.go +11 -12
- package/x/vibc/keeper/keeper.go +15 -1
- package/x/vibc/types/expected_keepers.go +1 -2
- package/x/vstorage/keeper/grpc_query.go +0 -221
- package/x/vstorage/keeper/querier.go +11 -31
- package/x/vstorage/types/path_keys.go +10 -22
- package/x/vstorage/types/path_keys_test.go +18 -84
- package/x/vstorage/types/query.pb.go +36 -646
- package/x/vstorage/types/query.pb.gw.go +0 -119
- package/x/vstorage/vstorage.go +15 -16
- package/x/vstorage/vstorage_test.go +4 -4
- package/cmd/agd/agvm.go +0 -42
- package/vm/client.go +0 -113
- package/vm/client_test.go +0 -184
- package/vm/jsonrpcconn/jsonrpcconn.go +0 -160
- package/vm/jsonrpcconn/jsonrpcconn_test.go +0 -126
- package/vm/server.go +0 -23
- package/x/vstorage/README.md +0 -95
- package/x/vstorage/capdata/capdata.go +0 -298
- package/x/vstorage/capdata/capdata_test.go +0 -352
- package/x/vstorage/keeper/keeper_grpc_test.go +0 -300
package/x/vbank/vbank_test.go
CHANGED
|
@@ -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 :=
|
|
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 :=
|
|
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 :=
|
|
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 :=
|
|
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 :=
|
|
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(
|
|
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,
|
package/x/vibc/keeper/keeper.go
CHANGED
|
@@ -92,7 +92,13 @@ func (k Keeper) ChanOpenInit(ctx sdk.Context, order channeltypes.Order, connecti
|
|
|
92
92
|
return err
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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,
|
|
36
|
-
switch
|
|
23
|
+
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err error) {
|
|
24
|
+
switch path[0] {
|
|
37
25
|
case QueryData:
|
|
38
|
-
|
|
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
|
-
|
|
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.
|
|
39
|
+
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "could not get vstorage path")
|
|
60
40
|
}
|
|
61
41
|
|
|
62
|
-
bz,
|
|
63
|
-
if
|
|
64
|
-
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal,
|
|
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
|
|
11
|
-
//
|
|
12
|
-
//
|
|
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
|
|
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
|
|
60
|
-
return
|
|
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
|
-
|
|
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
|
|
13
|
-
|
|
14
|
-
key
|
|
15
|
-
errContains string
|
|
10
|
+
name string
|
|
11
|
+
childStr string
|
|
12
|
+
key []byte
|
|
16
13
|
}{
|
|
17
14
|
{
|
|
18
|
-
name:
|
|
19
|
-
|
|
20
|
-
key:
|
|
15
|
+
name: "empty key is prefixed",
|
|
16
|
+
childStr: "",
|
|
17
|
+
key: []byte("0\x00"),
|
|
21
18
|
},
|
|
22
19
|
{
|
|
23
|
-
name:
|
|
24
|
-
|
|
25
|
-
key:
|
|
20
|
+
name: "some key string",
|
|
21
|
+
childStr: "some",
|
|
22
|
+
key: []byte("1\x00some"),
|
|
26
23
|
},
|
|
27
24
|
{
|
|
28
|
-
name:
|
|
29
|
-
|
|
30
|
-
key:
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
}
|