move coins and accounts out of types
This commit is contained in:
parent
3235b2d647
commit
3ba3d6b02f
|
@ -25,7 +25,7 @@ type testTx struct {
|
|||
func (tx testTx) Get(key interface{}) (value interface{}) { return nil }
|
||||
func (tx testTx) SignBytes() []byte { return nil }
|
||||
func (tx testTx) ValidateBasic() error { return nil }
|
||||
func (tx testTx) Signers() []types.Address { return nil }
|
||||
func (tx testTx) Signers() []crypto.Address { return nil }
|
||||
func (tx testTx) TxBytes() []byte { return nil }
|
||||
func (tx testTx) Signatures() []types.StdSignature { return nil }
|
||||
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// AppAccount - coin account structure
|
||||
type AppAccount struct {
|
||||
Address_ crypto.Address `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
PubKey_ crypto.PubKey `json:"public_key"` // can't conflict with PubKey()
|
||||
Sequence int64 `json:"sequence"`
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) Get(key interface{}) (value interface{}, err error) {
|
||||
switch key.(type) {
|
||||
case string:
|
||||
//
|
||||
default:
|
||||
panic("HURAH!")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) Set(key interface{}, value interface{}) error {
|
||||
switch key.(type) {
|
||||
case string:
|
||||
//
|
||||
default:
|
||||
panic("HURAH!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) Address() types.Address {
|
||||
return a.PubKey_.Address()
|
||||
}
|
||||
|
||||
// Implements auth.Account
|
||||
func (a *AppAccount) PubKey() crypto.PubKey {
|
||||
return a.PubKey_
|
||||
}
|
||||
|
||||
func (a *AppAccount) SetPubKey(pubKey crypto.PubKey) error {
|
||||
a.PubKey_ = pubKey
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements coinstore.Coinser
|
||||
func (a *AppAccount) GetCoins() types.Coins {
|
||||
return a.Coins
|
||||
}
|
||||
|
||||
// Implements coinstore.Coinser
|
||||
func (a *AppAccount) SetCoins(coins types.Coins) error {
|
||||
a.Coins = coins
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AppAccount) GetSequence() int64 {
|
||||
return a.Sequence
|
||||
}
|
||||
|
||||
func (a *AppAccount) SetSequence(seq int64) error {
|
||||
a.Sequence = seq
|
||||
return nil
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type AppAccountStore struct {
|
||||
kvStore types.KVStore
|
||||
}
|
||||
|
||||
func newAccountStore(kvStore types.KVStore) types.AccountStore {
|
||||
return AppAccountStore{kvStore}
|
||||
}
|
||||
|
||||
func (accStore AppAccountStore) NewAccountWithAddress(addr types.Address) types.Account {
|
||||
return &AppAccount{
|
||||
Address_: addr,
|
||||
}
|
||||
}
|
||||
|
||||
func (accStore AppAccountStore) GetAccount(addr types.Address) types.Account {
|
||||
v := accStore.kvStore.Get(keyAccount(addr))
|
||||
|
||||
if len(v) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
acc := new(AppAccount)
|
||||
if err := json.Unmarshal(v, acc); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return acc
|
||||
}
|
||||
|
||||
func (accStore AppAccountStore) SetAccount(acc types.Account) {
|
||||
b, err := json.Marshal(acc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
appAcc, ok := acc.(*AppAccount)
|
||||
if !ok {
|
||||
panic("acc is not *AppAccount") // XXX
|
||||
}
|
||||
|
||||
accStore.kvStore.Set(keyAccount(appAcc.Address_), b)
|
||||
}
|
||||
|
||||
func keyAccount(addr types.Address) []byte {
|
||||
return []byte(path.Join("account", string(addr)))
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
acm "github.com/cosmos/cosmos-sdk/x/account"
|
||||
"github.com/cosmos/cosmos-sdk/x/sendtx"
|
||||
"github.com/cosmos/cosmos-sdk/x/store"
|
||||
)
|
||||
|
||||
func txParser(txBytes []byte) (types.Tx, error) {
|
||||
var tx sendtx.SendTx
|
||||
err := json.Unmarshal(txBytes, &tx)
|
||||
return tx, err
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type AccountStore struct {
|
||||
kvStore types.KVStore
|
||||
}
|
||||
|
||||
func newAccountStore(kvStore types.KVStore) store.AccountStore {
|
||||
return AccountStore{kvStore}
|
||||
}
|
||||
|
||||
func (accStore AccountStore) NewAccountWithAddress(addr crypto.Address) store.Account {
|
||||
return acm.NewBaseAccountWithAddress(addr)
|
||||
}
|
||||
|
||||
func (accStore AccountStore) GetAccount(addr crypto.Address) store.Account {
|
||||
v := accStore.kvStore.Get(keyAccount(addr))
|
||||
|
||||
if len(v) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
acc := new(acm.BaseAccount)
|
||||
if err := json.Unmarshal(v, acc); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return acc
|
||||
}
|
||||
|
||||
func (accStore AccountStore) SetAccount(acc store.Account) {
|
||||
b, err := json.Marshal(acc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
appAcc, ok := acc.(*acm.BaseAccount)
|
||||
if !ok {
|
||||
panic("acc is not *acm.BaseAccount") // XXX
|
||||
}
|
||||
|
||||
accStore.kvStore.Set(keyAccount(appAcc.Address()), b)
|
||||
}
|
||||
|
||||
func keyAccount(addr crypto.Address) []byte {
|
||||
return []byte(path.Join("account", string(addr)))
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
|
@ -73,11 +72,3 @@ func main() {
|
|||
})
|
||||
return
|
||||
}
|
||||
|
||||
// create ctx in begin block to be used as background for txs ...
|
||||
|
||||
func txParser(txBytes []byte) (types.Tx, error) {
|
||||
var tx sendtx.SendTx
|
||||
err := json.Unmarshal(txBytes, &tx)
|
||||
return tx, err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/tendermint/abci/server"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
||||
|
@ -89,7 +90,7 @@ func (tx dummyTx) ValidateBasic() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (tx dummyTx) Signers() []types.Address {
|
||||
func (tx dummyTx) Signers() []crypto.Address {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/tendermint/go-wire/gen"
|
||||
_ "github.com/clipperhouse/stringer"
|
||||
)
|
|
@ -1,29 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
type Address = crypto.Address
|
||||
|
||||
type Account interface {
|
||||
Address() Address
|
||||
|
||||
PubKey() crypto.PubKey
|
||||
SetPubKey(crypto.PubKey) error
|
||||
|
||||
GetCoins() Coins
|
||||
SetCoins(Coins) error
|
||||
|
||||
GetSequence() int64
|
||||
SetSequence(int64) error
|
||||
|
||||
Get(key interface{}) (value interface{}, err error)
|
||||
Set(key interface{}, value interface{}) error
|
||||
}
|
||||
|
||||
type AccountStore interface {
|
||||
NewAccountWithAddress(addr Address) Account
|
||||
GetAccount(addr Address) Account
|
||||
SetAccount(acc Account)
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package types
|
||||
|
||||
import crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
type Msg interface {
|
||||
|
||||
// Get some property of the Msg.
|
||||
|
@ -15,7 +17,7 @@ type Msg interface {
|
|||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
// CONTRACT: Returns addrs in some deterministic order.
|
||||
Signers() []Address
|
||||
Signers() []crypto.Address
|
||||
}
|
||||
|
||||
type Tx interface {
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/coin"
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// BaseAccount
|
||||
|
||||
// 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()
|
||||
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
|
||||
}
|
||||
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:
|
||||
//
|
||||
default:
|
||||
panic("HURAH!")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Implements Account
|
||||
func (acc *BaseAccount) Set(key interface{}, value interface{}) error {
|
||||
switch key.(type) {
|
||||
case string:
|
||||
//
|
||||
default:
|
||||
panic("HURAH!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements Account
|
||||
func (acc *BaseAccount) Address() crypto.Address {
|
||||
return acc.pubKey.Address()
|
||||
}
|
||||
|
||||
// Implements Account
|
||||
func (acc *BaseAccount) GetPubKey() crypto.PubKey {
|
||||
return acc.pubKey
|
||||
}
|
||||
|
||||
func (acc *BaseAccount) SetPubKey(pubKey crypto.PubKey) error {
|
||||
acc.pubKey = pubKey
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements coinstore.Coinser
|
||||
func (acc *BaseAccount) GetCoins() coin.Coins {
|
||||
return acc.coins
|
||||
}
|
||||
|
||||
// Implements coinstore.Coinser
|
||||
func (acc *BaseAccount) SetCoins(coins coin.Coins) error {
|
||||
acc.coins = coins
|
||||
return nil
|
||||
}
|
||||
|
||||
func (acc *BaseAccount) GetSequence() int64 {
|
||||
return acc.sequence
|
||||
}
|
||||
|
||||
func (acc *BaseAccount) SetSequence(seq int64) error {
|
||||
acc.sequence = seq
|
||||
return nil
|
||||
}
|
|
@ -2,6 +2,7 @@ package auth
|
|||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/store"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -24,10 +25,10 @@ const (
|
|||
contextKeyAccount contextKey = iota
|
||||
)
|
||||
|
||||
func SetAccount(ctx types.Context, account types.Account) types.Context {
|
||||
func SetAccount(ctx types.Context, account store.Account) types.Context {
|
||||
return ctx.WithValueUnsafe(contextKeyAccount, account)
|
||||
}
|
||||
|
||||
func GetAccount(ctx types.Context) types.Account {
|
||||
return ctx.Value(contextKeyAccount).(types.Account)
|
||||
func GetAccount(ctx types.Context) store.Account {
|
||||
return ctx.Value(contextKeyAccount).(store.Account)
|
||||
}
|
||||
|
|
|
@ -2,15 +2,14 @@ package auth
|
|||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/cosmos/cosmos-sdk/x/store"
|
||||
)
|
||||
|
||||
func DecoratorFn(newAccountStore func(types.KVStore) types.AccountStore) types.Decorator {
|
||||
func DecoratorFn(newAccountStore func(types.KVStore) store.AccountStore) types.Decorator {
|
||||
return func(ctx types.Context, ms types.MultiStore, tx types.Tx, next types.Handler) types.Result {
|
||||
|
||||
accountStore := newAccountStore(ms.GetKVStore("main"))
|
||||
|
||||
// NOTE: we actually dont need Signers() since we have pubkeys in Signatures()
|
||||
signers := tx.Signers()
|
||||
signatures := tx.Signatures()
|
||||
|
||||
|
@ -68,11 +67,3 @@ func DecoratorFn(newAccountStore func(types.KVStore) types.AccountStore) types.D
|
|||
return next(ctx, ms, tx)
|
||||
}
|
||||
}
|
||||
|
||||
type Auther interface {
|
||||
GetPubKey() crypto.PubKey
|
||||
SetPubKey(crypto.PubKey) error
|
||||
|
||||
GetSequence() int64
|
||||
SetSequence() (int64, error)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/store"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
type SetPubKeyer interface {
|
||||
SetPubKey(crypto.PubKey)
|
||||
var _ Auther = (store.Account)(nil)
|
||||
|
||||
type Auther interface {
|
||||
GetPubKey() crypto.PubKey
|
||||
SetPubKey(crypto.PubKey) error
|
||||
|
||||
GetSequence() int64
|
||||
SetSequence(int64) error
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package types
|
||||
package coin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -202,14 +202,6 @@ var _ sort.Interface = Coins{}
|
|||
// Sort is a helper function to sort the set of coins inplace
|
||||
func (coins Coins) Sort() { sort.Sort(coins) }
|
||||
|
||||
//----------------------------------------
|
||||
// Misc
|
||||
|
||||
type Coinser interface {
|
||||
GetCoins() Coins
|
||||
SetCoins(Coins)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// Parsing
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package types
|
||||
package coin
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,117 +0,0 @@
|
|||
package coin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type Coins = types.Coins
|
||||
|
||||
type Coinser interface {
|
||||
GetCoins() Coins
|
||||
SetCoins(Coins)
|
||||
}
|
||||
|
||||
// CoinStore manages transfers between accounts
|
||||
type CoinStore struct {
|
||||
types.AccountStore
|
||||
}
|
||||
|
||||
// get the account as a Coinser. if the account doesn't exist, return nil.
|
||||
// if it's not a Coinser, return error.
|
||||
func (cs CoinStore) getCoinserAccount(addr types.Address) (types.Coinser, error) {
|
||||
_acc := cs.GetAccount(addr)
|
||||
if _acc == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
acc, ok := _acc.(Coinser)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Account %s is not a Coinser", addr)
|
||||
}
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
func (cs CoinStore) SubtractCoins(addr types.Address, amt Coins) (Coins, error) {
|
||||
acc, err := cs.getCoinserAccount(addr)
|
||||
if err != nil {
|
||||
return amt, err
|
||||
} else if acc == nil {
|
||||
return amt, fmt.Errorf("Sending account (%s) does not exist", addr)
|
||||
}
|
||||
|
||||
coins := acc.GetCoins()
|
||||
newCoins := coins.Minus(amt)
|
||||
if !newCoins.IsNotNegative() {
|
||||
return amt, ErrInsufficientCoins(fmt.Sprintf("%s < %s", coins, amt))
|
||||
}
|
||||
|
||||
acc.SetCoins(newCoins)
|
||||
cs.SetAccount(acc.(types.Account))
|
||||
return newCoins, nil
|
||||
}
|
||||
|
||||
func (cs CoinStore) AddCoins(addr types.Address, amt Coins) (Coins, error) {
|
||||
acc, err := cs.getCoinserAccount(addr)
|
||||
if err != nil {
|
||||
return amt, err
|
||||
} else if acc == nil {
|
||||
acc = cs.AccountStore.NewAccountWithAddress(addr).(Coinser)
|
||||
}
|
||||
|
||||
coins := acc.GetCoins()
|
||||
newCoins := coins.Plus(amt)
|
||||
|
||||
acc.SetCoins(newCoins)
|
||||
cs.SetAccount(acc.(types.Account))
|
||||
return newCoins, nil
|
||||
}
|
||||
|
||||
/*
|
||||
// TransferCoins transfers coins from fromAddr to toAddr.
|
||||
// It returns an error if the from account doesn't exist,
|
||||
// if the accounts doin't implement Coinser,
|
||||
// or if the from account does not have enough coins.
|
||||
func (cs CoinStore) TransferCoins(fromAddr, toAddr types.Address, amt Coins) error {
|
||||
var fromAcc, toAcc types.Account
|
||||
|
||||
// Get the accounts
|
||||
_fromAcc := cs.GetAccount(fromAddr)
|
||||
if _fromAcc == nil {
|
||||
return ErrUnknownAccount(fromAddr)
|
||||
}
|
||||
|
||||
_toAcc := cs.GetAccount(to)
|
||||
if _toAcc == nil {
|
||||
toAcc = cs.AccountStore.NewAccountWithAddress(to)
|
||||
}
|
||||
|
||||
// Ensure they are Coinser
|
||||
fromAcc, ok := _fromAcc.(Coinser)
|
||||
if !ok {
|
||||
return ErrAccountNotCoinser(from)
|
||||
}
|
||||
|
||||
toAcc, ok = _toAcc.(Coinser)
|
||||
if !ok {
|
||||
return ErrAccountNotCoinser(from)
|
||||
}
|
||||
|
||||
// Coin math
|
||||
fromCoins := fromAcc.GetCoins()
|
||||
newFromCoins := fromCoins.Minus(amt)
|
||||
if newFromCoins.Negative() {
|
||||
return ErrInsufficientCoins(fromCoins, amt)
|
||||
}
|
||||
toCoins := toAcc.GetCoins()
|
||||
newToCoins := toCoins.Plus(amt)
|
||||
|
||||
// Set everything!
|
||||
fromAcc.SetCoins(newFromCoins)
|
||||
toAcc.SetCoins(newToCoins)
|
||||
cs.SetAccount(fromAcc)
|
||||
cs.SetAccount(toAcc)
|
||||
|
||||
return nil
|
||||
}*/
|
|
@ -2,14 +2,14 @@ package sendtx
|
|||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
coinstore "github.com/cosmos/cosmos-sdk/x/coinstore"
|
||||
"github.com/cosmos/cosmos-sdk/x/store"
|
||||
)
|
||||
|
||||
func TransferHandlerFn(newAccStore func(types.KVStore) types.AccountStore) types.Handler {
|
||||
func TransferHandlerFn(newAccStore func(types.KVStore) store.AccountStore) types.Handler {
|
||||
return func(ctx types.Context, ms types.MultiStore, tx types.Tx) types.Result {
|
||||
|
||||
accStore := newAccStore(ms.GetKVStore("main"))
|
||||
cs := coinstore.CoinStore{accStore}
|
||||
cs := store.CoinStore{accStore}
|
||||
|
||||
sendTx, ok := tx.(SendTx)
|
||||
if !ok {
|
||||
|
|
|
@ -4,14 +4,16 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
coinstore "github.com/cosmos/cosmos-sdk/x/coinstore"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/coin"
|
||||
"github.com/cosmos/cosmos-sdk/x/store"
|
||||
)
|
||||
|
||||
type (
|
||||
Address = types.Address
|
||||
Coins = types.Coins
|
||||
Address = crypto.Address
|
||||
Coins = coin.Coins
|
||||
)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -28,16 +30,16 @@ type TxInput struct {
|
|||
// ValidateBasic - validate transaction input
|
||||
func (txIn TxInput) ValidateBasic() error {
|
||||
if len(txIn.Address) == 0 {
|
||||
return coinstore.ErrInvalidAddress(txIn.Address.String())
|
||||
return store.ErrInvalidAddress(txIn.Address.String())
|
||||
}
|
||||
if txIn.Sequence < 0 {
|
||||
return ErrInvalidSequence(txIn.Sequence)
|
||||
}
|
||||
if !txIn.Coins.IsValid() {
|
||||
return coinstore.ErrInvalidCoins(txIn.Coins.String())
|
||||
return store.ErrInvalidCoins(txIn.Coins.String())
|
||||
}
|
||||
if !txIn.Coins.IsPositive() {
|
||||
return coinstore.ErrInvalidCoins(txIn.Coins.String())
|
||||
return store.ErrInvalidCoins(txIn.Coins.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -66,13 +68,13 @@ type TxOutput struct {
|
|||
// ValidateBasic - validate transaction output
|
||||
func (txOut TxOutput) ValidateBasic() error {
|
||||
if len(txOut.Address) == 0 {
|
||||
return coinstore.ErrInvalidAddress(txOut.Address.String())
|
||||
return store.ErrInvalidAddress(txOut.Address.String())
|
||||
}
|
||||
if !txOut.Coins.IsValid() {
|
||||
return coinstore.ErrInvalidCoins(txOut.Coins.String())
|
||||
return store.ErrInvalidCoins(txOut.Coins.String())
|
||||
}
|
||||
if !txOut.Coins.IsPositive() {
|
||||
return coinstore.ErrInvalidCoins(txOut.Coins.String())
|
||||
return store.ErrInvalidCoins(txOut.Coins.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -92,28 +94,14 @@ func NewTxOutput(addr Address, coins Coins) TxOutput {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
var _ types.Tx = (*SendTx)(nil)
|
||||
|
||||
// SendTx - high level transaction of the coin module
|
||||
// Satisfies: TxInner
|
||||
type SendTx struct {
|
||||
Inputs []TxInput `json:"inputs"`
|
||||
Outputs []TxOutput `json:"outputs"`
|
||||
}
|
||||
|
||||
var _ types.Tx = (*SendTx)(nil)
|
||||
|
||||
// NewSendTx - construct arbitrary multi-in, multi-out sendtx
|
||||
func NewSendTx(in []TxInput, out []TxOutput) types.Tx {
|
||||
return SendTx{Inputs: in, Outputs: out}
|
||||
}
|
||||
|
||||
// NewSendOneTx is a helper for the standard (?) case where there is exactly
|
||||
// one sender and one recipient
|
||||
func NewSendOneTx(sender, recipient types.Address, amount types.Coins) types.Tx {
|
||||
in := []TxInput{{Address: sender, Coins: amount}}
|
||||
out := []TxOutput{{Address: recipient, Coins: amount}}
|
||||
return SendTx{Inputs: in, Outputs: out}
|
||||
}
|
||||
|
||||
// ValidateBasic - validate the send transaction
|
||||
func (tx SendTx) ValidateBasic() error {
|
||||
// this just makes sure all the inputs and outputs are properly formatted,
|
||||
|
@ -140,7 +128,7 @@ func (tx SendTx) ValidateBasic() error {
|
|||
}
|
||||
// make sure inputs and outputs match
|
||||
if !totalIn.IsEqual(totalOut) {
|
||||
return coinstore.ErrInvalidCoins(totalIn.String()) // TODO
|
||||
return store.ErrInvalidCoins(totalIn.String()) // TODO
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -149,8 +137,22 @@ func (tx SendTx) String() string {
|
|||
return fmt.Sprintf("SendTx{%v->%v}", tx.Inputs, tx.Outputs)
|
||||
}
|
||||
|
||||
// TODO
|
||||
// NewSendTx - construct arbitrary multi-in, multi-out sendtx
|
||||
func NewSendTx(in []TxInput, out []TxOutput) types.Tx {
|
||||
return SendTx{Inputs: in, Outputs: out}
|
||||
}
|
||||
|
||||
// NewSendOneTx is a helper for the standard (?) case where there is exactly
|
||||
// one sender and one recipient
|
||||
func NewSendOneTx(sender, recipient crypto.Address, amount coin.Coins) types.Tx {
|
||||
in := []TxInput{{Address: sender, Coins: amount}}
|
||||
out := []TxOutput{{Address: recipient, Coins: amount}}
|
||||
return SendTx{Inputs: in, Outputs: out}
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Implements types.Tx
|
||||
|
||||
func (tx SendTx) Get(key interface{}) (value interface{}) {
|
||||
switch k := key.(type) {
|
||||
case string:
|
||||
|
@ -170,8 +172,8 @@ func (tx SendTx) SignBytes() []byte {
|
|||
return b
|
||||
}
|
||||
|
||||
func (tx SendTx) Signers() []types.Address {
|
||||
addrs := make([]types.Address, len(tx.Inputs))
|
||||
func (tx SendTx) Signers() []crypto.Address {
|
||||
addrs := make([]crypto.Address, len(tx.Inputs))
|
||||
for i, in := range tx.Inputs {
|
||||
addrs[i] = in.Address
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/coin"
|
||||
)
|
||||
|
||||
// AccountStore indexes accounts by address.
|
||||
type AccountStore interface {
|
||||
NewAccountWithAddress(addr crypto.Address) Account
|
||||
GetAccount(addr crypto.Address) Account
|
||||
SetAccount(acc Account)
|
||||
}
|
||||
|
||||
// Account is a standard balance account
|
||||
// using a sequence number for replay protection
|
||||
// and a single pubkey for authentication.
|
||||
// TODO: multisig accounts?
|
||||
type Account interface {
|
||||
Address() crypto.Address
|
||||
|
||||
GetPubKey() crypto.PubKey
|
||||
SetPubKey(crypto.PubKey) error
|
||||
|
||||
GetCoins() coin.Coins
|
||||
SetCoins(coin.Coins) error
|
||||
|
||||
GetSequence() int64
|
||||
SetSequence(int64) error
|
||||
|
||||
Get(key interface{}) (value interface{}, err error)
|
||||
Set(key interface{}, value interface{}) error
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/coin"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
type Coins = coin.Coins
|
||||
|
||||
// Coinser can get and set coins
|
||||
type Coinser interface {
|
||||
GetCoins() Coins
|
||||
SetCoins(Coins)
|
||||
}
|
||||
|
||||
// CoinStore manages transfers between accounts
|
||||
type CoinStore struct {
|
||||
AccountStore
|
||||
}
|
||||
|
||||
// SubtractCoins subtracts amt from the coins at the addr.
|
||||
func (cs CoinStore) SubtractCoins(addr crypto.Address, amt Coins) (Coins, error) {
|
||||
acc, err := cs.getCoinserAccount(addr)
|
||||
if err != nil {
|
||||
return amt, err
|
||||
} else if acc == nil {
|
||||
return amt, fmt.Errorf("Sending account (%s) does not exist", addr)
|
||||
}
|
||||
|
||||
coins := acc.GetCoins()
|
||||
newCoins := coins.Minus(amt)
|
||||
if !newCoins.IsNotNegative() {
|
||||
return amt, ErrInsufficientCoins(fmt.Sprintf("%s < %s", coins, amt))
|
||||
}
|
||||
|
||||
acc.SetCoins(newCoins)
|
||||
cs.SetAccount(acc.(Account))
|
||||
return newCoins, nil
|
||||
}
|
||||
|
||||
// AddCoins adds amt to the coins at the addr.
|
||||
func (cs CoinStore) AddCoins(addr crypto.Address, amt Coins) (Coins, error) {
|
||||
acc, err := cs.getCoinserAccount(addr)
|
||||
if err != nil {
|
||||
return amt, err
|
||||
} else if acc == nil {
|
||||
acc = cs.AccountStore.NewAccountWithAddress(addr).(Coinser)
|
||||
}
|
||||
|
||||
coins := acc.GetCoins()
|
||||
newCoins := coins.Plus(amt)
|
||||
|
||||
acc.SetCoins(newCoins)
|
||||
cs.SetAccount(acc.(Account))
|
||||
return newCoins, nil
|
||||
}
|
||||
|
||||
// get the account as a Coinser. if the account doesn't exist, return nil.
|
||||
// if it's not a Coinser, return error.
|
||||
func (cs CoinStore) getCoinserAccount(addr crypto.Address) (Coinser, error) {
|
||||
_acc := cs.GetAccount(addr)
|
||||
if _acc == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
acc, ok := _acc.(Coinser)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Account %s is not a Coinser", addr)
|
||||
}
|
||||
return acc, nil
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//nolint
|
||||
package coin
|
||||
package store
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/errors"
|
Loading…
Reference in New Issue