auth.AccountStore assumes go-wire; Remove GetTxBytes() from Tx

This commit is contained in:
Jae Kwon 2018-01-20 18:03:20 -08:00
parent 6d3b5cb402
commit 8fda920de0
7 changed files with 118 additions and 79 deletions

View File

@ -30,7 +30,6 @@ func (tx testTx) Get(key interface{}) (value interface{}) { return nil }
func (tx testTx) GetSignBytes() []byte { return nil }
func (tx testTx) ValidateBasic() error { return nil }
func (tx testTx) GetSigners() []crypto.Address { return nil }
func (tx testTx) GetTxBytes() []byte { return nil }
func (tx testTx) GetFeePayer() crypto.Address { return nil }
func (tx testTx) GetSignatures() []sdk.StdSignature { return nil }

View File

@ -38,8 +38,18 @@ func (app *BasecoinApp) initMultiStore() {
// depends on initKeys()
func (app *BasecoinApp) initAppStore() {
app.accStore = auth.NewAccountStore(
app.mainStoreKey,
types.NewAppAccountCodecFromWireCodec(app.cdc),
accStore := auth.NewAccountStore(
app.mainStoreKey, // where accounts are persisted.
&types.AppAccount{}, // prototype sdk.Account.
)
// If there are additional interfaces & concrete types that need to be
// registered w/ wire.Codec, they can be registered here before the
// accStore is sealed.
//
// cdc := accStore.WireCodec()
// cdc.RegisterInterface(...)
// cdc.RegisterConcrete(...)
app.accStore = accStore.Seal()
}

View File

@ -1,8 +1,6 @@
package types
import (
wire "github.com/tendermint/go-wire"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
)
@ -12,7 +10,11 @@ var _ sdk.Account = (*AppAccount)(nil)
type AppAccount struct {
auth.BaseAccount
// Custom extensions for this application.
// Custom extensions for this application. This is just an example of
// extending auth.BaseAccount with custom fields.
//
// This is compatible with the stock auth.AccountStore, since
// auth.AccountStore uses the flexible go-wire library.
Name string
}
@ -23,27 +25,3 @@ func (acc AppAccount) GetName() string {
func (acc *AppAccount) SetName(name string) {
acc.Name = name
}
//----------------------------------------
type AppAccountCodec struct {
cdc *wire.Codec
}
func NewAppAccountCodecFromWireCodec(cdc *wire.Codec) AppAccountCodec {
return AppAccountCodec{cdc}
}
func (_ AppAccountCodec) Prototype() interface{} {
return &AppAccount{}
}
func (aac AppAccountCodec) Encode(o interface{}) (bz []byte, err error) {
return aac.cdc.MarshalBinary(o)
}
func (aac AppAccountCodec) Decode(bz []byte) (o interface{}, err error) {
o = aac.Prototype()
err = aac.cdc.UnmarshalBinary(bz, o)
return o, err
}

View File

@ -101,10 +101,6 @@ func (tx dummyTx) GetSigners() []crypto.Address {
return nil
}
func (tx dummyTx) GetTxBytes() []byte {
return tx.bytes
}
func (tx dummyTx) GetSignatures() []sdk.StdSignature {
return nil
}

View File

@ -1,14 +0,0 @@
package types
// A generic codec for a fixed type.
type Codec interface {
// Returns a prototype (empty) object.
Prototype() interface{}
// Encodes the object.
Encode(o interface{}) ([]byte, error)
// Decodes an object.
Decode(bz []byte) (interface{}, error)
}

View File

@ -2,7 +2,6 @@ package types
import (
crypto "github.com/tendermint/go-crypto"
wire "github.com/tendermint/go-wire"
)
type Msg interface {
@ -34,10 +33,6 @@ type Tx interface {
// deducted before the Msg is processed.
GetFeePayer() crypto.Address
// Get the canonical byte representation of the Tx.
// Includes any signatures (or empty slots).
GetTxBytes() []byte
// Signatures returns the signature of signers who signed the Msg.
// CONTRACT: Length returned is same as length of
// pubkeys returned from MsgKeySigners, and the order
@ -55,14 +50,7 @@ type StdTx struct {
Signatures []StdSignature
}
func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() }
func (tx StdTx) GetTxBytes() []byte {
bz, err := wire.MarshalBinary(tx) // XXX: this is bad
if err != nil {
panic(err)
}
return bz
}
func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() }
func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures }
type TxDecoder func(txBytes []byte) (Tx, error)

View File

@ -1,52 +1,134 @@
package auth
import (
"fmt"
"reflect"
crypto "github.com/tendermint/go-crypto"
wire "github.com/tendermint/go-wire"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Implements sdk.AccountStore
// Implements sdk.AccountStore.
// This AccountStore encodes/decodes accounts using the
// go-wire (binary) encoding/decoding library.
type accountStore struct {
key sdk.SubstoreKey
codec sdk.Codec
// The (unexposed) key used to access the store from the Context.
key sdk.SubstoreKey
// The prototypical sdk.Account concrete type.
proto sdk.Account
// The wire codec for binary encoding/decoding of accounts.
cdc *wire.Codec
}
func NewAccountStore(key sdk.SubstoreKey, codec sdk.Codec) accountStore {
// NewAccountStore returns a new sdk.AccountStore that
// uses go-wire to (binary) encode and decode concrete sdk.Accounts.
func NewAccountStore(key sdk.SubstoreKey, proto sdk.Account) accountStore {
return accountStore{
key: key,
codec: codec,
proto: proto,
cdc: wire.NewCodec(),
}
}
// Implements sdk.AccountStore
// Returns the go-wire codec. You may need to register interfaces
// and concrete types here, if your app's sdk.Account
// implementation includes interface fields.
// NOTE: It is not secure to expose the codec, so check out
// .Seal().
func (as accountStore) WireCodec() *wire.Codec {
return as.cdc
}
// Returns a "sealed" accountStore.
// The codec is not accessible from a sealedAccountStore
func (as accountStore) Seal() sealedAccountStore {
return sealedAccountStore{as}
}
// Implements sdk.AccountStore.
func (as accountStore) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) sdk.Account {
acc := as.codec.Prototype().(sdk.Account)
acc := as.clonePrototype()
acc.SetAddress(addr)
return acc
}
// Implements sdk.AccountStore
// Implements sdk.AccountStore.
func (as accountStore) GetAccount(ctx sdk.Context, addr crypto.Address) sdk.Account {
store := ctx.KVStore(as.key)
bz := store.Get(addr)
if bz == nil {
return nil // XXX
return nil
}
o, err := as.codec.Decode(bz)
if err != nil {
panic(err)
}
return o.(sdk.Account)
acc := as.decodeAccount(bz)
return acc
}
// Implements sdk.AccountStore
// Implements sdk.AccountStore.
func (as accountStore) SetAccount(ctx sdk.Context, acc sdk.Account) {
addr := acc.GetAddress()
store := ctx.KVStore(as.key)
bz, err := as.codec.Encode(acc)
bz := as.encodeAccount(acc)
store.Set(addr, bz)
}
//----------------------------------------
// misc.
// Creates a new struct (or pointer to struct) from as.proto.
func (as accountStore) clonePrototype() sdk.Account {
protoRt := reflect.TypeOf(as.proto)
if protoRt.Kind() == reflect.Ptr {
protoCrt := protoRt.Elem()
if protoCrt.Kind() != reflect.Struct {
panic("AccountStore requires a struct proto sdk.Account, or a pointer to one")
}
protoRv := reflect.New(protoCrt)
clone, ok := protoRv.Interface().(sdk.Account)
if !ok {
panic(fmt.Sprintf("AccountStore requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt))
}
return clone
} else {
protoRv := reflect.New(protoRt).Elem()
clone, ok := protoRv.Interface().(sdk.Account)
if !ok {
panic(fmt.Sprintf("AccountStore requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt))
}
return clone
}
}
func (as accountStore) encodeAccount(acc sdk.Account) []byte {
bz, err := as.cdc.MarshalBinary(acc)
if err != nil {
panic(err)
}
store.Set(addr, bz)
return bz
}
func (as accountStore) decodeAccount(bz []byte) sdk.Account {
acc := as.clonePrototype()
err := as.cdc.UnmarshalBinary(bz, &acc)
if err != nil {
panic(err)
}
return acc
}
//----------------------------------------
// sealedAccountStore
type sealedAccountStore struct {
accountStore
}
// There's no way for external modules to mutate the
// sas.accountStore.ctx from here, even with reflection.
func (sas sealedAccountStore) WireCodec() *wire.Codec {
panic("accountStore is sealed")
}