Skip to content

Commit

Permalink
chore: removed pool ID from Asset and optimized the relay code
Browse files Browse the repository at this point in the history
  • Loading branch information
ironman0x7b2 committed Nov 13, 2024
1 parent ce5b864 commit 77f6e7d
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 128 deletions.
9 changes: 4 additions & 5 deletions proto/sentinel/oracle/v1/asset.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ option (gogoproto.goproto_getters_all) = false;
message Asset {
string denom = 1;
int64 decimals = 2;
uint64 pool_id = 3 [(gogoproto.customname) = "PoolID"];
string base_asset_denom = 4;
string quote_asset_denom = 5;
string price = 6 [
string base_asset_denom = 3;
string quote_asset_denom = 4;
string price = 5 [
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
int64 height = 7;
int64 height = 6;
}
25 changes: 20 additions & 5 deletions x/oracle/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,47 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
ibchost "github.com/cosmos/ibc-go/v7/modules/core/24-host"

protorevtypes "github.com/sentinel-official/hub/v12/third_party/osmosis/x/protorev/types"
"github.com/sentinel-official/hub/v12/x/oracle/types/v1"
)

// EndBlock is called at the end of each block to trigger IBC query packets for relevant assets.
func (k *Keeper) EndBlock(ctx sdk.Context) []abcitypes.ValidatorUpdate {
// Retrieve necessary information for the IBC packet.
portID := k.GetPortID(ctx)
channelID := k.GetChannelID(ctx)
timeout := k.GetQueryTimeout(ctx)

// Get the channel capability to ensure we have the authority to send packets.
channelCap, found := k.capability.GetCapability(ctx, ibchost.ChannelCapabilityPath(portID, channelID))
if !found {
return nil
}

// Iterate over each asset and send a ProtoRevPool query for each.
k.IterateAssets(ctx, func(_ int, item v1.Asset) bool {
sequence, err := k.SendQueryPacket(
ctx, channelCap, portID, channelID, uint64(timeout),
item.ProtoRevPoolRequest(k.cdc),
item.SpotPriceRequest(k.cdc),
)
// Create a request for the GetProtoRevPool query using asset details.
req := abcitypes.RequestQuery{
Data: k.cdc.MustMarshal(
&protorevtypes.QueryGetProtoRevPoolRequest{
BaseDenom: item.BaseAssetDenom,
OtherDenom: item.QuoteAssetDenom,
},
),
Path: "/osmosis.protorev.v1beta1.Query/GetProtoRevPool",
}

// Send the GetProtoRevPool query packet over IBC.
sequence, err := k.SendQueryPacket(ctx, channelCap, portID, channelID, uint64(timeout), req)
if err != nil {
panic(err)
}

// Map the sequence number to the asset denom for tracking.
k.SetDenomForPacket(ctx, portID, channelID, sequence, item.Denom)
return false
})

// No validator updates in this function.
return nil
}
2 changes: 1 addition & 1 deletion x/oracle/keeper/msg_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ func (k *Keeper) HandleMsgCreateAsset(ctx sdk.Context, msg *v1.MsgCreateAssetReq
asset := v1.Asset{
Denom: msg.Denom,
Decimals: msg.Decimals,
PoolID: 0,
BaseAssetDenom: msg.BaseAssetDenom,
QuoteAssetDenom: msg.QuoteAssetDenom,
Price: sdkmath.ZeroInt(),
Height: 0,
}

k.SetAsset(ctx, asset)
Expand Down
3 changes: 2 additions & 1 deletion x/oracle/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ func (k *Keeper) GetTimeout(ctx sdk.Context) time.Duration {

// GetQueryTimeout returns the current block time adjusted by the module's timeout parameter in Unix nanoseconds.
func (k *Keeper) GetQueryTimeout(ctx sdk.Context) int64 {
return ctx.BlockTime().Add(k.GetTimeout(ctx)).UnixNano()
t := k.GetTimeout(ctx)
return ctx.BlockTime().Add(t).UnixNano()
}
93 changes: 71 additions & 22 deletions x/oracle/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (
ibcicqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types"
ibcclienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
ibcchanneltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
ibchost "github.com/cosmos/ibc-go/v7/modules/core/24-host"

"github.com/sentinel-official/hub/v12/third_party/osmosis/x/poolmanager/client/queryproto"
protorevtypes "github.com/sentinel-official/hub/v12/third_party/osmosis/x/protorev/types"
"github.com/sentinel-official/hub/v12/x/oracle/types/v1"
)

// SendQueryPacket serializes query requests and sends them as an IBC packet to a destination chain.
Expand All @@ -39,7 +41,6 @@ func (k *Keeper) SendQueryPacket(
}

// OnAcknowledgementPacket processes the acknowledgement packet received after sending an IBC query packet.
// It deserializes the packet data and acknowledgement, validates the response count, and updates the relevant asset.
func (k *Keeper) OnAcknowledgementPacket(
ctx sdk.Context, packet ibcchanneltypes.Packet, ack ibcchanneltypes.Acknowledgement,
) error {
Expand Down Expand Up @@ -93,40 +94,88 @@ func (k *Keeper) OnAcknowledgementPacket(

// Iterate through each request-response pair and update the asset accordingly.
for i := 0; i < len(reqs); i++ {
// Skip updates if the response height is older than the current asset height.
if resps[i].GetHeight() < asset.Height {
return nil
}

// Handle specific query paths to extract the required data and update the asset.
switch reqs[i].Path {
case "/osmosis.poolmanager.v1beta1.Query/SpotPrice":
// Extract the spot price from the response and update the asset price.
var res queryproto.SpotPriceResponse
if err := k.cdc.Unmarshal(resps[i].GetValue(), &res); err != nil {
return err
}

spotPrice, err := sdkmath.LegacyNewDecFromStr(res.GetSpotPrice())
if err != nil {
if err := k.handleSpotPriceQueryResponse(ctx, asset, &resps[i]); err != nil {
return err
}

// Update the asset price using the spot price and its exponent.
asset.Price = spotPrice.MulInt(asset.Exponent()).TruncateInt()
case "/osmosis.protorev.v1beta1.Query/GetProtoRevPool":
// Extract the pool ID from the response and update the asset pool ID.
var res protorevtypes.QueryGetProtoRevPoolResponse
if err := k.cdc.Unmarshal(resps[i].GetValue(), &res); err != nil {
if err := k.handleProtoRevPoolQueryResponse(ctx, asset, &resps[i]); err != nil {
return err
}

asset.PoolID = res.GetPoolId()
}
}

return nil
}

// handleSpotPriceQueryResponse handles the response for the SpotPrice query.
func (k *Keeper) handleSpotPriceQueryResponse(ctx sdk.Context, asset v1.Asset, resp *abcitypes.ResponseQuery) error {
// Skip updates if the response height is older than the current asset height.
if resp.GetHeight() < asset.Height {
return nil
}

var res queryproto.SpotPriceResponse
if err := k.cdc.Unmarshal(resp.GetValue(), &res); err != nil {
return err
}

spotPrice, err := sdkmath.LegacyNewDecFromStr(res.GetSpotPrice())
if err != nil {
return err
}

// Update the asset price using the spot price and its multiplier.
asset.Price = spotPrice.MulInt(asset.Multiplier()).TruncateInt()
asset.Height = resp.GetHeight()

// Persist the updated asset information in the store.
k.SetAsset(ctx, asset)

return nil
}

// handleProtoRevPoolQueryResponse handles the response for the GetProtoRevPool query.
func (k *Keeper) handleProtoRevPoolQueryResponse(ctx sdk.Context, asset v1.Asset, resp *abcitypes.ResponseQuery) error {
// Unmarshal the response to extract the pool ID and other relevant details.
var res protorevtypes.QueryGetProtoRevPoolResponse
if err := k.cdc.Unmarshal(resp.GetValue(), &res); err != nil {
return err
}

// Retrieve necessary information for sending a follow-up query.
portID := k.GetPortID(ctx)
channelID := k.GetChannelID(ctx)
timeout := k.GetQueryTimeout(ctx)

// Get the channel capability to ensure we have the authority to send packets.
channelCap, found := k.capability.GetCapability(ctx, ibchost.ChannelCapabilityPath(portID, channelID))
if !found {
return nil
}

// Create a new request for the SpotPrice query using the pool ID and asset details.
req := abcitypes.RequestQuery{
Data: k.cdc.MustMarshal(
&queryproto.SpotPriceRequest{
PoolId: res.GetPoolId(),
BaseAssetDenom: asset.BaseAssetDenom,
QuoteAssetDenom: asset.QuoteAssetDenom,
},
),
Path: "/osmosis.poolmanager.v1beta1.Query/SpotPrice",
}

// Send the SpotPrice query packet over IBC.
sequence, err := k.SendQueryPacket(ctx, channelCap, portID, channelID, uint64(timeout), req)
if err != nil {
return err
}

// Map the sequence number to the asset denom for tracking.
k.SetDenomForPacket(ctx, portID, channelID, sequence, asset.Denom)

return nil
}
2 changes: 1 addition & 1 deletion x/oracle/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewErrorAssetNotFound(denom string) error {
}

func NewErrorDenomtNotFound(portID, channelID string, sequence uint64) error {
return sdkerrors.Wrapf(ErrorAssetNotFound, "denom for packet %s/%s/%d does not exist", portID, channelID, sequence)
return sdkerrors.Wrapf(ErrorDenomNotFound, "denom for packet %s/%s/%d does not exist", portID, channelID, sequence)
}

func NewErrorInvalidSigner(from, expected string) error {
Expand Down
32 changes: 1 addition & 31 deletions x/oracle/types/v1/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,10 @@ import (
"math/big"

sdkmath "cosmossdk.io/math"
abcitypes "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/sentinel-official/hub/v12/third_party/osmosis/x/poolmanager/client/queryproto"
protorevtypes "github.com/sentinel-official/hub/v12/third_party/osmosis/x/protorev/types"
)

func (a *Asset) ProtoRevPoolRequest(cdc codec.Codec) abcitypes.RequestQuery {
return abcitypes.RequestQuery{
Data: cdc.MustMarshal(
&protorevtypes.QueryGetProtoRevPoolRequest{
BaseDenom: a.BaseAssetDenom,
OtherDenom: a.QuoteAssetDenom,
},
),
Path: "/osmosis.protorev.v1beta1.Query/GetProtoRevPool",
}
}

func (a *Asset) SpotPriceRequest(cdc codec.Codec) abcitypes.RequestQuery {
return abcitypes.RequestQuery{
Data: cdc.MustMarshal(
&queryproto.SpotPriceRequest{
PoolId: a.PoolID,
BaseAssetDenom: a.BaseAssetDenom,
QuoteAssetDenom: a.QuoteAssetDenom,
},
),
Path: "/osmosis.poolmanager.v1beta1.Query/SpotPrice",
}
}

func (a *Asset) Exponent() sdkmath.Int {
func (a *Asset) Multiplier() sdkmath.Int {
i := new(big.Int).Exp(big.NewInt(10), big.NewInt(a.Decimals), nil)
return sdkmath.NewIntFromBigInt(i)
}
Expand Down
Loading

0 comments on commit 77f6e7d

Please sign in to comment.