Skip to content

Commit

Permalink
fix: genesis auth account format (Finschia#517)
Browse files Browse the repository at this point in the history
* restore format of genesis auth

* add type

* add changelog

* fix wasm gas verification check

* fix TestBaseApp_BlockGas

* fix marshal/unmarshal pubkey

* restore MarshalJSONPB, UnmarshalJSONPB

* add unittest for MarshalJSONPB of vestingAccount

* add unittest for MarshalJSONPB of moduleAccount

* fix BaseVestingAccount UnmarshalJSONPB func

* refactor: change multi if to else if, Nil to NoError
  • Loading branch information
dudong2 authored May 11, 2022
1 parent ab3dfa8 commit 9b70a6d
Show file tree
Hide file tree
Showing 10 changed files with 466 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,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

Expand Down
2 changes: 1 addition & 1 deletion baseapp/block_gas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions x/auth/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
173 changes: 170 additions & 3 deletions x/auth/types/account.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
23 changes: 23 additions & 0 deletions x/auth/types/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"testing"

"github.com/gogo/protobuf/jsonpb"
"github.com/stretchr/testify/require"
yaml "gopkg.in/yaml.v2"

Expand Down Expand Up @@ -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())
Expand Down
Loading

0 comments on commit 9b70a6d

Please sign in to comment.