diff --git a/coin/coin.go b/coin/coin.go index a6e473ba..cd9195b7 100644 --- a/coin/coin.go +++ b/coin/coin.go @@ -56,7 +56,7 @@ func (c Coin) Divide(pieces int64) (Coin, Coin, error) { // This is an invalid use of the method. if pieces <= 0 { zero := Coin{Ticker: c.Ticker} - return zero, zero, errors.ErrHuman.New("pieces must be greater than zero") + return zero, zero, errors.Wrap(errors.ErrInvalidInput, "pieces must be greater than zero") } // When dividing whole and there is a leftover then convert it to @@ -142,7 +142,7 @@ func (c Coin) Add(o Coin) (Coin, error) { } if !c.SameType(o) { - err := ErrInvalidCurrency.Newf("adding %s to %s", c.Ticker, o.Ticker) + err := errors.Wrapf(errors.ErrCurrency, "adding %s to %s", c.Ticker, o.Ticker) return Coin{}, err } @@ -255,18 +255,18 @@ func (c *Coin) Clone() *Coin { // logic func (c Coin) Validate() error { if !IsCC(c.Ticker) { - return ErrInvalidCurrency.New(c.Ticker) + return errors.Wrapf(errors.ErrCurrency, "invalid currency: %s", c.Ticker) } if c.Whole < MinInt || c.Whole > MaxInt { - return ErrInvalidCoin.New(outOfRange) + return errors.ErrOverflow } if c.Fractional < MinFrac || c.Fractional > MaxFrac { - return ErrInvalidCoin.New(outOfRange) + return errors.ErrOverflow } // make sure signs match if c.Whole != 0 && c.Fractional != 0 && ((c.Whole > 0) != (c.Fractional > 0)) { - return ErrInvalidCoin.New("mismatched sign") + return errors.Wrap(errors.ErrInvalidState, "mismatched sign") } return nil @@ -299,7 +299,7 @@ func (c Coin) normalize() (Coin, error) { // return error if integer is out of range if c.Whole < MinInt || c.Whole > MaxInt { - return Coin{}, ErrInvalidCoin.New(outOfRange) + return Coin{}, errors.ErrOverflow } return c, nil } diff --git a/coin/coin_test.go b/coin/coin_test.go index 5423c167..3ed5a31d 100644 --- a/coin/coin_test.go +++ b/coin/coin_test.go @@ -169,7 +169,7 @@ func TestAddCoin(t *testing.T) { a: NewCoin(1, 2, "FOO"), b: NewCoin(2, 3, "BAR"), wantRes: Coin{}, - wantErr: ErrInvalidCurrency, + wantErr: errors.ErrCurrency, }, "normal math": { a: NewCoin(7, 5000, "ABC"), @@ -180,7 +180,7 @@ func TestAddCoin(t *testing.T) { a: NewCoin(500500500123456, 0, "SEE"), b: NewCoin(500500500123456, 0, "SEE"), wantRes: NewCoin(0, 0, ""), - wantErr: ErrInvalidCoin, + wantErr: errors.ErrOverflow, }, "adding to zero coin": { a: NewCoin(0, 0, ""), @@ -195,12 +195,12 @@ func TestAddCoin(t *testing.T) { "adding a non zero coin without a ticker": { a: NewCoin(1, 0, "DOGE"), b: NewCoin(1, 0, ""), - wantErr: ErrInvalidCurrency, + wantErr: errors.ErrCurrency, }, "adding to non zero coin without a ticker": { a: NewCoin(1, 0, ""), b: NewCoin(1, 0, "DOGE"), - wantErr: ErrInvalidCurrency, + wantErr: errors.ErrCurrency, }, } @@ -325,14 +325,14 @@ func TestCoinDivide(t *testing.T) { pieces: 0, wantOne: NewCoin(0, 0, "BTC"), wantRest: NewCoin(0, 0, "BTC"), - wantErr: errors.ErrHuman, + wantErr: errors.ErrInvalidInput, }, "negative pieces": { total: NewCoin(999, 0, "BTC"), pieces: -1, wantOne: NewCoin(0, 0, "BTC"), wantRest: NewCoin(0, 0, "BTC"), - wantErr: errors.ErrHuman, + wantErr: errors.ErrInvalidInput, }, "split fractional 2 by 3 should return 2 as leftover": { total: NewCoin(0, 2, "BTC"), diff --git a/coin/coins.go b/coin/coins.go index edca9090..d7bdb0a8 100644 --- a/coin/coins.go +++ b/coin/coins.go @@ -7,9 +7,8 @@ import ( "github.com/iov-one/weave/errors" ) -//--------------------- Coins ------------------------- - -// Coins is a +// Coins represents a set of coins. Most operations on the coin set require +// normalized form. Make sure to normalize you collection before using. type Coins []*Coin // CombineCoins creates a Coins containing all given coins. @@ -183,10 +182,10 @@ func (cs Coins) Validate() error { return err } if c.IsZero() { - return ErrInvalidWallet.New("zero coins") + return errors.Wrap(errors.ErrInvalidState, "zero coins") } if c.Ticker < last { - return ErrInvalidWallet.New("not sorted") + return errors.Wrap(errors.ErrInvalidState, "not sorted") } last = c.Ticker } diff --git a/coin/errors.go b/coin/errors.go deleted file mode 100644 index e294d5ec..00000000 --- a/coin/errors.go +++ /dev/null @@ -1,16 +0,0 @@ -package coin - -import ( - "github.com/iov-one/weave/errors" -) - -// Reserved codes 130~139 -var ( - ErrInvalidCurrency = errors.Register(130, "invalid currency code") - ErrInvalidCoin = errors.Register(131, "invalid coin") - ErrInvalidWallet = errors.Register(132, "invalid wallet") -) - -const ( - outOfRange = "overflow coin range" -) diff --git a/errors/errors.go b/errors/errors.go index 37af9720..a13f1884 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -71,6 +71,10 @@ var ( // because the result value exceeds the type. ErrOverflow = Register(16, "an operation cannot be completed due to value overflow") + // ErrCurrency is returned whenever an operation cannot be completed + // due to a currency issues. + ErrCurrency = Register(17, "currency") + // ErrPanic is only set when we recover from a panic, so we know to redact potentially sensitive system info ErrPanic = Register(111222, "panic") ) diff --git a/x/cash/dynamicfee.go b/x/cash/dynamicfee.go index 77f174c5..7b5997e2 100644 --- a/x/cash/dynamicfee.go +++ b/x/cash/dynamicfee.go @@ -198,7 +198,9 @@ func (d DynamicFeeDecorator) extractFee(ctx weave.Context, tx weave.Tx, store we return nil, errors.ErrHuman.New("minumal fee curency not set") } if !txFee.SameType(minFee) { - return nil, coin.ErrInvalidCurrency.Newf("min fee is %s and tx fee is %s", minFee.Ticker, txFee.Ticker) + err := errors.Wrapf(errors.ErrCurrency, + "min fee is %s and tx fee is %s", minFee.Ticker, txFee.Ticker) + return nil, err } if !txFee.IsGTE(minFee) { diff --git a/x/cash/msg_test.go b/x/cash/msg_test.go index 06ffaf30..ed322cb3 100644 --- a/x/cash/msg_test.go +++ b/x/cash/msg_test.go @@ -79,7 +79,7 @@ func TestValidateSendMsg(t *testing.T) { } err = ugly.Validate() assert.Error(t, err) - assert.True(t, coin.ErrInvalidCurrency.Is(err)) + assert.True(t, errors.ErrCurrency.Is(err)) } @@ -133,6 +133,6 @@ func TestValidateFeeTx(t *testing.T) { } err = ugly.Validate() assert.Error(t, err) - assert.True(t, coin.ErrInvalidCurrency.Is(err)) + assert.True(t, errors.ErrCurrency.Is(err)) } diff --git a/x/cash/staticfee.go b/x/cash/staticfee.go index cfa9c32b..dd9a8a13 100644 --- a/x/cash/staticfee.go +++ b/x/cash/staticfee.go @@ -137,11 +137,13 @@ func (d FeeDecorator) extractFee(ctx weave.Context, tx weave.Tx, store weave.KVS return finfo, nil } if cmp.Ticker == "" { - return nil, errors.Wrap(coin.ErrInvalidCurrency, "no ticker") + return nil, errors.Wrap(errors.ErrCurrency, "no ticker") } if !fee.SameType(cmp) { - return nil, coin.ErrInvalidCurrency.Newf("%s vs fee %s", cmp.Ticker, fee.Ticker) + err := errors.Wrapf(errors.ErrCurrency, + "%s vs fee %s", cmp.Ticker, fee.Ticker) + return nil, err } if !fee.IsGTE(cmp) { diff --git a/x/cash/staticfee_test.go b/x/cash/staticfee_test.go index 4d053253..77129268 100644 --- a/x/cash/staticfee_test.go +++ b/x/cash/staticfee_test.go @@ -103,7 +103,7 @@ func TestFees(t *testing.T) { initState: []orm.Object{must(WalletWith(perm.Address(), &cash))}, fee: &FeeInfo{Fees: &min}, min: coin.NewCoin(0, 1000, ""), - expect: coin.ErrInvalidCurrency.Is, + expect: errors.ErrCurrency.Is, }, "no fee (zero value) is acceptable": { signers: []weave.Condition{perm}, @@ -117,7 +117,7 @@ func TestFees(t *testing.T) { initState: []orm.Object{must(WalletWith(perm.Address(), &cash))}, fee: &FeeInfo{Fees: &min}, min: coin.NewCoin(0, 1000, "NOT"), - expect: coin.ErrInvalidCurrency.Is, + expect: errors.ErrCurrency.Is, }, "has the cash, but didn't offer enough fees": { signers: []weave.Condition{perm}, diff --git a/x/currency/model.go b/x/currency/model.go index 0fbed21b..97f4c2d4 100644 --- a/x/currency/model.go +++ b/x/currency/model.go @@ -3,10 +3,9 @@ package currency import ( "regexp" + "github.com/iov-one/weave" "github.com/iov-one/weave/coin" "github.com/iov-one/weave/errors" - - "github.com/iov-one/weave" "github.com/iov-one/weave/orm" ) @@ -56,7 +55,7 @@ func (b *TokenInfoBucket) Save(db weave.KVStore, obj orm.Object) error { return errors.WithType(errors.ErrInvalidModel, obj.Value()) } if n := string(obj.Key()); !coin.IsCC(n) { - return coin.ErrInvalidCurrency.New(n) + return errors.Wrapf(errors.ErrCurrency, "invalid ticker: %s", n) } return b.Bucket.Save(db, obj) } diff --git a/x/currency/msg.go b/x/currency/msg.go index 7ef7efe8..b9a41215 100644 --- a/x/currency/msg.go +++ b/x/currency/msg.go @@ -14,7 +14,7 @@ func (NewTokenInfoMsg) Path() string { func (t *NewTokenInfoMsg) Validate() error { if !coin.IsCC(t.Ticker) { - return coin.ErrInvalidCurrency.New(t.Ticker) + return errors.Wrapf(errors.ErrCurrency, "invalid ticker: %s", t.Ticker) } if !isTokenName(t.Name) { return errors.ErrInvalidState.Newf("invalid token name %v", t.Name) diff --git a/x/escrow/msg_test.go b/x/escrow/msg_test.go index ec91978d..68fd53be 100644 --- a/x/escrow/msg_test.go +++ b/x/escrow/msg_test.go @@ -96,7 +96,7 @@ func TestCreateEscrowMsg(t *testing.T) { Amount: mixed, Timeout: 52, }, - coin.ErrInvalidCurrency.Is, + errors.ErrCurrency.Is, }, // missing amount 6: { @@ -201,7 +201,7 @@ func TestReleaseEscrowMsg(t *testing.T) { EscrowId: escrow, Amount: mixed, }, - coin.ErrInvalidCurrency.Is, + errors.ErrCurrency.Is, }, } diff --git a/x/msgfee/decorator_test.go b/x/msgfee/decorator_test.go index 13d47230..22bb2e67 100644 --- a/x/msgfee/decorator_test.go +++ b/x/msgfee/decorator_test.go @@ -80,9 +80,9 @@ func TestFeeDecorator(t *testing.T) { DeliverResult: weave.DeliverResult{RequiredFee: coin.NewCoin(1, 0, "BTC")}, }, Tx: &weavetest.Tx{Msg: &weavetest.Msg{RoutePath: "foo/bar"}}, - WantCheckErr: coin.ErrInvalidCurrency, + WantCheckErr: errors.ErrCurrency, WantCheckFee: coin.NewCoin(1, 0, "BTC"), - WantDeliverErr: coin.ErrInvalidCurrency, + WantDeliverErr: errors.ErrCurrency, WantDeliverFee: coin.NewCoin(1, 0, "BTC"), }, } diff --git a/x/namecoin/handler_test.go b/x/namecoin/handler_test.go index b16662be..5e51e160 100644 --- a/x/namecoin/handler_test.go +++ b/x/namecoin/handler_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/iov-one/weave" - coin "github.com/iov-one/weave/coin" + "github.com/iov-one/weave/coin" "github.com/iov-one/weave/errors" "github.com/iov-one/weave/orm" "github.com/iov-one/weave/store" @@ -132,7 +132,7 @@ func TestNewTokenHandler(t *testing.T) { "wrong message type": {[]weave.Condition{perm1}, addr1, nil, new(cash.SendMsg), errors.ErrInvalidMsg.Is, errors.ErrInvalidMsg.Is, "", nil}, "invalid ticker symbol": {[]weave.Condition{perm1}, addr1, nil, BuildTokenMsg("YO", "digga", 7), - coin.ErrInvalidCurrency.Is, coin.ErrInvalidCurrency.Is, "", nil}, + errors.ErrCurrency.Is, errors.ErrCurrency.Is, "", nil}, "invalid token name": {[]weave.Condition{perm1}, addr1, nil, BuildTokenMsg("GOOD", "ill3glz!", 7), errors.ErrInvalidInput.Is, errors.ErrInvalidInput.Is, "", nil}, "invalid sig figs": {[]weave.Condition{perm1}, addr1, nil, BuildTokenMsg("GOOD", "my good token", 17), diff --git a/x/namecoin/msg.go b/x/namecoin/msg.go index 482fb74e..ee5cf9c1 100644 --- a/x/namecoin/msg.go +++ b/x/namecoin/msg.go @@ -4,7 +4,7 @@ import ( "regexp" "github.com/iov-one/weave" - coin "github.com/iov-one/weave/coin" + "github.com/iov-one/weave/coin" "github.com/iov-one/weave/errors" ) @@ -37,7 +37,7 @@ func (NewTokenMsg) Path() string { // Validate makes sure that this is sensible func (t *NewTokenMsg) Validate() error { if !coin.IsCC(t.Ticker) { - return coin.ErrInvalidCurrency.New(t.Ticker) + return errors.Wrapf(errors.ErrCurrency, "invalid ticker: %s", t.Ticker) } if !IsTokenName(t.Name) { return errors.ErrInvalidInput.Newf(invalidTokenNameFmt, t.Name)