From 1016c69c011f62e7a0ec4e5bc9865a336a9cfa19 Mon Sep 17 00:00:00 2001 From: MSalopek Date: Fri, 7 Jul 2023 12:27:25 +0200 Subject: [PATCH 01/15] deps: use cosmos-sdk v0.45.16-lsm-ics --- go.mod | 3 +-- go.sum | 17 ++++++----------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index d3768d1d09d..59d90dc1277 100644 --- a/go.mod +++ b/go.mod @@ -82,8 +82,6 @@ require ( github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/gobwas/ws v1.1.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect github.com/golang/glog v1.0.0 // indirect @@ -176,6 +174,7 @@ require ( replace ( // Use cosmos keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43 // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index 4038e69ea06..d5efea42484 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,6 @@ github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32 h1:zlCp9n3uwQieEL github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32/go.mod h1:kwMlEC4wWvB48zAShGKVqboJL6w4zCLesaNQ3YLU2BQ= github.com/cosmos/cosmos-proto v1.0.0-beta.1 h1:iDL5qh++NoXxG8hSy93FdYJut4XfgbShIocllGaXx/0= github.com/cosmos/cosmos-proto v1.0.0-beta.1/go.mod h1:8k2GNZghi5sDRFw/scPL8gMSowT1vDA+5ouxL8GjaUE= -github.com/cosmos/cosmos-sdk v0.45.16-ics h1:KsPigLNmdyyQMktAsJzW42eBFsq1uajhQF7rlnHDUgM= -github.com/cosmos/cosmos-sdk v0.45.16-ics/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -400,19 +398,15 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= -github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -617,6 +611,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43 h1:j299CKODCKQgtjKFtKesA4fQYaHXTXDW7WaanTa6/X4= +github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= @@ -1326,7 +1322,6 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 52463f44965f283bb145ccedd375e586bb86b95e Mon Sep 17 00:00:00 2001 From: MSalopek Date: Fri, 7 Jul 2023 12:39:15 +0200 Subject: [PATCH 02/15] deps&rebase: use cosmos-sdk v0.45.16-lsm-ics --- app/helpers/test_helpers.go | 23 +++++++++++------------ cmd/gaiad/cmd/testnet.go | 1 - go.mod | 3 +++ go.sum | 4 ++-- tests/e2e/validator.go | 4 ---- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/app/helpers/test_helpers.go b/app/helpers/test_helpers.go index 748927ff4e5..1925adcd0a2 100644 --- a/app/helpers/test_helpers.go +++ b/app/helpers/test_helpers.go @@ -164,20 +164,19 @@ func genesisStateWithValSet(t *testing.T, pkAny, err := codectypes.NewAnyWithValue(pk) require.NoError(t, err) validator := stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress(val.Address).String(), - ConsensusPubkey: pkAny, - Jailed: false, - Status: stakingtypes.Bonded, - Tokens: bondAmt, - DelegatorShares: sdk.OneDec(), - Description: stakingtypes.Description{}, - UnbondingHeight: int64(0), - UnbondingTime: time.Unix(0, 0).UTC(), - Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), - MinSelfDelegation: sdk.ZeroInt(), + OperatorAddress: sdk.ValAddress(val.Address).String(), + ConsensusPubkey: pkAny, + Jailed: false, + Status: stakingtypes.Bonded, + Tokens: bondAmt, + DelegatorShares: sdk.OneDec(), + Description: stakingtypes.Description{}, + UnbondingHeight: int64(0), + UnbondingTime: time.Unix(0, 0).UTC(), + Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), } validators = append(validators, validator) - delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) + delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec(), true)) } // set validators and delegations diff --git a/cmd/gaiad/cmd/testnet.go b/cmd/gaiad/cmd/testnet.go index 997ebfed7fc..940e3317399 100644 --- a/cmd/gaiad/cmd/testnet.go +++ b/cmd/gaiad/cmd/testnet.go @@ -243,7 +243,6 @@ func InitTestnet( sdk.NewCoin(sdk.DefaultBondDenom, valTokens), stakingtypes.NewDescription(nodeDirName, "", "", "", ""), stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()), - sdk.OneInt(), ) if err != nil { return err diff --git a/go.mod b/go.mod index 59d90dc1277..be2ad47bd81 100644 --- a/go.mod +++ b/go.mod @@ -174,7 +174,10 @@ require ( replace ( // Use cosmos keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + + // NOTE: @MSalopek test ics-lsm implementations github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43 + github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230707094121-790feda27368 // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index d5efea42484..07a59d90b99 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY= github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/ibc-go/v4 v4.4.2 h1:PG4Yy0/bw6Hvmha3RZbc53KYzaCwuB07Ot4GLyzcBvo= github.com/cosmos/ibc-go/v4 v4.4.2/go.mod h1:j/kD2JCIaV5ozvJvaEkWhLxM2zva7/KTM++EtKFYcB8= -github.com/cosmos/interchain-security/v2 v2.0.0 h1:FQeU+9hYrK+XF4bRfiFgn+h7JJoM71KQKpeKYNxpjA4= -github.com/cosmos/interchain-security/v2 v2.0.0/go.mod h1:3AHbp93smkSJFX6PW9OfYDJtU1i/Ty0yv/FVbF2dO20= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230707094121-790feda27368 h1:Elxq9qx9HMQFDSRB9C/ATPuPA6JXbMTq1qlfMsStlik= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230707094121-790feda27368/go.mod h1:sfU+zaMOUKUs2z2XD50xXnPLrR0UZgQp81UAvtnrPWM= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= diff --git a/tests/e2e/validator.go b/tests/e2e/validator.go index e6ac398b503..5242d79c073 100644 --- a/tests/e2e/validator.go +++ b/tests/e2e/validator.go @@ -227,9 +227,6 @@ func (v *validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { MaxChangeRate: sdk.MustNewDecFromStr("0.01"), } - // get the initial validator min self delegation - minSelfDelegation := sdk.OneInt() - valPubKey, err := cryptocodec.FromTmPubKeyInterface(v.consensusKey.PubKey) if err != nil { return nil, err @@ -241,7 +238,6 @@ func (v *validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { amount, description, commissionRates, - minSelfDelegation, ) } From 48b8b29d8b0fca9daf5f53577c470c65f6928ebb Mon Sep 17 00:00:00 2001 From: MSalopek Date: Fri, 7 Jul 2023 13:33:07 +0200 Subject: [PATCH 03/15] add local testing script --- contrib/scripts/local-gaia.sh | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100755 contrib/scripts/local-gaia.sh diff --git a/contrib/scripts/local-gaia.sh b/contrib/scripts/local-gaia.sh new file mode 100755 index 00000000000..c307b5c8e7d --- /dev/null +++ b/contrib/scripts/local-gaia.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -eux + +# User balance of stake tokens +USER_COINS="100000000000stake" +# Amount of stake tokens staked +STAKE="100000000stake" +# Node IP address +NODE_IP="127.0.0.1" + +# Home directory +HOME_DIR="/Users/msalopek" + +# Validator moniker +MONIKER="coordinator" + +# Validator directory +PROV_NODE_DIR=${HOME_DIR}/provider-${MONIKER} + +# Coordinator key +PROV_KEY=${MONIKER}-key + + +# Clean start +pkill -f gaiad &> /dev/null || true +rm -rf ${PROV_NODE_DIR} + +# Build file and node directory structure +gaiad init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} + jq ".app_state.gov.voting_params.voting_period = \"20s\" | .app_state.staking.params.unbonding_time = \"86400s\"" \ + ${PROV_NODE_DIR}/config/genesis.json > \ + ${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json + +sleep 1 + +# Create account keypair +gaiad keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 +sleep 1 + +# Add stake to user +PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) +gaiad add-genesis-account $PROV_ACCOUNT_ADDR $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test +sleep 1 + + +# Stake 1/1000 user's coins +gaiad gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER +sleep 1 + +gaiad collect-gentxs --home ${PROV_NODE_DIR} --gentx-dir ${PROV_NODE_DIR}/config/gentx/ +sleep 1 + +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26658\"/" ${PROV_NODE_DIR}/config/client.toml +sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml +sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml + + +# Start gaia +gaiad start \ + --home ${PROV_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26658 \ + --grpc.address ${NODE_IP}:9091 \ + --address tcp://${NODE_IP}:26655 \ + --p2p.laddr tcp://${NODE_IP}:26656 \ + --grpc-web.enable=false &> ${PROV_NODE_DIR}/logs From a00461c87f53ed3808b9f35e3ee27e88f8b4f07d Mon Sep 17 00:00:00 2001 From: MSalopek Date: Wed, 12 Jul 2023 15:51:53 +0200 Subject: [PATCH 04/15] fix: update test_helpers; use latest lsm/ics versions --- app/helpers/test_helpers.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/helpers/test_helpers.go b/app/helpers/test_helpers.go index 1925adcd0a2..cb3db33abb7 100644 --- a/app/helpers/test_helpers.go +++ b/app/helpers/test_helpers.go @@ -176,7 +176,7 @@ func genesisStateWithValSet(t *testing.T, Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), } validators = append(validators, validator) - delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec(), true)) + delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) } // set validators and delegations diff --git a/go.mod b/go.mod index be2ad47bd81..7780a0c5f59 100644 --- a/go.mod +++ b/go.mod @@ -176,8 +176,8 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // NOTE: @MSalopek test ics-lsm implementations - github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43 - github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230707094121-790feda27368 + github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230711153639-a118c0fc9ad3 + github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230711205607-21624a6f298a // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index 07a59d90b99..e7c564057ff 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY= github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/ibc-go/v4 v4.4.2 h1:PG4Yy0/bw6Hvmha3RZbc53KYzaCwuB07Ot4GLyzcBvo= github.com/cosmos/ibc-go/v4 v4.4.2/go.mod h1:j/kD2JCIaV5ozvJvaEkWhLxM2zva7/KTM++EtKFYcB8= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230707094121-790feda27368 h1:Elxq9qx9HMQFDSRB9C/ATPuPA6JXbMTq1qlfMsStlik= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230707094121-790feda27368/go.mod h1:sfU+zaMOUKUs2z2XD50xXnPLrR0UZgQp81UAvtnrPWM= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230711205607-21624a6f298a h1:8wws0sHxO9gIsXQ4beyht/pO0YEd+A86cjUYvxKuo0Q= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230711205607-21624a6f298a/go.mod h1:D+COoCXXTgJWTLqampNxwrUOWBZ589wzhGN3QjixtnE= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= @@ -611,8 +611,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43 h1:j299CKODCKQgtjKFtKesA4fQYaHXTXDW7WaanTa6/X4= -github.com/iqlusioninc/cosmos-sdk v0.34.4-0.20230628024121-1b4d7e811a43/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= +github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230711153639-a118c0fc9ad3 h1:WMKL82CAAOem/956NfUG+5R9Isz/JMmwpHwP8nnkmD0= +github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230711153639-a118c0fc9ad3/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= From 0952f5e68c4fe7f688c5404a540ae088814e554f Mon Sep 17 00:00:00 2001 From: MSalopek Date: Tue, 25 Jul 2023 12:16:11 +0200 Subject: [PATCH 05/15] chore: bump iqlusion:cosmos-sdk to latest --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9429e7f049b..8a87dbde4aa 100644 --- a/go.mod +++ b/go.mod @@ -176,8 +176,8 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // NOTE: @MSalopek test ics-lsm implementations - github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230711153639-a118c0fc9ad3 - github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230711205607-21624a6f298a + github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230720195127-73e72b9ef30f + github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230725101325-314cd35bbaea // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index 41bce5420a7..f6e6ddafacf 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY= github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/ibc-go/v4 v4.4.2 h1:PG4Yy0/bw6Hvmha3RZbc53KYzaCwuB07Ot4GLyzcBvo= github.com/cosmos/ibc-go/v4 v4.4.2/go.mod h1:j/kD2JCIaV5ozvJvaEkWhLxM2zva7/KTM++EtKFYcB8= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230711205607-21624a6f298a h1:8wws0sHxO9gIsXQ4beyht/pO0YEd+A86cjUYvxKuo0Q= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230711205607-21624a6f298a/go.mod h1:D+COoCXXTgJWTLqampNxwrUOWBZ589wzhGN3QjixtnE= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230725101325-314cd35bbaea h1:DBLsnL1v7P5JpxAHfab/2ruVPYFVrlomGQ1R1nal0b0= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230725101325-314cd35bbaea/go.mod h1:nLKbjneVlKIW/GGNFC+b6M142gXnjOImA5V1iClCPfE= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= @@ -611,8 +611,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230711153639-a118c0fc9ad3 h1:WMKL82CAAOem/956NfUG+5R9Isz/JMmwpHwP8nnkmD0= -github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230711153639-a118c0fc9ad3/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= +github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230720195127-73e72b9ef30f h1:hPQ61igc7i2RGbuDVhbAFx9p/Dra5pm5JJz4rbL6GNU= +github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230720195127-73e72b9ef30f/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= From 4343315da0201f8b17edc87c19211991ce8b25ab Mon Sep 17 00:00:00 2001 From: riley-stride <104941670+riley-stride@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:49:52 -0400 Subject: [PATCH 06/15] Jstr/lsm e2e tests (#2679) * lsm e2e test work - wip * Add validator bond functionality on lsm happy path * add tokenize share check on lsm test & redeemShare utility function * add bank send lsm tokens test * Add test for transfer reward ownership, and redeem shares * Add staking param query utility & LSM params update process on LSM e2e test * Add IBC transfer test on LSM share tokens & Resolve e2e tests by updating gas configs and result checker * resolve github action bot comments * bring all e2e test items back to enabled * Update tests/e2e/e2e_lsm_test.go Co-authored-by: sampocs * resolve comments * reenable tokenize share record module account balance check --------- Co-authored-by: jstr1121 Co-authored-by: jstr1121 <118450565+jstr1121@users.noreply.github.com> Co-authored-by: sampocs --- tests/e2e/e2e_exec_test.go | 105 +++++++++++++++++ tests/e2e/e2e_lsm_test.go | 221 ++++++++++++++++++++++++++++++++++++ tests/e2e/e2e_setup_test.go | 43 +++++++ tests/e2e/e2e_test.go | 8 ++ tests/e2e/query.go | 28 +++++ 5 files changed, 405 insertions(+) create mode 100644 tests/e2e/e2e_lsm_test.go diff --git a/tests/e2e/e2e_exec_test.go b/tests/e2e/e2e_exec_test.go index 4f1572cbd3d..650c236633a 100644 --- a/tests/e2e/e2e_exec_test.go +++ b/tests/e2e/e2e_exec_test.go @@ -693,3 +693,108 @@ func (s *IntegrationTestSuite) defaultExecValidation(chain *chain, valIdx int) f return false } } + +func (s *IntegrationTestSuite) executeValidatorBond(c *chain, valIdx int, valOperAddress, delegatorAddr, home, delegateFees string) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("Executing gaiad tx staking validator-bond %s", c.id) + + gaiaCommand := []string{ + gaiadBinary, + txCommand, + stakingtypes.ModuleName, + "validator-bond", + valOperAddress, + fmt.Sprintf("--%s=%s", flags.FlagFrom, delegatorAddr), + fmt.Sprintf("--%s=%s", flags.FlagChainID, c.id), + fmt.Sprintf("--%s=%s", flags.FlagGasPrices, delegateFees), + "--keyring-backend=test", + fmt.Sprintf("--%s=%s", flags.FlagHome, home), + "--output=json", + "-y", + } + + s.executeGaiaTxCommand(ctx, c, gaiaCommand, valIdx, s.defaultExecValidation(c, valIdx)) + s.T().Logf("%s successfully executed validator bond tx to %s", delegatorAddr, valOperAddress) +} + +func (s *IntegrationTestSuite) executeTokenizeShares(c *chain, valIdx int, amount, valOperAddress, delegatorAddr, home, delegateFees string) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("Executing gaiad tx staking tokenize-share %s", c.id) + + gaiaCommand := []string{ + gaiadBinary, + txCommand, + stakingtypes.ModuleName, + "tokenize-share", + valOperAddress, + amount, + delegatorAddr, + fmt.Sprintf("--%s=%s", flags.FlagFrom, delegatorAddr), + fmt.Sprintf("--%s=%s", flags.FlagChainID, c.id), + fmt.Sprintf("--%s=%s", flags.FlagGasPrices, delegateFees), + fmt.Sprintf("--%s=%d", flags.FlagGas, 1000000), + "--keyring-backend=test", + fmt.Sprintf("--%s=%s", flags.FlagHome, home), + "--output=json", + "-y", + } + + s.executeGaiaTxCommand(ctx, c, gaiaCommand, valIdx, s.defaultExecValidation(c, valIdx)) + s.T().Logf("%s successfully executed tokenize share tx from %s", delegatorAddr, valOperAddress) +} + +func (s *IntegrationTestSuite) executeRedeemShares(c *chain, valIdx int, amount, delegatorAddr, home, delegateFees string) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("Executing gaiad tx staking redeem-tokens %s", c.id) + + gaiaCommand := []string{ + gaiadBinary, + txCommand, + stakingtypes.ModuleName, + "redeem-tokens", + amount, + fmt.Sprintf("--%s=%s", flags.FlagFrom, delegatorAddr), + fmt.Sprintf("--%s=%s", flags.FlagChainID, c.id), + fmt.Sprintf("--%s=%s", flags.FlagGasPrices, delegateFees), + fmt.Sprintf("--%s=%d", flags.FlagGas, 1000000), + "--keyring-backend=test", + fmt.Sprintf("--%s=%s", flags.FlagHome, home), + "--output=json", + "-y", + } + + s.executeGaiaTxCommand(ctx, c, gaiaCommand, valIdx, s.defaultExecValidation(c, valIdx)) + s.T().Logf("%s successfully executed redeem share tx for %s", delegatorAddr, amount) +} + +func (s *IntegrationTestSuite) executeTransferTokenizeShareRecord(c *chain, valIdx int, recordId, owner, newOwner, home, txFees string) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("Executing gaiad tx staking transfer-tokenize-share-record %s", c.id) + + gaiaCommand := []string{ + gaiadBinary, + txCommand, + stakingtypes.ModuleName, + "transfer-tokenize-share-record", + recordId, + newOwner, + fmt.Sprintf("--%s=%s", flags.FlagFrom, owner), + fmt.Sprintf("--%s=%s", flags.FlagChainID, c.id), + fmt.Sprintf("--%s=%s", flags.FlagGasPrices, txFees), + "--keyring-backend=test", + fmt.Sprintf("--%s=%s", flags.FlagHome, home), + "--output=json", + "-y", + } + + s.executeGaiaTxCommand(ctx, c, gaiaCommand, valIdx, s.defaultExecValidation(c, valIdx)) + s.T().Logf("%s successfully executed transfer tokenize share record for %s", owner, recordId) +} diff --git a/tests/e2e/e2e_lsm_test.go b/tests/e2e/e2e_lsm_test.go new file mode 100644 index 00000000000..7eccaaf8824 --- /dev/null +++ b/tests/e2e/e2e_lsm_test.go @@ -0,0 +1,221 @@ +package e2e + +import ( + "fmt" + "strconv" + "strings" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + gov "github.com/cosmos/cosmos-sdk/x/gov/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func (s *IntegrationTestSuite) testLSM() { + chainEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + + validatorA := s.chainA.validators[0] + validatorAAddr := validatorA.keyInfo.GetAddress() + + validatorAddressA := sdk.ValAddress(validatorAAddr).String() + + // Set parameters (global liquid staking cap, validator liquid staking cap, validator bond factor) + s.writeLiquidStakingParamsUpdateProposal(s.chainA) + proposalCounter++ + submitGovFlags := []string{"param-change", configFile(proposalLSMParamUpdateFilename)} + depositGovFlags := []string{strconv.Itoa(proposalCounter), depositAmount.String()} + voteGovFlags := []string{strconv.Itoa(proposalCounter), "yes"} + + // gov proposing LSM parameters (global liquid staking cap, validator liquid staking cap, validator bond factor) + s.T().Logf("Proposal number: %d", proposalCounter) + s.T().Logf("Submitting, deposit and vote legacy Gov Proposal: Set parameters (global liquid staking cap, validator liquid staking cap, validator bond factor)") + s.runGovProcess(chainEndpoint, validatorAAddr.String(), proposalCounter, paramtypes.ProposalTypeChange, submitGovFlags, depositGovFlags, voteGovFlags, "vote", false) + + // query the proposal status and new fee + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainEndpoint, proposalCounter) + s.Require().NoError(err) + return proposal.GetProposal().Status == gov.StatusPassed + }, + 15*time.Second, + 5*time.Second, + ) + + s.Require().Eventually( + func() bool { + stakingParams, err := queryStakingParams(chainEndpoint) + s.T().Logf("After LSM parameters update proposal") + s.Require().NoError(err) + + s.Require().Equal(stakingParams.Params.GlobalLiquidStakingCap, sdk.NewDecWithPrec(25, 2)) + s.Require().Equal(stakingParams.Params.ValidatorLiquidStakingCap, sdk.NewDecWithPrec(50, 2)) + s.Require().Equal(stakingParams.Params.ValidatorBondFactor, sdk.NewDec(250)) + + return true + }, + 15*time.Second, + 5*time.Second, + ) + delegatorAddress := s.chainA.genesisAccounts[2].keyInfo.GetAddress().String() + + fees := sdk.NewCoin(uatomDenom, sdk.NewInt(1)) + + // Validator bond + s.executeValidatorBond(s.chainA, 0, validatorAddressA, validatorAAddr.String(), gaiaHomePath, fees.String()) + + // Validate validator bond successful + selfBondedShares := sdk.ZeroDec() + s.Require().Eventually( + func() bool { + res, err := queryDelegation(chainEndpoint, validatorAddressA, validatorAAddr.String()) + delegation := res.GetDelegationResponse().GetDelegation() + selfBondedShares = delegation.Shares + isValidatorBond := delegation.ValidatorBond + s.Require().NoError(err) + + return isValidatorBond == true + }, + 20*time.Second, + 5*time.Second, + ) + + delegationAmount := sdk.NewInt(500000000) + delegation := sdk.NewCoin(uatomDenom, delegationAmount) // 500 atom + + // Alice delegate uatom to Validator A + s.executeDelegate(s.chainA, 0, delegation.String(), validatorAddressA, delegatorAddress, gaiaHomePath, fees.String()) + + // Validate delegation successful + s.Require().Eventually( + func() bool { + res, err := queryDelegation(chainEndpoint, validatorAddressA, delegatorAddress) + amt := res.GetDelegationResponse().GetDelegation().GetShares() + s.Require().NoError(err) + + return amt.Equal(sdk.NewDecFromInt(delegationAmount)) + }, + 20*time.Second, + 5*time.Second, + ) + + // Tokenize shares + tokenizeAmount := sdk.NewInt(200000000) + tokenize := sdk.NewCoin(uatomDenom, tokenizeAmount) // 200 atom + s.executeTokenizeShares(s.chainA, 0, tokenize.String(), validatorAddressA, delegatorAddress, gaiaHomePath, fees.String()) + + // Validate delegation reduced + s.Require().Eventually( + func() bool { + res, err := queryDelegation(chainEndpoint, validatorAddressA, delegatorAddress) + amt := res.GetDelegationResponse().GetDelegation().GetShares() + s.Require().NoError(err) + + return amt.Equal(sdk.NewDecFromInt(delegationAmount.Sub(tokenizeAmount))) + }, + 20*time.Second, + 5*time.Second, + ) + + // Validate balance increased + recordID := int(1) + shareDenom := fmt.Sprintf("%s/%s", strings.ToLower(validatorAddressA), strconv.Itoa(recordID)) + s.Require().Eventually( + func() bool { + res, err := getSpecificBalance(chainEndpoint, delegatorAddress, shareDenom) + s.Require().NoError(err) + return res.Amount.Equal(tokenizeAmount) + }, + 20*time.Second, + 5*time.Second, + ) + + // Bank send LSM token + sendAmount := sdk.NewCoin(shareDenom, tokenizeAmount) + s.execBankSend(s.chainA, 0, delegatorAddress, validatorAAddr.String(), sendAmount.String(), standardFees.String(), false) + + // Validate tokens are sent properly + s.Require().Eventually( + func() bool { + afterSenderShareDenomBalance, err := getSpecificBalance(chainEndpoint, delegatorAddress, shareDenom) + s.Require().NoError(err) + + afterRecipientShareDenomBalance, err := getSpecificBalance(chainEndpoint, validatorAAddr.String(), shareDenom) + s.Require().NoError(err) + + decremented := afterSenderShareDenomBalance.IsNil() || afterSenderShareDenomBalance.IsZero() + incremented := afterRecipientShareDenomBalance.IsEqual(sendAmount) + + return decremented && incremented + }, + time.Minute, + 5*time.Second, + ) + + // transfer reward ownership + s.executeTransferTokenizeShareRecord(s.chainA, 0, strconv.Itoa(recordID), delegatorAddress, validatorAAddr.String(), gaiaHomePath, standardFees.String()) + tokenizeShareRecord := stakingtypes.TokenizeShareRecord{} + // Validate ownership transferred correctly + s.Require().Eventually( + func() bool { + record, err := queryTokenizeShareRecordByID(chainEndpoint, recordID) + s.Require().NoError(err) + tokenizeShareRecord = record + return record.Owner == validatorAAddr.String() + }, + time.Minute, + 5*time.Second, + ) + _ = tokenizeShareRecord + + // IBC transfer LSM token + ibcTransferAmount := sdk.NewCoin(shareDenom, sdk.NewInt(100000000)) + sendRecipientAddr := s.chainB.validators[0].keyInfo.GetAddress() + s.sendIBC(s.chainA, 0, validatorAAddr.String(), sendRecipientAddr.String(), ibcTransferAmount.String(), standardFees.String(), "memo") + + s.Require().Eventually( + func() bool { + afterSenderShareBalance, err := getSpecificBalance(chainEndpoint, validatorAAddr.String(), shareDenom) + s.Require().NoError(err) + + decremented := afterSenderShareBalance.Add(ibcTransferAmount).IsEqual(sendAmount) + return decremented + }, + 1*time.Minute, + 5*time.Second, + ) + + // Redeem tokens for shares + redeemAmount := sendAmount.Sub(ibcTransferAmount) + s.executeRedeemShares(s.chainA, 0, redeemAmount.String(), validatorAAddr.String(), gaiaHomePath, fees.String()) + + // check redeem success + s.Require().Eventually( + func() bool { + balanceRes, err := getSpecificBalance(chainEndpoint, validatorAAddr.String(), shareDenom) + s.Require().NoError(err) + if !balanceRes.Amount.IsNil() && balanceRes.Amount.IsZero() { + return false + } + + delegationRes, err := queryDelegation(chainEndpoint, validatorAddressA, validatorAAddr.String()) + delegation := delegationRes.GetDelegationResponse().GetDelegation() + s.Require().NoError(err) + + if !delegation.Shares.Equal(selfBondedShares.Add(sdk.NewDecFromInt(redeemAmount.Amount))) { + return false + } + + // check tokenize share record module account balance + balanceRes, err = getSpecificBalance(chainEndpoint, tokenizeShareRecord.GetModuleAddress().String(), uatomDenom) + s.Require().NoError(err) + if balanceRes.Amount.IsNil() || balanceRes.Amount.IsZero() { + return false + } + return true + }, + 20*time.Second, + 5*time.Second, + ) +} diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index a757b55194e..3d91f1d8005 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -73,6 +73,7 @@ const ( proposalCommunitySpendFilename = "proposal_community_spend.json" proposalAddConsumerChainFilename = "proposal_add_consumer.json" proposalRemoveConsumerChainFilename = "proposal_remove_consumer.json" + proposalLSMParamUpdateFilename = "proposal_lsm_param_update.json" hermesBinary = "hermes" hermesConfigWithGasPrices = "/root/.hermes/config.toml" @@ -930,6 +931,48 @@ func (s *IntegrationTestSuite) writeAddRemoveConsumerProposals(c *chain, consume s.Require().NoError(err) } +func (s *IntegrationTestSuite) writeLiquidStakingParamsUpdateProposal(c *chain) { + type ParamInfo struct { + Subspace string `json:"subspace"` + Key string `json:"key"` + Value sdk.Dec `json:"value"` + } + + type ParamChangeMessage struct { + Title string `json:"title"` + Description string `json:"description"` + Changes []ParamInfo `json:"changes"` + Deposit string `json:"deposit"` + } + + paramChangeProposalBody, err := json.MarshalIndent(ParamChangeMessage{ + Title: "liquid staking params update", + Description: "liquid staking params update", + Changes: []ParamInfo{ + { + Subspace: "staking", + Key: "GlobalLiquidStakingCap", + Value: sdk.NewDecWithPrec(25, 2), // 25% + }, + { + Subspace: "staking", + Key: "ValidatorLiquidStakingCap", + Value: sdk.NewDecWithPrec(50, 2), // 50% + }, + { + Subspace: "staking", + Key: "ValidatorBondFactor", + Value: sdk.NewDec(250), // -1 + }, + }, + Deposit: "1000uatom", + }, "", " ") + s.Require().NoError(err) + + err = writeFile(filepath.Join(c.validators[0].configDir(), "config", proposalLSMParamUpdateFilename), paramChangeProposalBody) + s.Require().NoError(err) +} + func configFile(filename string) string { filepath := filepath.Join(gaiaConfigPath, filename) return filepath diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index c2edd641fc5..d3b913b5d09 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -17,6 +17,7 @@ var ( runStakingAndDistributionTest = true runVestingTest = true runRestInterfacesTest = true + runLsmTest = true ) func (s *IntegrationTestSuite) TestRestInterfaces() { @@ -121,3 +122,10 @@ func (s *IntegrationTestSuite) TestVesting() { s.testContinuousVestingAccount(chainAAPI) // s.testPeriodicVestingAccount(chainAAPI) TODO: add back when v0.45 adds the missing CLI command. } + +func (s *IntegrationTestSuite) TestLSM() { + if !runLsmTest { + s.T().Skip() + } + s.testLSM() +} diff --git a/tests/e2e/query.go b/tests/e2e/query.go index c27d17252c7..c9c6f5b8d13 100644 --- a/tests/e2e/query.go +++ b/tests/e2e/query.go @@ -73,6 +73,20 @@ func queryGaiaAllBalances(endpoint, addr string) (sdk.Coins, error) { return balancesResp.Balances, nil } +func queryStakingParams(endpoint string) (stakingtypes.QueryParamsResponse, error) { + body, err := httpGet(fmt.Sprintf("%s/cosmos/staking/v1beta1/params", endpoint)) + if err != nil { + return stakingtypes.QueryParamsResponse{}, fmt.Errorf("failed to execute HTTP request: %w", err) + } + + var params stakingtypes.QueryParamsResponse + if err := cdc.UnmarshalJSON(body, ¶ms); err != nil { + return stakingtypes.QueryParamsResponse{}, err + } + + return params, nil +} + func queryGlobalFeeParams(endpoint string) (types.QueryParamsResponse, error) { body, err := httpGet(fmt.Sprintf("%s/gaia/globalfee/v1beta1/params", endpoint)) if err != nil { @@ -286,3 +300,17 @@ func queryAllEvidence(endpoint string) (evidencetypes.QueryAllEvidenceResponse, } return res, nil } + +func queryTokenizeShareRecordByID(endpoint string, recordID int) (stakingtypes.TokenizeShareRecord, error) { + var res stakingtypes.QueryTokenizeShareRecordByIdResponse + + body, err := httpGet(fmt.Sprintf("%s/cosmos/staking/v1beta1/tokenize_share_record_by_id/%d", endpoint, recordID)) + if err != nil { + return stakingtypes.TokenizeShareRecord{}, fmt.Errorf("failed to execute HTTP request: %w", err) + } + + if err := cdc.UnmarshalJSON(body, &res); err != nil { + return stakingtypes.TokenizeShareRecord{}, err + } + return res.Record, nil +} From 003c089ec8a72f1f16bf0c0ed28b11edbecefdf3 Mon Sep 17 00:00:00 2001 From: sampocs Date: Mon, 7 Aug 2023 11:07:04 -0500 Subject: [PATCH 07/15] Add lsm params to upgrade handler (#2686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * set LSM params in upgrade handler * added comments around constants * test: add migrateUBDEntries to upgrade handler — required adding exported.go to sdk * Revert "test: add migrateUBDEntries to upgrade handler — required adding exported.go to sdk" This reverts commit 7bd9727ce734e829ef54538485c3bbf327009345. --------- Co-authored-by: Riley Edmunds --- app/upgrades/v12/constants.go | 11 +++++++++++ app/upgrades/v12/upgrades.go | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/app/upgrades/v12/constants.go b/app/upgrades/v12/constants.go index fd90624bbf8..161d65519e5 100644 --- a/app/upgrades/v12/constants.go +++ b/app/upgrades/v12/constants.go @@ -7,6 +7,17 @@ import ( const ( // UpgradeName defines the on-chain upgrade name. UpgradeName = "v12" + + // The ValidatorBondFactor dictates the cap on the liquid shares + // for a validator - determined as a multiple to their validator bond + // (e.g. ValidatorBondShares = 1000, BondFactor = 250 -> LiquidSharesCap: 250,000) + ValidatorBondFactor = 250 + // GlobalLiquidStakingCap represents the percentage cap on + // the portion of a validator's stake that can be liquid + ValidatorLiquidStakingCap = 50 // 50% + // GlobalLiquidStakingCap represents the percentage cap on + // the portion of a chain's total stake can be liquid + GlobalLiquidStakingCap = 25 // 25% ) var Upgrade = upgrades.Upgrade{ diff --git a/app/upgrades/v12/upgrades.go b/app/upgrades/v12/upgrades.go index 0133940cc87..5531b8d2d8a 100644 --- a/app/upgrades/v12/upgrades.go +++ b/app/upgrades/v12/upgrades.go @@ -21,6 +21,14 @@ func CreateUpgradeHandler( return vm, err } + // Set liquid staking module parameters + params := keepers.StakingKeeper.GetParams(ctx) + params.ValidatorBondFactor = sdk.NewDec(ValidatorBondFactor) + params.ValidatorLiquidStakingCap = sdk.NewDec(ValidatorLiquidStakingCap) + params.GlobalLiquidStakingCap = sdk.NewDec(GlobalLiquidStakingCap) + + keepers.StakingKeeper.SetParams(ctx, params) + ctx.Logger().Info("Upgrade complete") return vm, err } From 7b1e69b4007af8e50ed4c15d78f3bda400044812 Mon Sep 17 00:00:00 2001 From: MSalopek Date: Mon, 7 Aug 2023 18:37:15 +0200 Subject: [PATCH 08/15] chore: bump cosmos-sdk and ics to latest --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 17c786ad323..4be24019a87 100644 --- a/go.mod +++ b/go.mod @@ -176,8 +176,8 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // NOTE: @MSalopek test ics-lsm implementations - github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230720195127-73e72b9ef30f - github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230725101325-314cd35bbaea + github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230803192832-aab739edf2ca + github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230807142151-863915e43e6a // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index f6e6ddafacf..6437070c9aa 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY= github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/ibc-go/v4 v4.4.2 h1:PG4Yy0/bw6Hvmha3RZbc53KYzaCwuB07Ot4GLyzcBvo= github.com/cosmos/ibc-go/v4 v4.4.2/go.mod h1:j/kD2JCIaV5ozvJvaEkWhLxM2zva7/KTM++EtKFYcB8= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230725101325-314cd35bbaea h1:DBLsnL1v7P5JpxAHfab/2ruVPYFVrlomGQ1R1nal0b0= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230725101325-314cd35bbaea/go.mod h1:nLKbjneVlKIW/GGNFC+b6M142gXnjOImA5V1iClCPfE= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230807142151-863915e43e6a h1:eLyWaPSxJCYLU/CWvJXzyA71VoO71ytdYQmshk8N8VE= +github.com/cosmos/interchain-security/v2 v2.0.1-0.20230807142151-863915e43e6a/go.mod h1:iDSje+UvpDKNYJvhgveKiYnAZNJnoZ5KsOCkG2jbT/4= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= @@ -611,8 +611,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230720195127-73e72b9ef30f h1:hPQ61igc7i2RGbuDVhbAFx9p/Dra5pm5JJz4rbL6GNU= -github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230720195127-73e72b9ef30f/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= +github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230803192832-aab739edf2ca h1:ddvixv/W+SIWAy0rCKiVmzq0aAzAowxj61rYJr06MH4= +github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230803192832-aab739edf2ca/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= From 80ccd20f05bef7a40e88499f88d61b0b4c0c3a78 Mon Sep 17 00:00:00 2001 From: sampocs Date: Mon, 7 Aug 2023 12:38:01 -0500 Subject: [PATCH 09/15] Fix staking & distribution e2e test with LSM (#2687) * lsm e2e test work - wip * Add validator bond functionality on lsm happy path * add tokenize share check on lsm test & redeemShare utility function * add bank send lsm tokens test * Add test for transfer reward ownership, and redeem shares * Add staking param query utility & LSM params update process on LSM e2e test * Add IBC transfer test on LSM share tokens & Resolve e2e tests by updating gas configs and result checker * resolve github action bot comments * bring all e2e test items back to enabled * Update tests/e2e/e2e_lsm_test.go Co-authored-by: sampocs * resolve comments * reenable tokenize share record module account balance check * fix staking test affected by other test --------- Co-authored-by: jstr1121 Co-authored-by: jstr1121 <118450565+jstr1121@users.noreply.github.com> --- tests/e2e/e2e_staking_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/e2e/e2e_staking_test.go b/tests/e2e/e2e_staking_test.go index b4a7b78a4dc..56217685047 100644 --- a/tests/e2e/e2e_staking_test.go +++ b/tests/e2e/e2e_staking_test.go @@ -22,6 +22,12 @@ func (s *IntegrationTestSuite) testStaking() { fees := sdk.NewCoin(uatomDenom, sdk.NewInt(1)) + existingDelegation := sdk.ZeroDec() + res, err := queryDelegation(chainEndpoint, validatorAddressA, delegatorAddress) + if err == nil { + existingDelegation = res.GetDelegationResponse().GetDelegation().GetShares() + } + delegationAmount := sdk.NewInt(500000000) delegation := sdk.NewCoin(uatomDenom, delegationAmount) // 500 atom @@ -35,7 +41,7 @@ func (s *IntegrationTestSuite) testStaking() { amt := res.GetDelegationResponse().GetDelegation().GetShares() s.Require().NoError(err) - return amt.Equal(sdk.NewDecFromInt(delegationAmount)) + return amt.Equal(existingDelegation.Add(sdk.NewDecFromInt(delegationAmount))) }, 20*time.Second, 5*time.Second, From a0a4b5477c84229afbd060e62a3addcbfa343440 Mon Sep 17 00:00:00 2001 From: MSalopek Date: Tue, 8 Aug 2023 12:48:17 +0200 Subject: [PATCH 10/15] chore: appease lint rules --- tests/e2e/e2e_exec_test.go | 6 +++--- tests/e2e/e2e_ibc_test.go | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/e2e/e2e_exec_test.go b/tests/e2e/e2e_exec_test.go index 650c236633a..71cac0667cd 100644 --- a/tests/e2e/e2e_exec_test.go +++ b/tests/e2e/e2e_exec_test.go @@ -773,7 +773,7 @@ func (s *IntegrationTestSuite) executeRedeemShares(c *chain, valIdx int, amount, s.T().Logf("%s successfully executed redeem share tx for %s", delegatorAddr, amount) } -func (s *IntegrationTestSuite) executeTransferTokenizeShareRecord(c *chain, valIdx int, recordId, owner, newOwner, home, txFees string) { +func (s *IntegrationTestSuite) executeTransferTokenizeShareRecord(c *chain, valIdx int, recordID, owner, newOwner, home, txFees string) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -784,7 +784,7 @@ func (s *IntegrationTestSuite) executeTransferTokenizeShareRecord(c *chain, valI txCommand, stakingtypes.ModuleName, "transfer-tokenize-share-record", - recordId, + recordID, newOwner, fmt.Sprintf("--%s=%s", flags.FlagFrom, owner), fmt.Sprintf("--%s=%s", flags.FlagChainID, c.id), @@ -796,5 +796,5 @@ func (s *IntegrationTestSuite) executeTransferTokenizeShareRecord(c *chain, valI } s.executeGaiaTxCommand(ctx, c, gaiaCommand, valIdx, s.defaultExecValidation(c, valIdx)) - s.T().Logf("%s successfully executed transfer tokenize share record for %s", owner, recordId) + s.T().Logf("%s successfully executed transfer tokenize share record for %s", owner, recordID) } diff --git a/tests/e2e/e2e_ibc_test.go b/tests/e2e/e2e_ibc_test.go index cfe2235beb0..85468361aef 100644 --- a/tests/e2e/e2e_ibc_test.go +++ b/tests/e2e/e2e_ibc_test.go @@ -29,6 +29,7 @@ type PacketMetadata struct { Forward *ForwardMetadata `json:"forward"` } +//nolint:unparam func (s *IntegrationTestSuite) sendIBC(c *chain, valIdx int, sender, recipient, token, fees, note string) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() From 63e1de441ef4438a1a3febea3c2f3bda13479182 Mon Sep 17 00:00:00 2001 From: riley-stride <104941670+riley-stride@users.noreply.github.com> Date: Fri, 11 Aug 2023 06:06:04 -0700 Subject: [PATCH 11/15] docs: Add LSM docs (#2683) * docs: validator FAQ updated with LSM docs * docs: validator faq - remove min self delegation references * docs: delegator faq - add lsm docs * docs: address Marius review comments on docs --- docs/delegators/delegator-faq.md | 29 ++++++++++++++- docs/validators/validator-faq.md | 60 ++++++++++++++++++++++++++---- docs/validators/validator-setup.md | 4 -- 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/docs/delegators/delegator-faq.md b/docs/delegators/delegator-faq.md index e643b4d7160..016d092832a 100644 --- a/docs/delegators/delegator-faq.md +++ b/docs/delegators/delegator-faq.md @@ -25,7 +25,7 @@ In order to choose their validators, delegators have access to a range of inform - **Initial commission rate**: The commission rate on revenue charged to any delegator by the validator (see below for more detail). - **Commission max change rate:** The maximum daily increase of the validator's commission. This parameter cannot be changed by the validator operator. - **Maximum commission:** The maximum commission rate this validator candidate can charge. This parameter cannot be changed by the validator operator. -- **Minimum self-bond amount**: Minimum amount of Atoms the validator candidate need to have bonded at all time. If the validator's self-bonded stake falls below this limit, their entire staking pool (i.e. all its delegators) will unbond. This parameter exists as a safeguard for delegators. Indeed, when a validator misbehaves, part of their total stake gets slashed. This included the validator's self-delegateds stake as well as their delegators' stake. Thus, a validator with a high amount of self-delegated Atoms has more skin-in-the-game than a validator with a low amount. The minimum self-bond amount parameter guarantees to delegators that a validator will never fall below a certain amount of self-bonded stake, thereby ensuring a minimum level of skin-in-the-game. This parameter can only be increased by the validator operator. +- **Validator self-bond amount**: A validator with a high amount of self-delegated Atoms has more skin-in-the-game than a validator with a low amount. ## Directives of delegators @@ -61,6 +61,33 @@ Our validator's staking pool represents 10% of the total stake, which means the Then, each delegator in the staking pool can claim their portion of the delegators' total revenue. +## Liquid Staking + +The Liquid Staking module enacts a safety framework and associated governance-controlled parameters to regulate the adoption of liquid staking. + +The LSM mitigates liquid staking risks by limiting the total amount of ATOM that can be liquid staked to a percentage of all staked ATOM. As an additional risk-mitigation feature, the LSM introduces a requirement that validators self-bond ATOM to be eligible for delegations from liquid staking providers or to be eligible to mint LSM tokens. This mechanism is called the “validator bond”, and is technically distinct from the current self-bond mechanism, but functions similarly. + +At the same time, the LSM introduces the ability for staked ATOM to be instantly liquid staked, without having to wait for the unbonding period. + +The LSM enables users to instantly liquid stake their staked ATOM, without having to wait the twenty-one day unbonding period. This is important, because a very large portion of the ATOM supply is currently staked. Liquid staking ATOM that is already staked incurs a switching cost in the form of three weeks’ forfeited staking rewards. The LSM eliminates this switching cost. + +A user would be able to visit any liquid staking provider that has integrated with the LSM and click a button to convert her staked ATOM to liquid staked ATOM. It would be as easy as liquid staking unstaked ATOM. + +Technically speaking, this is accomplished by using something called an “LSM share.” Using the liquid staking module, a user can tokenize their staked ATOM and turn it into LSM shares. LSM shares can be redeemed for underlying staked tokens and are transferable. After staked ATOM is tokenized it can be immediately transferred to a liquid staking provider in exchange for liquid staking tokens - without having to wait for the unbonding period. + +### Toggling the ability to tokenize shares + +Currently the liquid staking module facilitates the immediate conversion of staked assets into liquid staked tokens. Despite the many benefits that come with this capability, it does inadvertently negate a protective measure available via traditional staking, where an account can stake their tokens to render them illiquid in the event that their wallet is compromised (the attacker would first need to unbond, then transfer out the tokens). + +Tokenization obviates this potential recovery measure, as an attacker could tokenize and immediately transfer staked tokens to another wallet. So, as an additional protective measure, the staking module permit accounts to selectively disable the tokenization of their stake with the `DisableTokenizeShares` message. + +The `DisableTokenizeShares` message is exposed by the staking module and can be executed as follows: +``` +gaiad tx staking disable-tokenize-shares --from mykey +``` + +When tokenization is disabled, a lock is placed on the account, effectively preventing the tokenization of any delegations. Re-enabling tokenization would initiate the removal of the lock, but the process is not immediate. The lock removal is queued, with the lock itself persisting throughout the unbonding period. Following the completion of the unbonding period, the lock would be completely removed, restoring the account's ablility to tokenize. For liquid staking protocols that enable the lock, this delay better positions the base layer to coordinate a recovery in the event of an exploit. + ## Risks Staking Atoms is not free of risk. First, staked Atoms are locked up, and retrieving them requires a 3 week waiting period called unbonding period. Additionally, if a validator misbehaves, a portion of their total stake can be slashed (i.e. destroyed). This includes the stake of their delegators. diff --git a/docs/validators/validator-faq.md b/docs/validators/validator-faq.md index 8ab1c4cdc63..bb68a137710 100644 --- a/docs/validators/validator-faq.md +++ b/docs/validators/validator-faq.md @@ -53,7 +53,6 @@ Any participant in the network can signal that they want to become a validator b - **Initial commission rate**: The commission rate on block rewards and fees charged to delegators. - **Maximum commission:** The maximum commission rate that this validator can charge. This parameter is fixed and cannot be changed after the `create-validator` transaction is processed. - **Commission max change rate:** The maximum daily increase of the validator commission. This parameter is fixed cannot be changed after the `create-validator` transaction is processed. -- **Minimum self-delegation:** Minimum amount of ATOM the validator requires to have bonded at all time. If the validator's self-delegated stake falls below this limit, their validator gets jailed and kicked out of the active validator set. After a validator is created, ATOM holders can delegate ATOM to them, effectively adding stake to the validator's pool. The total stake of an address is the combination of ATOM bonded by delegators and ATOM self-bonded by the validator. @@ -95,9 +94,13 @@ After a validator is created with a `create-validator` transaction, the validato - `unbonded`: Validator is not in the active set, and therefore not signing blocks. The validator cannot be slashed and does not earn any reward. It is still possible to delegate ATOM to an unbonded validator. Undelegating from an `unbonded` validator is immediate, meaning that the tokens are not subject to the unbonding period. ### What is self-delegation? How can I increase my self-delegation? - + Self-delegation is a delegation of ATOM from a validator to themselves. The delegated amount can be increased by sending a `delegate` transaction from your validator's `application` application key. +### What is validator bond? How can I increase my validator bond? + +Validator bond is a delegation of ATOM from a delegator to a validator. Validator operators can validator bond to themselves. The validator bond amount can be increased by sending a `ValidatorBond` transaction from any account delegated to your validator. Validator bond is required before a validator can accept delegations from liquid staking providers. As such it forces validators to put “skin in the game” in order to be entrusted with delegations from liquid staking providers. This disincentivizes malicious behavior and enables the validator to negotiate its relationship with liquid staking providers. + ### Is there a minimum amount of ATOM that must be delegated to be an active (bonded) validator? The minimum is 1 ATOM. But the network is currently secured by much higher values. You can check the minimum required ATOM to become part of the active validator set on the [Mintscan validator page](https://www.mintscan.io/cosmos/validators). @@ -106,7 +109,7 @@ The minimum is 1 ATOM. But the network is currently secured by much higher value Delegators are free to choose validators according to their own subjective criteria. Selection criteria includes: -- **Amount of self-delegated ATOM:** Number of ATOM a validator self-delegated to themselves. A validator with a higher amount of self-delegated ATOM indicates that the validator is sharing the risk and experienced consequences for their actions. +- **Amount of validator-bonded ATOM:** Number of ATOM a validator validator-bonded to themselves. A validator with a higher amount of self-delegated ATOM indicates that the validator is sharing the risk and consequences for their actions, or has enough goodwill from the community so that others post validator bond on the validator's behalf. - **Amount of delegated ATOM:** Total number of ATOM delegated to a validator. A high voting power shows that the community trusts this validator. Larger validators also decrease the decentralization of the network, so delegators are suggested to consider delegating to smaller validators. - **Commission rate:** Commission applied on revenue by validators before the revenue is distributed to their delegators. - **Track record:** Delegators review the track record of the validators they plan to delegate to. This track record includes past votes on proposals and historical average uptime. @@ -158,7 +161,7 @@ This depends, currently no validators are required to validate other blockchains ### How can a validator safely quit validating on the Cosmos Hub? -If a validator simply shuts down their node, this would result in the validator and their delegators getting slashed for being offline. The only way to safely exit a validator node running on the Cosmos Hub is by unbonding the validator's self-delegated stake so that it falls below its minimum self-delegation limit. As a result, the validator gets jailed and kicked out of the active set of validators, without getting slashed. They can then proceed to shut down their node without risking their tokens. +If a validator simply shuts down their node, this would result in the validator and their delegators getting slashed for being offline. The only way to safely exit a validator node running on the Cosmos Hub is by unbonding the validator with the `UnbondValidator` message. As a result, the validator gets jailed and kicked out of the active set of validators, without getting slashed. They can then proceed to shut down their node without risking their tokens. It's highly advised to inform your delegators when doing this, as they will still be bonded to your validator after it got jailed. They will need to manually unbond and they might not have been made aware of this via their preferred wallet application. @@ -233,9 +236,7 @@ If a validator misbehaves, their delegated stake is partially slashed. Two fault ### Are validators required to self-delegate ATOM? -Yes, they do need to self-delegate at least `1 atom`. Even though there is no obligation for validators to self-delegate more than `1 atom`, delegators want their validator to have more self-delegated ATOM in their staking pool. In other words, validators share the risk. - -In order for delegators to have some guarantee about how much shared risk their validator has, the validator can signal a minimum amount of self-delegated ATOM. If a validator's self-delegation goes below the limit that it predefined, the validator gets jailed and kicked out of the active set of validators while its delegators remain bonded to it. +No, they do not need to self-delegate. Even though there is no obligation for validators to self-delegate, delegators may want their validator to have self-delegated ATOM in their staking pool. In other words, validators share the risk. Note however that it's possible that some validators decide to self-delegate via a different address for security reasons. @@ -243,6 +244,51 @@ Note however that it's possible that some validators decide to self-delegate via The community is expected to behave in a smart and self-preserving way. When a mining pool in Bitcoin gets too much mining power the community usually stops contributing to that pool. The Cosmos Hub relies on the same effect. Additionally, when delegaters switch to another validator, they are not subject to the unbonding period, which removes any barrier to quickly redelegating tokens in service of improving decentralization. +## Liquid Staking Module + +### What is the liquid staking module? + +The Liquid Staking Module is a set of safety features that mitigate liquid staking risks by: +- limiting the total amount of tokens that can be liquid staked to X% of all staked tokens. +- introducing a requirement that validators validator-bond tokens to be eligible for delegations from liquid staking providers. +- limiting the portion of validators's shares that can be liquid staked to X% of their total shares. + +The Liquid Staking Module also improves liquid staking UX by making delegations transferable under limited scenarios, to allow delegators to convert their delegations into liquid staking positions without having to wait the unbonding period. + +For a detailed and technical description, please see ADR-061 in the Cosmos SDK or the Liquid Staking Module Cosmos Hub [forum post](https://forum.cosmos.network/t/signaling-proposal-draft-add-liquid-staking-module-to-the-cosmos-hub/10368). + +### Who can validator bond? +The validator themselves, but also any other address delegated to the validator. + +### How can I validator bond? +Once delegated to a validator, a delegator (or validator operator) can convert their delegation to a validator into Validator Bond by signing a ValidatorBond message. + +The ValidatorBond message is exposed by the staking module and can be executed as follows: +``` +gaiad tx staking validator-bond cosmosvaloper13h5xdxhsdaugwdrkusf8lkgu406h8t62jkqv3h --from mykey +``` +There are no partial Validator Bonds: when a delegator or validator converts their shares to a particular validator into Validator Bond, their entire delegation to that validator is converted to Validator Bond. If a validator or delegator wishes to convert only some of their delegation to Validator Bond, they should transfer those funds to a separate address and Validator Bond from that address, or redelegate the funds that they do not wish to validator bond to another validator before converting their delegation to validator bond. + +To convert Validator Bond back into a standard delegation, simply unbond the shares. + +### How does a delegator or validator mark their delegation as a validator bond? +Once delegated to a validator, sign a `ValidatorBond` message. + +### Are validator bonds subject to additional slashing conditions? +No, in the event of a slash, a validator bond is slashed at the same rate as a regular bond. + +### Can I unbond my validator bond? +If all the liquid staking capacity made available by a validator’s validator bond is utilized, validator bond delegated to that validator cannot be unbonded. If new capacity becomes available (either by redemption of liquid staking tokens or addition or new validator bond), then existing validator bond can be undelegated. + +Example: Suppose the validator bond factor is 250 and Validator V bonds 2 ATOM, then liquid staking providers delegate 500 ATOM to Validator V. Now Validator V cannot remove any of their validator bond because the full liquid staking capacity made available by Validator V’s validator bond is consumed. + +If liquid staking providers undelegate 250 ATOM from Validator V, Validator V can now remove 1 ATOM of validator bond. + +If, instead, the ICF or a community member validator bonds 1 additional ATOM to Validator V, Validator V can now remove 1 ATOM of validator bond. + +### Can I validator bond some of my tokens and delegate the remaining portion normally? +The `ValidatorBond` message converts the full balance delegated to a validator into validator bond. To validator bond some tokens and delegate the remaining portion normally, use two addresses: the first will delegate + ValidatorBond, and the second will just delegate. + ## Technical Requirements ### What are hardware requirements? diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index 548829568a1..76c73bd35d6 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -46,7 +46,6 @@ gaiad tx staking create-validator \ --commission-rate="0.10" \ --commission-max-rate="0.20" \ --commission-max-change-rate="0.01" \ - --min-self-delegation="1000000" \ --gas="auto" \ --gas-prices="0.0025uatom" \ --from= @@ -56,9 +55,6 @@ gaiad tx staking create-validator \ When specifying commission parameters, the `commission-max-change-rate` is used to measure % _point_ change over the `commission-rate`. E.g. 1% to 2% is a 100% rate increase, but only 1 percentage point. ::: -::: tip -`Min-self-delegation` is a stritly positive integer that represents the minimum amount of self-delegated voting power your validator must always have. A `min-self-delegation` of `1000000` means your validator will never have a self-delegation lower than `1atom` -::: It's possible that you won't have enough ATOM to be part of the active set of validators in the beginning. Users are able to delegate to inactive validators (those outside of the active set) using the [Keplr web app](https://wallet.keplr.app/#/cosmoshub/stake?tab=inactive-validators). You can confirm that you are in the validator set by using a third party explorer like [Mintscan](https://www.mintscan.io/cosmos/validators). From 7b5a06ad0e2cad863a2a21fddb1b57722d1e93b3 Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 16 Aug 2023 14:07:14 +0200 Subject: [PATCH 12/15] bump SDK to 0.45.16-ics-lsm-rc0 and ICS to 2.0.0-lsm-rc0 --- go.mod | 8 +++++--- go.sum | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 8cb59580fbc..31c89604562 100644 --- a/go.mod +++ b/go.mod @@ -176,9 +176,11 @@ replace ( // Use cosmos keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - // NOTE: @MSalopek test ics-lsm implementations - github.com/cosmos/cosmos-sdk => github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230803192832-aab739edf2ca - github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.1-0.20230807142151-863915e43e6a + // Use special SDK release with support for both ICS and LSM + github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.45.16-ics-lsm-rc0 + + // Use special ICS release with support for LSM + github.com/cosmos/interchain-security/v2 => github.com/cosmos/interchain-security/v2 v2.0.0-lsm-rc0 // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 diff --git a/go.sum b/go.sum index 67273d1e461..5f1cb923aff 100644 --- a/go.sum +++ b/go.sum @@ -239,6 +239,8 @@ github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32 h1:zlCp9n3uwQieEL github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32/go.mod h1:kwMlEC4wWvB48zAShGKVqboJL6w4zCLesaNQ3YLU2BQ= github.com/cosmos/cosmos-proto v1.0.0-beta.1 h1:iDL5qh++NoXxG8hSy93FdYJut4XfgbShIocllGaXx/0= github.com/cosmos/cosmos-proto v1.0.0-beta.1/go.mod h1:8k2GNZghi5sDRFw/scPL8gMSowT1vDA+5ouxL8GjaUE= +github.com/cosmos/cosmos-sdk v0.45.16-ics-lsm-rc0 h1:zFSOIuoTbVCCnqIbfG0KZ099bIr6i9G+J3IOR9dgG80= +github.com/cosmos/cosmos-sdk v0.45.16-ics-lsm-rc0/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -250,8 +252,8 @@ github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.1.0 h1:96f github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.1.0/go.mod h1:Mn/jr9pIYr1ofFuptLEi9N6MjcshTT0cpoOY4ln1DeA= github.com/cosmos/ibc-go/v4 v4.4.2 h1:PG4Yy0/bw6Hvmha3RZbc53KYzaCwuB07Ot4GLyzcBvo= github.com/cosmos/ibc-go/v4 v4.4.2/go.mod h1:j/kD2JCIaV5ozvJvaEkWhLxM2zva7/KTM++EtKFYcB8= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230807142151-863915e43e6a h1:eLyWaPSxJCYLU/CWvJXzyA71VoO71ytdYQmshk8N8VE= -github.com/cosmos/interchain-security/v2 v2.0.1-0.20230807142151-863915e43e6a/go.mod h1:iDSje+UvpDKNYJvhgveKiYnAZNJnoZ5KsOCkG2jbT/4= +github.com/cosmos/interchain-security/v2 v2.0.0-lsm-rc0 h1:uYyMNGRA8Ac5cbtSqZkrPg1n067VJBkYyc5YWjHaHMc= +github.com/cosmos/interchain-security/v2 v2.0.0-lsm-rc0/go.mod h1:95jhiu/pUA2sBbfVPc+d+0AkL+A+zBYRHlEknIgcAvc= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= @@ -614,8 +616,6 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230803192832-aab739edf2ca h1:ddvixv/W+SIWAy0rCKiVmzq0aAzAowxj61rYJr06MH4= -github.com/iqlusioninc/cosmos-sdk v0.45.17-0.20230803192832-aab739edf2ca/go.mod h1:bScuNwWAP0TZJpUf+SHXRU3xGoUPp+X9nAzfeIXts40= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= From be57325f85a2d17298872ce4076bad503bdefedd Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 16 Aug 2023 14:26:04 +0200 Subject: [PATCH 13/15] add .changelog entries --- .changelog/unreleased/api-breaking/2643-lsm.md | 3 +++ .changelog/unreleased/dependencies/2643-bump-ics.md | 3 +++ .changelog/unreleased/dependencies/2643-bump-sdk.md | 3 +++ .changelog/unreleased/features/2643-lsm.md | 3 +++ .changelog/unreleased/state-breaking/2643-lsm.md | 3 +++ 5 files changed, 15 insertions(+) create mode 100644 .changelog/unreleased/api-breaking/2643-lsm.md create mode 100644 .changelog/unreleased/dependencies/2643-bump-ics.md create mode 100644 .changelog/unreleased/dependencies/2643-bump-sdk.md create mode 100644 .changelog/unreleased/features/2643-lsm.md create mode 100644 .changelog/unreleased/state-breaking/2643-lsm.md diff --git a/.changelog/unreleased/api-breaking/2643-lsm.md b/.changelog/unreleased/api-breaking/2643-lsm.md new file mode 100644 index 00000000000..b0ce066b4f1 --- /dev/null +++ b/.changelog/unreleased/api-breaking/2643-lsm.md @@ -0,0 +1,3 @@ +- Add Liquid Staking Module (LSM) and initialize the LSM params: + ValidatorBondFactor, ValidatorLiquidStakingCap, GlobalLiquidStakingCap + ([\#2643](https://github.com/cosmos/gaia/pull/2643)) \ No newline at end of file diff --git a/.changelog/unreleased/dependencies/2643-bump-ics.md b/.changelog/unreleased/dependencies/2643-bump-ics.md new file mode 100644 index 00000000000..1bfca86072e --- /dev/null +++ b/.changelog/unreleased/dependencies/2643-bump-ics.md @@ -0,0 +1,3 @@ +- Bump [interchain-security](https://github.com/cosmos/interchain-security) to + [v2.0.0-lsm](https://github.com/cosmos/interchain-security/releases/tag/v2.0.0-lsm) + ([\#2643](https://github.com/cosmos/gaia/pull/2643)) \ No newline at end of file diff --git a/.changelog/unreleased/dependencies/2643-bump-sdk.md b/.changelog/unreleased/dependencies/2643-bump-sdk.md new file mode 100644 index 00000000000..e13f5bfd215 --- /dev/null +++ b/.changelog/unreleased/dependencies/2643-bump-sdk.md @@ -0,0 +1,3 @@ +- Bump [cosmos-sdk](https://github.com/cosmos/cosmos-sdk) to + [v0.45.16-ics-lsm](https://github.com/cosmos/ibc-go/releases/tag/v0.45.16-ics-lsm) + ([\#2643](https://github.com/cosmos/gaia/pull/2643)) \ No newline at end of file diff --git a/.changelog/unreleased/features/2643-lsm.md b/.changelog/unreleased/features/2643-lsm.md new file mode 100644 index 00000000000..b0ce066b4f1 --- /dev/null +++ b/.changelog/unreleased/features/2643-lsm.md @@ -0,0 +1,3 @@ +- Add Liquid Staking Module (LSM) and initialize the LSM params: + ValidatorBondFactor, ValidatorLiquidStakingCap, GlobalLiquidStakingCap + ([\#2643](https://github.com/cosmos/gaia/pull/2643)) \ No newline at end of file diff --git a/.changelog/unreleased/state-breaking/2643-lsm.md b/.changelog/unreleased/state-breaking/2643-lsm.md new file mode 100644 index 00000000000..b0ce066b4f1 --- /dev/null +++ b/.changelog/unreleased/state-breaking/2643-lsm.md @@ -0,0 +1,3 @@ +- Add Liquid Staking Module (LSM) and initialize the LSM params: + ValidatorBondFactor, ValidatorLiquidStakingCap, GlobalLiquidStakingCap + ([\#2643](https://github.com/cosmos/gaia/pull/2643)) \ No newline at end of file From 6a99e8da70a7e71aea376354082afcd3f4916da9 Mon Sep 17 00:00:00 2001 From: Shawn <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 16 Aug 2023 08:14:38 -0700 Subject: [PATCH 14/15] use sdk.Dec --- app/upgrades/v12/constants.go | 13 ++++++++----- app/upgrades/v12/upgrades.go | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/upgrades/v12/constants.go b/app/upgrades/v12/constants.go index 161d65519e5..169de9252c8 100644 --- a/app/upgrades/v12/constants.go +++ b/app/upgrades/v12/constants.go @@ -1,23 +1,26 @@ package v12 import ( + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/gaia/v12/app/upgrades" ) const ( // UpgradeName defines the on-chain upgrade name. UpgradeName = "v12" +) +var ( // The ValidatorBondFactor dictates the cap on the liquid shares // for a validator - determined as a multiple to their validator bond // (e.g. ValidatorBondShares = 1000, BondFactor = 250 -> LiquidSharesCap: 250,000) - ValidatorBondFactor = 250 - // GlobalLiquidStakingCap represents the percentage cap on - // the portion of a validator's stake that can be liquid - ValidatorLiquidStakingCap = 50 // 50% + ValidatorBondFactor = sdk.NewDec(250) + // GlobalLiquidStakingCap represents a cap on the portion of stake that + // comes from liquid staking providers for a specific validator + ValidatorLiquidStakingCap = sdk.MustNewDecFromStr("0.5") // 50% // GlobalLiquidStakingCap represents the percentage cap on // the portion of a chain's total stake can be liquid - GlobalLiquidStakingCap = 25 // 25% + GlobalLiquidStakingCap = sdk.MustNewDecFromStr("0.25") // 25% ) var Upgrade = upgrades.Upgrade{ diff --git a/app/upgrades/v12/upgrades.go b/app/upgrades/v12/upgrades.go index 5531b8d2d8a..3aa086a1b19 100644 --- a/app/upgrades/v12/upgrades.go +++ b/app/upgrades/v12/upgrades.go @@ -23,9 +23,9 @@ func CreateUpgradeHandler( // Set liquid staking module parameters params := keepers.StakingKeeper.GetParams(ctx) - params.ValidatorBondFactor = sdk.NewDec(ValidatorBondFactor) - params.ValidatorLiquidStakingCap = sdk.NewDec(ValidatorLiquidStakingCap) - params.GlobalLiquidStakingCap = sdk.NewDec(GlobalLiquidStakingCap) + params.ValidatorBondFactor = ValidatorBondFactor + params.ValidatorLiquidStakingCap = ValidatorLiquidStakingCap + params.GlobalLiquidStakingCap = GlobalLiquidStakingCap keepers.StakingKeeper.SetParams(ctx, params) From a28eb3bf5a522eda1f58d3ed41126ec4a68c876b Mon Sep 17 00:00:00 2001 From: Shawn <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed, 16 Aug 2023 08:47:46 -0700 Subject: [PATCH 15/15] Update constants.go --- app/upgrades/v12/constants.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app/upgrades/v12/constants.go b/app/upgrades/v12/constants.go index 169de9252c8..574f844b2f7 100644 --- a/app/upgrades/v12/constants.go +++ b/app/upgrades/v12/constants.go @@ -2,6 +2,7 @@ package v12 import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gaia/v12/app/upgrades" )