Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

chore: sync main #904

Merged
merged 9 commits into from
Jul 26, 2022
6 changes: 3 additions & 3 deletions x/campaign/keeper/mainnet_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func (k Keeper) SetMainnetAccount(ctx sdk.Context, mainnetAccount types.MainnetAccount) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.MainnetAccountKeyPrefix))
b := k.cdc.MustMarshal(&mainnetAccount)
store.Set(types.MainnetAccountKey(
store.Set(types.AccountKeyPath(
mainnetAccount.CampaignID,
mainnetAccount.Address,
), b)
Expand All @@ -25,7 +25,7 @@ func (k Keeper) GetMainnetAccount(
) (val types.MainnetAccount, found bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.MainnetAccountKeyPrefix))

b := store.Get(types.MainnetAccountKey(campaignID, address))
b := store.Get(types.AccountKeyPath(campaignID, address))
if b == nil {
return val, false
}
Expand All @@ -41,7 +41,7 @@ func (k Keeper) RemoveMainnetAccount(
address string,
) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.MainnetAccountKeyPrefix))
store.Delete(types.MainnetAccountKey(
store.Delete(types.AccountKeyPath(
campaignID,
address,
))
Expand Down
6 changes: 5 additions & 1 deletion x/campaign/keeper/msg_mint_vouchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ func (k msgServer) MintVouchers(goCtx context.Context, msg *types.MsgMintVoucher

// Increase the campaign shares
campaign.AllocatedShares = types.IncreaseShares(campaign.AllocatedShares, msg.Shares)
if types.IsTotalSharesReached(campaign.AllocatedShares, k.GetTotalShares(ctx)) {
reached, err := types.IsTotalSharesReached(campaign.AllocatedShares, k.GetTotalShares(ctx))
if err != nil {
return nil, spnerrors.Criticalf("verified shares are invalid %s", err.Error())
}
if reached {
return nil, sdkerrors.Wrapf(types.ErrTotalSharesLimit, "%d", msg.CampaignID)
}

Expand Down
8 changes: 6 additions & 2 deletions x/campaign/keeper/msg_update_special_allocations.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ func (k msgServer) UpdateSpecialAllocations(goCtx context.Context, msg *types.Ms
// increase with new special allocations
campaign.AllocatedShares = types.IncreaseShares(campaign.AllocatedShares, msg.SpecialAllocations.TotalShares())

// check total is not reached
if types.IsTotalSharesReached(campaign.AllocatedShares, k.GetTotalShares(ctx)) {
// increase the campaign shares
reached, err := types.IsTotalSharesReached(campaign.AllocatedShares, k.GetTotalShares(ctx))
if err != nil {
return nil, spnerrors.Criticalf("verified shares are invalid %s", err.Error())
}
if reached {
return nil, sdkerrors.Wrapf(types.ErrTotalSharesLimit, "%d", msg.CampaignID)
}

Expand Down
9 changes: 5 additions & 4 deletions x/campaign/types/campaign.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ func (m Campaign) Validate(totalShareNumber uint64) error {
if !m.TotalSupply.IsValid() {
return errors.New("invalid total supply")
}
if !sdk.Coins(m.AllocatedShares).IsValid() {
return errors.New("invalid allocated shares")
}

if IsTotalSharesReached(m.AllocatedShares, totalShareNumber) {
reached, err := IsTotalSharesReached(m.AllocatedShares, totalShareNumber)
if err != nil {
return errors.Wrap(err, "invalid allocated shares")
}
if reached {
return errors.New("more allocated shares than total shares")
}

Expand Down
4 changes: 3 additions & 1 deletion x/campaign/types/campaign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ func TestCampaign_Validate(t *testing.T) {
totalSharesReached.AllocatedShares = campaign.NewSharesFromCoins(sdk.NewCoins(
sdk.NewCoin("foo", sdk.NewInt(spntypes.TotalShareNumber+1)),
))
require.True(t, campaign.IsTotalSharesReached(totalSharesReached.AllocatedShares, spntypes.TotalShareNumber))
reached, err := campaign.IsTotalSharesReached(totalSharesReached.AllocatedShares, spntypes.TotalShareNumber)
require.NoError(t, err)
require.True(t, reached)

invalidSpecialAllocations := campaign.NewSpecialAllocations(
sample.Shares(r),
Expand Down
2 changes: 1 addition & 1 deletion x/campaign/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (gs GenesisState) Validate() error {
return fmt.Errorf("campaign id %d doesn't exist for mainnet account %s",
elem.CampaignID, elem.Address)
}
index := string(MainnetAccountKey(elem.CampaignID, elem.Address))
index := string(AccountKeyPath(elem.CampaignID, elem.Address))
if _, ok := mainnetAccountIndexMap[index]; ok {
return fmt.Errorf("duplicated index for mainnetAccount")
}
Expand Down
11 changes: 2 additions & 9 deletions x/campaign/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ func CampaignChainsKey(campaignID uint64) []byte {
return append(spntypes.UintBytes(campaignID), byte('/'))
}

// MainnetAccountKey returns the store key to retrieve a MainnetAccount from the index fields
func MainnetAccountKey(campaignID uint64, address string) []byte {
// AccountKeyPath returns the store key path without prefix for an account defined by a campaign ID and an address
func AccountKeyPath(campaignID uint64, address string) []byte {
campaignIDBytes := append(spntypes.UintBytes(campaignID), byte('/'))
addressBytes := append([]byte(address), byte('/'))
return append(campaignIDBytes, addressBytes...)
Expand All @@ -60,13 +60,6 @@ func MainnetAccountAllKey(campaignID uint64) []byte {
return append(prefixBytes, campaignIDBytes...)
}

// MainnetVestingAccountKey returns the store key to retrieve a MainnetVestingAccount from the index fields
func MainnetVestingAccountKey(campaignID uint64, address string) []byte {
campaignIDBytes := append(spntypes.UintBytes(campaignID), byte('/'))
addressBytes := append([]byte(address), byte('/'))
return append(campaignIDBytes, addressBytes...)
}

// MainnetVestingAccountAllKey returns the store key to retrieve all MainnetVestingAccount by campaign id
func MainnetVestingAccountAllKey(campaignID uint64) []byte {
prefixBytes := []byte(MainnetVestingAccountKeyPrefix)
Expand Down
17 changes: 12 additions & 5 deletions x/campaign/types/shares.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package types

import (
"errors"
"fmt"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/pkg/errors"
)

// Shares represents the portion of a supply
Expand Down Expand Up @@ -73,14 +73,21 @@ func DecreaseShares(shares, toDecrease Shares) (Shares, error) {
}

// IsTotalSharesReached checks if the provided shares overflow the total number of shares
func IsTotalSharesReached(shares Shares, totalShareNumber uint64) bool {
func IsTotalSharesReached(shares Shares, maximumTotalShareNumber uint64) (bool, error) {
if err := sdk.Coins(shares).Validate(); err != nil {
return false, errors.Wrap(err, "invalid share")
}
if err := CheckShares(shares); err != nil {
return false, errors.Wrap(err, "invalid share format")
}

for _, share := range shares {
if share.Amount.Uint64() > totalShareNumber {
return true
if share.Amount.Uint64() > maximumTotalShareNumber {
return true, nil
}
}

return false
return false, nil
}

// IsAllLTE returns true iff for every denom in shares, the denom is present at
Expand Down
59 changes: 46 additions & 13 deletions x/campaign/types/shares_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,28 +133,61 @@ func TestDecreaseShares(t *testing.T) {

func TestShareIsTotalReached(t *testing.T) {
for _, tc := range []struct {
desc string
shares campaign.Shares
reached bool
desc string
shares campaign.Shares
maxTotalShares uint64
reached bool
isValid bool
}{
{
desc: "empty is false",
shares: campaign.EmptyShares(),
reached: false,
desc: "should return false with empty shares",
shares: campaign.EmptyShares(),
maxTotalShares: 0,
reached: false,
isValid: true,
},
{
desc: "no default total is reached",
shares: tc.Shares(t, fmt.Sprintf("%dfoo,100bar", spntypes.TotalShareNumber)),
reached: false,
desc: "should return false when total not reached",
shares: tc.Shares(t, "1000foo,100bar"),
maxTotalShares: 1000,
reached: false,
isValid: true,
},
{
desc: "a default total is reached",
shares: tc.Shares(t, fmt.Sprintf("%dfoo,100bar", spntypes.TotalShareNumber+1)),
reached: true,
desc: "should return true when total reached",
shares: tc.Shares(t, "1001foo,100bar"),
maxTotalShares: 1000,
reached: true,
isValid: true,
},
{
desc: "should return error if shares are invalid",
shares: campaign.NewSharesFromCoins(sdk.Coins{
sdk.NewCoin("foo", sdk.NewIntFromUint64(500)),
sdk.NewCoin("foo", sdk.NewIntFromUint64(500)),
}),
maxTotalShares: 1000,
reached: false,
isValid: false,
},
{
desc: "should return error if shares have invalid format",
shares: campaign.Shares(sdk.Coins{
sdk.NewCoin("foo", sdk.NewIntFromUint64(500)),
}),
maxTotalShares: 1000,
reached: false,
isValid: false,
},
} {
t.Run(tc.desc, func(t *testing.T) {
require.Equal(t, tc.reached, campaign.IsTotalSharesReached(tc.shares, spntypes.TotalShareNumber))
reached, err := campaign.IsTotalSharesReached(tc.shares, tc.maxTotalShares)
if tc.isValid {
require.NoError(t, err)
require.True(t, tc.reached == reached)
} else {
require.Error(t, err)
}
})
}
}
Expand Down
17 changes: 16 additions & 1 deletion x/launch/client/cli/tx_create_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package cli

import (
"context"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
neturl "net/url"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/spf13/cobra"

"github.com/tendermint/spn/x/launch/types"
)

Expand Down Expand Up @@ -88,6 +90,19 @@ func CmdCreateChain() *cobra.Command {

// getHashFromURL fetches content from url and returns the hash based on the genesis hash method
func getHashFromURL(ctx context.Context, url string) (string, error) {
// check url port
parsedUrl, err := neturl.Parse(url)
if err != nil {
return "", err
}
_, port, err := net.SplitHostPort(parsedUrl.Host)
if err != nil {
return "", err
}
if port != "443" {
return "", errors.New("port must be 443")
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", err
Expand Down
6 changes: 3 additions & 3 deletions x/launch/keeper/genesis_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func (k Keeper) SetGenesisAccount(ctx sdk.Context, genesisAccount types.GenesisAccount) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GenesisAccountKeyPrefix))
b := k.cdc.MustMarshal(&genesisAccount)
store.Set(types.GenesisAccountKey(
store.Set(types.AccountKeyPath(
genesisAccount.LaunchID,
genesisAccount.Address,
), b)
Expand All @@ -25,7 +25,7 @@ func (k Keeper) GetGenesisAccount(
) (val types.GenesisAccount, found bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GenesisAccountKeyPrefix))

b := store.Get(types.GenesisAccountKey(launchID, address))
b := store.Get(types.AccountKeyPath(launchID, address))
if b == nil {
return val, false
}
Expand All @@ -41,7 +41,7 @@ func (k Keeper) RemoveGenesisAccount(
address string,
) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GenesisAccountKeyPrefix))
store.Delete(types.GenesisAccountKey(launchID, address))
store.Delete(types.AccountKeyPath(launchID, address))
}

// GetAllGenesisAccount returns all genesisAccount
Expand Down
6 changes: 3 additions & 3 deletions x/launch/keeper/genesis_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func (k Keeper) SetGenesisValidator(ctx sdk.Context, genesisValidator types.GenesisValidator) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GenesisValidatorKeyPrefix))
b := k.cdc.MustMarshal(&genesisValidator)
store.Set(types.GenesisValidatorKey(
store.Set(types.AccountKeyPath(
genesisValidator.LaunchID,
genesisValidator.Address,
), b)
Expand All @@ -27,7 +27,7 @@ func (k Keeper) GetGenesisValidator(
) (val types.GenesisValidator, found bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GenesisValidatorKeyPrefix))

b := store.Get(types.GenesisValidatorKey(launchID, address))
b := store.Get(types.AccountKeyPath(launchID, address))
if b == nil {
return val, false
}
Expand All @@ -53,7 +53,7 @@ func (k Keeper) GetGenesisValidatorCount(ctx sdk.Context, launchID uint64) (coun
// RemoveGenesisValidator removes a genesisValidator from the store
func (k Keeper) RemoveGenesisValidator(ctx sdk.Context, launchID uint64, address string) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.GenesisValidatorKeyPrefix))
store.Delete(types.GenesisValidatorKey(launchID, address))
store.Delete(types.AccountKeyPath(launchID, address))
}

// GetAllGenesisValidator returns all genesisValidator
Expand Down
6 changes: 3 additions & 3 deletions x/launch/keeper/vesting_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func (k Keeper) SetVestingAccount(ctx sdk.Context, vestingAccount types.VestingAccount) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VestingAccountKeyPrefix))
b := k.cdc.MustMarshal(&vestingAccount)
store.Set(types.VestingAccountKey(
store.Set(types.AccountKeyPath(
vestingAccount.LaunchID,
vestingAccount.Address,
), b)
Expand All @@ -25,7 +25,7 @@ func (k Keeper) GetVestingAccount(
) (val types.VestingAccount, found bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VestingAccountKeyPrefix))

b := store.Get(types.VestingAccountKey(launchID, address))
b := store.Get(types.AccountKeyPath(launchID, address))
if b == nil {
return val, false
}
Expand All @@ -41,7 +41,7 @@ func (k Keeper) RemoveVestingAccount(
address string,
) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VestingAccountKeyPrefix))
store.Delete(types.VestingAccountKey(launchID, address))
store.Delete(types.AccountKeyPath(launchID, address))
}

// GetAllVestingAccount returns all vestingAccount
Expand Down
8 changes: 4 additions & 4 deletions x/launch/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func validateAccounts(gs GenesisState, launchIDMap map[uint64]struct{}) error {
// Check for duplicated index in genesisAccount
genesisAccountIndexMap := make(map[string]struct{})
for _, elem := range gs.GenesisAccountList {
index := string(GenesisAccountKey(elem.LaunchID, elem.Address))
index := string(AccountKeyPath(elem.LaunchID, elem.Address))
if _, ok := genesisAccountIndexMap[index]; ok {
return fmt.Errorf("duplicated index for genesisAccount")
}
Expand All @@ -135,7 +135,7 @@ func validateAccounts(gs GenesisState, launchIDMap map[uint64]struct{}) error {
// Check for duplicated index in vestingAccount
vestingAccountIndexMap := make(map[string]struct{})
for _, elem := range gs.VestingAccountList {
index := string(VestingAccountKey(elem.LaunchID, elem.Address))
index := string(AccountKeyPath(elem.LaunchID, elem.Address))
if _, ok := vestingAccountIndexMap[index]; ok {
return fmt.Errorf("duplicated index for vestingAccount")
}
Expand All @@ -150,7 +150,7 @@ func validateAccounts(gs GenesisState, launchIDMap map[uint64]struct{}) error {
}

// An address cannot be defined as a genesis account and a vesting account for the same chain
accountIndex := GenesisAccountKey(elem.LaunchID, elem.Address)
accountIndex := AccountKeyPath(elem.LaunchID, elem.Address)
if _, ok := genesisAccountIndexMap[string(accountIndex)]; ok {
return fmt.Errorf("account %s can't be a genesis account and a vesting account at the same time for the chain: %d",
elem.Address,
Expand All @@ -162,7 +162,7 @@ func validateAccounts(gs GenesisState, launchIDMap map[uint64]struct{}) error {
// Check for duplicated index in genesisValidator
genesisValidatorIndexMap := make(map[string]struct{})
for _, elem := range gs.GenesisValidatorList {
index := string(GenesisValidatorKey(elem.LaunchID, elem.Address))
index := string(AccountKeyPath(elem.LaunchID, elem.Address))
if _, ok := genesisValidatorIndexMap[index]; ok {
return fmt.Errorf("duplicated index for genesisValidator")
}
Expand Down
Loading