* wip: tests and fixes for kvstore iteration
* update for latest tmlibs
* types compiles
* x/coin almost compiles
* x/coin: move things out of the way so it builds
* rebase fixes
* update glide
* add test for ChainDecorators
This commit is contained in:
Ethan Buchman 2017-12-21 00:23:19 -05:00 committed by Jae Kwon
parent 72b0ed004b
commit a9b2636439
23 changed files with 320 additions and 321 deletions

View File

@ -1,15 +1,19 @@
package errors
import "fmt"
import (
"fmt"
"github.com/pkg/errors"
)
const (
// ABCI Response Codes
CodeInternalError = 1
CodeTxParseError = 2
CodeBadNonce = 3
CodeUnauthorized = 4
CodeInsufficientFunds = 5
CodeUnknownRequest = 6
CodeInternalError uint32 = 1
CodeTxParseError = 2
CodeBadNonce = 3
CodeUnauthorized = 4
CodeInsufficientFunds = 5
CodeUnknownRequest = 6
)
// NOTE: Don't stringer this, we'll put better messages in later.
@ -65,6 +69,8 @@ func UnknownRequest(log string) sdkError {
type ABCIError interface {
ABCICode() uint32
ABCILog() string
Error() string
}
/*
@ -132,3 +138,24 @@ func (err sdkError) WithCause(cause error) sdkError {
copy.cause = cause
return copy
}
// HasErrorCode checks if this error would return the named error code
func HasErrorCode(err error, code uint32) bool {
// XXX Get the cause if not ABCIError
if abciErr, ok := err.(ABCIError); ok {
return abciErr.ABCICode() == code
}
return code == CodeInternalError
}
func IsSameError(pattern error, err error) bool {
return err != nil && (errors.Cause(err) == errors.Cause(pattern))
}
func WithCode(err error, code uint32) sdkError {
return sdkError{
code: code,
cause: err,
log: "",
}
}

View File

@ -14,5 +14,5 @@ type (
Decorator = types.Decorator
// Type aliases for other modules.
MultiStore = store.MultiStore modules.
MultiStore = store.MultiStore
)

2
glide.lock generated
View File

@ -112,7 +112,7 @@ imports:
- leveldb/table
- leveldb/util
- name: github.com/tendermint/abci
version: bb9bb4aa465a31fd6a272765be381888e6898c74
version: e4b9f1abe794a2117a59738a1294e09b46d0fa00
subpackages:
- client
- example/dummy

View File

@ -2,6 +2,7 @@ package types
import (
"context"
abci "github.com/tendermint/abci/types"
)
@ -11,12 +12,12 @@ type Context struct {
// it's probably not what you want to do.
}
func NewContext(header tm.Header, isCheckTx bool, txBytes []byte) Context {
func NewContext(header abci.Header, isCheckTx bool, txBytes []byte) Context {
c := Context{
Context: context.Background(),
}
c = c.setBlockHeader(header)
c = c.setBlockHeight(int64(header.Height))
c = c.setBlockHeight(header.Height)
c = c.setChainID(header.ChainID)
c = c.setIsCheckTx(isCheckTx)
c = c.setTxBytes(txBytes)
@ -48,8 +49,8 @@ const (
contextKeyTxBytes
)
func (c Context) BlockHeader() tm.Header {
return c.Value(contextKeyBlockHeader).(tm.Header)
func (c Context) BlockHeader() abci.Header {
return c.Value(contextKeyBlockHeader).(abci.Header)
}
func (c Context) BlockHeight() int64 {
@ -69,18 +70,18 @@ func (c Context) TxBytes() []byte {
}
// Unexposed to prevent overriding.
func (c Context) setBlockHeader(header tm.Header) Context {
func (c Context) setBlockHeader(header abci.Header) Context {
return c.WithValueSDK(contextKeyBlockHeader, header)
}
// Unexposed to prevent overriding.
func (c Context) setBlockHeight(height int64) Context {
return c.WithValueSDK(contextKeyBlockHeight, header)
return c.WithValueSDK(contextKeyBlockHeight, height)
}
// Unexposed to prevent overriding.
func (c Context) setChainID(chainID string) Context {
return c.WithValueSDK(contextKeyChainID, header)
return c.WithValueSDK(contextKeyChainID, chainID)
}
// Unexposed to prevent overriding.

View File

@ -1,11 +1,15 @@
package types
import (
"github.com/cosmos/cosmos-sdk/store"
)
// A Decorator executes before/during/after a handler to enhance functionality.
type Decorator func(ctx Context, ms MultiStore, tx Tx, next Handler) Result
type Decorator func(ctx Context, ms store.MultiStore, tx Tx, next Handler) Result
// Return a decorated handler
func Decorate(dec Decorator, next Handler) Handler {
return func(ctx Context, ms MultiStore, tx Tx) Result {
return func(ctx Context, ms store.MultiStore, tx Tx) Result {
return dec(ctx, ms, tx, next)
}
}

39
types/decorators_test.go Normal file
View File

@ -0,0 +1,39 @@
package types
import (
"testing"
"github.com/cosmos/cosmos-sdk/store"
"github.com/stretchr/testify/assert"
)
func TestDecorate(t *testing.T) {
var calledDec1, calledDec2, calledHandler bool
dec1 := func(ctx Context, ms store.MultiStore, tx Tx, next Handler) Result {
calledDec1 = true
next(ctx, ms, tx)
return Result{}
}
dec2 := func(ctx Context, ms store.MultiStore, tx Tx, next Handler) Result {
calledDec2 = true
next(ctx, ms, tx)
return Result{}
}
handler := func(ctx Context, ms store.MultiStore, tx Tx) Result {
calledHandler = true
return Result{}
}
decoratedHandler := ChainDecorators(dec1, dec2).WithHandler(handler)
var ctx Context
var ms store.MultiStore
var tx Tx
decoratedHandler(ctx, ms, tx)
assert.True(t, calledDec1)
assert.True(t, calledDec2)
assert.True(t, calledHandler)
}

View File

@ -1,9 +1,9 @@
package types
import (
"github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/store"
)
// Handler handles both ABCI DeliverTx and CheckTx requests.
// Iff ABCI.CheckTx, ctx.IsCheckTx() returns true.
type Handler func(ctx Context, ms MultiStore, tx Tx)
type Handler func(ctx Context, ms store.MultiStore, tx Tx) Result

View File

@ -2,22 +2,7 @@ package types
import crypto "github.com/tendermint/go-crypto"
type Signature interface {
CryptoSig() crypto.Signature
Sequence() int
}
// StdSignature is a simple way to prevent replay attacks.
// There must be better strategies, but this is simplest.
type StdSignature struct {
crypto.Signature
Sequence int
}
func (ss StdSignature) CryptoSig() crypto.Signature {
return ss.Signature
}
func (ss StdSignature) Sequence() int {
return ss.Sequence
Sequence int64
}

View File

@ -32,5 +32,5 @@ type Tx interface {
// CONTRACT: If the signature is missing (ie the Msg is
// invalid), then the corresponding signature is
// .Empty().
Signatures() []Signature
Signatures() []StdSignature
}

View File

@ -1,7 +1,7 @@
package auth
import (
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/types"
)
/*
@ -13,7 +13,7 @@ import (
var acc accounts.Account
accounts.SetAccount(ctx, acc)
acc2, ok := accounts.GetAccount(ctx)
acc2 := accounts.GetAccount(ctx)
*/
@ -24,10 +24,10 @@ const (
contextKeyAccount contextKey = iota
)
func SetAccount(ctx sdk.Context, account Account) sdk.Context {
return ctx.WithValue(contextKeyAccount, account)
func SetAccount(ctx types.Context, account Account) types.Context {
return ctx.WithValueSDK(contextKeyAccount, account)
}
func GetAccount(ctx sdk.Context) (Account, bool) {
func GetAccount(ctx types.Context) Account {
return ctx.Value(contextKeyAccount).(Account)
}

View File

@ -1,35 +0,0 @@
package auth
import (
sdk "github.com/cosmos/cosmos-sdk"
)
type CheckSignatures struct{}
var _ sdk.Decorator = CheckSignatures{}
// CheckTx verifies the signatures are correct - fulfills Middlware interface
func (Signatures) CheckTx(ctx sdk.Context, store sdk.SimpleDB,
tx interface{}, next sdk.Checker) (res sdk.CheckResult, err error) {
// Check that signatures match
// TODO
// Add info to context
// TODO
return next.CheckTx(ctx2, store, tx)
}
// DeliverTx verifies the signatures are correct - fulfills Middlware interface
func (Signatures) DeliverTx(ctx sdk.Context, store sdk.SimpleDB,
tx interface{}, next sdk.Deliverer) (res sdk.DeliverResult, err error) {
// Check that signatures match
// TODO
// Add info to context
// TODO
return next.DeliverTx(ctx2, store, tx)
}

View File

@ -6,10 +6,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/errors"
"github.com/cosmos/cosmos-sdk/modules/auth"
"github.com/cosmos/cosmos-sdk/modules/ibc"
"github.com/cosmos/cosmos-sdk/stack"
"github.com/cosmos/cosmos-sdk/state"
"github.com/cosmos/cosmos-sdk/store"
"github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
// "github.com/cosmos/cosmos-sdk/x/ibc"
// "github.com/cosmos/cosmos-sdk/stack"
)
const (
@ -23,10 +24,10 @@ const (
// Handler includes an accountant
type Handler struct {
stack.PassInitValidate
// stack.PassInitValidate
}
var _ stack.Dispatchable = Handler{}
// var _ stack.Dispatchable = Handler{}
// NewHandler - new accountant handler for the coin module
func NewHandler() Handler {
@ -42,8 +43,8 @@ func (Handler) Name() string {
func (Handler) AssertDispatcher() {}
// CheckTx checks if there is enough money in the account
func (h Handler) CheckTx(ctx sdk.Context, store state.SimpleDB,
tx sdk.Tx, _ sdk.Checker) (res sdk.CheckResult, err error) {
func (h Handler) CheckTx(ctx types.Context, store store.MultiStore,
tx types.Tx, _ sdk.Checker) (res sdk.CheckResult, err error) {
err = tx.ValidateBasic()
if err != nil {
@ -63,8 +64,8 @@ func (h Handler) CheckTx(ctx sdk.Context, store state.SimpleDB,
}
// DeliverTx moves the money
func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB,
tx sdk.Tx, cb sdk.Deliver) (res sdk.DeliverResult, err error) {
func (h Handler) DeliverTx(ctx types.Context, store store.MultiStore,
tx types.Tx, cb sdk.Deliver) (res sdk.DeliverResult, err error) {
err = tx.ValidateBasic()
if err != nil {
@ -81,7 +82,7 @@ func (h Handler) DeliverTx(ctx sdk.Context, store state.SimpleDB,
}
// InitState - sets the genesis account balance
func (h Handler) InitState(l log.Logger, store state.SimpleDB,
func (h Handler) InitState(l log.Logger, store store.MultiStore,
module, key, value string, cb sdk.InitStater) (log string, err error) {
if module != NameCoin {
return "", errors.ErrUnknownModule(module)
@ -95,7 +96,7 @@ func (h Handler) InitState(l log.Logger, store state.SimpleDB,
return "", errors.ErrUnknownKey(key)
}
func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB,
func (h Handler) sendTx(ctx types.Context, store store.MultiStore,
send SendTx, cb sdk.Deliver) error {
err := checkTx(ctx, send)
@ -136,6 +137,8 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB,
}
outTx := NewSendTx(inputs, []TxOutput{out})
_ = outTx
/* TODO
packet := ibc.CreatePacketTx{
DestChain: out.Address.ChainID,
Permissions: senders,
@ -146,6 +149,7 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB,
if err != nil {
return err
}
*/
}
}
@ -153,7 +157,7 @@ func (h Handler) sendTx(ctx sdk.Context, store state.SimpleDB,
return nil
}
func (h Handler) creditTx(ctx sdk.Context, store state.SimpleDB,
func (h Handler) creditTx(ctx types.Context, store store.MultiStore,
credit CreditTx) error {
// first check permissions!!
@ -186,7 +190,7 @@ func (h Handler) creditTx(ctx sdk.Context, store state.SimpleDB,
return err
}
func checkTx(ctx sdk.Context, send SendTx) error {
func checkTx(ctx types.Context, send SendTx) error {
// check if all inputs have permission
for _, in := range send.Inputs {
if !ctx.HasPermission(in.Address) {
@ -196,7 +200,7 @@ func checkTx(ctx sdk.Context, send SendTx) error {
return nil
}
func (Handler) checkSendTx(ctx sdk.Context, store state.SimpleDB, send SendTx) error {
func (Handler) checkSendTx(ctx types.Context, store store.MultiStore, send SendTx) error {
err := checkTx(ctx, send)
if err != nil {
return err
@ -211,7 +215,7 @@ func (Handler) checkSendTx(ctx sdk.Context, store state.SimpleDB, send SendTx) e
return nil
}
func setAccount(store state.SimpleDB, value string) (log string, err error) {
func setAccount(store store.MultiStore, value string) (log string, err error) {
var acc GenesisAccount
err = data.FromJSON([]byte(value), &acc)
if err != nil {
@ -233,7 +237,7 @@ func setAccount(store state.SimpleDB, value string) (log string, err error) {
// setIssuer sets a permission for some super-powerful account to
// mint money
func setIssuer(store state.SimpleDB, value string) (log string, err error) {
func setIssuer(store store.MultiStore, value string) (log string, err error) {
var issuer sdk.Actor
err = data.FromJSON([]byte(value), &issuer)
if err != nil {

View File

@ -12,7 +12,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/errors"
"github.com/cosmos/cosmos-sdk/modules/auth"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/stack"
"github.com/cosmos/cosmos-sdk/state"
)

View File

@ -5,7 +5,7 @@ import (
"github.com/tendermint/go-wire/data"
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/modules/auth"
"github.com/cosmos/cosmos-sdk/x/auth"
)
// AccountWithKey is a helper for tests, that includes and account

View File

@ -7,8 +7,8 @@ import (
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/errors"
"github.com/cosmos/cosmos-sdk/modules/auth"
"github.com/cosmos/cosmos-sdk/modules/ibc"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/ibc"
"github.com/cosmos/cosmos-sdk/stack"
"github.com/cosmos/cosmos-sdk/state"
wire "github.com/tendermint/go-wire"

145
x/coin/_attic/store.go Normal file
View File

@ -0,0 +1,145 @@
package coin
import (
"fmt"
wire "github.com/tendermint/go-wire"
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/errors"
"github.com/cosmos/cosmos-sdk/store"
)
// GetAccount - Get account from store and address
func GetAccount(store store.MultiStore, addr sdk.Actor) (Account, error) {
// if the actor is another chain, we use one address for the chain....
addr = ChainAddr(addr)
acct, err := loadAccount(store, addr.Bytes())
// for empty accounts, don't return an error, but rather an empty account
if IsNoAccountErr(err) {
err = nil
}
return acct, err
}
// CheckCoins makes sure there are funds, but doesn't change anything
func CheckCoins(store store.MultiStore, addr sdk.Actor, coins Coins) (Coins, error) {
// if the actor is another chain, we use one address for the chain....
addr = ChainAddr(addr)
acct, err := updateCoins(store, addr, coins)
return acct.Coins, err
}
// ChangeCoins changes the money, returns error if it would be negative
func ChangeCoins(store store.MultiStore, addr sdk.Actor, coins Coins) (Coins, error) {
// if the actor is another chain, we use one address for the chain....
addr = ChainAddr(addr)
acct, err := updateCoins(store, addr, coins)
if err != nil {
return acct.Coins, err
}
err = storeAccount(store, addr.Bytes(), acct)
return acct.Coins, err
}
// ChainAddr collapses all addresses from another chain into one, so we can
// keep an over-all balance
//
// TODO: is there a better way to do this?
func ChainAddr(addr sdk.Actor) sdk.Actor {
if addr.ChainID == "" {
return addr
}
addr.App = ""
addr.Address = nil
return addr
}
// updateCoins will load the account, make all checks, and return the updated account.
//
// it doesn't save anything, that is up to you to decide (Check/Change Coins)
func updateCoins(store store.MultiStore, addr sdk.Actor, coins Coins) (acct Account, err error) {
acct, err = loadAccount(store, addr.Bytes())
// we can increase an empty account...
if IsNoAccountErr(err) && coins.IsPositive() {
err = nil
}
if err != nil {
return acct, err
}
// check amount
final := acct.Coins.Plus(coins)
if !final.IsNonnegative() {
return acct, ErrInsufficientFunds()
}
acct.Coins = final
return acct, nil
}
// Account - coin account structure
type Account struct {
// Coins is how much is on the account
Coins Coins `json:"coins"`
// Credit is how much has been "fronted" to the account
// (this is usually 0 except for trusted chains)
Credit Coins `json:"credit"`
}
func loadAccount(store store.MultiStore, key []byte) (acct Account, err error) {
// fmt.Printf("load: %X\n", key)
data := store.Get(key)
if len(data) == 0 {
return acct, ErrNoAccount()
}
err = wire.ReadBinaryBytes(data, &acct)
if err != nil {
msg := fmt.Sprintf("Error reading account %X", key)
return acct, errors.ErrInternal(msg)
}
return acct, nil
}
func storeAccount(store store.MultiStore, key []byte, acct Account) error {
// fmt.Printf("store: %X\n", key)
bin := wire.BinaryBytes(acct)
store.Set(key, bin)
return nil // real stores can return error...
}
// HandlerInfo - this is global info on the coin handler
type HandlerInfo struct {
Issuer sdk.Actor `json:"issuer"`
}
// TODO: where to store these special pieces??
var handlerKey = []byte{12, 34}
func loadHandlerInfo(store store.KVStore) (info HandlerInfo, err error) {
data := store.Get(handlerKey)
if len(data) == 0 {
return info, nil
}
err = wire.ReadBinaryBytes(data, &info)
if err != nil {
msg := "Error reading handler info"
return info, errors.ErrInternal(msg)
}
return info, nil
}
func storeIssuer(store store.KVStore, issuer sdk.Actor) error {
info, err := loadHandlerInfo(store)
if err != nil {
return err
}
info.Issuer = issuer
d := wire.BinaryBytes(info)
store.Set(handlerKey, d)
return nil // real stores can return error...
}

View File

@ -8,7 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/commands"
"github.com/cosmos/cosmos-sdk/client/commands/query"
"github.com/cosmos/cosmos-sdk/modules/coin"
"github.com/cosmos/cosmos-sdk/x/coin"
"github.com/cosmos/cosmos-sdk/stack"
)

View File

@ -7,7 +7,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/client/commands"
txcmd "github.com/cosmos/cosmos-sdk/client/commands/txs"
"github.com/cosmos/cosmos-sdk/modules/coin"
"github.com/cosmos/cosmos-sdk/x/coin"
)
// SendTxCmd is CLI command to send tokens between basecoin accounts

View File

@ -4,8 +4,6 @@ package coin
import (
"fmt"
abci "github.com/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/errors"
)
@ -17,73 +15,39 @@ var (
errNoOutputs = fmt.Errorf("No output coins")
errInvalidAddress = fmt.Errorf("Invalid address")
errInvalidCoins = fmt.Errorf("Invalid coins")
invalidInput = abci.CodeType_BaseInvalidInput
invalidOutput = abci.CodeType_BaseInvalidOutput
unknownAddress = abci.CodeType_BaseUnknownAddress
unknownRequest = abci.CodeType_UnknownRequest
)
// here are some generic handlers to grab classes of errors based on code
func IsInputErr(err error) bool {
return errors.HasErrorCode(err, invalidInput)
}
func IsOutputErr(err error) bool {
return errors.HasErrorCode(err, invalidOutput)
}
func IsAddressErr(err error) bool {
return errors.HasErrorCode(err, unknownAddress)
}
func IsCoinErr(err error) bool {
return err != nil && (IsInputErr(err) || IsOutputErr(err) || IsAddressErr(err))
const (
CodeInvalidInput uint32 = 101
CodeInvalidOutput uint32 = 102
CodeUnknownAddress uint32 = 103
CodeUnknownRequest uint32 = errors.CodeUnknownRequest
)
func ErrNoAccount() errors.ABCIError {
return errors.WithCode(errNoAccount, CodeUnknownAddress)
}
func ErrNoAccount() errors.TMError {
return errors.WithCode(errNoAccount, unknownAddress)
func ErrInvalidAddress() errors.ABCIError {
return errors.WithCode(errInvalidAddress, CodeInvalidInput)
}
func IsNoAccountErr(err error) bool {
return errors.IsSameError(errNoAccount, err)
func ErrInvalidCoins() errors.ABCIError {
return errors.WithCode(errInvalidCoins, CodeInvalidInput)
}
func ErrInvalidAddress() errors.TMError {
return errors.WithCode(errInvalidAddress, invalidInput)
}
func IsInvalidAddressErr(err error) bool {
return errors.IsSameError(errInvalidAddress, err)
func ErrInsufficientFunds() errors.ABCIError {
return errors.WithCode(errInsufficientFunds, CodeInvalidInput)
}
func ErrInvalidCoins() errors.TMError {
return errors.WithCode(errInvalidCoins, invalidInput)
}
func IsInvalidCoinsErr(err error) bool {
return errors.IsSameError(errInvalidCoins, err)
func ErrInsufficientCredit() errors.ABCIError {
return errors.WithCode(errInsufficientCredit, CodeInvalidInput)
}
func ErrInsufficientFunds() errors.TMError {
return errors.WithCode(errInsufficientFunds, invalidInput)
}
func IsInsufficientFundsErr(err error) bool {
return errors.IsSameError(errInsufficientFunds, err)
func ErrNoInputs() errors.ABCIError {
return errors.WithCode(errNoInputs, CodeInvalidInput)
}
func ErrInsufficientCredit() errors.TMError {
return errors.WithCode(errInsufficientCredit, invalidInput)
}
func IsInsufficientCreditErr(err error) bool {
return errors.IsSameError(errInsufficientCredit, err)
}
func ErrNoInputs() errors.TMError {
return errors.WithCode(errNoInputs, invalidInput)
}
func IsNoInputsErr(err error) bool {
return errors.IsSameError(errNoInputs, err)
}
func ErrNoOutputs() errors.TMError {
return errors.WithCode(errNoOutputs, invalidOutput)
}
func IsNoOutputsErr(err error) bool {
return errors.IsSameError(errNoOutputs, err)
func ErrNoOutputs() errors.ABCIError {
return errors.WithCode(errNoOutputs, CodeInvalidOutput)
}

View File

@ -13,11 +13,11 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/commands"
"github.com/cosmos/cosmos-sdk/client/commands/query"
"github.com/cosmos/cosmos-sdk/modules/auth"
"github.com/cosmos/cosmos-sdk/modules/base"
"github.com/cosmos/cosmos-sdk/modules/coin"
"github.com/cosmos/cosmos-sdk/modules/fee"
"github.com/cosmos/cosmos-sdk/modules/nonce"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/base"
"github.com/cosmos/cosmos-sdk/x/coin"
"github.com/cosmos/cosmos-sdk/x/fee"
"github.com/cosmos/cosmos-sdk/x/nonce"
"github.com/cosmos/cosmos-sdk/stack"
"github.com/tendermint/tmlibs/common"
)

View File

@ -1,85 +1,13 @@
package coin
import (
"fmt"
import "github.com/tendermint/go-wire/data"
wire "github.com/tendermint/go-wire"
// TEMP
sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/errors"
"github.com/cosmos/cosmos-sdk/state"
)
// GetAccount - Get account from store and address
func GetAccount(store state.SimpleDB, addr sdk.Actor) (Account, error) {
// if the actor is another chain, we use one address for the chain....
addr = ChainAddr(addr)
acct, err := loadAccount(store, addr.Bytes())
// for empty accounts, don't return an error, but rather an empty account
if IsNoAccountErr(err) {
err = nil
}
return acct, err
}
// CheckCoins makes sure there are funds, but doesn't change anything
func CheckCoins(store state.SimpleDB, addr sdk.Actor, coins Coins) (Coins, error) {
// if the actor is another chain, we use one address for the chain....
addr = ChainAddr(addr)
acct, err := updateCoins(store, addr, coins)
return acct.Coins, err
}
// ChangeCoins changes the money, returns error if it would be negative
func ChangeCoins(store state.SimpleDB, addr sdk.Actor, coins Coins) (Coins, error) {
// if the actor is another chain, we use one address for the chain....
addr = ChainAddr(addr)
acct, err := updateCoins(store, addr, coins)
if err != nil {
return acct.Coins, err
}
err = storeAccount(store, addr.Bytes(), acct)
return acct.Coins, err
}
// ChainAddr collapses all addresses from another chain into one, so we can
// keep an over-all balance
//
// TODO: is there a better way to do this?
func ChainAddr(addr sdk.Actor) sdk.Actor {
if addr.ChainID == "" {
return addr
}
addr.App = ""
addr.Address = nil
return addr
}
// updateCoins will load the account, make all checks, and return the updated account.
//
// it doesn't save anything, that is up to you to decide (Check/Change Coins)
func updateCoins(store state.SimpleDB, addr sdk.Actor, coins Coins) (acct Account, err error) {
acct, err = loadAccount(store, addr.Bytes())
// we can increase an empty account...
if IsNoAccountErr(err) && coins.IsPositive() {
err = nil
}
if err != nil {
return acct, err
}
// check amount
final := acct.Coins.Plus(coins)
if !final.IsNonnegative() {
return acct, ErrInsufficientFunds()
}
acct.Coins = final
return acct, nil
type Actor struct {
ChainID string
App string
Address data.Bytes
}
// Account - coin account structure
@ -90,56 +18,3 @@ type Account struct {
// (this is usually 0 except for trusted chains)
Credit Coins `json:"credit"`
}
func loadAccount(store state.SimpleDB, key []byte) (acct Account, err error) {
// fmt.Printf("load: %X\n", key)
data := store.Get(key)
if len(data) == 0 {
return acct, ErrNoAccount()
}
err = wire.ReadBinaryBytes(data, &acct)
if err != nil {
msg := fmt.Sprintf("Error reading account %X", key)
return acct, errors.ErrInternal(msg)
}
return acct, nil
}
func storeAccount(store state.SimpleDB, key []byte, acct Account) error {
// fmt.Printf("store: %X\n", key)
bin := wire.BinaryBytes(acct)
store.Set(key, bin)
return nil // real stores can return error...
}
// HandlerInfo - this is global info on the coin handler
type HandlerInfo struct {
Issuer sdk.Actor `json:"issuer"`
}
// TODO: where to store these special pieces??
var handlerKey = []byte{12, 34}
func loadHandlerInfo(store state.KVStore) (info HandlerInfo, err error) {
data := store.Get(handlerKey)
if len(data) == 0 {
return info, nil
}
err = wire.ReadBinaryBytes(data, &info)
if err != nil {
msg := "Error reading handler info"
return info, errors.ErrInternal(msg)
}
return info, nil
}
func storeIssuer(store state.KVStore, issuer sdk.Actor) error {
info, err := loadHandlerInfo(store)
if err != nil {
return err
}
info.Issuer = issuer
d := wire.BinaryBytes(info)
store.Set(handlerKey, d)
return nil // real stores can return error...
}

View File

@ -2,18 +2,18 @@ package coin
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk"
)
func init() {
/*func init() {
sdk.TxMapper.
RegisterImplementation(SendTx{}, TypeSend, ByteSend).
RegisterImplementation(CreditTx{}, TypeCredit, ByteCredit)
}
}*/
// we reserve the 0x20-0x3f range for standard modules
const (
NameCoin = "coin"
ByteSend = 0x20
TypeSend = NameCoin + "/send"
ByteCredit = 0x21
@ -24,8 +24,8 @@ const (
// TxInput - expected coin movement outputs, used with SendTx
type TxInput struct {
Address sdk.Actor `json:"address"`
Coins Coins `json:"coins"`
Address Actor `json:"address"`
Coins Coins `json:"coins"`
}
// ValidateBasic - validate transaction input
@ -51,7 +51,7 @@ func (txIn TxInput) String() string {
}
// NewTxInput - create a transaction input, used with SendTx
func NewTxInput(addr sdk.Actor, coins Coins) TxInput {
func NewTxInput(addr Actor, coins Coins) TxInput {
input := TxInput{
Address: addr,
Coins: coins,
@ -63,8 +63,8 @@ func NewTxInput(addr sdk.Actor, coins Coins) TxInput {
// TxOutput - expected coin movement output, used with SendTx
type TxOutput struct {
Address sdk.Actor `json:"address"`
Coins Coins `json:"coins"`
Address Actor `json:"address"`
Coins Coins `json:"coins"`
}
// ValidateBasic - validate transaction output
@ -90,7 +90,7 @@ func (txOut TxOutput) String() string {
}
// NewTxOutput - create a transaction output, used with SendTx
func NewTxOutput(addr sdk.Actor, coins Coins) TxOutput {
func NewTxOutput(addr Actor, coins Coins) TxOutput {
output := TxOutput{
Address: addr,
Coins: coins,
@ -107,19 +107,19 @@ type SendTx struct {
Outputs []TxOutput `json:"outputs"`
}
var _ sdk.Tx = NewSendTx(nil, nil)
// var _ types.Tx = NewSendTx(nil, nil)
// NewSendTx - construct arbitrary multi-in, multi-out sendtx
func NewSendTx(in []TxInput, out []TxOutput) sdk.Tx {
return SendTx{Inputs: in, Outputs: out}.Wrap()
func NewSendTx(in []TxInput, out []TxOutput) SendTx { // 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 sdk.Actor, amount Coins) sdk.Tx {
func NewSendOneTx(sender, recipient Actor, amount Coins) SendTx {
in := []TxInput{{Address: sender, Coins: amount}}
out := []TxOutput{{Address: recipient, Coins: amount}}
return SendTx{Inputs: in, Outputs: out}.Wrap()
return SendTx{Inputs: in, Outputs: out}
}
// ValidateBasic - validate the send transaction
@ -157,17 +157,12 @@ func (tx SendTx) String() string {
return fmt.Sprintf("SendTx{%v->%v}", tx.Inputs, tx.Outputs)
}
// Wrap - used to satisfy TxInner
func (tx SendTx) Wrap() sdk.Tx {
return sdk.Tx{tx}
}
//-----------------------------------------------------------------------------
// CreditTx - this allows a special issuer to give an account credit
// Satisfies: TxInner
type CreditTx struct {
Debitor sdk.Actor `json:"debitor"`
Debitor Actor `json:"debitor"`
// Credit is the amount to change the credit...
// This may be negative to remove some over-issued credit,
// but can never bring the credit or the balance to negative
@ -175,13 +170,8 @@ type CreditTx struct {
}
// NewCreditTx - modify the credit granted to a given account
func NewCreditTx(debitor sdk.Actor, credit Coins) sdk.Tx {
return CreditTx{Debitor: debitor, Credit: credit}.Wrap()
}
// Wrap - used to satisfy TxInner
func (tx CreditTx) Wrap() sdk.Tx {
return sdk.Tx{tx}
func NewCreditTx(debitor Actor, credit Coins) CreditTx {
return CreditTx{Debitor: debitor, Credit: credit}
}
// ValidateBasic - used to satisfy TxInner