Skip to content

Commit a7ec62d

Browse files
author
Mikhail Kornilov
authored
[DFI-575] LCS viewer (#182)
* [DFI-575] VM mod: LCS viewer prototype added * [DFI-575] CLI output fix * [DFI-575] CLI output fix * [DFI-575] ModulePath support added * [DFI-575] Docs added * [DFI-575] REST API added + REST test; Cosmos SDK Swagger dependency fix
1 parent 211a9f0 commit a7ec62d

19 files changed

Lines changed: 836 additions & 8 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ cosmos_dir=$(swagger_dir)/cosmos-sdk
1414
dnode = ./cmd/dnode
1515
dncli =./cmd/dncli
1616

17-
cosmos_version = backport/v0.39.1
17+
cosmos_version = backport/v0.39.x
1818

1919
all: install
2020
install: go.sum install-dnode install-dncli

app/rest_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package app
44

55
import (
6+
"encoding/json"
67
"fmt"
78
"io/ioutil"
89
"net/http"
@@ -744,6 +745,42 @@ func TestVM_REST(t *testing.T) {
744745
}
745746
}
746747
}
748+
749+
// check lcsView endpoint
750+
{
751+
moveAddress := "0000000000000000000000000000000000000001"
752+
movePath := "Block::BlockMetadata"
753+
viewRequest := `[ { "name": "height", "type": "U64" } ]`
754+
req, respMsg := ct.RestQueryVMLcsView(moveAddress, movePath, viewRequest)
755+
req.CheckSucceeded()
756+
757+
respStruct := struct {
758+
Height int64
759+
}{}
760+
require.NoError(t, json.Unmarshal([]byte(respMsg.Value), &respStruct))
761+
require.Greater(t, respStruct.Height, int64(0))
762+
t.Logf("LCS view:\n%s", respMsg.Value)
763+
764+
// check invalid inputs
765+
{
766+
// invalid address
767+
{
768+
req, _ := ct.RestQueryVMLcsView("invalid", movePath, viewRequest)
769+
req.CheckFailed(http.StatusBadRequest, nil)
770+
}
771+
772+
// invalid movePath: multiple "::"
773+
{
774+
req, _ := ct.RestQueryVMLcsView(moveAddress, "A::B::C", viewRequest)
775+
req.CheckFailed(http.StatusBadRequest, nil)
776+
}
777+
// invalid viewRequest: unparsable JSON
778+
{
779+
req, _ := ct.RestQueryVMLcsView(moveAddress, movePath, `[ { "A": 1 }`)
780+
req.CheckFailed(http.StatusBadRequest, nil)
781+
}
782+
}
783+
}
747784
}
748785

749786
func TestMarkets_REST(t *testing.T) {

docs/vm.md

Lines changed: 226 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,230 @@ It possible to read storage data by path, e.g.:
153153
dncli query vm get-data [address] [path]
154154

155155
Where:
156-
* `address` - address of account containing data, could be bech32 or hex string (libra);
156+
* `address` - address of account containing data, could be bech32 or hex string (Libra);
157157
* `path` - resource path, hex string;
158+
159+
## Get storage data LCS (Libra Canonical Serialization) view
160+
161+
If is possible to get VM resource string representation (LCS view) using Move path.
162+
This is similar to using `dncli query vm get-data` command, but VM path is build automatically:
163+
164+
dncli query vm get-lcs-view [address] [moduleStructMovePath] [viewRequestPath]
165+
166+
Where:
167+
* `address` - address of account containing data (or stdlib address), could be bech32 or hex string (Libra);
168+
* `moduleStructMovePath` - Move resource path;
169+
* `viewRequestPath` - path to file containing LCS view request in JSON format;
170+
171+
Here is an example reading stdlib `Block` resource data:
172+
173+
dncli query vm get-lcs-view 0x0000000000000000000000000000000000000001 Block::BlockMetadata ./block.json
174+
175+
`block.json` file contains the following request:
176+
```JSON
177+
[
178+
{
179+
"name": "height",
180+
"type": "U64"
181+
}
182+
]
183+
```
184+
185+
The output in the example above would look like:
186+
```JSON
187+
{
188+
"Height": 1894
189+
}
190+
```
191+
192+
### LCS view request format
193+
194+
LCS representation doesn't include any additional fields meta data (like JSON/gRPC for instance).
195+
LCS request is a struct schema description used to deserialize the resource data.
196+
197+
Request is the JSON array containing resource fields descriptions:
198+
```JSON
199+
[
200+
{ // first resource field description
201+
"name": "my_vector_field", // field name (any name)
202+
"type": "vector", // field type (supported types)
203+
"inner_item": [ // nested struct schema used for "vector" and "struct" types (null for others)
204+
{ // for "vector" type only one "inner_item" should exist (more for "struct" type)
205+
"name": "", // not used for "vector" types, but must be non-empty for "struct" type
206+
"type": "U64" // 0x1::Vector<u64>
207+
}
208+
]
209+
}
210+
]
211+
```
212+
213+
Notes:
214+
* fields order must match resource fields order;
215+
* request must include all resource fields;
216+
217+
#### Supported types
218+
219+
* `U8` - unsigned int with 8 bits;
220+
* `U64` - unsigned int with 64 bits;
221+
* `U128` - unsigned int with 128 bits;
222+
* `bool` - boolean;
223+
* `address` - Libra address;
224+
* `struct` - nested struct (`inner_item` must include nested struct fields schema);
225+
* `vector` - `0x1::Vector` type (`inner_item` must include exactly one field schema);
226+
227+
#### Example
228+
229+
Let's assume we have `Foo` Move module with `Bar` resource :
230+
231+
```Move
232+
address {module_address} {
233+
module Foo {
234+
use 0x1::Vector;
235+
236+
struct Inner {
237+
a: u8,
238+
b: bool
239+
}
240+
241+
resource struct Bar {
242+
u8Val: u8,
243+
u64Val: u64,
244+
u128Val: u128,
245+
boolVal: bool,
246+
addrVal: address,
247+
vU8Val: vector<u8>,
248+
vU64Val: vector<u64>,
249+
inStruct: Inner,
250+
vComplex: vector<Inner>
251+
}
252+
}
253+
}
254+
```
255+
256+
The LCS viewer request containing resource schema would look like:
257+
```JSON
258+
[
259+
{
260+
"name": "u8Val",
261+
"type": "U8",
262+
},
263+
{
264+
"name": "u64Val",
265+
"type": "U64",
266+
},
267+
{
268+
"name": "u128Val",
269+
"type": "U128",
270+
},
271+
{
272+
"name": "boolVal",
273+
"type": "bool",
274+
},
275+
{
276+
"name": "addrVal",
277+
"type": "address",
278+
},
279+
{
280+
"name": "vectU8Val",
281+
"type": "vector",
282+
"inner_item": [
283+
{
284+
"type": "U8",
285+
}
286+
]
287+
},
288+
{
289+
"name": "vectU64Val",
290+
"type": "vector",
291+
"inner_item": [
292+
{
293+
"type": "U64",
294+
}
295+
]
296+
},
297+
{
298+
"name": "innerStruct",
299+
"type": "struct",
300+
"inner_item": [
301+
{
302+
"name": "a",
303+
"type": "U8",
304+
},
305+
{
306+
"name": "b",
307+
"type": "bool",
308+
}
309+
]
310+
},
311+
{
312+
"name": "vectComplex",
313+
"type": "vector",
314+
"inner_item": [
315+
{
316+
"type": "struct",
317+
"inner_item": [
318+
{
319+
"name": "a",
320+
"type": "U8",
321+
},
322+
{
323+
"name": "b",
324+
"type": "bool",
325+
}
326+
]
327+
}
328+
]
329+
}
330+
]
331+
```
332+
333+
The output example:
334+
```JSON
335+
{
336+
"U8val": 100,
337+
"U64val": 10000,
338+
"U128val": 12345678910111213141516171819,
339+
"Boolval": true,
340+
"Addrval": [
341+
220,
342+
91,
343+
202,
344+
217,
345+
255,
346+
54,
347+
112,
348+
0,
349+
44,
350+
56,
351+
17,
352+
55,
353+
236,
354+
82,
355+
187,
356+
52,
357+
88,
358+
155,
359+
113,
360+
196
361+
],
362+
"Vectu8val": "ZMg=",
363+
"Vectu64val": [
364+
1,
365+
2
366+
],
367+
"Innerstruct": {
368+
"A": 128,
369+
"B": false
370+
},
371+
"Vectcomplex": [
372+
{
373+
"A": 1,
374+
"B": false
375+
},
376+
{
377+
"A": 2,
378+
"B": true
379+
}
380+
]
381+
}
382+
```

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ require (
1111
github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect
1212
github.com/cosmos/cosmos-sdk v0.39.0
1313
github.com/dfinance/dvm-proto/go v0.0.0-20200629145843-bfdcef619a26
14-
github.com/dfinance/glav v0.0.0-20200729153512-98d5f8ab9cb5
14+
github.com/dfinance/glav v0.0.0-20200731202515-8e21f58877c8
1515
github.com/dfinance/lcs v0.1.7-big
1616
github.com/fsouza/go-dockerclient v1.6.3
17+
github.com/g3co/go-swagger-merger v0.0.0-20200729134821-4edc8debe55f // indirect
1718
github.com/getsentry/sentry-go v0.5.1
1819
github.com/ghodss/yaml v1.0.0
1920
github.com/go-openapi/spec v0.19.9 // indirect
@@ -35,12 +36,12 @@ require (
3536
github.com/stretchr/testify v1.6.1
3637
github.com/swaggo/http-swagger v0.0.0-20200308142732-58ac5e232fba
3738
github.com/swaggo/swag v1.6.7
38-
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
3939
github.com/tendermint/go-amino v0.15.1
4040
github.com/tendermint/tendermint v0.33.6
4141
github.com/tendermint/tm-db v0.5.1
42+
github.com/urfave/cli/v2 v2.2.0 // indirect
4243
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
43-
golang.org/x/tools v0.0.0-20200729041821-df70183b1872 // indirect
44+
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d // indirect
4445
google.golang.org/grpc v1.30.0
4546
google.golang.org/protobuf v1.24.0 // indirect
4647
k8s.io/apimachinery v0.18.6 // indirect

go.sum

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
150150
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
151151
github.com/dfinance/dvm-proto/go v0.0.0-20200629145843-bfdcef619a26 h1:HjCcumhDVs5KmXxy7AAzcRzHVaHF3msBoWCpSewdFAc=
152152
github.com/dfinance/dvm-proto/go v0.0.0-20200629145843-bfdcef619a26/go.mod h1:Vt1T0G56AYXbsduNKzSkq1RDTNa8PFraSqB9DaTCV0U=
153-
github.com/dfinance/glav v0.0.0-20200729153512-98d5f8ab9cb5 h1:UYWSJLklh3ie5OQrwppAVHKQeScMmVi8Bh3x16mR3vA=
154-
github.com/dfinance/glav v0.0.0-20200729153512-98d5f8ab9cb5/go.mod h1:/0gr38+QzVxCNSNKc/WjGKtdTfV8NtMagCNO0/VjOQU=
153+
github.com/dfinance/glav v0.0.0-20200731202515-8e21f58877c8 h1:SpACwa85hu9vFveIBPE4Xe28KiSrwxU8Lge3Pcdtr8s=
154+
github.com/dfinance/glav v0.0.0-20200731202515-8e21f58877c8/go.mod h1:/0gr38+QzVxCNSNKc/WjGKtdTfV8NtMagCNO0/VjOQU=
155155
github.com/dfinance/lcs v0.1.7-big h1:z+Pvxcxvr6lKSy1vjYJtM5MnCTQ7DBjPitTywoWO9X0=
156156
github.com/dfinance/lcs v0.1.7-big/go.mod h1:0Ir8JvbtxibZYvgTrRbbjNjk2EImCEXOJc3WHuUaSzI=
157157
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
@@ -204,6 +204,8 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
204204
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
205205
github.com/fsouza/go-dockerclient v1.6.3 h1:VS/I3mxieZVIeaWXd57JKvSjheELafUJYtblGg75RIQ=
206206
github.com/fsouza/go-dockerclient v1.6.3/go.mod h1:OiSy/IhZIF+zheikZkXK7LVpGzxWchJPJKGWhBqOK4M=
207+
github.com/g3co/go-swagger-merger v0.0.0-20200729134821-4edc8debe55f h1:k5O6l2MEnI8MBFwK5SBGyC9OGVlPCbEf+HJwOHxGhQE=
208+
github.com/g3co/go-swagger-merger v0.0.0-20200729134821-4edc8debe55f/go.mod h1:jvC3b+YoOx9/SJYqqo1pN1vJ31StlOCugGCyO3EW9XA=
207209
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
208210
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
209211
github.com/getsentry/sentry-go v0.4.0/go.mod h1:xkGcb82SipKQloDNa5b7hTV4VdEyc2bhwd1/UczP52k=
@@ -749,6 +751,8 @@ github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
749751
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
750752
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
751753
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
754+
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
755+
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
752756
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
753757
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
754758
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -927,6 +931,8 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY
927931
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
928932
golang.org/x/tools v0.0.0-20200729041821-df70183b1872 h1:/U95VAvB4ZsR91rpZX2MwiKpejhWr+UxJ+N2VlJuESk=
929933
golang.org/x/tools v0.0.0-20200729041821-df70183b1872/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
934+
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d h1:szSOL78iTCl0LF1AMjhSWJj8tIM0KixlUUnBtYXsmd8=
935+
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
930936
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
931937
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
932938
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=

helpers/tests/clitester/cli_tester_rest.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,21 @@ func (ct *CLITester) RestQueryVMPublishModuleStdTx(senderAccName string, byteCod
420420
return r, respMsg
421421
}
422422

423+
func (ct *CLITester) RestQueryVMLcsView(address, movePath, viewRequest string) (*RestRequest, *vmRest.LcsViewResp) {
424+
req := vmRest.LcsViewReq{
425+
Account: address,
426+
MovePath: movePath,
427+
ViewRequest: viewRequest,
428+
}
429+
430+
reqSubPath := fmt.Sprintf("%s/%s", vm.ModuleName, "view")
431+
respMsg := &vmRest.LcsViewResp{}
432+
433+
r := ct.newRestRequest().SetQuery("GET", reqSubPath, nil, req, respMsg)
434+
435+
return r, respMsg
436+
}
437+
423438
func (ct *CLITester) RestTxOraclePostPrice(accName string, assetCode dnTypes.AssetCode, price sdk.Int, receivedAt time.Time) (*RestRequest, *sdk.TxResponse) {
424439
accInfo := ct.Accounts[accName]
425440
require.NotNil(ct.t, accInfo, "account %s: not found", accName)

0 commit comments

Comments
 (0)