add validation

This commit is contained in:
rhuairahrighairigh 2018-07-12 14:32:36 +01:00
parent af4c28e1b7
commit fbffc2d008
2 changed files with 115 additions and 47 deletions

View File

@ -58,60 +58,108 @@ func (keeper Keeper) setPaychan(pych Paychan) sdk.Error {
bz := k.cdc.MustMarshalBinary(pych) bz := k.cdc.MustMarshalBinary(pych)
// write to db // write to db
pychKey := paychanKey(pych.sender, pych.receiver, pych.id) pychKey := paychanKey(pych.sender, pych.receiver, pych.id)
store.Set(pychKey, bz) store.Set(pychKey, bz) // panics if something goes wrong
// TODO handler errors
} }
// Create a new payment channel and lock up sender funds. // Create a new payment channel and lock up sender funds.
func (keeer Keeper) CreatePaychan(sender sdk.Address, receiver sdkAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) { func (keeer Keeper) CreatePaychan(ctx sdk.Context, sender sdk.Address, receiver sdkAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) {
// TODO move validation somewhere nicer
// args present
if len(sender) == 0 {
return sdk.ErrInvalidAddress(sender.String())
}
if len(receiver) == 0 {
return sdk.ErrInvalidAddress(receiver.String())
}
if len(amount) == 0 {
return sdk.ErrInvalidCoins(amount.String())
}
// Check if coins are sorted, non zero, positive
if !amount.IsValid() {
return sdk.ErrInvalidCoins(amount.String())
}
if !amount.IsPositive() {
return sdk.ErrInvalidCoins(amount.String())
}
// sender should exist already as they had to sign.
// receiver address exists. am is the account mapper in the coin keeper.
// TODO automatically create account if not present?
if k.coinKepper.am.GetAccount(ctx, receiver) == nil {
return sdk.ErrUnknownAddress(receiver.String())
}
// sender has enough coins - done in Subtract method
// TODO check if sender and receiver different?
// Calculate next id (num existing paychans plus 1) // Calculate next id (num existing paychans plus 1)
id := len(keeper.GetPaychans(sender, receiver)) + 1 // TODO check for overflow? id := len(keeper.GetPaychans(sender, receiver)) + 1 // TODO check for overflow?
// subtract coins from sender // subtract coins from sender
k.coinKeeper.SubtractCoins(ctx, sender, amt) coins, tags, err := k.coinKeeper.SubtractCoins(ctx, sender, amt)
// create new Paychan struct (create ID) if err != nil {
return nil, err
}
// create new Paychan struct
pych := Paychan{sender, pych := Paychan{sender,
receiver, receiver,
id, id,
balance: amt} balance: amt}
// save to db // save to db
err := k.setPaychan(pych) k.setPaychan(pych)
// TODO validation
// coins valid and positive
// sender has enough coins - done in Subtract method
// receiver address exists?
// paychan doesn't exist already
// sender and receiver different?
// TODO create tags
tags := sdk.NewTags() tags := sdk.NewTags()
return tags, err return tags, err
} }
// Close a payment channel and distribute funds to participants. // Close a payment channel and distribute funds to participants.
func (keeper Keeper) ClosePaychan(sender sdk.Address, receiver sdk.Address, id integer, receiverAmt sdk.Coins) (sdk.Tags, sdk.Error) { func (keeper Keeper) ClosePaychan(sender sdk.Address, receiver sdk.Address, id integer, receiverAmt sdk.Coins) (sdk.Tags, sdk.Error) {
pych := GetPaychan(ctx, sender, receiver, id) if len(msg.sender) == 0 {
return sdk.ErrInvalidAddress(msg.sender.String())
}
if len(msg.receiver) == 0 {
return sdk.ErrInvalidAddress(msg.receiver.String())
}
if len(msg.receiverAmount) == 0 {
return sdk.ErrInvalidCoins(msg.receiverAmount.String())
}
// check id ≥ 0
if msg.id < 0 {
return sdk.ErrInvalidAddress(strconv.Itoa(id)) // TODO implement custom errors
}
// Check if coins are sorted, non zero, non negative
if !msg.receiverAmount.IsValid() {
return sdk.ErrInvalidCoins(msg.receiverAmount.String())
}
if !msg.receiverAmount.IsPositive() {
return sdk.ErrInvalidCoins(msg.receiverAmount.String())
}
store := ctx.KVStore(k.storeKey)
pych, exists := GetPaychan(ctx, sender, receiver, id)
if !exists {
return nil, sdk.ErrUnknownAddress() // TODO implement custom errors
}
// compute coin distribution // compute coin distribution
senderAmt = pych.balance.Minus(receiverAmt) // Minus sdk.Coins method senderAmt = pych.balance.Minus(receiverAmt) // Minus sdk.Coins method
// check that receiverAmt not greater than paychan balance
if !senderAmt.IsNotNegative() {
return nil, sdk.ErrInsufficientFunds(pych.balance.String())
}
// add coins to sender // add coins to sender
// creating account if it doesn't exist
k.coinKeeper.AddCoins(ctx, sender, senderAmt) k.coinKeeper.AddCoins(ctx, sender, senderAmt)
// add coins to receiver // add coins to receiver
k.coinKeeper.AddCoins(ctx, receiver, receiverAmt) k.coinKeeper.AddCoins(ctx, receiver, receiverAmt)
// delete paychan from db // delete paychan from db
pychKey := paychanKey(pych.sender, pych.receiver, pych.id) pychKey := paychanKey(pych.sender, pych.receiver, pych.id)
store.Delete(pychKey) store.Delete(pychKey)
// TODO create tags
// TODO validation
// id ≥ 0
// coins valid and positive
// paychan exists
// output coins are equal to paychan balance
// sender and receiver addresses exist?
// overflow in sender and receiver balances?
//sdk.NewTags( //sdk.NewTags(
// "action", []byte("channel closure"), // "action", []byte("channel closure"),
// "receiver", receiver.Bytes(), // "receiver", receiver.Bytes(),

View File

@ -1,6 +1,7 @@
package paychan package paychan
import ( import (
"strconv"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
) )
@ -78,24 +79,27 @@ func (msg MsgCreate) GetSignBytes() []byte {
} }
func (msg MsgCreate) ValidateBasic() sdk.Error { func (msg MsgCreate) ValidateBasic() sdk.Error {
// TODO implement
// Validate msg as an optimisation to avoid all validation going to keeper. It's run before the sigs are checked by the auth module. // Validate msg as an optimisation to avoid all validation going to keeper. It's run before the sigs are checked by the auth module.
// Validate without external information (such as account balance) // Validate without external information (such as account balance)
// check if all fields present / not 0 valued // check if all fields present / not 0 valued
// do coin checks for amount if len(msg.sender) == 0 {
// check if Address valid? return sdk.ErrInvalidAddress(msg.sender.String())
}
// example from bank if len(msg.receiver) == 0 {
// if len(in.Address) == 0 { return sdk.ErrInvalidAddress(msg.receiver.String())
// return sdk.ErrInvalidAddress(in.Address.String()) }
// } if len(msg.amount) == 0 {
// if !in.Coins.IsValid() { return sdk.ErrInvalidCoins(msg.amount.String())
// return sdk.ErrInvalidCoins(in.Coins.String()) }
// } // Check if coins are sorted, non zero, non negative
// if !in.Coins.IsPositive() { if !msg.amount.IsValid() {
// return sdk.ErrInvalidCoins(in.Coins.String()) return sdk.ErrInvalidCoins(msg.amount.String())
// } }
if !msg.amount.IsPositive() {
return sdk.ErrInvalidCoins(msg.amount.String())
}
// TODO check if Address valid?
} }
func (msg MsgCreate) GetSigners() []sdk.Address { func (msg MsgCreate) GetSigners() []sdk.Address {
@ -147,12 +151,28 @@ func (msg MsgClose) GetSignBytes() []byte {
} }
func (msg MsgClose) ValidateBasic() sdk.Error { func (msg MsgClose) ValidateBasic() sdk.Error {
// TODO implement
// check if all fields present / not 0 valued // check if all fields present / not 0 valued
if len(msg.sender) == 0 {
return sdk.ErrInvalidAddress(msg.sender.String())
}
if len(msg.receiver) == 0 {
return sdk.ErrInvalidAddress(msg.receiver.String())
}
if len(msg.receiverAmount) == 0 {
return sdk.ErrInvalidCoins(msg.receiverAmount.String())
}
// check id ≥ 0 // check id ≥ 0
// do coin checks for amount if msg.id < 0 {
// check if Address valid? return sdk.ErrInvalidAddress(strconv.Itoa(id)) // TODO implement custom errors
}
// Check if coins are sorted, non zero, non negative
if !msg.receiverAmount.IsValid() {
return sdk.ErrInvalidCoins(msg.receiverAmount.String())
}
if !msg.receiverAmount.IsPositive() {
return sdk.ErrInvalidCoins(msg.receiverAmount.String())
}
// TODO check if Address valid?
} }
func (msg MsgClose) GetSigners() []sdk.Address { func (msg MsgClose) GetSigners() []sdk.Address {