-
Notifications
You must be signed in to change notification settings - Fork 613
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
Conversation
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 |
There was a problem hiding this 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/utils.go
Outdated
|
||
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)) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, changing this
// sanity check | ||
for i := 0; i < numPairs; i++ { | ||
if pairGT[i] == pairLT[i] { | ||
panic("input had duplicated denom") |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
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) |
x/gamm/twap/types/keys.go
Outdated
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 |
There was a problem hiding this comment.
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?
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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a suggestion :)
type AmmInterface interface { | |
type AMMInterface interface { |
There was a problem hiding this 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) { |
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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
x/gamm/twap/types/keys.go
Outdated
var historicalTWAPTimeIndexNoSeparator = "historical_time_index" | ||
var historicalTWAPPoolIndexNoSeparator = "historical_pool_index" | ||
|
||
var mostRecentTWAPsPrefix = mostRecentTWAPsNoSeparator + KeySeparator |
There was a problem hiding this comment.
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?
There was a problem hiding this 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) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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
} | ||
for name, tt := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
gotTimeKey := FormatHistoricalTimeIndexTWAPKey(tt.time, tt.poolId, tt.denom1, tt.denom2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not?
From:
osmosis/x/gamm/twap/types/keys.go
Lines 60 to 62 in 6924e57
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(), |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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
Co-authored-by: Aleksandr Bezobchuk <[email protected]>
Thanks so much for the review here! |
"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}, |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
What is the purpose of the change
Smaller PR to extract complexity in review out of #2168 .
Brief Changelog
Testing and Verifying
This change adds tests for the types directory
keys
functions.Documentation and Release Note
Unreleased
section inCHANGELOG.md
? no