Skip to content

Commit

Permalink
Merge pull request DongCoNY#57 from onomyprotocol/nhan/oracle_specs
Browse files Browse the repository at this point in the history
[Docs] Add specs and readme for `Oracle module`
ThanhNhann authored Oct 29, 2024
2 parents 83ad2c9 + 13306ec commit ed81e8e
Showing 9 changed files with 461 additions and 8 deletions.
14 changes: 8 additions & 6 deletions proto/reserve/oracle/events.proto
Original file line number Diff line number Diff line change
@@ -6,16 +6,18 @@ import "gogoproto/gogo.proto";
option go_package = "github.com/onomyprotocol/reserve/x/oracle/types";

message EventBandAckSuccess {
string ack_result = 1;
int64 client_id = 2;
}
string ack_result = 1;
int64 client_id = 2;
}

message EventBandAckError {
string ack_error = 1;
int64 client_id = 2;
string ack_error = 1;
int64 client_id = 2;
}

message EventBandResponseTimeout { int64 client_id = 1; }
message EventBandResponseTimeout {
int64 client_id = 1;
}

message SetBandPriceEvent {
string relayer = 1;
2 changes: 1 addition & 1 deletion script/oracleDeleteBandOracleRequests.json
Original file line number Diff line number Diff line change
@@ -7,4 +7,4 @@
"deposit": "100000000stake",
"title": "My proposal",
"summary": "A short summary of my proposal"
}
}
2 changes: 1 addition & 1 deletion script/oracleUpdateBandOracleRequest.json
Original file line number Diff line number Diff line change
@@ -17,4 +17,4 @@
"deposit": "100000000stake",
"title": "My proposal",
"summary": "A short summary of my proposal"
}
}
152 changes: 152 additions & 0 deletions x/oracle/specs/01_state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
sidebar_position: 1
title: State
---

# State

## Params
The oracle module parameters.
```protobuf
message Params {
option (amino.name) = "reserve/x/oracle/Params";
option (gogoproto.equal) = true;
}
```

## Band Oracle

This section describes all the state management to maintain the price by connecting to Band chain via IBC.

- LatestClientID is maintained to manage unique clientID for band IBC packets. It is increased by 1 when sending price request packet into bandchain.

* LatestClientID: `0x03 -> Formated(LatestClientID)`

- LatestRequestID is maintained to manage unique `BandOracleRequests`. Incremented by 1 when creating a new `BandOracleRequest`.

* LatestRequestID: `0x06 -> Formated(LatestRequestID)`

- Band price data for a given symbol is stored as follows:

* BandPriceState: `0x05 | []byte(symbol) -> ProtocolBuffer(BandPriceState)`

```protobuf
message BandPriceState {
string symbol = 1;
string rate = 2 [
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
uint64 resolve_time = 3;
uint64 request_ID = 4;
PriceState price_state = 5 [ (gogoproto.nullable) = false ];
}
```

- BandCallDataRecord is stored as follows when sending price request packet into bandchain:

* CalldataRecord: `0x02 | []byte(ClientId) -> ProtocolBuffer(CalldataRecord)`

```protobuf
message CalldataRecord {
uint64 client_id = 1;
bytes calldata = 2;
}
```

- BandOracleRequest is stored as follows when the governance configure oracle requests to send:

* BandOracleRequest: `0x04 | []byte(RequestId) -> ProtocolBuffer(BandOracleRequest)`

```protobuf
message BandOracleRequest {
// Unique Identifier for band ibc oracle request
uint64 request_id = 1;
// OracleScriptID is the unique identifier of the oracle script to be executed.
int64 oracle_script_id = 2;
// Symbols is the list of symbols to prepare in the calldata
repeated string symbols = 3;
// AskCount is the number of validators that are requested to respond to this
// oracle request. Higher value means more security, at a higher gas cost.
uint64 ask_count = 4;
// MinCount is the minimum number of validators necessary for the request to
// proceed to the execution phase. Higher value means more security, at the
// cost of liveness.
uint64 min_count = 5;
// FeeLimit is the maximum tokens that will be paid to all data source providers.
repeated cosmos.base.v1beta1.Coin fee_limit = 6 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// PrepareGas is amount of gas to pay to prepare raw requests
uint64 prepare_gas = 7;
// ExecuteGas is amount of gas to reserve for executing
uint64 execute_gas = 8;
// MinSourceCount is the minimum number of data sources that must be used by each validator
uint64 min_source_count = 9;
}
```

- BandParams is stored as follows and configured by governance:

* BandParams: `0x01 -> ProtocolBuffer(BandParams)`

`BandParams` contains the information for IBC connection with band chain.

```protobuf
message BandParams {
// block request interval to send Band IBC prices
int64 ibc_request_interval = 1;
// band IBC source channel
string ibc_source_channel = 2;
// band IBC version
string ibc_version = 3;
// band IBC portID
string ibc_port_id = 4;
// legacy oracle scheme ids
repeated int64 legacy_oracle_ids = 5;
}
```

- BandOracleRequestParams is stored as follows and configured by governance:

* BandOracleRequestParams: `0x07 -> ProtocolBuffer(BandOracleRequestParams)`

`BandOracleRequestParams` contains the information for Band Oracle request.

```protobuf
message BandOracleRequestParams {
// AskCount is the number of validators that are requested to respond to this
// oracle request. Higher value means more security, at a higher gas cost.
uint64 ask_count = 1;
// MinCount is the minimum number of validators necessary for the request to
// proceed to the execution phase. Higher value means more security, at the
// cost of liveness.
uint64 min_count = 2;
// FeeLimit is the maximum tokens that will be paid to all data source
// providers.
repeated cosmos.base.v1beta1.Coin fee_limit = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
// PrepareGas is amount of gas to pay to prepare raw requests
uint64 prepare_gas = 4;
// ExecuteGas is amount of gas to reserve for executing
uint64 execute_gas = 5;
// MinSourceCount is the minimum number of data sources that must be used by
// each validator
uint64 min_source_count = 6;
}
```

Note:

1. `IbcSourceChannel`, `IbcVersion`, `IbcPortId` are common parameters required for IBC connection.
2. `IbcRequestInterval` describes the automatic price fetch request interval that is automatically triggered on onomy chain on beginblocker.
3. `AskCount`, `MinCount`, `FeeLimit`, `PrepareGas`, `ExecuteGas`, `MinSourceCount` are common parameters required for IBC connection parameters required for Band IBC oracle query
43 changes: 43 additions & 0 deletions x/oracle/specs/02_keeper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
sidebar_position: 2
title: Keepers
---

# Keepers

The oracle module currently provides the price state information of tokens which can be used by other modules
which need to read price feeds.

# Band oracle

The band oracle in oracle module provides the ability to create/modify/read/delete BandParams, BandOracleRequestParams, BandOracleRequest, BandPriceState, BandLatestClientID, BandOracleRequest and BandCallDataRecord.

```go
GetBandParams(ctx context.Context) types.BandParams
SetBandParams(ctx context.Context, bandParams types.BandParams) error

GetBandOracleRequestParams(ctx context.Context) types.BandOracleRequestParams
SetBandOracleRequestParams(ctx context.Context, bandOracleRequestParams types.BandOracleRequestParams) error

GetBandOracleRequest(ctx context.Context, requestID uint64) *types.BandOracleRequest
SetBandOracleRequest(ctx context.Context, req types.BandOracleRequest) error
DeleteBandOracleRequest(ctx context.Context, requestID uint64) error
GetAllBandOracleRequests(ctx context.Context) []*types.BandOracleRequest

GetBandPriceState(ctx context.Context, symbol string) *types.BandPriceState
SetBandPriceState(ctx context.Context, symbol string, priceState *types.BandPriceState) error
GetAllBandPriceStates(ctx context.Context) []*types.BandPriceState

GetBandLatestClientID(ctx context.Context) uint64
SetBandLatestClientID(ctx context.Context, clientID uint64) error

GetBandCallDataRecord(ctx context.Context, clientID uint64) *types.CalldataRecord
SetBandCallDataRecord(ctx context.Context, record *types.CalldataRecord) error
GetAllBandCalldataRecords(ctx context.Context) []*types.CalldataRecord
DeleteBandCallDataRecord(ctx context.Context, clientID uint64) error

GetBandOracleRequest(ctx context.Context, requestID uint64) *types.BandOracleRequest
SetBandOracleRequest(ctx context.Context, req types.BandOracleRequest) error
GetAllBandOracleRequests(ctx context.Context) []*types.BandOracleRequest
DeleteBandOracleRequest(ctx context.Context, requestID uint64) error
```
26 changes: 26 additions & 0 deletions x/oracle/specs/03_messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
sidebar_position: 3
title: Messages
---

# Messages

## RequestBandRates

`MsgRequestBandIBCRates` is a message to instantly broadcast a request to bandchain.

```protobuf
// MsgRequestBandRates defines a SDK message for requesting data from
// BandChain using IBC.
message MsgRequestBandRates {
option (amino.name) = "oracle/MsgRequestBandRates";
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
option (cosmos.msg.v1.signer) = "sender";
string sender = 1;
uint64 request_id = 2;
}
```

Anyone can broadcast this message and no specific authorization is needed.
160 changes: 160 additions & 0 deletions x/oracle/specs/04_msg_proposals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
sidebar_position: 4
title: Governance Proposal Messages
---

# Governance Proposal Messages

## MsgUpdateBandParams Gov

Band oracle parameters can be updated through a message gov `MsgUpdateBandParams`

```protobuf
// MsgUpdateBandParams define defines a SDK message for update band parameters
message MsgUpdateBandParams {
option (cosmos.msg.v1.signer) = "authority";
option (amino.name) = "oracle/UpdateBandParams";
option (gogoproto.goproto_getters) = false;
option (gogoproto.equal) = false;
// authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
BandParams band_params = 2 [ (gogoproto.nullable) = false ];
}
```

Example usage:

```json
{
"messages": [{
"@type": "/reserve.oracle.MsgUpdateBandParams",
"authority": "onomy10d07y265gmmuvt4z0w9aw880jnsr700jqr8n8k",
"band_params" : {
"ibc_request_interval": 7,
"ibc_source_channel": "channel-0",
"ibc_version":"bandchain-2",
"ibc_port_id": "oracle",
"legacy_oracle_ids": [42]
}
}],
"deposit": "100000000stake",
"title": "My proposal",
"summary": "A short summary of my proposal"
}
```

## UpdateBandOracleRequest Gov

Band oracle request can be updated through a message gov `MsgUpdateBandOracleRequestRequest`

```protobuf
// MsgUpdateBandOracleRequestRequest define defines a SDK message for update band oracle requests
message MsgUpdateBandOracleRequestRequest{
option (cosmos.msg.v1.signer) = "authority";
option (amino.name) = "oracle/UpdateBandOracleRequest";
option (gogoproto.goproto_getters) = false;
option (gogoproto.equal) = false;
// authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
BandOracleRequest update_oracle_request = 2;
}
```

Example usage:

```json
{
"messages": [{
"@type": "/reserve.oracle.MsgUpdateBandOracleRequestRequest",
"authority": "onomy10d07y265gmmuvt4z0w9aw880jnsr700jqr8n8k",
"update_oracle_request" : {
"request_id": 1,
"oracle_script_id": 42,
"symbols":["BTC","USD","EUR"],
"ask_count": 1,
"min_count": 1,
"fee_limit": [{"denom":"uband","amount":"300000"}],
"prepare_gas": 100,
"execute_gas": 200,
"min_source_count": 6
}
}],
"deposit": "100000000stake",
"title": "My proposal",
"summary": "A short summary of my proposal"
}
```

## DeleteBandOracleRequests Gov

Band oracle requests can be deleted through a message gov `MsgDeleteBandOracleRequests`

```protobuf
// MsgDeleteBandOracleRequests define defines a SDK message for delete band oracle requests
message MsgDeleteBandOracleRequests{
option (cosmos.msg.v1.signer) = "authority";
option (amino.name) = "oracle/UpdateBandOracleRequest";
option (gogoproto.goproto_getters) = false;
option (gogoproto.equal) = false;
// authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
repeated uint64 delete_request_ids = 2;
}
```

Example usage:

```json
{
"messages": [{
"@type": "/reserve.oracle.MsgDeleteBandOracleRequests",
"authority": "onomy10d07y265gmmuvt4z0w9aw880jnsr700jqr8n8k",
"delete_request_ids" : [1, 2]
}],
"deposit": "100000000stake",
"title": "My proposal",
"summary": "A short summary of my proposal"
}
```

## UpdateBandOracleRequestParams Gov

Band oracle request parameters can be updated through a message gov `MsgUpdateBandOracleRequestParamsRequest`

```protobuf
// MsgUpdateBandOracleRequestParamsRequest define defines a SDK message for update band oracle request parameters
message MsgUpdateBandOracleRequestParamsRequest {
option (cosmos.msg.v1.signer) = "authority";
option (amino.name) = "oracle/UpdateBandOracleRequestParams";
option (gogoproto.goproto_getters) = false;
option (gogoproto.equal) = false;
// authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
BandOracleRequestParams update_band_oracle_request_params = 2;
}
```

Example usage:

```json
{
"messages": [{
"@type": "/reserve.oracle.MsgUpdateBandOracleRequestParamsRequest",
"authority": "onomy10d07y265gmmuvt4z0w9aw880jnsr700jqr8n8k",
"update_band_oracle_request_params" : {
"ask_count": 1,
"min_count": 1,
"fee_limit": [{"denom":"uband","amount":"300000"}],
"prepare_gas": 100,
"execute_gas": 200,
"min_source_count": 6
}
}],
"deposit": "100000000stake",
"title": "My proposal",
"summary": "A short summary of my proposal"
}
```
37 changes: 37 additions & 0 deletions x/oracle/specs/05_events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
sidebar_position: 5
title: Events
---
# Events

The oracle module emits the following events:

## Band

```protobuf
message EventBandAckSuccess {
string ack_result = 1;
int64 client_id = 2;
}
message EventBandAckError {
string ack_error = 1;
int64 client_id = 2;
}
message EventBandResponseTimeout {
int64 client_id = 1;
}
message SetBandPriceEvent {
string relayer = 1;
repeated string symbols = 2;
repeated string prices = 3 [
(gogoproto.customtype) = "cosmossdk.io/math.LegacyDec",
(gogoproto.nullable) = false
];
uint64 resolve_time = 4;
uint64 request_id = 5;
int64 client_id = 6;
}
```
33 changes: 33 additions & 0 deletions x/oracle/specs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# `Oracle`

## Abstract

This specification specifies the oracle module, which is primarily used by the `vaults` modules to obtain external price data.

## Workflow

1. New asset must first approved through a msg governance proposal (from `vaults` module) which will be add to the `BandOracleRequest` later. <br/>
**Example message governance proposal**: `ActiveCollateralProposal`
2. Once the message governance proposal is approved, the specified asset will be added to the `BandOracleRequest`, then for each begin block will make the request to band chain to get the asset data.
3. Upon receiving the ibc packet, oracle module will process the data to parse and update the price state of asset.
4. Other Cosmos-SDK modules can then fetch the latest price data by querying the oracle module.

## Band IBC integration flow

Cosmos SDK blockchains are able to interact with each other using IBC and Onomy support the feature to fetch price feed from bandchain via IBC.

1. To communicate with BandChain's oracle using IBC, Onomy Chain must first initialize a communication channel with the oracle module on the BandChain using relayers.

2. Once the connection has been established, a pair of channel identifiers is generated -- one for the Onomy Chain and one for Band. The channel identifier is used by Onomy Chain to route outgoing oracle request packets to Band. Similarly, Band's oracle module uses the channel identifier when sending back the oracle response.

3. The list of prices to be fetched via IBC should be determined by `ActiveCollateralProposal` and `UpdateBandOracleRequest`.

4. Chain periodically (`IbcRequestInterval`) sends price request IBC packets (`OracleRequestPacketData`) to bandchain and bandchain responds with the price via IBC packet (`OracleResponsePacketData`). Band chain is providing prices when there are threshold number of data providers confirm and it takes time to get the price after sending requests. To request price before the configured interval, any user can broadcast `MsgRequestBandRates` message which is instantly executed.

## Contents

1. **[State](./01_state.md)**
2. **[Keeper](./02_keeper.md)**
3. **[Messages](./03_messages.md)**
4. **[Proposals](./04_proposals.md)**
5. **[Events](./05_events.md)**

0 comments on commit ed81e8e

Please sign in to comment.