WIP: refactor

Refactor

* No more decorators, but rather types.AntiHandler
* No more handlers, but rather types.MsgHandler
* Ability to pass "stores" in NewXYZHandler()
* Coins live in types, and Accounts have coins
* Coinstore -> bank
This commit is contained in:
Jae Kwon
2018-01-12 19:17:17 -08:00
parent 620bdf409f
commit ba2b4f0f21
28 changed files with 698 additions and 717 deletions
+22 -46
View File
@@ -13,76 +13,52 @@ import (
// BaseAccount - coin account structure
type BaseAccount struct {
address crypto.Address
coins coin.Coins
pubKey crypto.PubKey
sequence int64
}
func NewBaseAccountWithAddress(addr crypto.Address) *BaseAccount {
return &BaseAccount{
address: addr,
}
}
// BaseAccountWire is the account structure used for serialization
type BaseAccountWire struct {
Address crypto.Address `json:"address"`
Coins coin.Coins `json:"coins"`
PubKey crypto.PubKey `json:"public_key"` // can't conflict with PubKey()
PubKey crypto.PubKey `json:"public_key"`
Sequence int64 `json:"sequence"`
}
func (acc *BaseAccount) MarshalJSON() ([]byte, error) {
return json.Marshal(BaseAccountWire{
Address: acc.address,
Coins: acc.coins,
PubKey: acc.pubKey,
Sequence: acc.sequence,
})
}
func (acc *BaseAccount) UnmarshalJSON(bz []byte) error {
accWire := new(BaseAccountWire)
err := json.Unmarshal(bz, accWire)
if err != nil {
return err
func NewBaseAccountWithAddress(addr crypto.Address) BaseAccount {
return BaseAccount{
Address: addr,
}
acc.address = accWire.Address
acc.coins = accWire.Coins
acc.pubKey = accWire.PubKey
acc.sequence = accWire.Sequence
return nil
}
// Implements Account
func (acc *BaseAccount) Get(key interface{}) (value interface{}, err error) {
switch key.(type) {
case string:
}
return nil, nil
func (acc BaseAccount) Get(key interface{}) (value interface{}, err error) {
panic("not implemented yet")
}
// Implements Account
func (acc *BaseAccount) Set(key interface{}, value interface{}) error {
switch key.(type) {
case string:
}
return nil
panic("not implemented yet")
}
// Implements Account
func (acc *BaseAccount) Address() crypto.Address {
// TODO: assert address == pubKey.Address()
func (acc BaseAccount) GetAddress() crypto.Address {
return acc.address
}
// Implements Account
func (acc *BaseAccount) GetPubKey() crypto.PubKey {
func (acc *BaseAccount) SetAddress(addr crypto.Address) error {
if acc.address != "" {
return errors.New("cannot override BaseAccount address")
}
acc.address = addr
return nil
}
// Implements Account
func (acc BaseAccount) GetPubKey() crypto.PubKey {
return acc.pubKey
}
// Implements Account
func (acc *BaseAccount) SetPubKey(pubKey crypto.PubKey) error {
if acc.pubKey != "" {
return errors.New("cannot override BaseAccount pubkey")
}
acc.pubKey = pubKey
return nil
}
+81
View File
@@ -0,0 +1,81 @@
package auth
import (
"github.com/cosmos/cosmos-sdk/types"
)
func NewAnteHandler(store types.AccountStore) types.AnteHandler {
return func(
ctx types.Context, tx types.Tx,
) (newCtx types.Context, res types.Result, abort bool) {
// Deduct the fee from the fee payer.
// This is done first because it only
// requires fetching 1 account.
payerAddr := tx.GetFeePayer()
payerAcc := store.GetAccount(ctx, payerAddr)
if payerAcc == nil {
return ctx, Result{
Code: 1, // TODO
}, true
}
payerAcc.Subtract
// Ensure that signatures are correct.
var signerAddrs = tx.Signers()
var signerAccs = make([]types.Account, len(signerAddrs))
var signatures = tx.Signatures()
// Assert that there are signers.
if len(signatures) == 0 {
return ctx, types.Result{
Code: 1, // TODO
}, true
}
if len(signatures) != len(signers) {
return ctx, types.Result{
Code: 1, // TODO
}, true
}
// Check each nonce and sig.
for i, sig := range signatures {
var signerAcc = store.GetAccount(signers[i])
signerAccs[i] = signerAcc
// If no pubkey, set pubkey.
if acc.GetPubKey().Empty() {
err := acc.SetPubKey(sig.PubKey)
if err != nil {
return ctx, types.Result{
Code: 1, // TODO
}, true
}
}
// Check and incremenet sequence number.
seq := acc.GetSequence()
if seq != sig.Sequence {
return ctx, types.Result{
Code: 1, // TODO
}, true
}
acc.SetSequence(seq + 1)
// Check sig.
if !sig.PubKey.VerifyBytes(tx.SignBytes(), sig.Signature) {
return ctx, types.Result{
Code: 1, // TODO
}, true
}
// Save the account.
store.SetAccount(acc)
}
ctx = WithSigners(ctx, signerAccs)
return ctx, types.Result{}, false // continue...
}
}
+20 -11
View File
@@ -6,28 +6,37 @@ import (
/*
Usage:
Usage:
import "accounts"
var accountStore types.AccountStore
var acc accounts.Account
// Fetch all signer accounts.
addrs := tx.GetSigners()
signers := make([]types.Account, len(addrs))
for i, addr := range addrs {
acc := accountStore.GetAccount(ctx)
signers[i] = acc
}
ctx = auth.SetSigners(ctx, signers)
accounts.SetAccount(ctx, acc)
acc2 := accounts.GetAccount(ctx)
// Get all signer accounts.
signers := auth.GetSigners(ctx)
for i, signer := range signers {
signer.Address() == tx.GetSigners()[i]
}
*/
type contextKey int // local to the auth module
const (
// A context key of the Account variety
contextKeyAccount contextKey = iota
contextKeySigners contextKey = iota
)
func SetAccount(ctx types.Context, account types.Account) types.Context {
return ctx.WithValueUnsafe(contextKeyAccount, account)
func WithSigners(ctx types.Context, accounts []types.Account) types.Context {
return ctx.WithValueUnsafe(contextKeySigners, accounts)
}
func GetAccount(ctx types.Context) types.Account {
return ctx.Value(contextKeyAccount).(types.Account)
func GetSigners(ctx types.Context) []types.Account {
return ctx.Value(contextKeySigners).([]types.Account)
}
-59
View File
@@ -1,59 +0,0 @@
package auth
import "github.com/cosmos/cosmos-sdk/types"
func DecoratorFn(newAccountStore func(types.KVStore) types.AccountStore) types.Decorator {
return func(ctx types.Context, ms types.MultiStore, tx types.Tx, next types.Handler) types.Result {
accountStore := newAccountStore(ms.GetKVStore("main"))
signers := tx.Signers()
signatures := tx.Signatures()
// assert len
if len(signatures) == 0 {
return types.Result{
Code: 1, // TODO
}
}
if len(signatures) != len(signers) {
return types.Result{
Code: 1, // TODO
}
}
// check each nonce and sig
for i, sig := range signatures {
// get account
acc := accountStore.GetAccount(signers[i])
// if no pubkey, set pubkey
if acc.GetPubKey().Empty() {
err := acc.SetPubKey(sig.PubKey)
if err != nil {
return types.Result{
Code: 1, // TODO
}
}
}
// check and incremenet sequence number
seq := acc.GetSequence()
if seq != sig.Sequence {
return types.Result{
Code: 1, // TODO
}
}
acc.SetSequence(seq + 1)
// check sig
if !sig.PubKey.VerifyBytes(tx.SignBytes(), sig.Signature) {
return types.Result{
Code: 1, // TODO
}
}
}
return next(ctx, ms, tx)
}
}
+50
View File
@@ -0,0 +1,50 @@
package auth
import (
"github.com/cosmos/cosmos-sdk/types"
)
// Implements types.AccountStore
type accountStore struct {
key *types.KVStoreKey
codec types.Codec
}
func NewAccountStore(key *types.KVStoreKey, codec types.Codec) accountStore {
return accountStore{
key: key,
codec: codec,
}
}
// Implements types.AccountStore
func (as accountStore) NewAccountWithAddress(ctx types.Context, addr crypto.Address) {
acc := as.codec.Prototype().(types.Account)
acc.SetAddress(addr)
return acc
}
// Implements types.AccountStore
func (as accountStore) GetAccount(ctx types.Context, addr crypto.Address) types.Account {
store := ctx.KVStore(as.key)
bz := store.Get(addr)
if bz == nil {
return
}
o, err := as.codec.Decode(bz)
if err != nil {
panic(err)
}
return o.(types.Account)
}
// Implements types.AccountStore
func (as accountStore) SetAccount(ctx types.Context, acc types.Account) {
addr := acc.GetAddress()
store := ctx.KVStore(as.key)
bz, err := as.codec.Encode(acc)
if err != nil {
panic(err)
}
store.Set(addr, bz)
}