Documentation

Overview

Package cash defines a simple implementation of sending coins between multi-signature wallets.

There is no logic in the coins (tokens), except that the balance of any coin may not go below zero. Thus, this implementation is referred to as cash. Simple and safe.

In the future, there should be more implementations that support sending and issuing tokens with much more logic inside.

Index

Constants

View Source
const BucketName = "cash"

BucketName is where we store the balances

Variables

View Source
var (
	ErrInvalidLengthCodec = fmt.Errorf("proto: negative length found during unmarshaling")
	ErrIntOverflowCodec   = fmt.Errorf("proto: integer overflow")
)

Functions

func Add

func Add(cng Coinage, c coin.Coin) error

Add modifies the coinage to add Coin c

func AsCoins

func AsCoins(obj orm.Object) coin.Coins

AsCoins will extract XCoins from any object

func Concat

func Concat(cng Coinage, coins coin.Coins) error

Concat combines the coins to make sure they are sorted and rounded off, with no duplicates or 0 values.

func MoveCoins

func MoveCoins(db weave.KVStore, bank CoinMover, src, dest weave.Address, amounts []*coin.Coin) error

func NewConfigHandler

func NewConfigHandler(auth x.Authenticator) weave.Handler

func NewWallet

func NewWallet(key weave.Address) orm.Object

NewWallet creates an empty wallet with this address serves as an object for the bucket. NewWallet wraps Set into an object for the Bucket.

func RegisterQuery

func RegisterQuery(qr weave.QueryRouter)

RegisterQuery will register this bucket as "/wallets"

func RegisterRoutes

func RegisterRoutes(r weave.Registry, auth x.Authenticator, control Controller)

RegisterRoutes will instantiate and register all handlers in this package

func Subtract

func Subtract(cng Coinage, c coin.Coin) error

Subtract modifies the coinage to remove Coin c

func ValidateWalletBucket

func ValidateWalletBucket(bucket WalletBucket)

ValidateWalletBucket makes sure that it supports AsCoinage objects, unfortunately this check is done runtime....

panics on error (meant as a sanity check in init)

func WalletWith

func WalletWith(key weave.Address, coins ...*coin.Coin) (orm.Object, error)

WalletWith creates an wallet with a balance

func XCoins

func XCoins(c Coinage) coin.Coins

XCoins returns the stored coins cast properly

Types

type Balancer

type Balancer interface {
	// Balance returns the amount of funds stored under given account address.
	Balance(weave.KVStore, weave.Address) (coin.Coins, error)
}

Balancer is an interface to query the amount of coins.

type BaseController

type BaseController struct {
	// contains filtered or unexported fields
}

BaseController implements Controller interface, using WalletBucket as the storage engine. Wallet must return something that supports AsSet.

func NewController

func NewController(bucket WalletBucket) BaseController

NewController returns a base controller implementation.

func (BaseController) Balance

func (c BaseController) Balance(store weave.KVStore, src weave.Address) (coin.Coins, error)

Balance returns the amount of funds stored under given account address.

func (BaseController) CoinMint

func (c BaseController) CoinMint(store weave.KVStore,
	dest weave.Address, amount coin.Coin) error

CoinMint attempts to add the given amount of coins to the destination address. Fails if it overflows the wallet.

Note the amount may also be negative: "the lord giveth and the lord taketh away"

func (BaseController) MoveCoins

func (c BaseController) MoveCoins(store weave.KVStore,
	src weave.Address, dest weave.Address, amount coin.Coin) error

MoveCoins moves the given amount from src to dest. If src doesn't exist, or doesn't have sufficient coins, it fails.

type Bucket

type Bucket struct {
	orm.Bucket
}

Bucket is a type-safe wrapper around orm.Bucket

func NewBucket

func NewBucket() Bucket

NewBucket initializes a cash.Bucket with default name

func (Bucket) GetOrCreate

func (b Bucket) GetOrCreate(db weave.KVStore, key weave.Address) (orm.Object, error)

GetOrCreate will return the object if found, or create one if not.

type CoinMinter

type CoinMinter interface {
	// CoinMint increase the number of funds on given account by a
	// specified amount.
	CoinMint(weave.KVStore, weave.Address, coin.Coin) error
}

CoinMinter is an interface to create new coins.

type CoinMover

type CoinMover interface {
	// Moving coins must happen from the source to the destination address.
	// Zero or negative values must result in an error.
	MoveCoins(store weave.KVStore, src weave.Address, dest weave.Address, amount coin.Coin) error
}

CoinsMover is an interface for moving coins between accounts.

type Coinage

type Coinage interface {
	GetCoins() []*coin.Coin
	SetCoins([]*coin.Coin)
}

Coinage is any model that allows getting and setting coins, Below functions work on these models (oh, how I long for default implementations for interface, like rust traits)

func AsCoinage

func AsCoinage(obj orm.Object) Coinage

AsCoinage will safely type-cast any value from Bucket to Coinage

type Configuration

type Configuration struct {
	Metadata *weave.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
	// Owner is present to implement gconf.OwnedConfig interface
	// This defines the Address that is allowed to update the Configuration object and is
	// needed to make use of gconf.NewUpdateConfigurationHandler
	Owner            github_com_iov_one_weave.Address `protobuf:"bytes,2,opt,name=owner,proto3,casttype=github.com/iov-one/weave.Address" json:"owner,omitempty"`
	CollectorAddress github_com_iov_one_weave.Address `` /* 151-byte string literal not displayed */
	MinimalFee       coin.Coin                        `protobuf:"bytes,4,opt,name=minimal_fee,json=minimalFee,proto3" json:"minimal_fee"`
}

func (*Configuration) Descriptor

func (*Configuration) Descriptor() ([]byte, []int)

func (*Configuration) GetCollectorAddress

func (m *Configuration) GetCollectorAddress() github_com_iov_one_weave.Address

func (*Configuration) GetMetadata

func (m *Configuration) GetMetadata() *weave.Metadata

func (*Configuration) GetMinimalFee

func (m *Configuration) GetMinimalFee() coin.Coin

func (*Configuration) GetOwner

func (*Configuration) Marshal

func (m *Configuration) Marshal() (dAtA []byte, err error)

func (*Configuration) MarshalTo

func (m *Configuration) MarshalTo(dAtA []byte) (int, error)

func (*Configuration) ProtoMessage

func (*Configuration) ProtoMessage()

func (*Configuration) Reset

func (m *Configuration) Reset()

func (*Configuration) Size

func (m *Configuration) Size() (n int)

func (*Configuration) String

func (m *Configuration) String() string

func (*Configuration) Unmarshal

func (m *Configuration) Unmarshal(dAtA []byte) error

func (*Configuration) Validate

func (c *Configuration) Validate() error

func (*Configuration) XXX_DiscardUnknown

func (m *Configuration) XXX_DiscardUnknown()

func (*Configuration) XXX_Marshal

func (m *Configuration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Configuration) XXX_Merge

func (m *Configuration) XXX_Merge(src proto.Message)

func (*Configuration) XXX_Size

func (m *Configuration) XXX_Size() int

func (*Configuration) XXX_Unmarshal

func (m *Configuration) XXX_Unmarshal(b []byte) error

type Controller

type Controller interface {
	CoinMover
	Balancer
}

Controller is the functionality needed by cash.Handler and cash.Decorator. BaseController should work plenty fine, but you can add other logic if so desired

type DynamicFeeDecorator

type DynamicFeeDecorator struct {
	// contains filtered or unexported fields
}

func NewDynamicFeeDecorator

func NewDynamicFeeDecorator(auth x.Authenticator, ctrl Controller) DynamicFeeDecorator

NewDynamicFeeDecorator returns a DynamicFeeDecorator with the given minimum fee, and all collected fees going to a default address.

func (DynamicFeeDecorator) Check

func (d DynamicFeeDecorator) Check(ctx weave.Context, store weave.KVStore, tx weave.Tx, next weave.Checker) (cres *weave.CheckResult, cerr error)

Check verifies and deducts fees before calling down the stack

func (DynamicFeeDecorator) Deliver

func (d DynamicFeeDecorator) Deliver(ctx weave.Context, store weave.KVStore, tx weave.Tx, next weave.Deliverer) (dres *weave.DeliverResult, derr error)

Deliver verifies and deducts fees before calling down the stack

type FeeDecorator

type FeeDecorator struct {
	// contains filtered or unexported fields
}

func NewFeeDecorator

func NewFeeDecorator(auth x.Authenticator, ctrl CoinMover) FeeDecorator

NewFeeDecorator returns a FeeDecorator with the given minimum fee, and all collected fees going to a default address.

func (FeeDecorator) Check

func (d FeeDecorator) Check(ctx weave.Context, store weave.KVStore, tx weave.Tx, next weave.Checker) (*weave.CheckResult, error)

Check verifies and deducts fees before calling down the stack

func (FeeDecorator) Deliver

func (d FeeDecorator) Deliver(ctx weave.Context, store weave.KVStore, tx weave.Tx, next weave.Deliverer) (*weave.DeliverResult, error)

Deliver verifies and deducts fees before calling down the stack

type FeeInfo

type FeeInfo struct {
	// Payer represents an address that will pay the fee. A fee fund will be
	// withdrawn from that account in order to process a transaction.
	// Warning: This field is optional and when not set it will default to any
	// signer. It is recommended to always explicitely set the value of this
	// field, as the signer order is not guaranteed.
	Payer github_com_iov_one_weave.Address `protobuf:"bytes,2,opt,name=payer,proto3,casttype=github.com/iov-one/weave.Address" json:"payer,omitempty"`
	Fees  *coin.Coin                       `protobuf:"bytes,3,opt,name=fees,proto3" json:"fees,omitempty"`
}

FeeInfo records who pays what fees to have this message processed

func (*FeeInfo) DefaultPayer

func (f *FeeInfo) DefaultPayer(addr []byte) *FeeInfo

DefaultPayer makes sure there is a payer. If it was already set, returns f. If none was set, returns a new FeeInfo, with the New address set

func (*FeeInfo) Descriptor

func (*FeeInfo) Descriptor() ([]byte, []int)

func (*FeeInfo) GetFees

func (m *FeeInfo) GetFees() *coin.Coin

func (*FeeInfo) GetPayer

func (*FeeInfo) Marshal

func (m *FeeInfo) Marshal() (dAtA []byte, err error)

func (*FeeInfo) MarshalTo

func (m *FeeInfo) MarshalTo(dAtA []byte) (int, error)

func (*FeeInfo) ProtoMessage

func (*FeeInfo) ProtoMessage()

func (*FeeInfo) Reset

func (m *FeeInfo) Reset()

func (*FeeInfo) Size

func (m *FeeInfo) Size() (n int)

func (*FeeInfo) String

func (m *FeeInfo) String() string

func (*FeeInfo) Unmarshal

func (m *FeeInfo) Unmarshal(dAtA []byte) error

func (*FeeInfo) Validate

func (f *FeeInfo) Validate() error

Validate makes sure that this is sensible. Note that fee must be present, even if 0

func (*FeeInfo) XXX_DiscardUnknown

func (m *FeeInfo) XXX_DiscardUnknown()

func (*FeeInfo) XXX_Marshal

func (m *FeeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*FeeInfo) XXX_Merge

func (m *FeeInfo) XXX_Merge(src proto.Message)

func (*FeeInfo) XXX_Size

func (m *FeeInfo) XXX_Size() int

func (*FeeInfo) XXX_Unmarshal

func (m *FeeInfo) XXX_Unmarshal(b []byte) error

type FeeTx

type FeeTx interface {
	GetFees() *FeeInfo
}

FeeTx exposes information about the fees that should be paid.

type GenesisAccount

type GenesisAccount struct {
	Address weave.Address `json:"address"`
	Set
}

GenesisAccount is used to parse the json from genesis file use weave.Address, so address in hex, not base64

type Initializer

type Initializer struct{}

Initializer fulfils the InitStater interface to load data from the genesis file

func (Initializer) FromGenesis

func (Initializer) FromGenesis(opts weave.Options, params weave.GenesisParams, kv weave.KVStore) error

FromGenesis will parse initial account info from genesis and save it to the database

type SendHandler

type SendHandler struct {
	// contains filtered or unexported fields
}

SendHandler will handle sending coins

func NewSendHandler

func NewSendHandler(auth x.Authenticator, control Controller) SendHandler

NewSendHandler creates a handler for SendMsg

func (SendHandler) Check

func (h SendHandler) Check(ctx weave.Context, store weave.KVStore, tx weave.Tx) (*weave.CheckResult, error)

Check just verifies it is properly formed and returns the cost of executing it

func (SendHandler) Deliver

func (h SendHandler) Deliver(ctx weave.Context, store weave.KVStore, tx weave.Tx) (*weave.DeliverResult, error)

Deliver moves the tokens from source to receiver if all preconditions are met

type SendMsg

type SendMsg struct {
	Metadata    *weave.Metadata                  `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
	Source      github_com_iov_one_weave.Address `protobuf:"bytes,2,opt,name=source,proto3,casttype=github.com/iov-one/weave.Address" json:"source,omitempty"`
	Destination github_com_iov_one_weave.Address `protobuf:"bytes,3,opt,name=destination,proto3,casttype=github.com/iov-one/weave.Address" json:"destination,omitempty"`
	Amount      *coin.Coin                       `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"`
	// max length 128 character
	Memo string `protobuf:"bytes,5,opt,name=memo,proto3" json:"memo,omitempty"`
	// max length 64 bytes
	Ref []byte `protobuf:"bytes,6,opt,name=ref,proto3" json:"ref,omitempty"`
}

SendMsg is a request to move these coins from the given source to the given destination address. memo is an optional human-readable message ref is optional binary data, that can refer to another eg. tx hash

func (*SendMsg) DefaultSource

func (s *SendMsg) DefaultSource(addr []byte) *SendMsg

DefaultSource makes sure there is a payer. If it was already set, returns s. If none was set, returns a new SendMsg with the source set

func (*SendMsg) Descriptor

func (*SendMsg) Descriptor() ([]byte, []int)

func (*SendMsg) GetAmount

func (m *SendMsg) GetAmount() *coin.Coin

func (*SendMsg) GetDestination

func (m *SendMsg) GetDestination() github_com_iov_one_weave.Address

func (*SendMsg) GetMemo

func (m *SendMsg) GetMemo() string

func (*SendMsg) GetMetadata

func (m *SendMsg) GetMetadata() *weave.Metadata

func (*SendMsg) GetRef

func (m *SendMsg) GetRef() []byte

func (*SendMsg) GetSource

func (m *SendMsg) GetSource() github_com_iov_one_weave.Address

func (*SendMsg) Marshal

func (m *SendMsg) Marshal() (dAtA []byte, err error)

func (*SendMsg) MarshalTo

func (m *SendMsg) MarshalTo(dAtA []byte) (int, error)

func (SendMsg) Path

func (SendMsg) Path() string

Path returns the routing path for this message.

func (*SendMsg) ProtoMessage

func (*SendMsg) ProtoMessage()

func (*SendMsg) Reset

func (m *SendMsg) Reset()

func (*SendMsg) Size

func (m *SendMsg) Size() (n int)

func (*SendMsg) String

func (m *SendMsg) String() string

func (*SendMsg) Unmarshal

func (m *SendMsg) Unmarshal(dAtA []byte) error

func (*SendMsg) Validate

func (s *SendMsg) Validate() error

Validate makes sure that this is sensible.

func (*SendMsg) XXX_DiscardUnknown

func (m *SendMsg) XXX_DiscardUnknown()

func (*SendMsg) XXX_Marshal

func (m *SendMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*SendMsg) XXX_Merge

func (m *SendMsg) XXX_Merge(src proto.Message)

func (*SendMsg) XXX_Size

func (m *SendMsg) XXX_Size() int

func (*SendMsg) XXX_Unmarshal

func (m *SendMsg) XXX_Unmarshal(b []byte) error

type Set

type Set struct {
	Metadata *weave.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
	Coins    []*coin.Coin    `protobuf:"bytes,2,rep,name=coins,proto3" json:"coins,omitempty"`
}

Set may contain Coin of many different currencies. It handles adding and subtracting sets of currencies.

func (*Set) Descriptor

func (*Set) Descriptor() ([]byte, []int)

func (*Set) GetCoins

func (m *Set) GetCoins() []*coin.Coin

func (*Set) GetMetadata

func (m *Set) GetMetadata() *weave.Metadata

func (*Set) Marshal

func (m *Set) Marshal() (dAtA []byte, err error)

func (*Set) MarshalTo

func (m *Set) MarshalTo(dAtA []byte) (int, error)

func (*Set) ProtoMessage

func (*Set) ProtoMessage()

func (*Set) Reset

func (m *Set) Reset()

func (*Set) SetCoins

func (s *Set) SetCoins(coins []*coin.Coin)

SetCoins allows us to modify the Set

func (*Set) Size

func (m *Set) Size() (n int)

func (*Set) String

func (m *Set) String() string

func (*Set) Unmarshal

func (m *Set) Unmarshal(dAtA []byte) error

func (*Set) Validate

func (s *Set) Validate() error

Validate requires that all coins are in alphabetical

func (*Set) XXX_DiscardUnknown

func (m *Set) XXX_DiscardUnknown()

func (*Set) XXX_Marshal

func (m *Set) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*Set) XXX_Merge

func (m *Set) XXX_Merge(src proto.Message)

func (*Set) XXX_Size

func (m *Set) XXX_Size() int

func (*Set) XXX_Unmarshal

func (m *Set) XXX_Unmarshal(b []byte) error

type UpdateConfigurationMsg

type UpdateConfigurationMsg struct {
	Metadata *weave.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
	Patch    *Configuration  `protobuf:"bytes,2,opt,name=patch,proto3" json:"patch,omitempty"`
}

func (*UpdateConfigurationMsg) Descriptor

func (*UpdateConfigurationMsg) Descriptor() ([]byte, []int)

func (*UpdateConfigurationMsg) GetMetadata

func (m *UpdateConfigurationMsg) GetMetadata() *weave.Metadata

func (*UpdateConfigurationMsg) GetPatch

func (m *UpdateConfigurationMsg) GetPatch() *Configuration

func (*UpdateConfigurationMsg) Marshal

func (m *UpdateConfigurationMsg) Marshal() (dAtA []byte, err error)

func (*UpdateConfigurationMsg) MarshalTo

func (m *UpdateConfigurationMsg) MarshalTo(dAtA []byte) (int, error)

func (*UpdateConfigurationMsg) Path

func (*UpdateConfigurationMsg) ProtoMessage

func (*UpdateConfigurationMsg) ProtoMessage()

func (*UpdateConfigurationMsg) Reset

func (m *UpdateConfigurationMsg) Reset()

func (*UpdateConfigurationMsg) Size

func (m *UpdateConfigurationMsg) Size() (n int)

func (*UpdateConfigurationMsg) String

func (m *UpdateConfigurationMsg) String() string

func (*UpdateConfigurationMsg) Unmarshal

func (m *UpdateConfigurationMsg) Unmarshal(dAtA []byte) error

func (*UpdateConfigurationMsg) Validate

func (m *UpdateConfigurationMsg) Validate() error

Validate will skip any zero fields and validate the set ones.

func (*UpdateConfigurationMsg) XXX_DiscardUnknown

func (m *UpdateConfigurationMsg) XXX_DiscardUnknown()

func (*UpdateConfigurationMsg) XXX_Marshal

func (m *UpdateConfigurationMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*UpdateConfigurationMsg) XXX_Merge

func (m *UpdateConfigurationMsg) XXX_Merge(src proto.Message)

func (*UpdateConfigurationMsg) XXX_Size

func (m *UpdateConfigurationMsg) XXX_Size() int

func (*UpdateConfigurationMsg) XXX_Unmarshal

func (m *UpdateConfigurationMsg) XXX_Unmarshal(b []byte) error

type WalletBucket

type WalletBucket interface {
	GetOrCreate(db weave.KVStore, key weave.Address) (orm.Object, error)
	Get(db weave.ReadOnlyKVStore, key []byte) (orm.Object, error)
	Save(db weave.KVStore, obj orm.Object) error
}

WalletBucket is what we expect to be able to do with wallets The object it returns must support AsSet (only checked runtime :()