@agoric/cosmos 0.35.0-upgrade-14-dev-8be87aa.0 → 0.35.0-upgrade-14-dev-c8f9e7b.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 (74) hide show
  1. package/Makefile +25 -12
  2. package/ante/ante.go +7 -5
  3. package/app/app.go +62 -47
  4. package/app/export.go +13 -6
  5. package/cmd/agd/main.go +5 -3
  6. package/cmd/libdaemon/main.go +5 -2
  7. package/daemon/cmd/genaccounts.go +13 -9
  8. package/daemon/cmd/root.go +27 -11
  9. package/daemon/cmd/root_test.go +1 -1
  10. package/daemon/cmd/testnet.go +17 -6
  11. package/daemon/main.go +3 -2
  12. package/git-revision.txt +1 -1
  13. package/go.mod +95 -64
  14. package/go.sum +592 -243
  15. package/package.json +2 -2
  16. package/proto/agoric/vstorage/query.proto +53 -1
  17. package/scripts/protocgen.sh +12 -1
  18. package/third_party/proto/buf.yaml +1 -0
  19. package/third_party/proto/cosmos/base/query/v1beta1/pagination.proto +4 -1
  20. package/third_party/proto/cosmos/base/v1beta1/coin.proto +7 -4
  21. package/third_party/proto/cosmos/upgrade/v1beta1/upgrade.proto +16 -6
  22. package/third_party/proto/cosmos_proto/cosmos.proto +97 -0
  23. package/third_party/proto/google/api/annotations.proto +1 -1
  24. package/third_party/proto/google/api/http.proto +181 -120
  25. package/third_party/proto/google/api/httpbody.proto +9 -6
  26. package/third_party/proto/google/protobuf/any.proto +1 -7
  27. package/third_party/proto/ibc/core/channel/v1/channel.proto +15 -1
  28. package/third_party/proto/ibc/core/client/v1/client.proto +9 -6
  29. package/upgradegaia.sh +13 -4
  30. package/vm/action.go +24 -21
  31. package/vm/action_test.go +5 -5
  32. package/vm/controller.go +9 -10
  33. package/x/lien/keeper/account.go +3 -3
  34. package/x/lien/keeper/keeper.go +5 -4
  35. package/x/lien/keeper/keeper_test.go +8 -8
  36. package/x/lien/lien.go +6 -4
  37. package/x/lien/lien_test.go +20 -16
  38. package/x/swingset/client/cli/query.go +2 -2
  39. package/x/swingset/client/cli/tx.go +48 -33
  40. package/x/swingset/client/proposal_handler.go +2 -17
  41. package/x/swingset/keeper/keeper.go +8 -11
  42. package/x/swingset/keeper/keeper_test.go +1 -1
  43. package/x/swingset/keeper/msg_server.go +2 -4
  44. package/x/swingset/keeper/proposal.go +10 -0
  45. package/x/swingset/keeper/querier.go +14 -6
  46. package/x/swingset/proposal_handler.go +3 -3
  47. package/x/swingset/swingset.go +4 -2
  48. package/x/swingset/types/codec.go +2 -2
  49. package/x/swingset/types/msgs.pb.go +16 -16
  50. package/x/swingset/types/proposal.go +5 -5
  51. package/x/swingset/types/types.go +30 -28
  52. package/x/vbank/keeper/keeper.go +3 -2
  53. package/x/vbank/keeper/querier.go +6 -2
  54. package/x/vbank/keeper/rewards.go +1 -1
  55. package/x/vbank/vbank.go +11 -10
  56. package/x/vbank/vbank_test.go +8 -8
  57. package/x/vibc/ibc.go +27 -26
  58. package/x/vibc/keeper/keeper.go +19 -18
  59. package/x/vibc/types/expected_keepers.go +13 -5
  60. package/x/vibc/types/msgs.go +1 -1
  61. package/x/vibc/types/msgs.pb.go +1 -1
  62. package/x/vstorage/README.md +138 -0
  63. package/x/vstorage/capdata/capdata.go +298 -0
  64. package/x/vstorage/capdata/capdata_test.go +352 -0
  65. package/x/vstorage/client/cli/query.go +51 -4
  66. package/x/vstorage/keeper/grpc_query.go +221 -0
  67. package/x/vstorage/keeper/keeper.go +3 -2
  68. package/x/vstorage/keeper/keeper_grpc_test.go +300 -0
  69. package/x/vstorage/keeper/keeper_test.go +1 -1
  70. package/x/vstorage/keeper/querier.go +6 -2
  71. package/x/vstorage/types/query.pb.go +646 -36
  72. package/x/vstorage/types/query.pb.gw.go +119 -0
  73. package/x/vstorage/vstorage.go +16 -15
  74. package/x/vstorage/vstorage_test.go +5 -5
package/x/vibc/ibc.go CHANGED
@@ -1,17 +1,18 @@
1
1
  package vibc
2
2
 
3
3
  import (
4
+ "context"
4
5
  "encoding/json"
5
6
  "fmt"
6
7
 
7
8
  "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
8
9
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
9
10
  capability "github.com/cosmos/cosmos-sdk/x/capability/types"
10
- channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
11
- porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types"
12
- host "github.com/cosmos/ibc-go/v4/modules/core/24-host"
11
+ channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
12
+ porttypes "github.com/cosmos/ibc-go/v6/modules/core/05-port/types"
13
+ host "github.com/cosmos/ibc-go/v6/modules/core/24-host"
13
14
 
14
- "github.com/cosmos/ibc-go/v4/modules/core/exported"
15
+ "github.com/cosmos/ibc-go/v6/modules/core/exported"
15
16
 
16
17
  sdk "github.com/cosmos/cosmos-sdk/types"
17
18
  )
@@ -63,8 +64,9 @@ func NewIBCModule(keeper Keeper) IBCModule {
63
64
  }
64
65
  }
65
66
 
66
- func (ch IBCModule) Receive(ctx *vm.ControllerContext, str string) (ret string, err error) {
67
+ func (ch IBCModule) Receive(cctx context.Context, str string) (ret string, err error) {
67
68
  // fmt.Println("ibc.go downcall", str)
69
+ ctx := sdk.UnwrapSDKContext(cctx)
68
70
  keeper := ch.keeper
69
71
 
70
72
  msg := new(portMessage)
@@ -79,29 +81,28 @@ func (ch IBCModule) Receive(ctx *vm.ControllerContext, str string) (ret string,
79
81
 
80
82
  switch msg.Method {
81
83
  case "sendPacket":
82
- seq, ok := keeper.GetNextSequenceSend(
83
- ctx.Context,
84
- msg.Packet.SourcePort,
85
- msg.Packet.SourceChannel,
86
- )
87
- if !ok {
88
- return "", fmt.Errorf("unknown sequence number")
89
- }
90
-
91
84
  timeoutTimestamp := msg.Packet.TimeoutTimestamp
92
85
  if msg.Packet.TimeoutHeight.IsZero() && msg.Packet.TimeoutTimestamp == 0 {
93
86
  // Use the relative timeout if no absolute timeout is specifiied.
94
- timeoutTimestamp = uint64(ctx.Context.BlockTime().UnixNano()) + msg.RelativeTimeoutNs
87
+ timeoutTimestamp = uint64(ctx.BlockTime().UnixNano()) + msg.RelativeTimeoutNs
95
88
  }
96
89
 
97
- packet := channeltypes.NewPacket(
98
- msg.Packet.Data, seq,
99
- msg.Packet.SourcePort, msg.Packet.SourceChannel,
100
- msg.Packet.DestinationPort, msg.Packet.DestinationChannel,
101
- msg.Packet.TimeoutHeight, timeoutTimestamp,
90
+ seq, err := keeper.SendPacket(
91
+ ctx,
92
+ msg.Packet.SourcePort,
93
+ msg.Packet.SourceChannel,
94
+ msg.Packet.TimeoutHeight,
95
+ timeoutTimestamp,
96
+ msg.Packet.Data,
102
97
  )
103
- err = keeper.SendPacket(ctx.Context, packet)
104
98
  if err == nil {
99
+ // synthesize the sent packet
100
+ packet := channeltypes.NewPacket(
101
+ msg.Packet.Data, seq,
102
+ msg.Packet.SourcePort, msg.Packet.SourceChannel,
103
+ msg.Packet.DestinationPort, msg.Packet.DestinationChannel,
104
+ msg.Packet.TimeoutHeight, timeoutTimestamp,
105
+ )
105
106
  bytes, err := json.Marshal(&packet)
106
107
  if err == nil {
107
108
  ret = string(bytes)
@@ -109,14 +110,14 @@ func (ch IBCModule) Receive(ctx *vm.ControllerContext, str string) (ret string,
109
110
  }
110
111
 
111
112
  case "receiveExecuted":
112
- err = keeper.WriteAcknowledgement(ctx.Context, msg.Packet, msg.Ack)
113
+ err = keeper.WriteAcknowledgement(ctx, msg.Packet, msg.Ack)
113
114
  if err == nil {
114
115
  ret = "true"
115
116
  }
116
117
 
117
118
  case "startChannelOpenInit":
118
119
  err = keeper.ChanOpenInit(
119
- ctx.Context, stringToOrder(msg.Order), msg.Hops,
120
+ ctx, stringToOrder(msg.Order), msg.Hops,
120
121
  msg.Packet.SourcePort,
121
122
  msg.Packet.DestinationPort,
122
123
  msg.Version,
@@ -126,19 +127,19 @@ func (ch IBCModule) Receive(ctx *vm.ControllerContext, str string) (ret string,
126
127
  }
127
128
 
128
129
  case "startChannelCloseInit":
129
- err = keeper.ChanCloseInit(ctx.Context, msg.Packet.SourcePort, msg.Packet.SourceChannel)
130
+ err = keeper.ChanCloseInit(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
130
131
  if err == nil {
131
132
  ret = "true"
132
133
  }
133
134
 
134
135
  case "bindPort":
135
- err = keeper.BindPort(ctx.Context, msg.Packet.SourcePort)
136
+ err = keeper.BindPort(ctx, msg.Packet.SourcePort)
136
137
  if err == nil {
137
138
  ret = "true"
138
139
  }
139
140
 
140
141
  case "timeoutExecuted":
141
- err = keeper.TimeoutExecuted(ctx.Context, msg.Packet)
142
+ err = keeper.TimeoutExecuted(ctx, msg.Packet)
142
143
  if err == nil {
143
144
  ret = "true"
144
145
  }
@@ -4,15 +4,17 @@ import (
4
4
  "fmt"
5
5
 
6
6
  "github.com/cosmos/cosmos-sdk/codec"
7
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
7
8
  sdk "github.com/cosmos/cosmos-sdk/types"
8
9
 
9
10
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
10
11
  capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
11
12
  capability "github.com/cosmos/cosmos-sdk/x/capability/types"
12
- channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
13
- porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types"
14
- host "github.com/cosmos/ibc-go/v4/modules/core/24-host"
15
- ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported"
13
+ clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
14
+ channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
15
+ porttypes "github.com/cosmos/ibc-go/v6/modules/core/05-port/types"
16
+ host "github.com/cosmos/ibc-go/v6/modules/core/24-host"
17
+ ibcexported "github.com/cosmos/ibc-go/v6/modules/core/exported"
16
18
 
17
19
  bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
18
20
 
@@ -22,7 +24,7 @@ import (
22
24
 
23
25
  // Keeper maintains the link to data storage and exposes getter/setter methods for the various parts of the state machine
24
26
  type Keeper struct {
25
- storeKey sdk.StoreKey
27
+ storeKey storetypes.StoreKey
26
28
  cdc codec.Codec
27
29
 
28
30
  channelKeeper types.ChannelKeeper
@@ -35,7 +37,7 @@ type Keeper struct {
35
37
 
36
38
  // NewKeeper creates a new dIBC Keeper instance
37
39
  func NewKeeper(
38
- cdc codec.Codec, key sdk.StoreKey,
40
+ cdc codec.Codec, key storetypes.StoreKey,
39
41
  channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper,
40
42
  bankKeeper bankkeeper.Keeper,
41
43
  scopedKeeper capabilitykeeper.ScopedKeeper,
@@ -57,12 +59,6 @@ func (k Keeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) s
57
59
  return k.bankKeeper.GetBalance(ctx, addr, denom)
58
60
  }
59
61
 
60
- // GetNextSequenceSend defines a wrapper function for the channel Keeper's function
61
- // in order to expose it to the vibc IBC handler.
62
- func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) {
63
- return k.channelKeeper.GetNextSequenceSend(ctx, portID, channelID)
64
- }
65
-
66
62
  // GetChannel defines a wrapper function for the channel Keeper's function
67
63
  // in order to expose it to the vibc IBC handler.
68
64
  func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (channeltypes.Channel, bool) {
@@ -98,15 +94,20 @@ func (k Keeper) ChanOpenInit(ctx sdk.Context, order channeltypes.Order, connecti
98
94
 
99
95
  // SendPacket defines a wrapper function for the channel Keeper's function
100
96
  // in order to expose it to the vibc IBC handler.
101
- func (k Keeper) SendPacket(ctx sdk.Context, packet ibcexported.PacketI) error {
102
- portID := packet.GetSourcePort()
103
- channelID := packet.GetSourceChannel()
104
- capName := host.ChannelCapabilityPath(portID, channelID)
97
+ func (k Keeper) SendPacket(
98
+ ctx sdk.Context,
99
+ sourcePort string,
100
+ sourceChannel string,
101
+ timeoutHeight clienttypes.Height,
102
+ timeoutTimestamp uint64,
103
+ data []byte,
104
+ ) (uint64, error) {
105
+ capName := host.ChannelCapabilityPath(sourcePort, sourceChannel)
105
106
  chanCap, ok := k.GetCapability(ctx, capName)
106
107
  if !ok {
107
- return sdkerrors.Wrapf(channeltypes.ErrChannelCapabilityNotFound, "could not retrieve channel capability at: %s", capName)
108
+ return 0, sdkerrors.Wrapf(channeltypes.ErrChannelCapabilityNotFound, "could not retrieve channel capability at: %s", capName)
108
109
  }
109
- return k.channelKeeper.SendPacket(ctx, chanCap, packet)
110
+ return k.channelKeeper.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data)
110
111
  }
111
112
 
112
113
  var _ ibcexported.Acknowledgement = (*rawAcknowledgement)(nil)
@@ -3,16 +3,24 @@ package types
3
3
  import (
4
4
  sdk "github.com/cosmos/cosmos-sdk/types"
5
5
  capability "github.com/cosmos/cosmos-sdk/x/capability/types"
6
- connection "github.com/cosmos/ibc-go/v4/modules/core/03-connection/types"
7
- channel "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
8
- ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported"
6
+ clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
7
+ connection "github.com/cosmos/ibc-go/v6/modules/core/03-connection/types"
8
+ channel "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
9
+ ibcexported "github.com/cosmos/ibc-go/v6/modules/core/exported"
9
10
  )
10
11
 
11
12
  // ChannelKeeper defines the expected IBC channel keeper
12
13
  type ChannelKeeper interface {
13
14
  GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channel.Channel, found bool)
14
- GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool)
15
- SendPacket(ctx sdk.Context, channelCap *capability.Capability, packet ibcexported.PacketI) error
15
+ SendPacket(
16
+ ctx sdk.Context,
17
+ channelCap *capability.Capability,
18
+ sourcePort string,
19
+ sourceChannel string,
20
+ timeoutHeight clienttypes.Height,
21
+ timeoutTimestamp uint64,
22
+ data []byte,
23
+ ) (uint64, error)
16
24
  WriteAcknowledgement(ctx sdk.Context, channelCap *capability.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error
17
25
  ChanOpenInit(ctx sdk.Context, order channel.Order, connectionHops []string, portID string,
18
26
  portCap *capability.Capability, counterparty channel.Counterparty, version string) (string, *capability.Capability, error)
@@ -4,7 +4,7 @@ import (
4
4
  sdk "github.com/cosmos/cosmos-sdk/types"
5
5
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
6
6
 
7
- chanTypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
7
+ chanTypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
8
8
  )
9
9
 
10
10
  const RouterKey = ModuleName // this was defined in your key.go file
@@ -7,7 +7,7 @@ import (
7
7
  context "context"
8
8
  fmt "fmt"
9
9
  github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
10
- types "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
10
+ types "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
11
11
  _ "github.com/gogo/protobuf/gogoproto"
12
12
  grpc1 "github.com/gogo/protobuf/grpc"
13
13
  proto "github.com/gogo/protobuf/proto"
@@ -0,0 +1,138 @@
1
+ # Virtual Storage
2
+
3
+ This module manages "[IAVL](https://github.com/cosmos/iavl)" chain storage data with a hierarchical keyspace in which each key is a "[path](./types/path_keys.go)" composed of zero or more dot-separated nonempty segments in a restricted alphabet. It exposes gRPC endpoints to arbitrary external clients for reading data, and internal read/write interfaces for use by SwingSet (which itself manages further subtree-scoped attenuation).
4
+
5
+ ## Internal Go interface
6
+
7
+ [Keeper](./keeper/keeper.go)
8
+ * generic
9
+ * GetChildren
10
+ * GetEntry
11
+ * HasEntry
12
+ * HasStorage
13
+ * SetStorage[AndNotify]
14
+ * StreamCell-oriented (a StreamCell captures a block height and an array of values)
15
+ * AppendStorageValue[AndNotify]
16
+ * queue-oriented (a queue stores items at paths like "$prefix.$n", documenting
17
+ the n for the next item to be consumed at "$prefix.head" and the n for the next
18
+ next item to be pushed at "$prefix.tail" such that the queue is empty when both
19
+ head and tail store the same n)
20
+ * GetQueueLength
21
+ * PushQueueItem
22
+
23
+ ## Internal JSON interface
24
+
25
+ This is used by the SwingSet "bridge".
26
+
27
+ [Receive](./vstorage.go) with input `{ "method": "...", "args": [...] }`
28
+ * generic
29
+ * method "entries", args path
30
+ * method "get"/"has", args path
31
+ * method "set"/"setWithoutNotify", args [[path, value?], ...]
32
+ * method "children", args path
33
+ * method "values", args path (returns values for children in the same order as method "children")
34
+ * method "size", args path (returns the count of children)
35
+ * StreamCell-oriented
36
+ * method "append", args [[path, value?], ...]
37
+
38
+ ## CLI
39
+
40
+ A blockchain node may be interrogated by RPC using `agd [--node $url] query vstorage path` via [client/cli](./client/cli/query.go). (See command help for options and variants `data` and `children`.)
41
+
42
+ Examples:
43
+ ```sh
44
+ $ agd --node https://main.rpc.agoric.net:443/ query vstorage path published.reserve.
45
+ children:
46
+ - governance
47
+ - metrics
48
+ pagination: null
49
+
50
+ $ agd --node https://main.rpc.agoric.net:443/ query vstorage path -o json published.reserve.
51
+ {"children":["governance","metrics"],"pagination":null}
52
+
53
+ $ agd --node https://main.rpc.agoric.net:443/ query vstorage path published.reserve.metrics
54
+ value: '{"blockHeight":"11030240","values":["{\"body\":\"#{\\\"allocations\\\":{\\\"Fee\\\":{\\\"brand\\\":\\\"$0.Alleged:
55
+ IST brand\\\",\\\"value\\\":\\\"+20053582387\\\"}},\\\"shortfallBalance\\\":{\\\"brand\\\":\\\"$0\\\",\\\"value\\\":\\\"+0\\\"},\\\"totalFeeBurned\\\":{\\\"brand\\\":\\\"$0\\\",\\\"value\\\":\\\"+0\\\"},\\\"totalFeeMinted\\\":{\\\"brand\\\":\\\"$0\\\",\\\"value\\\":\\\"+0\\\"}}\",\"slots\":[\"board0257\"]}"]}'
56
+ ```
57
+
58
+ ## External protobuf interface
59
+
60
+ RPC via [Querier](./keeper/grpc_query.go),
61
+ and [CometBFT method "abci_query"](https://docs.cometbft.com/main/rpc/#/ABCI/abci_query)
62
+ with params `path` "/agoric.vstorage.Query/..."
63
+ and `data` \<serialized protobuf per [vstorage/query.proto](../../proto/agoric/vstorage/query.proto)>
64
+ (also via [Querier](./keeper/grpc_query.go))
65
+ * /agoric.vstorage.Query/CapData
66
+ * /agoric.vstorage.Query/Children
67
+ * /agoric.vstorage.Query/Data
68
+
69
+ Example:
70
+ ```sh
71
+ $ curl -sS 'https://main.rpc.agoric.net/' -H 'Content-Type: application/json' -X POST --data "$(
72
+ jq -n --arg queryChildrenRequestHex 0a147075626c69736865642e636f6d6d697474656573 '{
73
+ id: 1,
74
+ method: "abci_query",
75
+ params: { path: "/agoric.vstorage.Query/Children", data: $queryChildrenRequestHex }
76
+ }' | \
77
+ tee /dev/stderr \
78
+ )" | \
79
+ jq . | \
80
+ tee /dev/stderr | \
81
+ jq -r '.result.response.value' | \
82
+ base64 -d | \
83
+ protoc -I golang/cosmos/proto/agoric/vstorage/ -I golang/cosmos/third_party/proto/ \
84
+ --decode=agoric.vstorage.QueryChildrenResponse golang/cosmos/proto/agoric/vstorage/query.proto
85
+ {
86
+ "id": 1,
87
+ "method": "abci_query",
88
+ "params": {
89
+ "path": "/agoric.vstorage.Query/Children",
90
+ "data": "0a147075626c69736865642e636f6d6d697474656573"
91
+ }
92
+ }
93
+ {
94
+ "jsonrpc": "2.0",
95
+ "id": 1,
96
+ "result": {
97
+ "response": {
98
+ "code": 0,
99
+ "log": "",
100
+ "info": "",
101
+ "index": "0",
102
+ "key": null,
103
+ "value": "ChJFY29ub21pY19Db21taXR0ZWUKCWtyZWFkLWdvdg==",
104
+ "proofOps": null,
105
+ "height": "12222836",
106
+ "codespace": ""
107
+ }
108
+ }
109
+ }
110
+ children: "Economic_Committee"
111
+ children: "kread-gov"
112
+ ```
113
+
114
+ ## External JSON interface
115
+
116
+ As described at [Cosmos SDK: Using the REST Endpoints](https://docs.cosmos.network/main/run-node/interact-node#using-the-rest-endpoints), a blockchain node whose [`app.toml` configuration](https://docs.cosmos.network/main/run-node/run-node#configuring-the-node-using-apptoml-and-configtoml) enables the "REST" API server uses [gRPC-Gateway](https://grpc-ecosystem.github.io/grpc-gateway/) and `google.api.http` annotations in [vstorage/query.proto](../../proto/agoric/vstorage/query.proto) to automatically translate the protobuf-based RPC endpoints into URL paths that accept query parameters and emit JSON.
117
+ * /agoric/vstorage/capdata/$path?remotableValueFormat={object,string}[&mediaType=JSON%20Lines][&itemFormat=flat]
118
+ * /agoric/vstorage/children/$path
119
+ * /agoric/vstorage/data/$path
120
+
121
+ Example:
122
+ ```sh
123
+ $ curl -sS 'https://main.api.agoric.net/agoric/vstorage/children/published.committees'
124
+ {
125
+ "children": [
126
+ "Economic_Committee"
127
+ ],
128
+ "pagination": null
129
+ }
130
+ ```
131
+
132
+ ## Arbitrary-response HTTP interface
133
+
134
+ This depends upon appModule `LegacyQuerierHandler` functionality that is [removed from cosmos-sdk as of v0.47](https://github.com/cosmos/cosmos-sdk/blob/fa4d87ef7e6d87aaccc94c337ffd2fe90fcb7a9d/CHANGELOG.md#api-breaking-changes-3)
135
+
136
+ [legacy querier](./keeper/querier.go)
137
+ * /custom/vstorage/children/$path
138
+ * /custom/vstorage/data/$path
@@ -0,0 +1,298 @@
1
+ package capdata
2
+
3
+ import (
4
+ "bytes"
5
+ "encoding/json"
6
+ "fmt"
7
+ "regexp"
8
+ "strconv"
9
+ "strings"
10
+ )
11
+
12
+ // JsonMarshal returns JSON text representing its input,
13
+ // without special replacement of "<", ">", "&", U+2028, or U+2029.
14
+ func JsonMarshal(val any) ([]byte, error) {
15
+ buf := &bytes.Buffer{}
16
+ encoder := json.NewEncoder(buf)
17
+ encoder.SetEscapeHTML(false)
18
+ if err := encoder.Encode(val); err != nil {
19
+ return nil, err
20
+ }
21
+ // Return without a trailing line feed.
22
+ lineTerminatedJson := buf.Bytes()
23
+ return bytes.TrimSuffix(lineTerminatedJson, []byte("\n")), nil
24
+ }
25
+
26
+ // cf. https://github.com/endojs/endo/tree/master/packages/marshal
27
+
28
+ type Capdata struct {
29
+ Body string `json:"body"`
30
+ Slots []interface{} `json:"slots"`
31
+ }
32
+
33
+ var validBigint = regexp.MustCompile(`^-?(?:0|[1-9][0-9]*)$`)
34
+
35
+ type CapdataBigint struct {
36
+ Normalized string
37
+ }
38
+
39
+ type CapdataRemotable struct {
40
+ Id interface{}
41
+ Iface *string
42
+ Representation interface{}
43
+ }
44
+
45
+ func NewCapdataBigint(str string) *CapdataBigint {
46
+ if !validBigint.MatchString(str) {
47
+ return nil
48
+ }
49
+ bigint := CapdataBigint{str}
50
+ return &bigint
51
+ }
52
+
53
+ func (r *CapdataRemotable) MarshalJSON() ([]byte, error) {
54
+ return JsonMarshal(r.Representation)
55
+ }
56
+
57
+ type CapdataValueTransformations struct {
58
+ Bigint func(*CapdataBigint) interface{}
59
+ Remotable func(*CapdataRemotable) interface{}
60
+ }
61
+
62
+ // upsertCapdataRemotable either adds a new CapdataRemotable to `remotables` at the specified
63
+ // slot index or updates the iface of the value that is already there, ensuring lack of iface name
64
+ // inconsistency (iteration order is not guaranteed to correspond with JSON text like it does in
65
+ // JavaScript, so we must accept encountering the "first" reference to a slot late
66
+ // and must therefore also defer transformations).
67
+ func upsertCapdataRemotable(remotables map[uint64]*CapdataRemotable, slotIndex uint64, id interface{}, iface *string) (*CapdataRemotable, error) {
68
+ r := remotables[slotIndex]
69
+ if r == nil {
70
+ r = new(CapdataRemotable)
71
+ r.Id = id
72
+ r.Iface = iface
73
+ remotables[slotIndex] = r
74
+ } else if iface != nil {
75
+ if r.Iface != nil && *iface != *r.Iface {
76
+ return nil, fmt.Errorf("slot iface mismatch: %q", *iface)
77
+ }
78
+ r.Iface = iface
79
+ }
80
+ return r, nil
81
+ }
82
+
83
+ // decodeCapdataLegacyValue decodes the non-smallcaps encoding of
84
+ // https://github.com/endojs/endo/blob/master/packages/marshal/src/encodeToCapData.js
85
+ func decodeCapdataLegacyValue(
86
+ encoded interface{},
87
+ slots []interface{},
88
+ remotables map[uint64]*CapdataRemotable,
89
+ transformations CapdataValueTransformations,
90
+ ) (interface{}, error) {
91
+ if arr, ok := encoded.([]interface{}); ok {
92
+ for i, v := range arr {
93
+ decoded, err := decodeCapdataLegacyValue(v, slots, remotables, transformations)
94
+ if err != nil {
95
+ return nil, err
96
+ }
97
+ arr[i] = decoded
98
+ }
99
+ return arr, nil
100
+ } else if obj, ok := encoded.(map[string]interface{}); ok {
101
+ if qclassVal, ok := obj["@qclass"]; ok {
102
+ qclass, ok := qclassVal.(string)
103
+ if !ok {
104
+ return nil, fmt.Errorf("invalid @qclass: %q", qclassVal)
105
+ }
106
+ switch qclass {
107
+ case "bigint":
108
+ var bigint *CapdataBigint
109
+ digitsVal := obj["digits"]
110
+ if digitsStr, ok := digitsVal.(string); ok {
111
+ bigint = NewCapdataBigint(digitsStr)
112
+ }
113
+ if bigint == nil {
114
+ return nil, fmt.Errorf("invalid bigint: %q", digitsVal)
115
+ }
116
+ if transformations.Bigint == nil {
117
+ return nil, fmt.Errorf("untransformed bigint")
118
+ }
119
+ return transformations.Bigint(bigint), nil
120
+ case "slot":
121
+ var iface *string
122
+ slotIndexVal, ifaceVal := obj["index"], obj["iface"]
123
+ slotIndexNum, ok := slotIndexVal.(float64)
124
+ slotIndex := uint64(slotIndexNum)
125
+ if !ok || float64(slotIndex) != slotIndexNum || slotIndex >= uint64(len(slots)) {
126
+ return nil, fmt.Errorf("invalid slot index: %q", slotIndexVal)
127
+ }
128
+ if ifaceStr, ok := ifaceVal.(string); ok {
129
+ iface = &ifaceStr
130
+ } else if ifaceVal != nil {
131
+ return nil, fmt.Errorf("invalid slot iface: %q", ifaceVal)
132
+ }
133
+ return upsertCapdataRemotable(remotables, slotIndex, slots[slotIndex], iface)
134
+ case "hilbert":
135
+ fallthrough
136
+ case "undefined":
137
+ fallthrough
138
+ case "NaN":
139
+ fallthrough
140
+ case "Infinity":
141
+ fallthrough
142
+ case "symbol":
143
+ fallthrough
144
+ case "tagged":
145
+ fallthrough
146
+ case "error":
147
+ fallthrough
148
+ case "-Infinity":
149
+ return nil, fmt.Errorf("not implemented: @qclass %q", qclass)
150
+ default:
151
+ return nil, fmt.Errorf("unrecognized @qclass: %q", qclass)
152
+ }
153
+ }
154
+ for k, v := range obj {
155
+ decoded, err := decodeCapdataLegacyValue(v, slots, remotables, transformations)
156
+ if err != nil {
157
+ return nil, err
158
+ }
159
+ obj[k] = decoded
160
+ }
161
+ return obj, nil
162
+ } else {
163
+ return encoded, nil
164
+ }
165
+ }
166
+
167
+ // decodeCapdataSmallcapsValue decodes the "smallcaps" encoding from
168
+ // https://github.com/endojs/endo/blob/master/packages/marshal/src/encodeToSmallcaps.js
169
+ func decodeCapdataSmallcapsValue(
170
+ encoded interface{},
171
+ slots []interface{},
172
+ remotables map[uint64]*CapdataRemotable,
173
+ transformations CapdataValueTransformations,
174
+ ) (interface{}, error) {
175
+ if arr, ok := encoded.([]interface{}); ok {
176
+ for i, v := range arr {
177
+ decoded, err := decodeCapdataSmallcapsValue(v, slots, remotables, transformations)
178
+ if err != nil {
179
+ return nil, err
180
+ }
181
+ arr[i] = decoded
182
+ }
183
+ return arr, nil
184
+ } else if encodedObj, ok := encoded.(map[string]interface{}); ok {
185
+ if _, ok := encodedObj["#tag"]; ok {
186
+ return nil, fmt.Errorf("not implemented: #tag")
187
+ }
188
+ if _, ok := encodedObj["#error"]; ok {
189
+ return nil, fmt.Errorf("not implemented: #error")
190
+ }
191
+ // We need a distinct output map to avoid reprocessing already-decoded keys.
192
+ decodedObj := make(map[string]interface{}, len(encodedObj))
193
+ for encodedK, v := range encodedObj {
194
+ if strings.HasPrefix(encodedK, "#") {
195
+ return nil, fmt.Errorf("unrecognized record type: %q", encodedK)
196
+ }
197
+ decodedK, err := decodeCapdataSmallcapsValue(encodedK, slots, remotables, CapdataValueTransformations{})
198
+ k, ok := decodedK.(string)
199
+ if err != nil || !ok {
200
+ return nil, fmt.Errorf("invalid copyRecord key: %q", encodedK)
201
+ }
202
+ decoded, err := decodeCapdataSmallcapsValue(v, slots, remotables, transformations)
203
+ if err != nil {
204
+ return nil, err
205
+ }
206
+ decodedObj[k] = decoded
207
+ }
208
+ return decodedObj, nil
209
+ } else if str, ok := encoded.(string); ok {
210
+ if len(str) == 0 {
211
+ return str, nil
212
+ }
213
+ switch str[0] {
214
+ case '!':
215
+ return str[1:], nil
216
+ case '+':
217
+ // Normalize to no leading "+".
218
+ str = str[1:]
219
+ fallthrough
220
+ case '-':
221
+ bigint := NewCapdataBigint(str)
222
+ if bigint == nil {
223
+ return nil, fmt.Errorf("invalid bigint: %q", encoded.(string))
224
+ }
225
+ if transformations.Bigint == nil {
226
+ return nil, fmt.Errorf("untransformed bigint")
227
+ }
228
+ return transformations.Bigint(bigint), nil
229
+ case '$':
230
+ var slotIndexStr string
231
+ var iface *string
232
+ if dotIndex := strings.IndexByte(str, '.'); dotIndex >= 0 {
233
+ slotIndexStr = str[1:dotIndex]
234
+ ifaceStr := str[dotIndex+1:]
235
+ iface = &ifaceStr
236
+ } else {
237
+ slotIndexStr = str[1:]
238
+ }
239
+ slotIndex, err := strconv.ParseUint(slotIndexStr, 10, 0)
240
+ if err != nil || slotIndex >= uint64(len(slots)) {
241
+ return nil, fmt.Errorf("invalid slot index: %q", str)
242
+ }
243
+ r, err := upsertCapdataRemotable(remotables, slotIndex, slots[slotIndex], iface)
244
+ if err != nil {
245
+ return nil, fmt.Errorf("slot iface mismatch: %q", str)
246
+ }
247
+ return r, nil
248
+ case '#':
249
+ fallthrough
250
+ case '%':
251
+ fallthrough
252
+ case '&':
253
+ return nil, fmt.Errorf("not implemented: %q", str)
254
+ default:
255
+ if str[0] >= '!' && str[0] <= '-' {
256
+ return nil, fmt.Errorf("invalid smallcaps encoding prefix: %q", str[:1])
257
+ }
258
+ }
259
+ return str, nil
260
+ } else {
261
+ return encoded, nil
262
+ }
263
+ }
264
+
265
+ // DecodeSerializedCapdata accepts JSON text representing encoded CapData and
266
+ // decodes it, applying specified transformations for values that otherwise
267
+ // hinder interchange.
268
+ func DecodeSerializedCapdata(
269
+ serializedCapdata string,
270
+ transformations CapdataValueTransformations,
271
+ ) (interface{}, error) {
272
+ var capdata Capdata
273
+ if err := json.Unmarshal([]byte(serializedCapdata), &capdata); err != nil {
274
+ return nil, err
275
+ }
276
+ if capdata.Body == "" || capdata.Slots == nil {
277
+ return nil, fmt.Errorf("invalid CapData")
278
+ }
279
+ serializedBody, decodeValue := capdata.Body, decodeCapdataLegacyValue
280
+ if strings.HasPrefix(serializedBody, "#") {
281
+ serializedBody, decodeValue = serializedBody[1:], decodeCapdataSmallcapsValue
282
+ }
283
+ var encoded interface{}
284
+ if err := json.Unmarshal([]byte(serializedBody), &encoded); err != nil {
285
+ return nil, err
286
+ }
287
+ remotables := map[uint64]*CapdataRemotable{}
288
+ decoded, err := decodeValue(encoded, capdata.Slots, remotables, transformations)
289
+ if err == nil && len(remotables) > 0 {
290
+ if transformations.Remotable == nil {
291
+ return nil, fmt.Errorf("untransformed remotable")
292
+ }
293
+ for _, r := range remotables {
294
+ r.Representation = transformations.Remotable(r)
295
+ }
296
+ }
297
+ return decoded, err
298
+ }