mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 09:57:27 +00:00 
			
		
		
		
	add error handling and fix compile errors
This commit is contained in:
		
							parent
							
								
									a4baa34ee0
								
							
						
					
					
						commit
						c268088260
					
				@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
				
			|||||||
@ -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}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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?
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user