Commit 952a2e68 authored by Dev Ojha's avatar Dev Ojha
Browse files

Merge branch 'main' into nicolas/ibc-rate-limit-integration-and-tests

parents c50cf10b 20c72cce
Showing with 470 additions and 560 deletions
+470 -560
......@@ -38,14 +38,6 @@ pull_request_rules:
backport:
branches:
- v4.x
- name: backport patches to v5.x branch
conditions:
- base=main
- label=A:backport/v5.x
actions:
backport:
branches:
- v5.x
- name: backport patches to v6.x branch
conditions:
- base=main
......@@ -54,14 +46,6 @@ pull_request_rules:
backport:
branches:
- v6.x
- name: backport patches to v7.x branch
conditions:
- base=main
- label=A:backport/v7.x
actions:
backport:
branches:
- v7.x
- name: backport patches to v8.x branch
conditions:
- base=main
......@@ -70,14 +54,6 @@ pull_request_rules:
backport:
branches:
- v8.x
- name: backport patches to v9.x branch
conditions:
- base=main
- label=A:backport/v9.x
actions:
backport:
branches:
- v9.x
- name: backport patches to v10.x branch
conditions:
- base=main
......@@ -113,7 +89,7 @@ pull_request_rules:
- name: backport patches to concentrated-liquidity-main
conditions:
- base=main
- label=A:backport/concentrated-liquidity-main
- label=A:backport/cl
actions:
backport:
branches:
......
......@@ -12,27 +12,7 @@ on:
workflow_dispatch:
jobs:
should_run_go_test:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
-
id: skip_check
uses: fkirc/skip-duplicate-actions@master
with:
cancel_others: "true" # workflow-runs from outdated commits will be cancelled.
concurrent_skipping: "same_content"
skip_after_successful_duplicate: "true"
paths: '["**/*.go", "**/*.mod", "**/*.sum"]'
do_not_skip: '["pull_request", "workflow_dispatch", "schedule"]'
-
name: Skipping test
run: echo Should I skip tests? ${{ steps.skip_check.outputs.should_skip }}
go:
needs: should_run_go_test
if: ${{ needs.should_run_test.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest
steps:
-
......
......@@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Features
* [#2788](https://github.com/osmosis-labs/osmosis/pull/2788) Add logarithm base 2 implementation.
* [#2739](https://github.com/osmosis-labs/osmosis/pull/2739) Add pool type query
### Bug fixes
......
......@@ -350,6 +350,14 @@ func (s *KeeperTestHelper) BuildTx(
return txBuilder.GetTx()
}
// StateNotAltered validates that app state is not altered. Fails if it is.
func (s *KeeperTestHelper) StateNotAltered() {
oldState := s.App.ExportState(s.Ctx)
s.Commit()
newState := s.App.ExportState(s.Ctx)
s.Require().Equal(oldState, newState)
}
// CreateRandomAccounts is a function return a list of randomly generated AccAddresses
func CreateRandomAccounts(numAccts int) []sdk.AccAddress {
testAddrs := make([]sdk.AccAddress, numAccts)
......
......@@ -195,3 +195,7 @@ func (app *OsmosisApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddr
},
)
}
func (app *OsmosisApp) ExportState(ctx sdk.Context) map[string]json.RawMessage {
return app.mm.ExportGenesis(ctx, app.AppCodec())
}
......@@ -12,7 +12,7 @@ require (
github.com/gogo/protobuf v1.3.3
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/golangci/golangci-lint v1.50.0
github.com/golangci/golangci-lint v1.50.1
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/mattn/go-sqlite3 v1.14.15
......@@ -24,13 +24,13 @@ require (
github.com/spf13/cobra v1.6.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.13.0
github.com/stretchr/testify v1.8.0
github.com/tendermint/tendermint v0.34.21
github.com/stretchr/testify v1.8.1
github.com/tendermint/tendermint v0.34.22
github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b
go.uber.org/multierr v1.8.0
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b
google.golang.org/grpc v1.49.0
google.golang.org/grpc v1.50.0
gopkg.in/yaml.v2 v2.4.0
mvdan.cc/gofumpt v0.4.0
)
......@@ -43,7 +43,7 @@ require (
github.com/curioswitch/go-reassign v0.2.0 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/google/btree v1.0.0 // indirect
github.com/kkHAIKE/contextcheck v1.1.2 // indirect
github.com/kkHAIKE/contextcheck v1.1.3 // indirect
github.com/maratori/testableexamples v1.0.0 // indirect
github.com/regen-network/cosmos-proto v0.3.1 // indirect
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
......@@ -51,8 +51,8 @@ require (
github.com/sivchari/nosnakecase v1.7.0 // indirect
github.com/timonwong/loggercheck v0.9.3 // indirect
github.com/zimmski/go-mutesting v0.0.0-20210610104036-6d9217011a00 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/zap v1.21.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/zap v1.22.0 // indirect
)
require (
......@@ -63,7 +63,7 @@ require (
github.com/Antonboom/errname v0.1.7 // indirect
github.com/Antonboom/nilnil v0.1.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/BurntSushi/toml v1.2.0 // indirect
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/CosmWasm/wasmvm v1.0.0
github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect
......@@ -97,7 +97,7 @@ require (
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
github.com/cosmos/ledger-go v0.9.3 // indirect
github.com/daixiang0/gci v0.8.0 // indirect
github.com/daixiang0/gci v0.8.1 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denis-tingaikin/go-header v0.4.3 // indirect
......@@ -199,11 +199,11 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
github.com/mgechev/revive v1.2.4 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
github.com/moricho/tparallel v0.2.1 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/nakabonne/nestif v0.3.1 // indirect
......@@ -228,14 +228,14 @@ require (
github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rs/cors v1.8.2 // indirect
github.com/rs/zerolog v1.27.0 // indirect
github.com/ryancurrah/gomodguard v1.2.4 // indirect
github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect
github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/securego/gosec/v2 v2.13.1 // indirect
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
......@@ -247,7 +247,7 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
github.com/stretchr/objx v0.4.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca
github.com/tdakkota/asciicheck v0.1.1 // indirect
......@@ -256,8 +256,8 @@ require (
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tetafro/godot v1.4.11 // indirect
github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect
github.com/tomarrell/wrapcheck/v2 v2.6.2 // indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.0 // indirect
github.com/tomarrell/wrapcheck/v2 v2.7.0 // indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
github.com/ultraware/funlen v0.0.3 // indirect
github.com/ultraware/whitespace v0.0.5 // indirect
github.com/uudashr/gocognit v1.0.6 // indirect
......@@ -272,15 +272,15 @@ require (
gitlab.com/bosi/decorder v0.2.3 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20220726230323-06994584191e // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.12 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/protobuf v1.28.1
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
......
This diff is collapsed.
......@@ -30,6 +30,9 @@ const (
// max number of iterations in ApproxRoot function
maxApproxRootIterations = 100
// max number of iterations in Log2 function
maxLog2Iterations = 300
)
var (
......@@ -39,6 +42,10 @@ var (
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)
// initialized in init() since requires
// precision to be defined.
twoBigDec BigDec
)
// Decimal errors
......@@ -54,6 +61,8 @@ func init() {
for i := 0; i <= Precision; i++ {
precisionMultipliers[i] = calcPrecisionMultiplier(int64(i))
}
twoBigDec = NewBigDec(2)
}
func precisionInt() *big.Int {
......@@ -211,7 +220,8 @@ func (d BigDec) GTE(d2 BigDec) bool { return (d.i).Cmp(d2.i) >= 0 } /
func (d BigDec) LT(d2 BigDec) bool { return (d.i).Cmp(d2.i) < 0 } // less than
func (d BigDec) LTE(d2 BigDec) bool { return (d.i).Cmp(d2.i) <= 0 } // less than or equal
func (d BigDec) Neg() BigDec { return BigDec{new(big.Int).Neg(d.i)} } // reverse the decimal sign
func (d BigDec) Abs() BigDec { return BigDec{new(big.Int).Abs(d.i)} } // absolute value
// nolint: stylecheck
func (d BigDec) Abs() BigDec { return BigDec{new(big.Int).Abs(d.i)} } // absolute value
// BigInt returns a copy of the underlying big.Int.
func (d BigDec) BigInt() *big.Int {
......@@ -856,3 +866,54 @@ func DecApproxEq(t *testing.T, d1 BigDec, d2 BigDec, tol BigDec) (*testing.T, bo
diff := d1.Sub(d2).Abs()
return t, diff.LTE(tol), "expected |d1 - d2| <:\t%v\ngot |d1 - d2| = \t\t%v", tol.String(), diff.String()
}
// LogBase2 returns log_2 {x}.
// Rounds down by truncations during division and right shifting.
// Accurate up to 32 precision digits.
// Implementation is based on:
// https://stm32duinoforum.com/forum/dsp/BinaryLogarithm.pdf
func (x BigDec) LogBase2() BigDec {
// create a new decimal to avoid mutating
// the receiver's int buffer.
xCopy := ZeroDec()
xCopy.i = new(big.Int).Set(x.i)
if xCopy.LTE(ZeroDec()) {
panic(fmt.Sprintf("log is not defined at <= 0, given (%s)", xCopy))
}
// Normalize x to be 1 <= x < 2.
// y is the exponent that results in a whole multiple of 2.
y := ZeroDec()
// repeat until: x >= 1.
for xCopy.LT(OneDec()) {
xCopy.i.Lsh(xCopy.i, 1)
y = y.Sub(OneDec())
}
// repeat until: x < 2.
for xCopy.GTE(twoBigDec) {
xCopy.i.Rsh(xCopy.i, 1)
y = y.Add(OneDec())
}
b := OneDec().Quo(twoBigDec)
// N.B. At this point x is a positive real number representing
// mantissa of the log. We estimate it using the following
// algorithm:
// https://stm32duinoforum.com/forum/dsp/BinaryLogarithm.pdf
// This has shown precision of 32 digits relative
// to Wolfram Alpha in tests.
for i := 0; i < maxLog2Iterations; i++ {
xCopy = xCopy.Mul(xCopy)
if xCopy.GTE(twoBigDec) {
xCopy.i.Rsh(xCopy.i, 1)
y = y.Add(b)
}
b.i.Rsh(b.i, 1)
}
return y
}
......@@ -11,6 +11,8 @@ import (
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gopkg.in/yaml.v2"
"github.com/osmosis-labs/osmosis/v12/app/apptesting/osmoassert"
)
type decimalTestSuite struct {
......@@ -152,8 +154,8 @@ func (s *decimalTestSuite) TestDecFloat64() {
func (s *decimalTestSuite) TestSdkDec() {
tests := []struct {
d BigDec
want sdk.Dec
d BigDec
want sdk.Dec
expPanic bool
}{
{NewBigDec(0), sdk.MustNewDecFromStr("0.000000000000000000"), false},
......@@ -177,8 +179,8 @@ func (s *decimalTestSuite) TestSdkDec() {
func (s *decimalTestSuite) TestBigDecFromSdkDec() {
tests := []struct {
d sdk.Dec
want BigDec
d sdk.Dec
want BigDec
expPanic bool
}{
{sdk.MustNewDecFromStr("0.000000000000000000"), NewBigDec(0), false},
......@@ -202,8 +204,8 @@ func (s *decimalTestSuite) TestBigDecFromSdkDec() {
func (s *decimalTestSuite) TestBigDecFromSdkDecSlice() {
tests := []struct {
d []sdk.Dec
want []BigDec
d []sdk.Dec
want []BigDec
expPanic bool
}{
{[]sdk.Dec{sdk.MustNewDecFromStr("0.000000000000000000")}, []BigDec{NewBigDec(0)}, false},
......@@ -441,14 +443,14 @@ func (s *decimalTestSuite) TestDecCeil() {
input BigDec
expected BigDec
}{
{MustNewDecFromStr("0.001"), NewBigDec(1)}, // 0.001 => 1.0
{MustNewDecFromStr("-0.001"), ZeroDec()}, // -0.001 => 0.0
{ZeroDec(), ZeroDec()}, // 0.0 => 0.0
{MustNewDecFromStr("0.9"), NewBigDec(1)}, // 0.9 => 1.0
{MustNewDecFromStr("0.001"), NewBigDec(1)}, // 0.001 => 1.0
{MustNewDecFromStr("-0.001"), ZeroDec()}, // -0.001 => 0.0
{ZeroDec(), ZeroDec()}, // 0.0 => 0.0
{MustNewDecFromStr("0.9"), NewBigDec(1)}, // 0.9 => 1.0
{MustNewDecFromStr("4.001"), NewBigDec(5)}, // 4.001 => 5.0
{MustNewDecFromStr("-4.001"), NewBigDec(-4)}, // -4.001 => -4.0
{MustNewDecFromStr("4.7"), NewBigDec(5)}, // 4.7 => 5.0
{MustNewDecFromStr("-4.7"), NewBigDec(-4)}, // -4.7 => -4.0
{MustNewDecFromStr("4.7"), NewBigDec(5)}, // 4.7 => 5.0
{MustNewDecFromStr("-4.7"), NewBigDec(-4)}, // -4.7 => -4.0
}
for i, tc := range testCases {
......@@ -463,11 +465,11 @@ func (s *decimalTestSuite) TestPower() {
power uint64
expected BigDec
}{
{OneDec(), 10, OneDec()}, // 1.0 ^ (10) => 1.0
{NewDecWithPrec(5, 1), 2, NewDecWithPrec(25, 2)}, // 0.5 ^ 2 => 0.25
{NewDecWithPrec(2, 1), 2, NewDecWithPrec(4, 2)}, // 0.2 ^ 2 => 0.04
{NewDecFromInt(NewInt(3)), 3, NewDecFromInt(NewInt(27))}, // 3 ^ 3 => 27
{NewDecFromInt(NewInt(-3)), 4, NewDecFromInt(NewInt(81))}, // -3 ^ 4 = 81
{OneDec(), 10, OneDec()}, // 1.0 ^ (10) => 1.0
{NewDecWithPrec(5, 1), 2, NewDecWithPrec(25, 2)}, // 0.5 ^ 2 => 0.25
{NewDecWithPrec(2, 1), 2, NewDecWithPrec(4, 2)}, // 0.2 ^ 2 => 0.04
{NewDecFromInt(NewInt(3)), 3, NewDecFromInt(NewInt(27))}, // 3 ^ 3 => 27
{NewDecFromInt(NewInt(-3)), 4, NewDecFromInt(NewInt(81))}, // -3 ^ 4 = 81
{MustNewDecFromStr("1.414213562373095048801688724209698079"), 2, NewDecFromInt(NewInt(2))}, // 1.414213562373095048801688724209698079 ^ 2 = 2
}
......@@ -483,14 +485,14 @@ func (s *decimalTestSuite) TestApproxRoot() {
root uint64
expected BigDec
}{
{OneDec(), 10, OneDec()}, // 1.0 ^ (0.1) => 1.0
{NewDecWithPrec(25, 2), 2, NewDecWithPrec(5, 1)}, // 0.25 ^ (0.5) => 0.5
{NewDecWithPrec(4, 2), 2, NewDecWithPrec(2, 1)}, // 0.04 ^ (0.5) => 0.2
{NewDecFromInt(NewInt(27)), 3, NewDecFromInt(NewInt(3))}, // 27 ^ (1/3) => 3
{NewDecFromInt(NewInt(-81)), 4, NewDecFromInt(NewInt(-3))}, // -81 ^ (0.25) => -3
{NewDecFromInt(NewInt(2)), 2, MustNewDecFromStr("1.414213562373095048801688724209698079")}, // 2 ^ (0.5) => 1.414213562373095048801688724209698079
{OneDec(), 10, OneDec()}, // 1.0 ^ (0.1) => 1.0
{NewDecWithPrec(25, 2), 2, NewDecWithPrec(5, 1)}, // 0.25 ^ (0.5) => 0.5
{NewDecWithPrec(4, 2), 2, NewDecWithPrec(2, 1)}, // 0.04 ^ (0.5) => 0.2
{NewDecFromInt(NewInt(27)), 3, NewDecFromInt(NewInt(3))}, // 27 ^ (1/3) => 3
{NewDecFromInt(NewInt(-81)), 4, NewDecFromInt(NewInt(-3))}, // -81 ^ (0.25) => -3
{NewDecFromInt(NewInt(2)), 2, MustNewDecFromStr("1.414213562373095048801688724209698079")}, // 2 ^ (0.5) => 1.414213562373095048801688724209698079
{NewDecWithPrec(1005, 3), 31536000, MustNewDecFromStr("1.000000000158153903837946258002096839")}, // 1.005 ^ (1/31536000) ≈ 1.000000000158153903837946258002096839
{SmallestDec(), 2, NewDecWithPrec(1, 18)}, // 1e-36 ^ (0.5) => 1e-18
{SmallestDec(), 2, NewDecWithPrec(1, 18)}, // 1e-36 ^ (0.5) => 1e-18
{SmallestDec(), 3, MustNewDecFromStr("0.000000000001000000000000000002431786")}, // 1e-36 ^ (1/3) => 1e-12
{NewDecWithPrec(1, 8), 3, MustNewDecFromStr("0.002154434690031883721759293566519280")}, // 1e-8 ^ (1/3) ≈ 0.002154434690031883721759293566519
}
......@@ -511,11 +513,11 @@ func (s *decimalTestSuite) TestApproxSqrt() {
input BigDec
expected BigDec
}{
{OneDec(), OneDec()}, // 1.0 => 1.0
{NewDecWithPrec(25, 2), NewDecWithPrec(5, 1)}, // 0.25 => 0.5
{NewDecWithPrec(4, 2), NewDecWithPrec(2, 1)}, // 0.09 => 0.3
{NewDecFromInt(NewInt(9)), NewDecFromInt(NewInt(3))}, // 9 => 3
{NewDecFromInt(NewInt(-9)), NewDecFromInt(NewInt(-3))}, // -9 => -3
{OneDec(), OneDec()}, // 1.0 => 1.0
{NewDecWithPrec(25, 2), NewDecWithPrec(5, 1)}, // 0.25 => 0.5
{NewDecWithPrec(4, 2), NewDecWithPrec(2, 1)}, // 0.09 => 0.3
{NewDecFromInt(NewInt(9)), NewDecFromInt(NewInt(3))}, // 9 => 3
{NewDecFromInt(NewInt(-9)), NewDecFromInt(NewInt(-3))}, // -9 => -3
{NewDecFromInt(NewInt(2)), MustNewDecFromStr("1.414213562373095048801688724209698079")}, // 2 => 1.414213562373095048801688724209698079
}
......@@ -650,3 +652,90 @@ func BenchmarkMarshalTo(b *testing.B) {
}
}
}
func (s *decimalTestSuite) TestLog2() {
var expectedErrTolerance = MustNewDecFromStr("0.000000000000000000000000000000000100")
tests := map[string]struct {
initialValue BigDec
expected BigDec
expectedPanic bool
}{
"log_2{-1}; invalid; panic": {
initialValue: OneDec().Neg(),
expectedPanic: true,
},
"log_2{0}; invalid; panic": {
initialValue: ZeroDec(),
expectedPanic: true,
},
"log_2{0.001} = -9.965784284662087043610958288468170528": {
initialValue: MustNewDecFromStr("0.001"),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+0.999912345+with+33+digits
expected: MustNewDecFromStr("-9.965784284662087043610958288468170528"),
},
"log_2{0.56171821941421412902170941} = -0.832081497183140708984033250637831402": {
initialValue: MustNewDecFromStr("0.56171821941421412902170941"),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+0.56171821941421412902170941+with+36+digits
expected: MustNewDecFromStr("-0.832081497183140708984033250637831402"),
},
"log_2{0.999912345} = -0.000126464976533858080645902722235833": {
initialValue: MustNewDecFromStr("0.999912345"),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+0.999912345+with+37+digits
expected: MustNewDecFromStr("-0.000126464976533858080645902722235833"),
},
"log_2{1} = 0": {
initialValue: NewBigDec(1),
expected: NewBigDec(0),
},
"log_2{2} = 1": {
initialValue: NewBigDec(2),
expected: NewBigDec(1),
},
"log_2{7} = 2.807354922057604107441969317231830809": {
initialValue: NewBigDec(7),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+7+37+digits
expected: MustNewDecFromStr("2.807354922057604107441969317231830809"),
},
"log_2{512} = 9": {
initialValue: NewBigDec(512),
expected: NewBigDec(9),
},
"log_2{580} = 9.179909090014934468590092754117374938": {
initialValue: NewBigDec(580),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+600+37+digits
expected: MustNewDecFromStr("9.179909090014934468590092754117374938"),
},
"log_2{1024} = 10": {
initialValue: NewBigDec(1024),
expected: NewBigDec(10),
},
"log_2{1024.987654321} = 10.001390817654141324352719749259888355": {
initialValue: NewDecWithPrec(1024987654321, 9),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+1024.987654321+38+digits
expected: MustNewDecFromStr("10.001390817654141324352719749259888355"),
},
"log_2{912648174127941279170121098210.92821920190204131121} = 99.525973560175362367047484597337715868": {
initialValue: MustNewDecFromStr("912648174127941279170121098210.92821920190204131121"),
// From: https://www.wolframalpha.com/input?i=log+base+2+of+912648174127941279170121098210.92821920190204131121+38+digits
expected: MustNewDecFromStr("99.525973560175362367047484597337715868"),
},
}
for name, tc := range tests {
s.Run(name, func() {
osmoassert.ConditionalPanic(s.T(), tc.expectedPanic, func() {
// Create a copy to test that the original was not modified.
// That is, that LogbBase2() is non-mutative.
initialCopy := ZeroDec()
initialCopy.i.Set(tc.initialValue.i)
// system under test.
res := tc.initialValue.LogBase2()
require.True(DecApproxEq(s.T(), tc.expected, res, expectedErrTolerance))
require.Equal(s.T(), initialCopy, tc.initialValue)
})
})
}
}
package osmomath
import (
"math/rand"
"testing"
)
func BenchmarkLog2(b *testing.B) {
tests := []BigDec{
MustNewDecFromStr("1.2"),
MustNewDecFromStr("1.234"),
MustNewDecFromStr("1024"),
NewBigDec(2048 * 2048 * 2048 * 2048 * 2048),
MustNewDecFromStr("999999999999999999999999999999999999999999999999999999.9122181273612911"),
MustNewDecFromStr("0.563289239121902491248219047129047129"),
}
for i := 0; i < b.N; i++ {
b.StopTimer()
test := tests[rand.Int63n(int64(len(tests)))]
b.StartTimer()
_ = test.LogBase2()
}
}
......@@ -42,7 +42,6 @@ func TestDivIntByU64ToBigDec(t *testing.T) {
addTCForAllRoundingModes("odd divided by 2", sdk.NewInt(5), 2, NewDecWithPrec(25, 1))
for name, tt := range tests {
fmt.Println("start")
t.Run(name, func(t *testing.T) {
got, err := DivIntByU64ToBigDec(tt.i, tt.u, tt.round)
require.Equal(t, tt.want, got)
......
......@@ -7,6 +7,7 @@ import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "osmosis/lockup/lock.proto";
import "osmosis/lockup/params.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/lockup/types";
......@@ -118,6 +119,10 @@ service Query {
option (google.api.http).get =
"/osmosis/lockup/v1beta1/account_locked_longer_duration_denom/{owner}";
}
// Params returns lockup params.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/osmosis/lockup/v1beta1/params";
}
}
message ModuleBalanceRequest {};
......@@ -287,3 +292,8 @@ message AccountLockedLongerDurationDenomRequest {
message AccountLockedLongerDurationDenomResponse {
repeated PeriodLock locks = 1 [ (gogoproto.nullable) = false ];
};
message QueryParamsRequest {}
message QueryParamsResponse {
Params params = 1 [ (gogoproto.nullable) = false ];
}
syntax = "proto3";
package osmosis.streamswap.v1;
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/streamswap/types";
option (gogoproto.goproto_getters_all) = false;
message EventCreateSale {
uint64 id = 1;
string creator = 2;
string token_in = 3;
cosmos.base.v1beta1.Coin token_out = 4 [ (gogoproto.nullable) = false ];
}
message EventSubscribe {
string sender = 1;
uint64 sale_id = 2;
string amount = 3;
}
message EventWithdraw {
string sender = 1;
uint64 sale_id = 2;
// amount of staked token_in withdrawn by user.
string amount = 3;
}
message EventExit {
string sender = 1;
uint64 sale_id = 2;
// amount of purchased token_out sent to the user
string purchased = 3;
}
message EventFinalizeSale {
uint64 sale_id = 1;
// amount of earned tokens_in
string income = 3;
}
syntax = "proto3";
package osmosis.streamswap.v1;
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "osmosis/streamswap/v1/state.proto";
import "osmosis/streamswap/v1/params.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/streamswap/types";
// GenesisState defines the streamswap module's genesis state.
message GenesisState {
repeated Sale sales = 1 [ (gogoproto.nullable) = false ];
repeated UserPositionKV user_positions = 2 [ (gogoproto.nullable) = false ];
uint64 next_sale_id = 3;
Params params = 4 [ (gogoproto.nullable) = false ];
}
// UserPositionKV is a record in genesis representing acc_address user position
// of a sale_id sale.
message UserPositionKV {
// user account address
string acc_address = 1;
uint64 sale_id = 2;
UserPosition user_position = 3 [ (gogoproto.nullable) = false ];
}
syntax = "proto3";
package osmosis.streamswap.v1;
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "google/protobuf/duration.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/streamswap/types";
// Params holds parameters for the streamswap module
message Params {
// fee charged when creating a new sale. The fee will go to the
// sale_fee_recipient unless it is not defined (empty).
repeated cosmos.base.v1beta1.Coin sale_creation_fee = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.moretags) = "yaml:\"sale_creation_fee\"",
(gogoproto.nullable) = false
];
// bech32 address of the fee recipient
string sale_creation_fee_recipient = 2;
// minimum amount duration of time between the sale creation and the sale
// start time.
google.protobuf.Duration min_duration_until_start_time = 3
[ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ];
// minimum duration for every new sale.
google.protobuf.Duration min_sale_duration = 4
[ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ];
}
syntax = "proto3";
package osmosis.streamswap.v1;
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "osmosis/streamswap/v1/state.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/streamswap/types";
option (gogoproto.goproto_getters_all) = false;
// Query defines the gRPC querier service.
service Query {
// Returns list of Sales ordered by the creation time
rpc Sales(QuerySales) returns (QuerySalesResponse) {
option (google.api.http).get = "/cosmos/streamswap/v1/sales";
}
// Returns the specific Sale object
rpc Sale(QuerySale) returns (QuerySaleResponse) {
option (google.api.http).get = "/cosmos/streamswap/v1/sales/{sale_id}";
}
rpc UserPosition(QueryUserPosition) returns (QueryUserPositionResponse) {
option (google.api.http).get =
"/cosmos/streamswap/v1/sales/{sale_id}/{user}";
}
}
message QuerySales {
// pagination defines an pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QuerySalesResponse {
repeated osmosis.streamswap.v1.Sale sales = 1
[ (gogoproto.nullable) = false ];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// Request type for Query/Sale
message QuerySale {
// Sale ID
uint64 sale_id = 1;
}
message QuerySaleResponse {
osmosis.streamswap.v1.Sale sale = 1 [ (gogoproto.nullable) = false ];
}
// Request type for Query/Sale
message QueryUserPosition {
// ID of the Sale
uint64 sale_id = 1;
// user account address
string user = 2;
}
message QueryUserPositionResponse {
osmosis.streamswap.v1.UserPosition user_position = 1
[ (gogoproto.nullable) = false ];
}
syntax = "proto3";
package osmosis.streamswap.v1;
import "google/protobuf/timestamp.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/streamswap/types";
option (gogoproto.goproto_getters_all) = false;
message Sale {
// Destination for the earned token_in
string treasury = 1;
uint64 id = 2;
// token_out is a token denom to be bootstraped. May be referred as base
// currency, or a sale token.
string token_out = 3;
// token_in is a token denom used to buy sale tokens (`token_out`). May be
// referred as quote_currency or payment token.
string token_in = 4;
// total number of `tokens_out` to be sold during the continuous sale.
string token_out_supply = 5 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// start time when the token emission starts.
google.protobuf.Timestamp start_time = 6
[ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ];
// end time when the token emission ends. Can't be bigger than start +
// 139years (to avoid round overflow)
google.protobuf.Timestamp end_time = 7
[ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ];
// Round number when the sale was last time updated.
int64 round = 8;
// Last round of the Sale;
int64 end_round = 9;
// amout of remaining token_out to sell
string out_remaining = 10 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// amount of token_out sold
string out_sold = 11 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// out token per share
string out_per_share = 12 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// total amount of currently staked coins (token_in) but not spent coins.
string staked = 13 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// total amount of earned coins (token_in)
string income = 14 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// total amount of shares
string shares = 15 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// Name for the sale.
string name = 20;
// URL with sale and project details.
string url = 21;
}
// UserPosition represents user account in a sale
message UserPosition {
string shares = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// total number of currently staked tokens
string staked = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// last token/share ratio
string out_per_share = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// amount of token_in spent
string spent = 4 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// Amount of accumulated, not withdrawn, purchased tokens (token_out)
string purchased = 5 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}
syntax = "proto3";
package osmosis.streamswap.v1;
import "gogoproto/gogo.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
option go_package = "github.com/osmosis-labs/osmosis/v12/x/streamswap/types";
option (gogoproto.goproto_getters_all) = false;
service Msg {
// CreateSale creates new token sale. Anyone can create a new sale.
// params.SaleBond OSMO will be charged as a bond (returned in FinalizeSale)
// to avoid spams.
// The sale follows the streamswap functionality explained in the
// x/launchapd/spec
rpc CreateSale(MsgCreateSale) returns (MsgCreateSaleResponse);
// Subscribe to a token sale. Any use at any time before the sale end can join
// the sale by sending `token_in` to the Sale through the Subscribe msg.
// During the sale, user `token_in` will be automatically charged every
// epoch to purchase `token_out`.
rpc Subscribe(MsgSubscribe) returns (google.protobuf.Empty);
// Withdraw sends back `amount` of unspent tokens_in to the user.
// If `amount` is empty, it will default to all unspent tokens.
// User can do it any time unless his deposit is empty.
rpc Withdraw(MsgWithdraw) returns (google.protobuf.Empty);
// ExitSale withdraws (by a user who subscribed to the sale) purchased
// tokens_out from the pool and remained tokens_in. Must be called after
// the sale end.
rpc ExitSale(MsgExitSale) returns (MsgExitSaleResponse);
// FinalizeSale clean ups the sale and sends income (earned tokens_in) to the
// Sale recipient. Returns error if called before the Sale end or it was
// already finalized. Anyone can call this method.
rpc FinalizeSale(MsgFinalizeSale) returns (MsgFinalizeSaleResponse);
}
message MsgCreateSale {
// Sale creator and the account which provides token (token_out) to the sale.
// When processing this message, token_out
string creator = 1;
// token_in is a denom used to buy `token_out`. May be referred as a
// "quote currency".
string token_in = 2;
// token_out is a coin supply (denom + amount) to sell. May be referred as
// "base currency". The whole supply will be transferred from the creator
// to the module and will be sold during the sale.
cosmos.base.v1beta1.Coin token_out = 3 [ (gogoproto.nullable) = false ];
// Maximum fee the creator is going to pay for creating a sale. The creator
// will be charged params.SaleCreationFee. Transaction will fail if
// max_fee is smaller than params.SaleCreationFee. If empty, the creator
// doesn't accept any fee.
repeated cosmos.base.v1beta1.Coin max_fee = 4
[ (gogoproto.nullable) = false ];
// start time when the token sale starts.
google.protobuf.Timestamp start_time = 5
[ (gogoproto.nullable) = false, (gogoproto.stdtime) = true ];
// duration time that the sale takes place over
google.protobuf.Duration duration = 6
[ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ];
// Recipient is the account which receives earned `token_in` from when the
// sale is finalized. If not defined (empty) the creator
// account will be used.
string recipient = 7;
// Name for the sale, max 40 characters, min 4. Required.
string name = 8;
// URL with sale and project details. Can be a link a link to IPFS,
// hackmd, project page, blog post... Max 120 characters. Must be
// valid agains Go url.ParseRequestURI. Required.
string url = 9;
}
message MsgCreateSaleResponse {
uint64 sale_id = 1 [ (gogoproto.moretags) = "yaml:\"sale_id\"" ];
}
message MsgSubscribe {
// sender is an account address adding a deposit
string sender = 1;
// ID of an existing sale.
uint64 sale_id = 2 [ (gogoproto.moretags) = "yaml:\"sale_id\"" ];
// number of sale.token_in staked by a user.
string amount = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}
message MsgWithdraw {
// sender is an account address subscribed to the sale_id
string sender = 1;
// ID of a sale.
uint64 sale_id = 2 [ (gogoproto.moretags) = "yaml:\"sale_id\"" ];
// amount of tokens_in to withdraw. Must be at most the amount of not spent
// tokens, unless set to null - then all remaining balance will be withdrawn.
string amount = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = true
];
}
message MsgExitSale {
// sender is an account address exiting a sale
string sender = 1;
// ID of an existing sale.
uint64 sale_id = 2 [ (gogoproto.moretags) = "yaml:\"sale_id\"" ];
}
message MsgExitSaleResponse {
// Purchased amount of "out" tokens withdrawn to the user.
string purchased = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}
message MsgFinalizeSale {
// sender is an account signing the message and triggering the finalization.
string sender = 1;
// ID of an existing sale.
uint64 sale_id = 2 [ (gogoproto.moretags) = "yaml:\"sale_id\"" ];
}
message MsgFinalizeSaleResponse {
// Income amount of token_in sent to the sale recipient.
string income = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}
package cli_test
import (
gocontext "context"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/osmosis-labs/osmosis/v12/app/apptesting"
"github.com/osmosis-labs/osmosis/v12/x/epochs/types"
)
type QueryTestSuite struct {
apptesting.KeeperTestHelper
queryClient types.QueryClient
}
func (s *QueryTestSuite) SetupSuite() {
s.Setup()
s.queryClient = types.NewQueryClient(s.QueryHelper)
// add new epoch
epoch := types.EpochInfo{
Identifier: "weekly",
StartTime: time.Time{},
Duration: time.Hour,
CurrentEpoch: 0,
CurrentEpochStartHeight: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
}
s.App.EpochsKeeper.AddEpochInfo(s.Ctx, epoch)
s.Commit()
}
func (s *QueryTestSuite) TestQueriesNeverAlterState() {
testCases := []struct {
name string
query string
input interface{}
output interface{}
}{
{
"Query current epoch",
"/osmosis.epochs.v1beta1.Query/CurrentEpoch",
&types.QueryCurrentEpochRequest{Identifier: "weekly"},
&types.QueryCurrentEpochResponse{},
},
{
"Query epochs info",
"/osmosis.epochs.v1beta1.Query/EpochInfos",
&types.QueryEpochsInfoRequest{},
&types.QueryEpochsInfoResponse{},
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
s.SetupSuite()
err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
s.Require().NoError(err)
s.StateNotAltered()
})
}
}
func TestQueryTestSuite(t *testing.T) {
suite.Run(t, new(QueryTestSuite))
}
package cli_test
import (
gocontext "context"
"testing"
"github.com/stretchr/testify/suite"
"github.com/osmosis-labs/osmosis/v12/app/apptesting"
"github.com/osmosis-labs/osmosis/v12/x/gamm/types"
)
type QueryTestSuite struct {
apptesting.KeeperTestHelper
queryClient types.QueryClient
}
func (s *QueryTestSuite) SetupSuite() {
s.Setup()
s.queryClient = types.NewQueryClient(s.QueryHelper)
// create a new pool
s.PrepareBalancerPool()
s.Commit()
}
func (s *QueryTestSuite) TestQueriesNeverAlterState() {
testCases := []struct {
name string
query string
input interface{}
output interface{}
}{
{
"Query pools",
"/osmosis.gamm.v1beta1.Query/Pools",
&types.QueryPoolsRequest{},
&types.QueryPoolsResponse{},
},
{
"Query single pool",
"/osmosis.gamm.v1beta1.Query/Pool",
&types.QueryPoolRequest{PoolId: 1},
&types.QueryPoolsResponse{},
},
{
"Query num pools",
"/osmosis.gamm.v1beta1.Query/NumPools",
&types.QueryNumPoolsRequest{},
&types.QueryNumPoolsResponse{},
},
{
"Query pool params",
"/osmosis.gamm.v1beta1.Query/PoolParams",
&types.QueryPoolParamsRequest{PoolId: 1},
&types.QueryPoolParamsResponse{},
},
{
"Query pool type",
"/osmosis.gamm.v1beta1.Query/PoolType",
&types.QueryPoolTypeRequest{PoolId: 1},
&types.QueryPoolTypeResponse{},
},
{
"Query spot price",
"/osmosis.gamm.v1beta1.Query/SpotPrice",
&types.QuerySpotPriceRequest{PoolId: 1, BaseAssetDenom: "foo", QuoteAssetDenom: "bar"},
&types.QuerySpotPriceResponse{},
},
{
"Query total liquidity",
"/osmosis.gamm.v1beta1.Query/TotalLiquidity",
&types.QueryTotalLiquidityRequest{},
&types.QueryTotalLiquidityResponse{},
},
{
"Query pool total liquidity",
"/osmosis.gamm.v1beta1.Query/TotalPoolLiquidity",
&types.QueryTotalPoolLiquidityRequest{PoolId: 1},
&types.QueryTotalPoolLiquidityResponse{},
},
{
"Query total shares",
"/osmosis.gamm.v1beta1.Query/TotalShares",
&types.QueryTotalSharesRequest{PoolId: 1},
&types.QueryTotalSharesResponse{},
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
s.SetupSuite()
err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output)
s.Require().NoError(err)
s.StateNotAltered()
})
}
}
func TestQueryTestSuite(t *testing.T) {
suite.Run(t, new(QueryTestSuite))
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment