add error handling and fix compile errors

This commit is contained in:
rhuairahrighairigh 2018-08-27 23:48:48 -04:00
parent a4baa34ee0
commit c268088260
7 changed files with 200 additions and 149 deletions

View File

@ -7,7 +7,10 @@ Simplifications:
TODO TODO
- error handling (getter setter return values? and what happens in failures)
- chnge module name to "channel"? - chnge module name to "channel"?
- Find a better name for Queue - clarify distinction between int slice and abstract queue concept - Find a better name for Queue - clarify distinction between int slice and abstract queue concept
- Do all the small functions need to be methods on the keeper or can they just be floating around? - Do all the small functions need to be methods on the keeper or can they just be floating around?
- Tidy up - standardise var names, comments and method descriptions
- is having all the get functions return a bool if not found reasonable?
- any problem in signing your own address?
- Gas

View File

@ -1,22 +1,36 @@
package paychan package paychan
import () import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
func EndBlocker(ctx sdk.Context, k Keeper) sdk.Tags { func EndBlocker(ctx sdk.Context, k Keeper) sdk.Tags {
var err sdk.Error
var channelTags sdk.Tags
tags := sdk.EmptyTags()
// Iterate through submittedUpdatesQueue // Iterate through submittedUpdatesQueue
// TODO optimise so it doesn't pull every update from DB every block // TODO optimise so it doesn't pull every update from DB every block
var sUpdate SubmittedUpdate var sUpdate SubmittedUpdate
q := k.getSubmittedUpdatesQueue(ctx) q, found := k.getSubmittedUpdatesQueue(ctx)
if !found {
panic("SubmittedUpdatesQueue not found.")
}
for _, id := range q { for _, id := range q {
// close the channel if the update has reached its execution time. // close the channel if the update has reached its execution time.
// Using >= in case some are somehow missed. // Using >= in case some are somehow missed.
sUpdate = k.getSubmittedUpdate(ctx, id) sUpdate, found = k.getSubmittedUpdate(ctx, id)
if !found {
panic("can't find element in queue that should exist")
}
if ctx.BlockHeight() >= sUpdate.ExecutionTime { if ctx.BlockHeight() >= sUpdate.ExecutionTime {
k.closeChannel(ctx, sUpdate.Update) channelTags, err = k.closeChannel(ctx, sUpdate.Update)
if err != nil {
panic(err)
}
tags.AppendTags(channelTags)
} }
} }
tags := sdk.NewTags()
return tags return tags
} }

View File

@ -37,15 +37,19 @@ func handleMsgCreate(ctx sdk.Context, k Keeper, msg MsgCreate) sdk.Result {
// Handle MsgSubmitUpdate // Handle MsgSubmitUpdate
// Leaves validation to the keeper methods. // Leaves validation to the keeper methods.
func handleMsgSubmitUpdate(ctx sdk.Context, k Keeper, msg MsgSubmitUpdate) sdk.Result { func handleMsgSubmitUpdate(ctx sdk.Context, k Keeper, msg MsgSubmitUpdate) sdk.Result {
var err sdk.Error
tags := sdk.EmptyTags()
participants := k.getChannel(ctx, msg.Update.ChannelID).Participants // TODO refactor signer detection - move to keeper or find nicer setup
channel, _ := k.getChannel(ctx, msg.Update.ChannelID)
participants := channel.Participants
// if only sender signed // if only sender signed
if msg.submitter == participants[0] { if reflect.DeepEqual(msg.submitter, participants[0]) {
tags, err := k.InitCloseChannelBySender() tags, err = k.InitCloseChannelBySender(ctx, msg.Update)
// else if receiver signed // else if receiver signed
} else if msg.submitter == participants[len(participants)-1] { } else if reflect.DeepEqual(msg.submitter, participants[len(participants)-1]) {
tags, err := k.CloseChannelByReceiver() tags, err = k.CloseChannelByReceiver(ctx, msg.Update)
} }
if err != nil { if err != nil {

View File

@ -1,8 +1,7 @@
package paychan package paychan
import ( import (
"strconv" "fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank"
@ -33,9 +32,8 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper) Keeper {
// ============================================== Main Business Logic // ============================================== Main Business Logic
// Create a new payment channel and lock up sender funds. // Create a new payment channel and lock up sender funds.
func (k Keeper) CreateChannel(ctx sdk.Context, sender sdk.Address, receiver sdk.Address, coins sdk.Coins) (sdk.Tags, sdk.Error) { func (k Keeper) CreateChannel(ctx sdk.Context, sender sdk.AccAddress, receiver sdk.AccAddress, coins sdk.Coins) (sdk.Tags, sdk.Error) {
// TODO do validation and maybe move somewhere nicer // TODO do validation and maybe move somewhere nicer
/* /*
// args present // args present
@ -67,18 +65,18 @@ func (k Keeper) CreateChannel(ctx sdk.Context, sender sdk.Address, receiver sdk.
// TODO check if sender and receiver different? // TODO check if sender and receiver different?
*/ */
// Calculate next id
id := k.getNewChannelID(ctx)
// subtract coins from sender // subtract coins from sender
_, tags, err := k.coinKeeper.SubtractCoins(ctx, sender, coins) _, tags, err := k.coinKeeper.SubtractCoins(ctx, sender, coins)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Calculate next id
id := k.getNewChannelID(ctx)
// create new Paychan struct // create new Paychan struct
channel := Channel{ channel := Channel{
ID: id ID: id,
Participants: [2]sdk.AccAddress{sender, receiver}, Participants: [2]sdk.AccAddress{sender, receiver},
Coins: coins, Coins: coins,
} }
// save to db // save to db
k.setChannel(ctx, channel) k.setChannel(ctx, channel)
@ -88,51 +86,64 @@ func (k Keeper) CreateChannel(ctx sdk.Context, sender sdk.Address, receiver sdk.
return tags, err return tags, err
} }
func (k Keeper) InitCloseChannelBySender(ctx sdk.Context, update Update) (sdk.Tags, sdk.Error) {
func (k Keeper) InitCloseChannelBySender(update Update) {
// This is roughly the default path for non unidirectional channels // This is roughly the default path for non unidirectional channels
// TODO Validate update - e.g. check signed by sender // TODO Validate update - e.g. check signed by sender
q := k.getSubmittedUpdateQueue(ctx) q, found := k.getSubmittedUpdatesQueue(ctx)
if !found {
panic("SubmittedUpdatesQueue not found.") // TODO nicer custom errors
}
if q.Contains(update.ChannelID) { if q.Contains(update.ChannelID) {
// Someone has previously tried to update channel // Someone has previously tried to update channel
existingSUpdate := k.getSubmittedUpdate(ctx, update.ChannelID) existingSUpdate, found := k.getSubmittedUpdate(ctx, update.ChannelID)
k.addToSubmittedUpdateQueue(ctx, k.applyNewUpdate(existingSUpdate, update)) if !found {
} else { panic("can't find element in queue that should exist")
// No one has tried to update channel.
submittedUpdate := SubmittedUpdate{
Update: update
executionTime: ctx.BlockHeight()+ChannelDisputeTime //TODO check what exactly BlockHeight refers to
} }
k.addToSubmittedUpdateQueue(ctx, submittedUpdate) k.addToSubmittedUpdatesQueue(ctx, k.applyNewUpdate(existingSUpdate, update))
} else {
// No one has tried to update channel
submittedUpdate := SubmittedUpdate{
Update: update,
ExecutionTime: ctx.BlockHeight() + ChannelDisputeTime, //TODO check what exactly BlockHeight refers to
}
k.addToSubmittedUpdatesQueue(ctx, submittedUpdate)
} }
tags := sdk.EmptyTags() // TODO tags
return tags, nil
} }
func (k Keeper) CloseChannelByReceiver(update Update) () { func (k Keeper) CloseChannelByReceiver(ctx sdk.Context, update Update) (sdk.Tags, sdk.Error) {
// TODO Validate update // TODO Validate update
// Check if there is an update in the queue already // Check if there is an update in the queue already
q := k.getSubmittedUpdateQueue(ctx) q, found := k.getSubmittedUpdatesQueue(ctx)
if !found {
panic("SubmittedUpdatesQueue not found.") // TODO nicer custom errors
}
if q.Contains(update.ChannelID) { if q.Contains(update.ChannelID) {
// Someone has previously tried to update channel but receiver has final say // Someone has previously tried to update channel but receiver has final say
k.removeFromSubmittedUpdateQueue(ctx, update.ChannelID) k.removeFromSubmittedUpdatesQueue(ctx, update.ChannelID)
} }
k.closeChannel(ctx, update) tags, err := k.closeChannel(ctx, update)
return tags, err
} }
// Main function that compare updates against each other. // Main function that compare updates against each other.
// Pure function // Pure function
func (k Keeper) applyNewUpdate(existingSUpdate, proposedUpdate) SubmittedUpdate { func (k Keeper) applyNewUpdate(existingSUpdate SubmittedUpdate, proposedUpdate Update) SubmittedUpdate {
var returnUpdate SubmittedUpdate var returnUpdate SubmittedUpdate
if existingSUpdate.sequence > proposedUpdate.sequence { if existingSUpdate.Sequence > proposedUpdate.Sequence {
// update accepted // update accepted
returnUpdate = SubmittedUpdate{ returnUpdate = SubmittedUpdate{
Update: proposedUpdate Update: proposedUpdate,
ExecutionTime: existingSUpdate.ExecutionTime ExecutionTime: existingSUpdate.ExecutionTime,
} }
} else { } else {
// update rejected // update rejected
@ -141,62 +152,79 @@ func (k Keeper) applyNewUpdate(existingSUpdate, proposedUpdate) SubmittedUpdate
return returnUpdate return returnUpdate
} }
func (k Keeper) closeChannel(ctx sdk.Context, update Update) { // unsafe close channel - doesn't check if update matches existing channel TODO make safer?
channel := k.getChannel(ctx, update.ChannelID) func (k Keeper) closeChannel(ctx sdk.Context, update Update) (sdk.Tags, sdk.Error) {
var err error
var sdkErr sdk.Error
var tags sdk.Tags
// Add coins to sender and receiver // Add coins to sender and receiver
for address, coins := range update.CoinsUpdate { // TODO check for possible errors first to avoid coins being half paid out?
var address sdk.AccAddress
for bech32Address, coins := range update.CoinsUpdate {
address, err = sdk.AccAddressFromBech32(bech32Address)
if err != nil {
panic(err)
}
// TODO check somewhere if coins are not negative? // TODO check somewhere if coins are not negative?
k.ck.AddCoins(ctx, address, coins) _, tags, sdkErr = k.coinKeeper.AddCoins(ctx, address, coins)
if sdkErr != nil {
panic(sdkErr)
}
} }
k.deleteChannel(ctx, update.ChannelID) k.deleteChannel(ctx, update.ChannelID)
return tags, nil
} }
// =========================================== QUEUE // =========================================== QUEUE
func (k Keeper) addToSubmittedUpdatesQueue(ctx sdk.Context, sUpdate SubmittedUpdate) { func (k Keeper) addToSubmittedUpdatesQueue(ctx sdk.Context, sUpdate SubmittedUpdate) {
// always overwrite prexisting values - leave paychan logic to higher levels // always overwrite prexisting values - leave paychan logic to higher levels
// get current queue // get current queue
q := k.getSubmittedUpdateQueue(ctx) q, found := k.getSubmittedUpdatesQueue(ctx)
if !found {
panic("SubmittedUpdatesQueue not found.")
}
// append ID to queue // append ID to queue
if q.Contains(sUpdate.ChannelID)! { if !q.Contains(sUpdate.ChannelID) {
q = append(q, sUpdate.ChannelID) q = append(q, sUpdate.ChannelID)
} }
// set queue // set queue
k.setSubmittedUpdateQueue(ctx, q) k.setSubmittedUpdatesQueue(ctx, q)
// store submittedUpdate // store submittedUpdate
k.setSubmittedUpdate(ctx, sUpdate) k.setSubmittedUpdate(ctx, sUpdate)
} }
func (k Keeper) removeFromSubmittdUpdatesQueue(ctx sdk.Context, channelID) { func (k Keeper) removeFromSubmittedUpdatesQueue(ctx sdk.Context, channelID ChannelID) {
// get current queue // get current queue
q := k.getSubmittedUpdateQueue(ctx) q, found := k.getSubmittedUpdatesQueue(ctx)
if !found {
panic("SubmittedUpdatesQueue not found.")
}
// remove id // remove id
q.RemoveMatchingElements(channelID) q.RemoveMatchingElements(channelID)
// set queue // set queue
k.setSubmittedUpdateQueue(ctx, q) k.setSubmittedUpdatesQueue(ctx, q)
// delete submittedUpdate // delete submittedUpdate
k.deleteSubmittedUpdate(ctx, channelID) k.deleteSubmittedUpdate(ctx, channelID)
} }
func (k Keeper) getSubmittedUpdatesQueue(ctx sdk.Context) (Queue, bool) { func (k Keeper) getSubmittedUpdatesQueue(ctx sdk.Context) (SubmittedUpdatesQueue, bool) {
// load from DB // load from DB
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(k.getSubmittedUpdatesQueueKey()) bz := store.Get(k.getSubmittedUpdatesQueueKey())
var q Queue var suq SubmittedUpdatesQueue
if bz == nil { if bz == nil {
return q, false return suq, false // TODO maybe create custom error to pass up here
} }
// unmarshal // unmarshal
k.cdc.MustUnmarshalBinary(bz, &q) k.cdc.MustUnmarshalBinary(bz, &suq)
// return // return
return q, true return suq, true
} }
func (k Keeper) setSubmittedUpdatesQueue(ctx sdk.Context, q Queue) { func (k Keeper) setSubmittedUpdatesQueue(ctx sdk.Context, q SubmittedUpdatesQueue) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
// marshal // marshal
bz := k.cdc.MustMarshalBinary(q) bz := k.cdc.MustMarshalBinary(q)
@ -213,7 +241,7 @@ func (k Keeper) getSubmittedUpdatesQueueKey() []byte {
// This section deals with only setting and getting // This section deals with only setting and getting
func (k Keeper) getSubmittedUpdate(ctx sdk.Context, channelID ChannelID) (SubmittedUpdate, bool) { func (k Keeper) getSubmittedUpdate(ctx sdk.Context, channelID ChannelID) (SubmittedUpdate, bool) {
// load from DB // load from DB
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(k.getSubmittedUpdateKey(channelID)) bz := store.Get(k.getSubmittedUpdateKey(channelID))
@ -234,11 +262,11 @@ func (k Keeper) setSubmittedUpdate(ctx sdk.Context, sUpdate SubmittedUpdate) {
// marshal // marshal
bz := k.cdc.MustMarshalBinary(sUpdate) // panics if something goes wrong bz := k.cdc.MustMarshalBinary(sUpdate) // panics if something goes wrong
// write to db // write to db
key := k.getSubmittedUpdateKey(sUpdate.channelID) key := k.getSubmittedUpdateKey(sUpdate.ChannelID)
store.Set(key, bz) // panics if something goes wrong store.Set(key, bz) // panics if something goes wrong
} }
func (k Keeper) deleteSubmittedUpdate(ctx sdk.Context, channelID ) { func (k Keeper) deleteSubmittedUpdate(ctx sdk.Context, channelID ChannelID) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
store.Delete(k.getSubmittedUpdateKey(channelID)) store.Delete(k.getSubmittedUpdateKey(channelID))
// TODO does this have return values? What happens when key doesn't exist? // TODO does this have return values? What happens when key doesn't exist?
@ -247,12 +275,10 @@ func (k Keeper) getSubmittedUpdateKey(channelID ChannelID) []byte {
return []byte(fmt.Sprintf("submittedUpdate:%d", channelID)) return []byte(fmt.Sprintf("submittedUpdate:%d", channelID))
} }
// ========================================== CHANNELS // ========================================== CHANNELS
// Reteive a payment channel struct from the blockchain store. // Reteive a payment channel struct from the blockchain store.
func (k Keeper) getChannel(ctx sdk.Context, channelID ChannelID) (Channel, bool) { func (k Keeper) getChannel(ctx sdk.Context, channelID ChannelID) (Channel, bool) {
// load from DB // load from DB
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(k.getChannelKey(channelID)) bz := store.Get(k.getChannelKey(channelID))
@ -273,27 +299,28 @@ func (k Keeper) setChannel(ctx sdk.Context, channel Channel) {
// marshal // marshal
bz := k.cdc.MustMarshalBinary(channel) // panics if something goes wrong bz := k.cdc.MustMarshalBinary(channel) // panics if something goes wrong
// write to db // write to db
key := sdk.getChannelKey(channel.ID) key := k.getChannelKey(channel.ID)
store.Set(key, bz) // panics if something goes wrong store.Set(key, bz) // panics if something goes wrong
} }
func (k Keeper) deleteChannel(ctx sdk.Context, channelID ) { func (k Keeper) deleteChannel(ctx sdk.Context, channelID ChannelID) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
store.Delete(k.getChannelKey(channelID)) store.Delete(k.getChannelKey(channelID))
// TODO does this have return values? What happens when key doesn't exist? // TODO does this have return values? What happens when key doesn't exist?
} }
func (k Keeper) getNewChannelID(ctx sdk.Context) (int64, error) { func (k Keeper) getNewChannelID(ctx sdk.Context) ChannelID {
// get last channel ID // get last channel ID
store := k.KVStore(k.storeKey) var lastID ChannelID
store := ctx.KVStore(k.storeKey)
bz := store.Get(k.getLastChannelIDKey()) bz := store.Get(k.getLastChannelIDKey())
if bz == nil { if bz == nil {
return nil, // TODO throw some error (assumes this has been initialized elsewhere) or just set to zero here lastID = -1 // TODO is just setting to zero if uninitialized ok?
} else {
k.cdc.MustUnmarshalBinary(bz, &lastID)
} }
var lastID ChannelID
k.cdc.MustUnmarshalBinary(bz, &lastID)
// increment to create new one // increment to create new one
newID := lastID+1 newID := lastID + 1
bz = k.cdc.MustMarshalBinary(newID) bz = k.cdc.MustMarshalBinary(newID)
// set last channel id again // set last channel id again
store.Set(k.getLastChannelIDKey(), bz) store.Set(k.getLastChannelIDKey(), bz)
@ -302,11 +329,12 @@ func (k Keeper) getNewChannelID(ctx sdk.Context) (int64, error) {
} }
func (k Keeper) getChannelKey(channelID ChannelID) []byte { func (k Keeper) getChannelKey(channelID ChannelID) []byte {
return []bytes(fmt.Sprintf("channel:%d", channelID)) return []byte(fmt.Sprintf("channel:%d", channelID))
} }
func (k Keeper) getLastChannelIDKey() []byte { func (k Keeper) getLastChannelIDKey() []byte {
return []bytes("lastChannelID") return []byte("lastChannelID")
} }
/* /*
// Close a payment channel and distribute funds to participants. // Close a payment channel and distribute funds to participants.
func (k Keeper) ClosePaychan(ctx sdk.Context, sender sdk.Address, receiver sdk.Address, id int64, receiverAmount sdk.Coins) (sdk.Tags, sdk.Error) { func (k Keeper) ClosePaychan(ctx sdk.Context, sender sdk.Address, receiver sdk.Address, id int64, receiverAmount sdk.Coins) (sdk.Tags, sdk.Error) {

View File

@ -1,5 +1,6 @@
package paychan package paychan
/*
import ( import (
"testing" "testing"
//"github.com/stretchr/testify/assert" //"github.com/stretchr/testify/assert"
@ -139,3 +140,4 @@ func TestKeeper(t *testing.T) {
} }
} }
*/

View File

@ -2,7 +2,7 @@ package paychan
import ( import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"strconv" "github.com/tendermint/tendermint/crypto"
) )
/* CHANNEL TYPES */ /* CHANNEL TYPES */
@ -11,32 +11,35 @@ import (
// Participants is limited to two as currently these are unidirectional channels. // Participants is limited to two as currently these are unidirectional channels.
// Last participant is designated as receiver. // Last participant is designated as receiver.
type Channel struct { type Channel struct {
ID ChannelID ID ChannelID
Participants [2]sdk.AccAddress Participants [2]sdk.AccAddress // [senderAddr, receiverAddr]
Coins sdk.Coins Coins sdk.Coins
} }
type ChannelID int64 // TODO should this be positive only type ChannelID int64 // TODO should this be positive only
// The data that is passed between participants as payments, and submitted to the blockchain to close a channel. // The data that is passed between participants as payments, and submitted to the blockchain to close a channel.
type Update struct { type Update struct {
ChannelID int64 ChannelID ChannelID
CoinsUpdate map[sdk.AccAddress]sdk.Coins CoinsUpdate map[string]sdk.Coins // map of bech32 addresses to coins
Sequence int64 Sequence int64
sig // TODO type, only sender needs to sign Sigs [1]{crypto.Signature} // only sender needs to sign
} }
var ChannelDisputeTime = int64(2000) // measured in blocks TODO pick reasonable time
// An update that has been submitted to the blockchain, but not yet acted on. // An update that has been submitted to the blockchain, but not yet acted on.
type SubmittedUpdate { type SubmittedUpdate struct {
Update Update
executionTime int64 // BlockHeight ExecutionTime int64 // BlockHeight
} }
type SubmittedUpdateQueue []ChannelID type SubmittedUpdatesQueue []ChannelID
// Check if value is in queue // Check if value is in queue
func (suq SubmittedChannelID) Contains(channelID ChannelID) bool { func (suq SubmittedUpdatesQueue) Contains(channelID ChannelID) bool {
found := false found := false
for _, id := range(suq) { for _, id := range suq {
if id == channelID { if id == channelID {
found = true found = true
break break
@ -44,11 +47,12 @@ func (suq SubmittedChannelID) Contains(channelID ChannelID) bool {
} }
return found return found
} }
// Remove all values from queue that match argument
func (suq SubmittedUpdateQueue) RemoveMatchingElements(channelID ChannelID) {
newSUQ := SubmittedUpdateQueue{}
for _, id := range(suq) { // Remove all values from queue that match argument
func (suq SubmittedUpdatesQueue) RemoveMatchingElements(channelID ChannelID) {
newSUQ := SubmittedUpdatesQueue{}
for _, id := range suq {
if id != channelID { if id != channelID {
newSUQ = append(newSUQ, id) newSUQ = append(newSUQ, id)
} }
@ -56,8 +60,6 @@ func (suq SubmittedUpdateQueue) RemoveMatchingElements(channelID ChannelID) {
suq = newSUQ suq = newSUQ
} }
var ChannelDisputeTime = 2000 // measured in blocks
/* MESSAGE TYPES */ /* MESSAGE TYPES */
/* /*
Message implement the sdk.Msg interface: Message implement the sdk.Msg interface:
@ -77,14 +79,14 @@ type Msg interface {
// Signers returns the addrs of signers that must sign. // Signers returns the addrs of signers that must sign.
// CONTRACT: All signatures must be present to be valid. // CONTRACT: All signatures must be present to be valid.
// CONTRACT: Returns addrs in some deterministic order. // CONTRACT: Returns addrs in some deterministic order.
GetSigners() []Address GetSigners() []AccAddress
} }
*/ */
// A message to create a payment channel. // A message to create a payment channel.
type MsgCreate struct { type MsgCreate struct {
Participants [2]sdk.AccAddress Participants [2]sdk.AccAddress
Coins sdk.Coins Coins sdk.Coins
} }
//Create a new message. //Create a new message.
@ -103,12 +105,11 @@ func (msg CreatMsg) NewMsgCreate(sender sdk.Address, receiver sdk.Address, amoun
func (msg MsgCreate) Type() string { return "paychan" } func (msg MsgCreate) Type() string { return "paychan" }
func (msg MsgCreate) GetSignBytes() []byte { func (msg MsgCreate) GetSignBytes() []byte {
// TODO create msgCdc in wire.go bz, err := msgCdc.MarshalJSON(msg)
bz, err := msgCdc.Marshal(msg)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return MustSortJSON(bz) return sdk.MustSortJSON(bz)
} }
func (msg MsgCreate) ValidateBasic() sdk.Error { func (msg MsgCreate) ValidateBasic() sdk.Error {
@ -118,29 +119,29 @@ func (msg MsgCreate) ValidateBasic() sdk.Error {
//TODO implement //TODO implement
/* /*
// check if all fields present / not 0 valued // check if all fields present / not 0 valued
if len(msg.Sender) == 0 { if len(msg.Sender) == 0 {
return sdk.ErrInvalidAddress(msg.Sender.String()) return sdk.ErrInvalidAddress(msg.Sender.String())
} }
if len(msg.Receiver) == 0 { if len(msg.Receiver) == 0 {
return sdk.ErrInvalidAddress(msg.Receiver.String()) return sdk.ErrInvalidAddress(msg.Receiver.String())
} }
if len(msg.Amount) == 0 { if len(msg.Amount) == 0 {
return sdk.ErrInvalidCoins(msg.Amount.String()) return sdk.ErrInvalidCoins(msg.Amount.String())
} }
// Check if coins are sorted, non zero, non negative // Check if coins are sorted, non zero, non negative
if !msg.Amount.IsValid() { if !msg.Amount.IsValid() {
return sdk.ErrInvalidCoins(msg.Amount.String()) return sdk.ErrInvalidCoins(msg.Amount.String())
} }
if !msg.Amount.IsPositive() { if !msg.Amount.IsPositive() {
return sdk.ErrInvalidCoins(msg.Amount.String()) return sdk.ErrInvalidCoins(msg.Amount.String())
} }
// TODO check if Address valid? // TODO check if Address valid?
*/ */
return nil return nil
} }
func (msg MsgCreate) GetSigners() []sdk.Address { func (msg MsgCreate) GetSigners() []sdk.AccAddress {
// Only sender must sign to create a paychan // Only sender must sign to create a paychan
return []sdk.AccAddress{msg.Participants[0]} // select sender address return []sdk.AccAddress{msg.Participants[0]} // select sender address
} }
@ -160,46 +161,45 @@ type MsgSubmitUpdate struct {
func (msg MsgSubmitUpdate) Type() string { return "paychan" } func (msg MsgSubmitUpdate) Type() string { return "paychan" }
func (msg MsgSubmitUpdate) GetSignBytes() []byte { func (msg MsgSubmitUpdate) GetSignBytes() []byte {
// TODO create msgCdc in wire.go bz, err := msgCdc.MarshalJSON(msg)
bz, err := msgCdc.Marshal(msg)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return MustSortJSON(bz) return sdk.MustSortJSON(bz)
} }
func (msg MsgSubmitUpdate) ValidateBasic() sdk.Error { func (msg MsgSubmitUpdate) ValidateBasic() sdk.Error {
// TODO implement // TODO implement
/* /*
// check if all fields present / not 0 valued // check if all fields present / not 0 valued
if len(msg.Sender) == 0 { if len(msg.Sender) == 0 {
return sdk.ErrInvalidAddress(msg.Sender.String()) return sdk.ErrInvalidAddress(msg.Sender.String())
} }
if len(msg.Receiver) == 0 { if len(msg.Receiver) == 0 {
return sdk.ErrInvalidAddress(msg.Receiver.String()) return sdk.ErrInvalidAddress(msg.Receiver.String())
} }
if len(msg.ReceiverAmount) == 0 { if len(msg.ReceiverAmount) == 0 {
return sdk.ErrInvalidCoins(msg.ReceiverAmount.String()) return sdk.ErrInvalidCoins(msg.ReceiverAmount.String())
} }
// check id ≥ 0 // check id ≥ 0
if msg.Id < 0 { if msg.Id < 0 {
return sdk.ErrInvalidAddress(strconv.Itoa(int(msg.Id))) // TODO implement custom errors return sdk.ErrInvalidAddress(strconv.Itoa(int(msg.Id))) // TODO implement custom errors
} }
// Check if coins are sorted, non zero, non negative // Check if coins are sorted, non zero, non negative
if !msg.ReceiverAmount.IsValid() { if !msg.ReceiverAmount.IsValid() {
return sdk.ErrInvalidCoins(msg.ReceiverAmount.String()) return sdk.ErrInvalidCoins(msg.ReceiverAmount.String())
} }
if !msg.ReceiverAmount.IsPositive() { if !msg.ReceiverAmount.IsPositive() {
return sdk.ErrInvalidCoins(msg.ReceiverAmount.String()) return sdk.ErrInvalidCoins(msg.ReceiverAmount.String())
} }
// TODO check if Address valid? // TODO check if Address valid?
*/ */
return nil return nil
} }
func (msg MsgSubmitUpdate) GetSigners() []sdk.Address { func (msg MsgSubmitUpdate) GetSigners() []sdk.AccAddress {
// Signing not strictly necessary as signatures contained within the channel update. // Signing not strictly necessary as signatures contained within the channel update.
// TODO add signature by submitting address // TODO add signature by submitting address
return []sdk.Address{} return []sdk.AccAddress{msg.submitter}
} }

View File

@ -4,14 +4,14 @@ import (
"github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/wire"
) )
/*
func RegisterWire(cdc *wire.Codec) { func RegisterWire(cdc *wire.Codec) {
cdc.RegisterConcrete(MsgCreate{}, "paychan/MsgCreate", nil) cdc.RegisterConcrete(MsgCreate{}, "paychan/MsgCreate", nil)
cdc.RegisterConcrete(MsgClose{}, "paychan/MsgClose", nil) cdc.RegisterConcrete(MsgSubmitUpdate{}, "paychan/MsgSubmitUpdate", nil)
} }
var msgCdc = wire.NewCodec() var msgCdc = wire.NewCodec()
/*
func init() { func init() {
RegisterWire(msgCdc) RegisterWire(msgCdc)
// TODO is this needed? // TODO is this needed?