Skip to content

Commit

Permalink
Added the possibility to verify a profile with an external application
Browse files Browse the repository at this point in the history
See PR #502
  • Loading branch information
RiccardoM authored Jun 22, 2021
1 parent 77981c8 commit 35217c9
Show file tree
Hide file tree
Showing 17 changed files with 264 additions and 105 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Added the logging of some interesting operations ([#483](https://github.com/desmos-labs/desmos/issues/483))
- Make `x/profiles` DTag case-insensitive ([#492](https://github.com/desmos-labs/desmos/issues/492))
- Updated Cosmos SDK to `v0.42.6` ([#509](https://github.com/desmos-labs/desmos/issues/509))
- Added the possibility to verify a profile with an external application ([#472](https://github.com/desmos-labs/desmos/issues/472))

# Version 0.16.3
## Changes
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ TM_ABCI_TYPES = third_party/proto/tendermint/abci
TM_TYPES = third_party/proto/tendermint/types
TM_VERSION = third_party/proto/tendermint/version
TM_LIBS = third_party/proto/tendermint/libs/bits
IBC_TYPES = third_party/proto/ibc

GOGO_PROTO_TYPES = third_party/proto/gogoproto
COSMOS_TYPES = third_party/proto/cosmos
Expand Down
Binary file added docs/assets/desmos-band-process.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/desmos-band-setup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions docs/developers/msgs/profiles/link-application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# `MsgLinkApplication`
This message allows you to start the process that will verify
an [application link](../../types/profiles/application-link.md) and add it to your Desmos profile.

## Structure

```json
{
"@type": "/desmos.profiles.v1beta1.MsgLinkApplication",
"link_data": {
"application": "<Name of the application to link>",
"username": "<Username of the application account to link>"
},
"call_data": "<Hex encoded call data for the data source>",
"source_channel": "<IBC channel to be used>",
"source_port": "<IBC port to be used>",
"sender": "<Desmos address of the profile to which link the application>"
}
```

### Attributes

| Attribute | Type | Description |
| :-------: | :----: | :-------- |
| `link_data` | [Data](../../types/profiles/application-link.md#data) | Data of the link to be verified |
| `call_data`| `string` | Hex encoded data that will be sent to the data source to verify the link |
| `source_channel` | String | ID of the IBC channel to be used in order to send the packet |
| `source_port` | String | ID of the IBC port to be used in order to send the packet |
| `sender` | String | Desmos address of the profile to which the link will be associated |

#### Note
You can also specify an optional timeout after which the request will be marked as invalid. This can be done using the
appropriate fields:

- `height` (type [Height](https://docs.cosmos.network/v0.42/core/proto-docs.html#height)), or
- `timeout_timestamp` (nanoseconds).

## Example

````json
{
"@type": "/desmos.profiles.v1beta1.MsgLinkApplication",
"link_data": {
"application": "github",
"username": "RiccardoM"
},
"call_data": "7B22757365726E616D65223A22526963636172646F4D222C22676973745F6964223A223732306530303732333930613930316262383065353966643630643766646564227D",
"source_channel": "channel-0",
"source_port": "profiles",
"sender": "desmos1qchdngxk8zkl4c4mheqdlpgcegkdrtucmwllpx"
}
````

## Message action
The action associated to this message is the following:

```
link_application
```
39 changes: 39 additions & 0 deletions docs/developers/msgs/profiles/unlink-application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# `MsgUnlinkApplication`
This message allows you to remove a previously linked application from your Desmos profile.

## Structure

```json
{
"@type": "/desmos.profiles.v1beta1.MsgUnlinkApplication",
"application": "<Name of the application to unlink>",
"username": "<Name of the account inside the application that should be unlinked>",
"signer": "<Desmos address of the profile that should remove the link>"
}
```

### Attributes

| Attribute | Type | Description |
| :-------: | :----: | :-------- |
| `application` | `string` | Name of the application to unlink |
| `username`| `string` | Name of the account inside the application that should be unlinked |
| `signer` | String | Desmos address of the profile that should remove the link |

## Example

````json
{
"@type": "/desmos.profiles.v1beta1.MsgUnlinkApplication",
"application": "twitter",
"username": "RicMontagnin",
"signer": "desmos1qchdngxk8zkl4c4mheqdlpgcegkdrtucmwllpx"
}
````

## Message action
The action associated to this message is the following:

```
unlink_application
```
2 changes: 2 additions & 0 deletions docs/developers/perform-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ transactions for the Desmos chain.
* [`MsgDeleteRelationship`](msgs/profiles/delete-relationship.md): allows you to delete a relationship.
* [`MsgBlockUser`](msgs/profiles/block-user.md): allows you to block a user.
* [`MsgUnblockUser`](msgs/profiles/unblock-user.md): allows you to unblock a user.
* [`MsgLinkApplication`](msgs/profiles/link-application.md): allows you to link a centralized application to your Desmos profile.
* [`MsgUnlinkApplication`](msgs/profiles/unlink-application.md): allows you to unlink a previously linked application from your Desmos profile.

### Posts

Expand Down
1 change: 1 addition & 0 deletions docs/developers/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Following you can find all the custom types that are used to represent the data
- [DTag transfer request](types/profiles/dtag-transfer-request.md)
- [Relationship](types/profiles/relationship.md)
- [User block](types/profiles/user-block.md)
- [Application link](types/profiles/application-link.md)

## Posts

Expand Down
69 changes: 69 additions & 0 deletions docs/developers/types/profiles/application-link.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Application link
An application link (abbr. _app link_) represents a link to an external (and possibly centralized) application. These links are created by the user and their validity is checked using a multi-step verification process described inside the [_"Themis"_ repository](https://github.com/desmos-labs/themis).

## `User`
Address of the Desmos profile to which the link is associated.

## `Data`
Object that contains the details of the link.

### `Application`
Name of the application to which the link refers to (eg. `twitter`, `github`, `reddit`, etc).

### `Username`
Identifier of the application account which the link refers to (eg. Twitter username, GitHub profile, Reddit username, etc).

## `State`
Representation of the current state of the link. There can be five different states in which a link can be:

- `APPLICATION_LINK_STATE_INITIALIZED_UNSPECIFIED` if the link has just been created, and it still needs to be processed;
- `APPLICATION_LINK_STATE_VERIFICATION_STARTED` if the verification process has started;
- `APPLICATION_LINK_STATE_VERIFICATION_ERROR` if the verification process ended with an error;
- `APPLICATION_LINK_STATE_VERIFICATION_SUCCESS` if the verification process ended with success;
- `APPLICATION_LINK_STATE_TIMED_OUT` if the verification process expired due to a timeout.

## `OracleRequest`
The `OracleRequest` field contains all the data that has been sent to the oracle script in order to verify the authenticity of the link.

### `ID`
This is the unique id of the request that has been made to verify the link.

### `OracleScriptID`
Unique id of the script that has been called to verify the authenticity of the link.

### `CallData`
Contains the details of the data that will be used to call the oracle script.

#### `Application`
Name of the application for which the link is valid (eg. `twitter`, `github`, `reddit`, etc).

#### `CallData`
The `CallData` field represents the hex-encoded data that will be given to the data source in order to fetch and verify the validity of the link.

### `ClientID`
ID of the client that has performed the request.

## `Result`
The `Result` field contains the effective result of the verification process. This is set only if the link state is either `APPLICATION_LINK_STATE_VERIFICATION_SUCCESS` or `APPLICATION_LINK_STATE_VERIFICATION_ERROR`.

The `Result` field can be of two types:
- `Result_Success`
- `Result_Error`

### `Result_Success`
Represents a successful result. It contains two fields.

#### `Value`
Plain text value that has been signed from the user with their Desmos private key to prove the ownership of the Desmos profile.

#### `Signature`
Hex-encoded result of the plain text value signature.

### `Result_Error`
Identifies an error during the verification process. It contains only one field.

#### `Error`
Represents the description of the error that has been emitted during the verification process.

## `CreationTime`
Contains the time at which the link has been created.
3 changes: 1 addition & 2 deletions proto/desmos/posts/v1beta1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ option go_package = "github.com/desmos-labs/desmos/x/staging/posts/types";
message GenesisState {
repeated desmos.posts.v1beta1.Post posts = 1 [ (gogoproto.nullable) = false ];

repeated UserAnswer users_poll_answers = 2
[ (gogoproto.nullable) = false ];
repeated UserAnswer users_poll_answers = 2 [ (gogoproto.nullable) = false ];
repeated PostReactionsEntry posts_reactions = 3
[ (gogoproto.nullable) = false ];
repeated desmos.posts.v1beta1.RegisteredReaction registered_reactions = 4
Expand Down
11 changes: 6 additions & 5 deletions proto/desmos/profiles/v1beta1/msgs_app_links.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,24 @@ message MsgLinkApplication {
(gogoproto.moretags) = "yaml:\"link_data\""
];

// CallData contains the data used to verify the link
OracleRequest.CallData call_data = 3 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"call_data\""
];
// Hex encoded call data that will be sent to the data source in order to
// verify the link
string call_data = 3 [ (gogoproto.moretags) = "yaml:\"call_data\"" ];

// The port on which the packet will be sent
string source_port = 4 [ (gogoproto.moretags) = "yaml:\"source_port\"" ];

// The channel by which the packet will be sent
string source_channel = 5
[ (gogoproto.moretags) = "yaml:\"source_channel\"" ];

// Timeout height relative to the current block height.
// The timeout is disabled when set to 0.
ibc.core.client.v1.Height timeout_height = 6 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"timeout_height\""
];

// Timeout timestamp (in nanoseconds) relative to the current block timestamp.
// The timeout is disabled when set to 0.
uint64 timeout_timestamp = 7
Expand Down
3 changes: 1 addition & 2 deletions x/profiles/client/cli/cli_app_links.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ to the counterparty channel. Any timeout set to 0 is disabled.`),
srcPort := args[0]
srcChannel := args[1]
linkData := types.NewData(args[2], args[3])
oracleRequestCallData := types.NewOracleRequestCallData(args[2], args[4])

timeoutHeightStr, err := cmd.Flags().GetString(flagPacketTimeoutHeight)
if err != nil {
Expand Down Expand Up @@ -88,7 +87,7 @@ to the counterparty channel. Any timeout set to 0 is disabled.`),
}

msg := types.NewMsgLinkApplication(
linkData, oracleRequestCallData, sender.String(),
linkData, args[4], sender.String(),
srcPort, srcChannel, timeoutHeight, timeoutTimestamp,
)
if err := msg.ValidateBasic(); err != nil {
Expand Down
13 changes: 9 additions & 4 deletions x/profiles/keeper/relay_app_links.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type resultData struct {
func (k Keeper) StartProfileConnection(
ctx sdk.Context,
applicationData types.Data,
oracleRequestCallData types.OracleRequest_CallData,
dataSourceCallData string,
sender sdk.AccAddress,
sourcePort,
sourceChannel string,
Expand Down Expand Up @@ -87,8 +87,8 @@ func (k Keeper) StartProfileConnection(

// Create the call data to be used
data := oracleScriptCallData{
Application: oracleRequestCallData.Application,
CallData: oracleRequestCallData.CallData,
Application: strings.ToLower(applicationData.Application),
CallData: dataSourceCallData,
}

// Serialize the call data using the OBI encoding
Expand Down Expand Up @@ -134,7 +134,12 @@ func (k Keeper) StartProfileConnection(
sender.String(),
applicationData,
types.ApplicationLinkStateInitialized,
types.NewOracleRequest(-1, int64(OracleScriptID), oracleRequestCallData, clientID),
types.NewOracleRequest(
-1,
int64(OracleScriptID),
types.NewOracleRequestCallData(applicationData.Application, dataSourceCallData),
clientID,
),
nil,
ctx.BlockTime(),
))
Expand Down
14 changes: 7 additions & 7 deletions x/profiles/keeper/relay_app_links_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ func createResponsePacketData(

func (suite *KeeperTestSuite) TestKeeper_StartProfileConnection() {
var (
applicationData types.Data
oracleRequestCallData types.OracleRequest_CallData
channelA, channelB ibctesting.TestChannel
err error
applicationData types.Data
callData string
channelA, channelB ibctesting.TestChannel
err error
)

testCases := []struct {
Expand Down Expand Up @@ -120,7 +120,7 @@ func (suite *KeeperTestSuite) TestKeeper_StartProfileConnection() {
_, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint)
channelA, channelB = suite.coordinator.CreateIBCProfilesChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED)
applicationData = types.NewData("twitter", "twitteruser")
oracleRequestCallData = types.NewOracleRequestCallData("application", "call_data")
callData = "call_data"
},
expPass: false,
},
Expand All @@ -130,7 +130,7 @@ func (suite *KeeperTestSuite) TestKeeper_StartProfileConnection() {
_, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint)
channelA, channelB = suite.coordinator.CreateIBCProfilesChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED)
applicationData = types.NewData("twitter", "twitteruser")
oracleRequestCallData = types.NewOracleRequestCallData("application", "call_data")
callData = "call_data"
},
storeChainA: func(ctx sdk.Context) {
profile := suite.CreateProfileFromAddress(suite.chainA.Account.GetAddress().String())
Expand All @@ -151,7 +151,7 @@ func (suite *KeeperTestSuite) TestKeeper_StartProfileConnection() {
}

err = suite.chainA.App.ProfileKeeper.StartProfileConnection(
suite.chainA.GetContext(), applicationData, oracleRequestCallData, suite.chainA.Account.GetAddress(),
suite.chainA.GetContext(), applicationData, callData, suite.chainA.Account.GetAddress(),
channelA.PortID, channelA.ID,
clienttypes.NewHeight(0, 110), 0,
)
Expand Down
8 changes: 4 additions & 4 deletions x/profiles/types/msgs_app_links.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"encoding/hex"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -12,7 +13,7 @@ import (
// NewMsgLinkApplication creates a new MsgLinkApplication instance
// nolint:interfacer
func NewMsgLinkApplication(
linkData Data, callData OracleRequest_CallData, sender string,
linkData Data, callData string, sender string,
sourcePort, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64,
) *MsgLinkApplication {
return &MsgLinkApplication{
Expand Down Expand Up @@ -44,9 +45,8 @@ func (msg MsgLinkApplication) ValidateBasic() error {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
}

err = msg.CallData.Validate()
if err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
if _, err := hex.DecodeString(msg.CallData); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid call data: must be hex encoded")
}

err = host.ChannelIdentifierValidator(msg.SourceChannel)
Expand Down
Loading

0 comments on commit 35217c9

Please sign in to comment.