Skip to content
Permalink
Browse files
[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
  • Loading branch information
Mikhail Kornilov committed Aug 4, 2020
1 parent 211a9f0 commit a7ec62d0208510fe47f21b91e9247acbba119683
Show file tree
Hide file tree
Showing 19 changed files with 836 additions and 8 deletions.
@@ -14,7 +14,7 @@ cosmos_dir=$(swagger_dir)/cosmos-sdk
dnode = ./cmd/dnode
dncli =./cmd/dncli

cosmos_version = backport/v0.39.1
cosmos_version = backport/v0.39.x

all: install
install: go.sum install-dnode install-dncli
@@ -3,6 +3,7 @@
package app

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@@ -744,6 +745,42 @@ func TestVM_REST(t *testing.T) {
}
}
}

// check lcsView endpoint
{
moveAddress := "0000000000000000000000000000000000000001"
movePath := "Block::BlockMetadata"
viewRequest := `[ { "name": "height", "type": "U64" } ]`
req, respMsg := ct.RestQueryVMLcsView(moveAddress, movePath, viewRequest)
req.CheckSucceeded()

respStruct := struct {
Height int64
}{}
require.NoError(t, json.Unmarshal([]byte(respMsg.Value), &respStruct))
require.Greater(t, respStruct.Height, int64(0))
t.Logf("LCS view:\n%s", respMsg.Value)

// check invalid inputs
{
// invalid address
{
req, _ := ct.RestQueryVMLcsView("invalid", movePath, viewRequest)
req.CheckFailed(http.StatusBadRequest, nil)
}

// invalid movePath: multiple "::"
{
req, _ := ct.RestQueryVMLcsView(moveAddress, "A::B::C", viewRequest)
req.CheckFailed(http.StatusBadRequest, nil)
}
// invalid viewRequest: unparsable JSON
{
req, _ := ct.RestQueryVMLcsView(moveAddress, movePath, `[ { "A": 1 }`)
req.CheckFailed(http.StatusBadRequest, nil)
}
}
}
}

func TestMarkets_REST(t *testing.T) {
@@ -153,5 +153,230 @@ It possible to read storage data by path, e.g.:
dncli query vm get-data [address] [path]
Where:
* `address` - address of account containing data, could be bech32 or hex string (libra);
* `address` - address of account containing data, could be bech32 or hex string (Libra);
* `path` - resource path, hex string;
## Get storage data LCS (Libra Canonical Serialization) view
If is possible to get VM resource string representation (LCS view) using Move path.
This is similar to using `dncli query vm get-data` command, but VM path is build automatically:
dncli query vm get-lcs-view [address] [moduleStructMovePath] [viewRequestPath]
Where:
* `address` - address of account containing data (or stdlib address), could be bech32 or hex string (Libra);
* `moduleStructMovePath` - Move resource path;
* `viewRequestPath` - path to file containing LCS view request in JSON format;
Here is an example reading stdlib `Block` resource data:
dncli query vm get-lcs-view 0x0000000000000000000000000000000000000001 Block::BlockMetadata ./block.json
`block.json` file contains the following request:
```JSON
[
{
"name": "height",
"type": "U64"
}
]
```

The output in the example above would look like:
```JSON
{
"Height": 1894
}
```

### LCS view request format

LCS representation doesn't include any additional fields meta data (like JSON/gRPC for instance).
LCS request is a struct schema description used to deserialize the resource data.

Request is the JSON array containing resource fields descriptions:
```JSON
[
{ // first resource field description
"name": "my_vector_field", // field name (any name)
"type": "vector", // field type (supported types)
"inner_item": [ // nested struct schema used for "vector" and "struct" types (null for others)
{ // for "vector" type only one "inner_item" should exist (more for "struct" type)
"name": "", // not used for "vector" types, but must be non-empty for "struct" type
"type": "U64" // 0x1::Vector<u64>
}
]
}
]
```

Notes:
* fields order must match resource fields order;
* request must include all resource fields;

#### Supported types

* `U8` - unsigned int with 8 bits;
* `U64` - unsigned int with 64 bits;
* `U128` - unsigned int with 128 bits;
* `bool` - boolean;
* `address` - Libra address;
* `struct` - nested struct (`inner_item` must include nested struct fields schema);
* `vector` - `0x1::Vector` type (`inner_item` must include exactly one field schema);

#### Example

Let's assume we have `Foo` Move module with `Bar` resource :

```Move
address {module_address} {
module Foo {
use 0x1::Vector;
struct Inner {
a: u8,
b: bool
}
resource struct Bar {
u8Val: u8,
u64Val: u64,
u128Val: u128,
boolVal: bool,
addrVal: address,
vU8Val: vector<u8>,
vU64Val: vector<u64>,
inStruct: Inner,
vComplex: vector<Inner>
}
}
}
```

The LCS viewer request containing resource schema would look like:
```JSON
[
{
"name": "u8Val",
"type": "U8",
},
{
"name": "u64Val",
"type": "U64",
},
{
"name": "u128Val",
"type": "U128",
},
{
"name": "boolVal",
"type": "bool",
},
{
"name": "addrVal",
"type": "address",
},
{
"name": "vectU8Val",
"type": "vector",
"inner_item": [
{
"type": "U8",
}
]
},
{
"name": "vectU64Val",
"type": "vector",
"inner_item": [
{
"type": "U64",
}
]
},
{
"name": "innerStruct",
"type": "struct",
"inner_item": [
{
"name": "a",
"type": "U8",
},
{
"name": "b",
"type": "bool",
}
]
},
{
"name": "vectComplex",
"type": "vector",
"inner_item": [
{
"type": "struct",
"inner_item": [
{
"name": "a",
"type": "U8",
},
{
"name": "b",
"type": "bool",
}
]
}
]
}
]
```

The output example:
```JSON
{
"U8val": 100,
"U64val": 10000,
"U128val": 12345678910111213141516171819,
"Boolval": true,
"Addrval": [
220,
91,
202,
217,
255,
54,
112,
0,
44,
56,
17,
55,
236,
82,
187,
52,
88,
155,
113,
196
],
"Vectu8val": "ZMg=",
"Vectu64val": [
1,
2
],
"Innerstruct": {
"A": 128,
"B": false
},
"Vectcomplex": [
{
"A": 1,
"B": false
},
{
"A": 2,
"B": true
}
]
}
```
7 go.mod
@@ -11,9 +11,10 @@ require (
github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect
github.com/cosmos/cosmos-sdk v0.39.0
github.com/dfinance/dvm-proto/go v0.0.0-20200629145843-bfdcef619a26
github.com/dfinance/glav v0.0.0-20200729153512-98d5f8ab9cb5
github.com/dfinance/glav v0.0.0-20200731202515-8e21f58877c8
github.com/dfinance/lcs v0.1.7-big
github.com/fsouza/go-dockerclient v1.6.3
github.com/g3co/go-swagger-merger v0.0.0-20200729134821-4edc8debe55f // indirect
github.com/getsentry/sentry-go v0.5.1
github.com/ghodss/yaml v1.0.0
github.com/go-openapi/spec v0.19.9 // indirect
@@ -35,12 +36,12 @@ require (
github.com/stretchr/testify v1.6.1
github.com/swaggo/http-swagger v0.0.0-20200308142732-58ac5e232fba
github.com/swaggo/swag v1.6.7
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
github.com/tendermint/go-amino v0.15.1
github.com/tendermint/tendermint v0.33.6
github.com/tendermint/tm-db v0.5.1
github.com/urfave/cli/v2 v2.2.0 // indirect
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
golang.org/x/tools v0.0.0-20200729041821-df70183b1872 // indirect
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d // indirect
google.golang.org/grpc v1.30.0
google.golang.org/protobuf v1.24.0 // indirect
k8s.io/apimachinery v0.18.6 // indirect
10 go.sum
@@ -150,8 +150,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dfinance/dvm-proto/go v0.0.0-20200629145843-bfdcef619a26 h1:HjCcumhDVs5KmXxy7AAzcRzHVaHF3msBoWCpSewdFAc=
github.com/dfinance/dvm-proto/go v0.0.0-20200629145843-bfdcef619a26/go.mod h1:Vt1T0G56AYXbsduNKzSkq1RDTNa8PFraSqB9DaTCV0U=
github.com/dfinance/glav v0.0.0-20200729153512-98d5f8ab9cb5 h1:UYWSJLklh3ie5OQrwppAVHKQeScMmVi8Bh3x16mR3vA=
github.com/dfinance/glav v0.0.0-20200729153512-98d5f8ab9cb5/go.mod h1:/0gr38+QzVxCNSNKc/WjGKtdTfV8NtMagCNO0/VjOQU=
github.com/dfinance/glav v0.0.0-20200731202515-8e21f58877c8 h1:SpACwa85hu9vFveIBPE4Xe28KiSrwxU8Lge3Pcdtr8s=
github.com/dfinance/glav v0.0.0-20200731202515-8e21f58877c8/go.mod h1:/0gr38+QzVxCNSNKc/WjGKtdTfV8NtMagCNO0/VjOQU=
github.com/dfinance/lcs v0.1.7-big h1:z+Pvxcxvr6lKSy1vjYJtM5MnCTQ7DBjPitTywoWO9X0=
github.com/dfinance/lcs v0.1.7-big/go.mod h1:0Ir8JvbtxibZYvgTrRbbjNjk2EImCEXOJc3WHuUaSzI=
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
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/go-dockerclient v1.6.3 h1:VS/I3mxieZVIeaWXd57JKvSjheELafUJYtblGg75RIQ=
github.com/fsouza/go-dockerclient v1.6.3/go.mod h1:OiSy/IhZIF+zheikZkXK7LVpGzxWchJPJKGWhBqOK4M=
github.com/g3co/go-swagger-merger v0.0.0-20200729134821-4edc8debe55f h1:k5O6l2MEnI8MBFwK5SBGyC9OGVlPCbEf+HJwOHxGhQE=
github.com/g3co/go-swagger-merger v0.0.0-20200729134821-4edc8debe55f/go.mod h1:jvC3b+YoOx9/SJYqqo1pN1vJ31StlOCugGCyO3EW9XA=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
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=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
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
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200729041821-df70183b1872 h1:/U95VAvB4ZsR91rpZX2MwiKpejhWr+UxJ+N2VlJuESk=
golang.org/x/tools v0.0.0-20200729041821-df70183b1872/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d h1:szSOL78iTCl0LF1AMjhSWJj8tIM0KixlUUnBtYXsmd8=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
@@ -420,6 +420,21 @@ func (ct *CLITester) RestQueryVMPublishModuleStdTx(senderAccName string, byteCod
return r, respMsg
}

func (ct *CLITester) RestQueryVMLcsView(address, movePath, viewRequest string) (*RestRequest, *vmRest.LcsViewResp) {
req := vmRest.LcsViewReq{
Account: address,
MovePath: movePath,
ViewRequest: viewRequest,
}

reqSubPath := fmt.Sprintf("%s/%s", vm.ModuleName, "view")
respMsg := &vmRest.LcsViewResp{}

r := ct.newRestRequest().SetQuery("GET", reqSubPath, nil, req, respMsg)

return r, respMsg
}

func (ct *CLITester) RestTxOraclePostPrice(accName string, assetCode dnTypes.AssetCode, price sdk.Int, receivedAt time.Time) (*RestRequest, *sdk.TxResponse) {
accInfo := ct.Accounts[accName]
require.NotNil(ct.t, accInfo, "account %s: not found", accName)

0 comments on commit a7ec62d

Please sign in to comment.