diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b0f734957..4187e7da1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/wasm) [\#453](https://github.com/line/lbm-sdk/pull/453) modify wasm grpc query api path * (client) [\#476](https://github.com/line/lbm-sdk/pull/476) change the default value of the client output format in the config * (server/grpc) [\#516](https://github.com/line/lbm-sdk/pull/516) restore build norace flag +* (genesis) [\#517](https://github.com/line/lbm-sdk/pull/517) fix genesis auth account format(cosmos-sdk style -> lbm-sdk style) ### Breaking Changes diff --git a/baseapp/block_gas_test.go b/baseapp/block_gas_test.go index aa2f12d6a2..f524ed3cee 100644 --- a/baseapp/block_gas_test.go +++ b/baseapp/block_gas_test.go @@ -124,7 +124,7 @@ func TestBaseApp_BlockGas(t *testing.T) { require.Equal(t, []byte("ok"), okValue) } // check block gas is always consumed - baseGas := uint64(36950) // baseGas is the gas consumed before tx msg + baseGas := uint64(35000) // baseGas is the gas consumed before tx msg expGasConsumed := addUint64Saturating(tc.gasToConsume, baseGas) if expGasConsumed > txtypes.MaxGasWanted { // capped by gasLimit diff --git a/x/auth/keeper/keeper.go b/x/auth/keeper/keeper.go index cad4379cbe..9e7d034f61 100644 --- a/x/auth/keeper/keeper.go +++ b/x/auth/keeper/keeper.go @@ -226,14 +226,13 @@ func (ak AccountKeeper) decodeAccount(bz []byte) types.AccountI { // MarshalAccount protobuf serializes an Account interface func (ak AccountKeeper) MarshalAccount(accountI types.AccountI) ([]byte, error) { // nolint:interfacer - return ak.cdc.MarshalInterface(accountI) + return types.MarshalAccountX(ak.cdc, accountI) } // UnmarshalAccount returns an Account interface from raw encoded account // bytes of a Proto-based Account type func (ak AccountKeeper) UnmarshalAccount(bz []byte) (types.AccountI, error) { - var acc types.AccountI - return acc, ak.cdc.UnmarshalInterface(bz, &acc) + return types.UnmarshalAccountX(ak.cdc, bz) } // GetCodec return codec.Codec object used by the keeper diff --git a/x/auth/types/account.go b/x/auth/types/account.go index 768c974a7c..1c7a1eb550 100644 --- a/x/auth/types/account.go +++ b/x/auth/types/account.go @@ -1,11 +1,14 @@ package types import ( + "bytes" "encoding/json" "errors" "fmt" + "strconv" "strings" + "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" "github.com/line/ostracon/crypto" "gopkg.in/yaml.v2" @@ -31,8 +34,9 @@ var ( ModuleAccountSig = []byte("macc") PubKeyTypeSecp256k1 = byte(1) - PubKeyTypeEd25519 = byte(2) - PubKeyTypeMultisig = byte(3) + PubKeyTypeSecp256R1 = byte(2) + PubKeyTypeEd25519 = byte(3) + PubKeyTypeMultisig = byte(4) ) // NewBaseAccount creates a new BaseAccount object @@ -359,7 +363,38 @@ type AccountI interface { MarshalX() ([]byte, error) } -// TODO(dudong2): remove MarshalAccountX, UnmarshalAccountX(because codec.BinaryMarshaler is removed -> build failed) - ref. https://github.com/line/lbm-sdk/pull/320 +func MarshalAccountX(cdc codec.BinaryCodec, acc AccountI) ([]byte, error) { + if bacc, ok := acc.(*BaseAccount); ok && bacc.MultisigPubKey == nil { + return acc.MarshalX() + } else if macc, ok := acc.(*ModuleAccount); ok && macc.MultisigPubKey == nil { + return acc.MarshalX() + } else { + return cdc.MarshalInterface(acc) + } +} + +func UnmarshalAccountX(cdc codec.BinaryCodec, bz []byte) (AccountI, error) { + sigLen := len(BaseAccountSig) + if len(bz) < sigLen { + return nil, fmt.Errorf("invalid data") + } + if bytes.Equal(bz[:sigLen], BaseAccountSig) { + acc := &BaseAccount{} + if err := acc.Unmarshal(bz[sigLen:]); err != nil { + return nil, err + } + return acc, nil + } else if bytes.Equal(bz[:sigLen], ModuleAccountSig) { + acc := &ModuleAccount{} + if err := acc.Unmarshal(bz[sigLen:]); err != nil { + return nil, err + } + return acc, nil + } else { + var acc AccountI + return acc, cdc.UnmarshalInterface(bz, &acc) + } +} // ModuleAccountI defines an account interface for modules that hold tokens in // an escrow. @@ -392,3 +427,135 @@ type GenesisAccount interface { Validate() error } + +// custom json marshaler for BaseAccount & ModuleAccount + +type PubKeyJSON struct { + Type byte `json:"type"` + Key []byte `json:"key"` +} + +type BaseAccountJSON struct { + Address string `json:"address"` + PubKey PubKeyJSON `json:"pub_key"` + AccountNumber uint64 `json:"account_number"` + Sequence string `json:"sequence"` +} + +func (acc BaseAccount) MarshalJSONPB(m *jsonpb.Marshaler) ([]byte, error) { + var bi BaseAccountJSON + + bi.Address = acc.GetAddress().String() + bi.AccountNumber = acc.GetAccountNumber() + bi.Sequence = strconv.FormatUint(acc.Sequence, 10) + var bz []byte + var err error + if acc.Secp256K1PubKey != nil { + bi.PubKey.Type = PubKeyTypeSecp256k1 + bz, err = acc.Secp256K1PubKey.Marshal() + } else if acc.Secp256R1PubKey != nil { + bi.PubKey.Type = PubKeyTypeSecp256R1 + bz, err = acc.Secp256R1PubKey.Marshal() + } else if acc.Ed25519PubKey != nil { + bi.PubKey.Type = PubKeyTypeEd25519 + bz, err = acc.Ed25519PubKey.Marshal() + } else if acc.MultisigPubKey != nil { + bi.PubKey.Type = PubKeyTypeMultisig + bz, err = acc.MultisigPubKey.Marshal() + } + if err != nil { + return nil, err + } + bi.PubKey.Key = bz + return json.Marshal(bi) +} + +func (acc *BaseAccount) UnmarshalJSONPB(m *jsonpb.Unmarshaler, bz []byte) error { + var bi BaseAccountJSON + + err := json.Unmarshal(bz, &bi) + if err != nil { + return err + } + /* TODO: do we need to validate address format here + err = sdk.ValidateAccAddress(bi.Address) + if err != nil { + return err + } + */ + + acc.Address = bi.Address + acc.AccountNumber = bi.AccountNumber + acc.Sequence, err = strconv.ParseUint(bi.Sequence, 10, 64) + if err != nil { + return err + } + + switch bi.PubKey.Type { + case PubKeyTypeEd25519: + pk := new(ed25519.PubKey) + if err := pk.Unmarshal(bi.PubKey.Key); err != nil { + return err + } + acc.SetPubKey(pk) + case PubKeyTypeSecp256k1: + pk := new(secp256k1.PubKey) + if err := pk.Unmarshal(bi.PubKey.Key); err != nil { + return err + } + acc.SetPubKey(pk) + case PubKeyTypeSecp256R1: + pk := new(secp256r1.PubKey) + if err := pk.Unmarshal(bi.PubKey.Key); err != nil { + return err + } + acc.SetPubKey(pk) + case PubKeyTypeMultisig: + pk := new(multisig.LegacyAminoPubKey) + if err := pk.Unmarshal(bi.PubKey.Key); err != nil { + return err + } + acc.SetPubKey(pk) + } + return nil +} + +type ModuleAccountJSON struct { + BaseAccount json.RawMessage `json:"base_account"` + Name string `json:"name"` + Permissions []string `json:"permissions"` +} + +func (ma ModuleAccount) MarshalJSONPB(m *jsonpb.Marshaler) ([]byte, error) { + var mi ModuleAccountJSON + + bz, err := ma.BaseAccount.MarshalJSONPB(m) + if err != nil { + return nil, err + } + mi.BaseAccount = bz + mi.Name = ma.Name + mi.Permissions = ma.Permissions + + return json.Marshal(mi) +} + +func (ma *ModuleAccount) UnmarshalJSONPB(m *jsonpb.Unmarshaler, bz []byte) error { + var mi ModuleAccountJSON + + err := json.Unmarshal(bz, &mi) + if err != nil { + return err + } + + ma.Name = mi.Name + ma.Permissions = mi.Permissions + + ba := new(BaseAccount) + if err := m.Unmarshal(strings.NewReader(string(mi.BaseAccount)), ba); err != nil { + return err + } + ma.BaseAccount = ba + + return nil +} diff --git a/x/auth/types/account_test.go b/x/auth/types/account_test.go index 016aeb312e..0a5b7179b7 100644 --- a/x/auth/types/account_test.go +++ b/x/auth/types/account_test.go @@ -6,6 +6,7 @@ import ( "fmt" "testing" + "github.com/gogo/protobuf/jsonpb" "github.com/stretchr/testify/require" yaml "gopkg.in/yaml.v2" @@ -214,6 +215,28 @@ func TestModuleAccountJSON(t *testing.T) { require.Equal(t, acc.String(), a.String()) } +func TestModuleAccountJSONPB(t *testing.T) { + pubkey := secp256k1.GenPrivKey().PubKey() + addr := sdk.BytesToAccAddress(pubkey.Address()) + baseAcc := types.NewBaseAccount(addr, nil, 10, 50) + acc := types.NewModuleAccount(baseAcc, "test", types.Burner) + + jm := jsonpb.Marshaler{} + bz, err := acc.MarshalJSONPB(&jm) + require.NoError(t, err) + + jum := jsonpb.Unmarshaler{} + addr2 := sdk.AccAddress("") + baseAcc2 := types.NewBaseAccount(addr2, nil, 0, 0) + acc2 := types.NewModuleAccount(baseAcc2, "") + err = acc2.UnmarshalJSONPB(&jum, bz) + require.NoError(t, err) + + // error on bad bytes + err = acc2.UnmarshalJSONPB(&jum, bz[:len(bz)/2]) + require.Error(t, err) +} + func TestGenesisAccountsContains(t *testing.T) { pubkey := secp256k1.GenPrivKey().PubKey() addr := sdk.BytesToAccAddress(pubkey.Address()) diff --git a/x/auth/vesting/types/vesting_account.go b/x/auth/vesting/types/vesting_account.go index bf5648b4c2..cb3f28bd8c 100644 --- a/x/auth/vesting/types/vesting_account.go +++ b/x/auth/vesting/types/vesting_account.go @@ -1,9 +1,11 @@ package types import ( + "encoding/json" "errors" "time" + "github.com/gogo/protobuf/jsonpb" yaml "gopkg.in/yaml.v2" cryptotypes "github.com/line/lbm-sdk/crypto/types" @@ -196,6 +198,54 @@ func (bva BaseVestingAccount) MarshalYAML() (interface{}, error) { return marshalYaml(out) } +type vestingAccountJSON struct { + BaseAccount json.RawMessage `json:"base_account"` + OriginalVesting sdk.Coins `json:"original_vesting"` + DelegatedFree sdk.Coins `json:"delegated_free"` + DelegatedVesting sdk.Coins `json:"delegated_vesting"` + EndTime int64 `json:"end_time"` + + StartTime int64 `json:"start_time,omitempty"` + VestingPeriods Periods `json:"vesting_periods,omitempty"` +} + +func (bva BaseVestingAccount) MarshalJSONPB(m *jsonpb.Marshaler) ([]byte, error) { + bz, err := bva.BaseAccount.MarshalJSONPB(m) + if err != nil { + return nil, err + } + alias := vestingAccountJSON{ + BaseAccount: bz, + OriginalVesting: bva.OriginalVesting, + DelegatedFree: bva.DelegatedFree, + DelegatedVesting: bva.DelegatedVesting, + EndTime: bva.EndTime, + } + + return json.Marshal(alias) +} + +func (bva *BaseVestingAccount) UnmarshalJSONPB(m *jsonpb.Unmarshaler, bz []byte) error { + var va vestingAccountJSON + + err := json.Unmarshal(bz, &va) + if err != nil { + return err + } + + var ba authtypes.BaseAccount + if err := (&ba).UnmarshalJSONPB(m, va.BaseAccount); err != nil { + return err + } + bva.BaseAccount = &ba + bva.OriginalVesting = va.OriginalVesting + bva.DelegatedFree = va.DelegatedFree + bva.DelegatedVesting = va.DelegatedVesting + bva.EndTime = va.EndTime + + return nil +} + // Continuous Vesting Account var _ vestexported.VestingAccount = (*ContinuousVestingAccount)(nil) @@ -305,6 +355,45 @@ func (cva ContinuousVestingAccount) MarshalYAML() (interface{}, error) { return marshalYaml(out) } +func (cva ContinuousVestingAccount) MarshalJSONPB(m *jsonpb.Marshaler) ([]byte, error) { + bz, err := cva.BaseVestingAccount.BaseAccount.MarshalJSONPB(m) + if err != nil { + return nil, err + } + alias := vestingAccountJSON{ + BaseAccount: bz, + OriginalVesting: cva.BaseVestingAccount.OriginalVesting, + DelegatedFree: cva.BaseVestingAccount.DelegatedFree, + DelegatedVesting: cva.BaseVestingAccount.DelegatedVesting, + EndTime: cva.BaseVestingAccount.EndTime, + StartTime: cva.StartTime, + } + return json.Marshal(alias) +} + +func (cva *ContinuousVestingAccount) UnmarshalJSONPB(m *jsonpb.Unmarshaler, bz []byte) error { + var va vestingAccountJSON + + err := json.Unmarshal(bz, &va) + if err != nil { + return err + } + + var ba authtypes.BaseAccount + if err := (&ba).UnmarshalJSONPB(m, va.BaseAccount); err != nil { + return err + } + cva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: &ba, + OriginalVesting: va.OriginalVesting, + DelegatedFree: va.DelegatedFree, + DelegatedVesting: va.DelegatedVesting, + EndTime: va.EndTime, + } + cva.StartTime = va.StartTime + return nil +} + // Periodic Vesting Account var _ vestexported.VestingAccount = (*PeriodicVestingAccount)(nil) @@ -444,6 +533,49 @@ func (pva PeriodicVestingAccount) MarshalYAML() (interface{}, error) { return marshalYaml(out) } +func (pva PeriodicVestingAccount) MarshalJSONPB(m *jsonpb.Marshaler) ([]byte, error) { + bz, err := pva.BaseVestingAccount.BaseAccount.MarshalJSONPB(m) + if err != nil { + return nil, err + } + alias := vestingAccountJSON{ + BaseAccount: bz, + OriginalVesting: pva.BaseVestingAccount.OriginalVesting, + DelegatedFree: pva.BaseVestingAccount.DelegatedFree, + DelegatedVesting: pva.BaseVestingAccount.DelegatedVesting, + EndTime: pva.BaseVestingAccount.EndTime, + StartTime: pva.StartTime, + VestingPeriods: pva.VestingPeriods, + } + + return json.Marshal(alias) +} + +func (pva *PeriodicVestingAccount) UnmarshalJSONPB(m *jsonpb.Unmarshaler, bz []byte) error { + var va vestingAccountJSON + + err := json.Unmarshal(bz, &va) + if err != nil { + return err + } + + var ba authtypes.BaseAccount + if err := (&ba).UnmarshalJSONPB(m, va.BaseAccount); err != nil { + return err + } + pva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: &ba, + OriginalVesting: va.OriginalVesting, + DelegatedFree: va.DelegatedFree, + DelegatedVesting: va.DelegatedVesting, + EndTime: va.EndTime, + } + pva.StartTime = va.StartTime + pva.VestingPeriods = va.VestingPeriods + + return nil +} + // Delayed Vesting Account var _ vestexported.VestingAccount = (*DelayedVestingAccount)(nil) @@ -511,6 +643,45 @@ func (dva DelayedVestingAccount) String() string { return out.(string) } +func (dva DelayedVestingAccount) MarshalJSONPB(m *jsonpb.Marshaler) ([]byte, error) { + bz, err := dva.BaseAccount.MarshalJSONPB(m) + if err != nil { + return nil, err + } + alias := vestingAccountJSON{ + BaseAccount: bz, + OriginalVesting: dva.BaseVestingAccount.OriginalVesting, + DelegatedFree: dva.BaseVestingAccount.DelegatedFree, + DelegatedVesting: dva.BaseVestingAccount.DelegatedVesting, + EndTime: dva.BaseVestingAccount.EndTime, + } + + return json.Marshal(alias) +} + +func (dva *DelayedVestingAccount) UnmarshalJSONPB(m *jsonpb.Unmarshaler, bz []byte) error { + var va vestingAccountJSON + + err := json.Unmarshal(bz, &va) + if err != nil { + return err + } + + var ba authtypes.BaseAccount + if err := (&ba).UnmarshalJSONPB(m, va.BaseAccount); err != nil { + return err + } + dva.BaseVestingAccount = &BaseVestingAccount{ + BaseAccount: &ba, + OriginalVesting: va.OriginalVesting, + DelegatedFree: va.DelegatedFree, + DelegatedVesting: va.DelegatedVesting, + EndTime: va.EndTime, + } + + return nil +} + //----------------------------------------------------------------------------- // Permanent Locked Vesting Account diff --git a/x/auth/vesting/types/vesting_account_test.go b/x/auth/vesting/types/vesting_account_test.go index 557213b008..273982e167 100644 --- a/x/auth/vesting/types/vesting_account_test.go +++ b/x/auth/vesting/types/vesting_account_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/gogo/protobuf/jsonpb" osttime "github.com/line/ostracon/types/time" "github.com/stretchr/testify/require" @@ -803,6 +804,90 @@ func TestPermanentLockedAccountMarshal(t *testing.T) { require.NotNil(t, err) } +func TestBaseVestingAccountMarshalJSONPB(t *testing.T) { + baseAcc, coins := initBaseAccount() + acc := types.NewBaseVestingAccount(baseAcc, coins, time.Now().Unix()) + + jm := jsonpb.Marshaler{} + bz, err := acc.MarshalJSONPB(&jm) + require.NoError(t, err) + + jum := jsonpb.Unmarshaler{} + acc2 := types.NewBaseVestingAccount(nil, sdk.NewCoins(), 0) + err = acc2.UnmarshalJSONPB(&jum, bz) + require.NoError(t, err) + require.IsType(t, &types.BaseVestingAccount{}, acc2) + require.Equal(t, acc.String(), acc2.String()) + + // error on bad bytes + err = acc2.UnmarshalJSONPB(&jum, bz[:len(bz)/2]) + require.Error(t, err) +} + +func TestContinuousVestingAccountMarshalJSONPB(t *testing.T) { + baseAcc, coins := initBaseAccount() + baseVesting := types.NewBaseVestingAccount(baseAcc, coins, time.Now().Unix()) + acc := types.NewContinuousVestingAccountRaw(baseVesting, baseVesting.EndTime) + + jm := jsonpb.Marshaler{} + bz, err := acc.MarshalJSONPB(&jm) + require.NoError(t, err) + + jum := jsonpb.Unmarshaler{} + baseVesting2 := types.NewBaseVestingAccount(nil, sdk.NewCoins(), 0) + acc2 := types.NewContinuousVestingAccountRaw(baseVesting2, baseVesting2.EndTime) + err = acc2.UnmarshalJSONPB(&jum, bz) + require.NoError(t, err) + require.IsType(t, &types.ContinuousVestingAccount{}, acc2) + require.Equal(t, acc.String(), acc2.String()) + + // error on bad bytes + err = acc2.UnmarshalJSONPB(&jum, bz[:len(bz)/2]) + require.Error(t, err) +} + +func TestPeriodicVestingAccountMarshalJSONPB(t *testing.T) { + baseAcc, coins := initBaseAccount() + baseVesting := types.NewBaseVestingAccount(baseAcc, coins, time.Now().Unix()) + acc := types.NewPeriodicVestingAccountRaw(baseVesting, baseVesting.EndTime, types.Periods{types.Period{3600, coins}}) + + jm := jsonpb.Marshaler{} + bz, err := acc.MarshalJSONPB(&jm) + require.NoError(t, err) + + jum := jsonpb.Unmarshaler{} + baseVesting2 := types.NewBaseVestingAccount(nil, sdk.NewCoins(), 0) + acc2 := types.NewPeriodicVestingAccountRaw(baseVesting2, baseVesting2.EndTime, types.Periods{}) + err = acc2.UnmarshalJSONPB(&jum, bz) + require.NoError(t, err) + require.IsType(t, &types.PeriodicVestingAccount{}, acc2) + require.Equal(t, acc.String(), acc2.String()) + + // error on bad bytes + err = acc2.UnmarshalJSONPB(&jum, bz[:len(bz)/2]) + require.Error(t, err) +} + +func TestDelayedVestingAccountMarshalJSONPB(t *testing.T) { + baseAcc, coins := initBaseAccount() + acc := types.NewDelayedVestingAccount(baseAcc, coins, time.Now().Unix()) + + jm := jsonpb.Marshaler{} + bz, err := acc.MarshalJSONPB(&jm) + require.NoError(t, err) + + jum := jsonpb.Unmarshaler{} + acc2 := types.NewDelayedVestingAccount(nil, sdk.NewCoins(), 0) + err = acc2.UnmarshalJSONPB(&jum, bz) + require.NoError(t, err) + require.IsType(t, &types.DelayedVestingAccount{}, acc2) + require.Equal(t, acc.String(), acc2.String()) + + // error on bad bytes + err = acc2.UnmarshalJSONPB(&jum, bz[:len(bz)/2]) + require.Error(t, err) +} + func initBaseAccount() (*authtypes.BaseAccount, sdk.Coins) { _, _, addr := testdata.KeyTestPubAddr() origCoins := sdk.Coins{sdk.NewInt64Coin(feeDenom, 1000), sdk.NewInt64Coin(stakeDenom, 100)} diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 0914d5b04c..6cdc31e421 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -237,7 +237,9 @@ func (k BaseKeeper) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metad } var metadata types.Metadata - k.cdc.MustUnmarshal(bz, &metadata) + if err := metadata.Unmarshal(bz); err != nil { + panic(err) + } return metadata, true } diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index d875b780b4..3116f1633d 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -259,7 +259,10 @@ func (k BaseSendKeeper) setBalance(ctx sdk.Context, addr sdk.AccAddress, balance if balance.IsZero() { accountStore.Delete([]byte(balance.Denom)) } else { - bz := k.cdc.MustMarshal(&balance) + bz, err := balance.Marshal() + if err != nil { + return err + } accountStore.Set([]byte(balance.Denom), bz) } @@ -278,7 +281,10 @@ func (k BaseSendKeeper) SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance if balance.IsZero() { accountStore.Delete([]byte(balance.Denom)) } else { - bz := k.cdc.MustMarshal(&balance) + bz, err := balance.Marshal() + if err != nil { + return err + } accountStore.Set([]byte(balance.Denom), bz) } diff --git a/x/wasm/keeper/keeper_test.go b/x/wasm/keeper/keeper_test.go index 01c5bb0888..74faca93e4 100644 --- a/x/wasm/keeper/keeper_test.go +++ b/x/wasm/keeper/keeper_test.go @@ -319,7 +319,7 @@ func TestInstantiate(t *testing.T) { gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x142fa), gasAfter-gasBefore) + require.Equal(t, uint64(0x1402a), gasAfter-gasBefore) } // ensure it is stored properly @@ -554,7 +554,7 @@ func TestExecute(t *testing.T) { // make sure gas is properly deducted from ctx gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x1278a), gasAfter-gasBefore) + require.Equal(t, uint64(0x1242a), gasAfter-gasBefore) } // ensure bob now exists and got both payments released bobAcct = accKeeper.GetAccount(ctx, bob)