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:
+22
-46
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user