From 757b6eaff4a7fef65188ab138fbbf81ad8770083 Mon Sep 17 00:00:00 2001 From: rhuairahrighairigh Date: Mon, 9 Jul 2018 19:46:51 +0100 Subject: [PATCH] add basic keeper logic --- internal/x/paychan/handler.go | 1 + internal/x/paychan/keeper.go | 80 ++++++++++++++++++++++++++++------- internal/x/paychan/types.go | 1 + 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/internal/x/paychan/handler.go b/internal/x/paychan/handler.go index e25c68f9..b32556f9 100644 --- a/internal/x/paychan/handler.go +++ b/internal/x/paychan/handler.go @@ -5,6 +5,7 @@ import ( "reflect" ) +// Called when adding routes to a newly created app. // NewHandler returns a handler for "paychan" type messages. func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { diff --git a/internal/x/paychan/keeper.go b/internal/x/paychan/keeper.go index 058ec628..58209f63 100644 --- a/internal/x/paychan/keeper.go +++ b/internal/x/paychan/keeper.go @@ -1,62 +1,112 @@ package paychan +import ( + "strconv" +) + // keeper of the paychan store type Keeper struct { - storeKey sdk.StoreKey - cdc *wire.Codec // needed? + storeKey sdk.StoreKey + //cdc *wire.Codec // needed? coinKeeper bank.Keeper // codespace - codespace sdk.CodespaceType // ?? + //codespace sdk.CodespaceType // ?? } -func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { +// Called when creating new app. +//func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper { +func NewKeeper(key sdk.StoreKey, ck bank.Keeper) Keeper { keeper := Keeper{ - storeKey: key, - cdc: cdc, + storeKey: key, + //cdc: cdc, coinKeeper: ck, - codespace: codespace, + //codespace: codespace, } return keeper } // bunch of business logic ... -func (keeper Keeper) GetPaychan(paychanID) Paychan { + +// Reteive a payment channel struct from the blockchain store. +// They are indexed by a concatenation of sender address, receiver address, and an integer. +func (keeper Keeper) GetPaychan(ctx sdk.Context, sender sdk.Address, receiver sdk.Address, id integer) (Paychan, bool) { + // Return error as second argument instead of bool? + var pych Paychan // load from DB - // unmarshall + store := ctx.KVStore(k.storeKey) + bz := store.Get(paychanKey(sender, receiver, id)) + if bz == nil { + return pych, false + } + // unmarshal + k.cdc.MustUnmarshalBinary(bz, &pych) // return + return pych, true } +// Store payment channel struct in blockchain store. func (keeper Keeper) setPaychan(pych Paychan) sdk.Error { + store := ctx.KVStore(k.storeKey) // marshal + bz := k.cdc.MustMarshalBinary(pych) // write to db + pychKey := paychanKey(pych.sender, pych.receiver, pych.id) + store.Set(pychKey, bz) + // TODO handler errors } -func (keeer Keeper) CreatePaychan(receiver sdkAddress, amt sdk.Coins) (Paychan, sdk.Error) { +// Create a new payment channel and lock up sender funds. +func (keeer Keeper) CreatePaychan(sender sdk.Address, receiver sdkAddress, id integer, amt sdk.Coins) (Paychan, sdk.Error) { // subtract coins from sender + k.coinKeeper.SubtractCoins(ctx, sender, amt) // create new Paychan struct (create ID) + pych := Paychan{sender, + receiver, + id, + balance: amt} // save to db + err := k.setPaychan(pych) - // validation: - // sender has enough coins + return pych, err + + // TODO validation + // sender has enough coins - done in Subtract method // receiver address exists? // paychan doesn't exist already } -func (keeper Keeper) ClosePaychan() sdk.Error { +// 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.Error { + pych := GetPaychan(ctx, sender, receiver, id) + // compute coin distribution + senderAmt = pych.balance.Minus(receiverAmt) // Minus sdk.Coins method // add coins to sender + k.coinKeeper.AddCoins(ctx, sender, senderAmt) // add coins to receiver + k.coinKeeper.AddCoins(ctx, receiver, receiverAmt) // delete paychan from db + pychKey := paychanKey(pych.sender, pych.receiver, pych.id) + store.Delete(pychKey) - // validation: + + // TODO validation // paychan exists // output coins are less than paychan balance // sender and receiver addresses exist? + + return nil } -func paychanKey(Paychan) { +// Creates a key to reference a paychan in the blockchain store. +func paychanKey(sender sdk.Address, receiver sdk.Address, id integer) []byte { + + //sdk.Address is just a slice of bytes under a different name + //convert id to string then to byte slice + idAsBytes := []byte(strconv.Itoa(id)) // concat sender and receiver and integer ID + return append(sender.Bytes(), receiver.Bytes()..., idAsBytes...) } // maybe getAllPaychans(sender sdk.address) []Paychan diff --git a/internal/x/paychan/types.go b/internal/x/paychan/types.go index aec54ebc..a710c554 100644 --- a/internal/x/paychan/types.go +++ b/internal/x/paychan/types.go @@ -11,6 +11,7 @@ struct Paychan { balance sdk.Coins sender sdk.Address receiver sdk.Address + id integer }