Example tag implementation for CoinKeeper

This commit is contained in:
Christopher Goes 2018-04-26 16:14:51 +02:00
parent be975fc264
commit bef7e44f6d
No known key found for this signature in database
GPG Key ID: E828D98232D328D3
12 changed files with 109 additions and 41 deletions

View File

@ -53,7 +53,7 @@ func handleMsgQuiz(ctx sdk.Context, k Keeper, msg MsgQuiz) sdk.Result {
bonusCoins := sdk.Coins{{msg.CoolAnswer, 69}}
_, err := k.ck.AddCoins(ctx, msg.Sender, bonusCoins)
_, _, err := k.ck.AddCoins(ctx, msg.Sender, bonusCoins)
if err != nil {
return err.Result()
}

View File

@ -125,7 +125,7 @@ func (k Keeper) CheckValid(ctx sdk.Context, difficulty uint64, count uint64) (ui
// Add some coins for a POW well done
func (k Keeper) ApplyValid(ctx sdk.Context, sender sdk.Address, newDifficulty uint64, newCount uint64) sdk.Error {
_, ckErr := k.ck.AddCoins(ctx, sender, []sdk.Coin{sdk.Coin{k.config.Denomination, k.config.Reward}})
_, _, ckErr := k.ck.AddCoins(ctx, sender, []sdk.Coin{sdk.Coin{k.config.Denomination, k.config.Reward}})
if ckErr != nil {
return ckErr
}

View File

@ -66,7 +66,7 @@ func (k Keeper) Bond(ctx sdk.Context, addr sdk.Address, pubKey crypto.PubKey, st
return 0, ErrIncorrectStakingToken(k.codespace)
}
_, err := k.ck.SubtractCoins(ctx, addr, []sdk.Coin{stake})
_, _, err := k.ck.SubtractCoins(ctx, addr, []sdk.Coin{stake})
if err != nil {
return 0, err
}
@ -95,7 +95,7 @@ func (k Keeper) Unbond(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, int64,
returnedBond := sdk.Coin{stakingToken, bi.Power}
_, err := k.ck.AddCoins(ctx, addr, []sdk.Coin{returnedBond})
_, _, err := k.ck.AddCoins(ctx, addr, []sdk.Coin{returnedBond})
if err != nil {
return bi.PubKey, bi.Power, err
}

View File

@ -2,7 +2,6 @@ package types
import (
abci "github.com/tendermint/abci/types"
cmn "github.com/tendermint/tmlibs/common"
)
// Result is the union of ResponseDeliverTx and ResponseCheckTx.
@ -31,7 +30,7 @@ type Result struct {
ValidatorUpdates []abci.Validator
// Tags are used for transaction indexing and pubsub.
Tags []cmn.KVPair
Tags Tags
}
// TODO: In the future, more codes may be OK.

31
types/tags.go Normal file
View File

@ -0,0 +1,31 @@
package types
import (
cmn "github.com/tendermint/tmlibs/common"
)
type Tag = cmn.KVPair
type Tags = cmn.KVPairs
// Append two lists of tags
func AppendTags(a, b Tags) Tags {
return append(a, b...)
}
// New empty tags
func EmptyTags() Tags {
return make(Tags, 0)
}
// Single tag to tags
func SingleTag(t Tag) Tags {
return append(EmptyTags(), t)
}
// Make a tag from a key and a value
func MakeTag(k string, v []byte) Tag {
return Tag{Key: []byte(k), Value: v}
}
// TODO: Deduplication?

30
types/tags_test.go Normal file
View File

@ -0,0 +1,30 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestAppendTags(t *testing.T) {
a := SingleTag(MakeTag("a", []byte("1")))
b := SingleTag(MakeTag("b", []byte("2")))
c := AppendTags(a, b)
require.Equal(t, c, Tags{MakeTag("a", []byte("1")), MakeTag("b", []byte("2"))})
}
func TestEmptyTags(t *testing.T) {
a := EmptyTags()
require.Equal(t, a, Tags{})
}
func TestSingleTag(t *testing.T) {
a := MakeTag("a", []byte("1"))
b := SingleTag(a)
require.Equal(t, b, Tags{MakeTag("a", []byte("1"))})
}
func TestMakeTag(t *testing.T) {
a := MakeTag("a", []byte("1"))
require.Equal(t, a, Tag{[]byte("a"), []byte("1")})
}

View File

@ -25,13 +25,14 @@ func NewHandler(k Keeper) sdk.Handler {
func handleMsgSend(ctx sdk.Context, k Keeper, msg MsgSend) sdk.Result {
// NOTE: totalIn == totalOut should already have been checked
err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs)
tags, err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs)
if err != nil {
return err.Result()
}
// TODO: add some tags so we can search it!
return sdk.Result{} // TODO
return sdk.Result{
Tags: tags,
}
}
// Handle MsgIssue.

View File

@ -32,22 +32,22 @@ func (keeper Keeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins)
}
// SubtractCoins subtracts amt from the coins at the addr.
func (keeper Keeper) SubtractCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func (keeper Keeper) SubtractCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
return subtractCoins(ctx, keeper.am, addr, amt)
}
// AddCoins adds amt to the coins at the addr.
func (keeper Keeper) AddCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func (keeper Keeper) AddCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
return addCoins(ctx, keeper.am, addr, amt)
}
// SendCoins moves coins from one account to another
func (keeper Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error {
func (keeper Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) (sdk.Tags, sdk.Error) {
return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt)
}
// InputOutputCoins handles a list of inputs and outputs
func (keeper Keeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) sdk.Error {
func (keeper Keeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
return inputOutputCoins(ctx, keeper.am, inputs, outputs)
}
@ -74,12 +74,12 @@ func (keeper SendKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coi
}
// SendCoins moves coins from one account to another
func (keeper SendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error {
func (keeper SendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) (sdk.Tags, sdk.Error) {
return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt)
}
// InputOutputCoins handles a list of inputs and outputs
func (keeper SendKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) sdk.Error {
func (keeper SendKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
return inputOutputCoins(ctx, keeper.am, inputs, outputs)
}
@ -131,59 +131,65 @@ func hasCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.C
}
// SubtractCoins subtracts amt from the coins at the addr.
func subtractCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func subtractCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
oldCoins := getCoins(ctx, am, addr)
newCoins := oldCoins.Minus(amt)
if !newCoins.IsNotNegative() {
return amt, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
return amt, nil, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
}
err := setCoins(ctx, am, addr, newCoins)
return newCoins, err
tags := sdk.SingleTag(sdk.MakeTag("sender", addr.Bytes()))
return newCoins, tags, err
}
// AddCoins adds amt to the coins at the addr.
func addCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func addCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
oldCoins := getCoins(ctx, am, addr)
newCoins := oldCoins.Plus(amt)
if !newCoins.IsNotNegative() {
return amt, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
return amt, nil, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
}
err := setCoins(ctx, am, addr, newCoins)
return newCoins, err
tags := sdk.SingleTag(sdk.MakeTag("recipient", addr.Bytes()))
return newCoins, tags, err
}
// SendCoins moves coins from one account to another
// NOTE: Make sure to revert state changes from tx on error
func sendCoins(ctx sdk.Context, am sdk.AccountMapper, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error {
_, err := subtractCoins(ctx, am, fromAddr, amt)
func sendCoins(ctx sdk.Context, am sdk.AccountMapper, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) (sdk.Tags, sdk.Error) {
_, subTags, err := subtractCoins(ctx, am, fromAddr, amt)
if err != nil {
return err
return nil, err
}
_, err = addCoins(ctx, am, toAddr, amt)
_, addTags, err := addCoins(ctx, am, toAddr, amt)
if err != nil {
return err
return nil, err
}
return nil
return sdk.AppendTags(subTags, addTags), nil
}
// InputOutputCoins handles a list of inputs and outputs
// NOTE: Make sure to revert state changes from tx on error
func inputOutputCoins(ctx sdk.Context, am sdk.AccountMapper, inputs []Input, outputs []Output) sdk.Error {
func inputOutputCoins(ctx sdk.Context, am sdk.AccountMapper, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
allTags := sdk.EmptyTags()
for _, in := range inputs {
_, err := subtractCoins(ctx, am, in.Address, in.Coins)
_, tags, err := subtractCoins(ctx, am, in.Address, in.Coins)
if err != nil {
return err
return nil, err
}
allTags = sdk.AppendTags(allTags, tags)
}
for _, out := range outputs {
_, err := addCoins(ctx, am, out.Address, out.Coins)
_, tags, err := addCoins(ctx, am, out.Address, out.Coins)
if err != nil {
return err
return nil, err
}
allTags = sdk.AppendTags(allTags, tags)
}
return nil
return allTags, nil
}

View File

@ -65,7 +65,7 @@ func TestKeeper(t *testing.T) {
coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{{"barcoin", 5}})
assert.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{{"barcoin", 10}, {"foocoin", 15}}))
_, err := coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{{"barcoin", 11}})
_, _, err := coinKeeper.SubtractCoins(ctx, addr, sdk.Coins{{"barcoin", 11}})
assert.Implements(t, (*sdk.Error)(nil), err)
assert.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{{"barcoin", 10}, {"foocoin", 15}}))
@ -78,7 +78,7 @@ func TestKeeper(t *testing.T) {
assert.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{{"foocoin", 10}}))
assert.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{{"foocoin", 5}}))
err2 := coinKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{{"foocoin", 50}})
_, err2 := coinKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{{"foocoin", 50}})
assert.Implements(t, (*sdk.Error)(nil), err2)
assert.True(t, coinKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{{"foocoin", 10}}))
assert.True(t, coinKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{{"foocoin", 5}}))
@ -147,7 +147,7 @@ func TestSendKeeper(t *testing.T) {
assert.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{{"foocoin", 10}}))
assert.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{{"foocoin", 5}}))
err2 := sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{{"foocoin", 50}})
_, err2 := sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{{"foocoin", 50}})
assert.Implements(t, (*sdk.Error)(nil), err2)
assert.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.Coins{{"foocoin", 10}}))
assert.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.Coins{{"foocoin", 5}}))

View File

@ -25,7 +25,7 @@ func NewHandler(ibcm Mapper, ck bank.Keeper) sdk.Handler {
func handleIBCTransferMsg(ctx sdk.Context, ibcm Mapper, ck bank.Keeper, msg IBCTransferMsg) sdk.Result {
packet := msg.IBCPacket
_, err := ck.SubtractCoins(ctx, packet.SrcAddr, packet.Coins)
_, _, err := ck.SubtractCoins(ctx, packet.SrcAddr, packet.Coins)
if err != nil {
return err.Result()
}
@ -47,7 +47,7 @@ func handleIBCReceiveMsg(ctx sdk.Context, ibcm Mapper, ck bank.Keeper, msg IBCRe
return ErrInvalidSequence(ibcm.codespace).Result()
}
_, err := ck.AddCoins(ctx, packet.DestAddr, packet.Coins)
_, _, err := ck.AddCoins(ctx, packet.DestAddr, packet.Coins)
if err != nil {
return err.Result()
}

View File

@ -34,7 +34,8 @@ func newAddress() crypto.Address {
func getCoins(ck bank.Keeper, ctx sdk.Context, addr crypto.Address) (sdk.Coins, sdk.Error) {
zero := sdk.Coins(nil)
return ck.AddCoins(ctx, addr, zero)
coins, _, err := ck.AddCoins(ctx, addr, zero)
return coins, err
}
func makeCodec() *wire.Codec {
@ -70,7 +71,7 @@ func TestIBC(t *testing.T) {
zero := sdk.Coins(nil)
mycoins := sdk.Coins{sdk.Coin{"mycoin", 10}}
coins, err := ck.AddCoins(ctx, src, mycoins)
coins, _, err := ck.AddCoins(ctx, src, mycoins)
assert.Nil(t, err)
assert.Equal(t, mycoins, coins)

View File

@ -171,7 +171,7 @@ func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address,
// Account new shares, save
pool := k.GetPool(ctx)
_, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{bondAmt})
_, _, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{bondAmt})
if err != nil {
return err
}