Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TWAP proto, types package, and osmoutils #2175

Merged
merged 9 commits into from
Jul 22, 2022
Merged

TWAP proto, types package, and osmoutils #2175

merged 9 commits into from
Jul 22, 2022

Conversation

ValarDragon
Copy link
Member

What is the purpose of the change

Smaller PR to extract complexity in review out of #2168 .

Brief Changelog

  • Adds a number of helper methods to osmoutils
  • Adds TwapRecord proto struct
  • Adds Twap types package

Testing and Verifying

This change adds tests for the types directory keys functions.

Documentation and Release Note

  • Does this pull request introduce a new feature or user-facing behavior changes? no
  • Is a relevant changelog entry added to the Unreleased section in CHANGELOG.md? no
  • How is the feature or change documented? N/A, should come in logic PR, or other incremental updates

@ValarDragon ValarDragon requested a review from a team July 20, 2022 21:16
@github-actions github-actions bot added the C:x/gamm Changes, features and bugs related to the gamm module. label Jul 20, 2022
@ValarDragon
Copy link
Member Author

ValarDragon commented Jul 20, 2022

Sorry the diff is so large 😅 , 900 of the lines are generated proto at least

At least its better than having the 1350 lines of periphery in the core logic PR

Copy link
Member

@czarcas7ic czarcas7ic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, only had a few questions!

x/gamm/twap/types/keys.go Outdated Show resolved Hide resolved
x/gamm/twap/types/utils.go Outdated Show resolved Hide resolved
x/gamm/twap/types/expected_interfaces.go Outdated Show resolved Hide resolved
x/gamm/twap/types/keys.go Outdated Show resolved Hide resolved
osmoutils/slice_helper.go Show resolved Hide resolved
osmoutils/slice_helper.go Show resolved Hide resolved
osmoutils/store_helper.go Show resolved Hide resolved

func NewTwapRecord(k AmmInterface, ctx sdk.Context, poolId uint64, denom0 string, denom1 string) TwapRecord {
if !(denom0 > denom1) {
panic(fmt.Sprintf("precondition denom0 > denom1 not satisfied. denom0 %s | denom1 %s", denom0, denom1))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we return an error here instead of panicking for testability?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, changing this

x/gamm/twap/types/utils_test.go Outdated Show resolved Hide resolved
// sanity check
for i := 0; i < numPairs; i++ {
if pairGT[i] == pairLT[i] {
panic("input had duplicated denom")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider returning error for easier testing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding a test

nit: I still think that for this specific case error makes more than panic so that we can assert that a panic is coming exactly from here.

Otherwise, what if in the future this starts panicking in another location, then the test would be a false pass

x/gamm/twap/types/utils.go Outdated Show resolved Hide resolved
x/gamm/twap/types/keys.go Show resolved Hide resolved
@ValarDragon
Copy link
Member Author

ValarDragon commented Jul 21, 2022

All comments resolved, except for panic <> error changes I believe!

(I guess no tests for store_helpers -- can we do that in a subsequent PR, just to get the main PR diff down. The usages in twap have unit tests in context already)

Comment on lines 27 to 33
var mostRecentTWAPsNoSeparator = "recent_twap"
var historicalTWAPTimeIndexNoSeparator = "historical_time_index"
var historicalTWAPPoolIndexNoSeparator = "historical_pool_index"

var mostRecentTWAPsPrefix = mostRecentTWAPsNoSeparator + KeySeparator
var historicalTWAPTimeIndexPrefix = historicalTWAPTimeIndexNoSeparator + KeySeparator
var historicalTWAPPoolIndexPrefix = historicalTWAPPoolIndexNoSeparator + KeySeparator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we group these?

x/gamm/twap/types/keys.go Outdated Show resolved Hide resolved
x/gamm/twap/types/keys.go Outdated Show resolved Hide resolved
x/gamm/twap/types/keys.go Outdated Show resolved Hide resolved
import sdk "github.com/cosmos/cosmos-sdk/types"

// AmmInterface is the functionality needed from a given pool ID, in order to maintain records and serve TWAPs.
type AmmInterface interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a suggestion :)

Suggested change
type AmmInterface interface {
type AMMInterface interface {

Copy link
Member

@mattverse mattverse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌮

return keys
}

func GatherValuesFromStore[T any](storeObj store.KVStore, keyStart []byte, keyEnd []byte, parseValue func([]byte) (T, error)) ([]T, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah we can replace so much existing code and remove so much unnecessary duplocation with this single method :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup! And then we can do generic optimizations here as well

proto/osmosis/gamm/twap/v1beta1/twap_record.proto Outdated Show resolved Hide resolved
var historicalTWAPTimeIndexNoSeparator = "historical_time_index"
var historicalTWAPPoolIndexNoSeparator = "historical_pool_index"

var mostRecentTWAPsPrefix = mostRecentTWAPsNoSeparator + KeySeparator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this is plural?

x/gamm/twap/types/utils.go Show resolved Hide resolved
Copy link
Member

@p0mvn p0mvn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, awesome work on TWAP so far @ValarDragon

I bumped up some comments that seem unaddressed or with no reply. However, I think all of them are minor / nits and should not be blocking this.

UPDATE: noticed that an issue is created so removed my earlier comment about an issue for osmoutils tests. Thanks!

// using the specified pool.
// E.g. if pool 1 traded 2 atom for 3 osmo, the quote asset was atom, and the base asset was osmo,
// this would return 1.5. (Meaning that 1 atom costs 1.5 osmo)
// AmmInterface is the functionality needed from a given pool ID, in order to maintain records and serve TWAPs.
type AmmInterface interface {
GetPoolDenoms(ctx sdk.Context, poolId uint64) (denoms []string, err error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

godoc for GetPoolDenoms please

// A TWAP record should be indexed in state by pool_id, (asset pair), timestamp
// The asset pair assets should be lexicographically sorted.
// Technically (pool_id, asset_0_denom, asset_1_denom, height) do not need to
// appear in the struct however we view this as the wrong performance tradeoff
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump

// The asset pair assets should be lexicographically sorted.
// Technically (pool_id, asset_0_denom, asset_1_denom, height) do not need to
// appear in the struct however we view this as the wrong performance tradeoff
// given SDK today. Would rather we optimize for readability and correctness,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, please consider including this in the comment. Might be useful for future readers

x/gamm/twap/types/keys.go Outdated Show resolved Hide resolved
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
gotTimeKey := FormatHistoricalTimeIndexTWAPKey(tt.time, tt.poolId, tt.denom1, tt.denom2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

From:

if len(s) != 5 || s[0] != historicalTWAPTimeIndexNoSeparator {
panic("Called ParseTimeFromHistoricalTimeIndexKey on incorrectly formatted key")
}

What if we give bytes of invalid length to ParseTimeFromHistoricalTimeIndexKey?

Time: baseTime,
P0LastSpotPrice: sdk.NewDecWithPrec(1, 5),
P1LastSpotPrice: sdk.NewDecWithPrec(2, 5), // inconsistent value
P0ArithmeticTwapAccumulator: sdk.ZeroDec(),
Copy link
Member

@p0mvn p0mvn Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up to you, I don't think this is critical

// sanity check
for i := 0; i < numPairs; i++ {
if pairGT[i] == pairLT[i] {
panic("input had duplicated denom")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding a test

nit: I still think that for this specific case error makes more than panic so that we can assert that a panic is coming exactly from here.

Otherwise, what if in the future this starts panicking in another location, then the test would be a false pass

x/gamm/twap/types/utils.go Show resolved Hide resolved
@ValarDragon ValarDragon mentioned this pull request Jul 21, 2022
20 tasks
@ValarDragon
Copy link
Member Author

Thanks so much for the review here!

@ValarDragon ValarDragon merged commit e69e260 into main Jul 22, 2022
@ValarDragon ValarDragon deleted the dev/twap_types branch July 22, 2022 03:39
"basicRev": {[]string{"B", "A"}, []string{"B"}, []string{"A"}, false},
// AB > A
"prefixed": {[]string{"A", "AB"}, []string{"AB"}, []string{"A"}, false},
"basic-3": {[]string{"A", "B", "C"}, []string{"C", "C", "B"}, []string{"B", "A", "A"}, false},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the basic-3 test case. How is the the resulting GT pair and LT Pair the correct unique denom pairs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorts by gt symbol first then lt symbol

So
C,b
C,a
B,a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C:x/gamm Changes, features and bugs related to the gamm module.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

5 participants