Merge PR #4541: Events Tracking / Tendermint v0.32.0 Update

* Update Tendermint to v0.32.0-dev0

* Initial refactor of tags

* Update event types and add unit tests

* Refactor context

* Update module manager

* Update result godoc

* Implement ToABCIEvents

* Update BaseApp

* Minor cleanup

* Fix typo

* Update x/bank message handler

* Update x/bank keeper

* Update x/bank

* Update x/bank events docs

* Update x/crisis module events

* Reset context with events on each message exec

* Update x/distribution events and docs

* Update BaseApp to not set empty events manually

* Implement simple event manager

* Update module manager

* Update modules to use event manager

* Update x/gov module to use events

* Update events docs

* Update gov queries and crisis app module

* Update bank keeper

* Add events to minting begin blocker

* Update modules to use types/events.go

* Cleanup x/mint

* Update x/staking events

* Update x/staking events

* Update events to have sender part of message.sender

* Fix build

* Fix module unit tests

* Add pending log entry

* Update deps

* Update x/crisis/types/events.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/bank/internal/types/events.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/distribution/types/events.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/mint/internal/types/events.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/slashing/types/events.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/staking/types/events.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/gov/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/gov/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/mint/abci.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/mint/abci.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/slashing/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/staking/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/slashing/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/staking/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/staking/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/staking/handler.go

Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Upgrade TM to v0.32.0-dev1

* Update events as strings

* Update Tendermint to v0.32.0-dev2

* Fix BaseApp unit tests

* Fix unit tests

* Bump tendermint version to v0.32.0

* typos
This commit is contained in:
Alexander Bezobchuk 2019-06-26 12:03:25 -04:00 committed by frog power 4000
parent 3950017bd9
commit 67f6b02118
89 changed files with 1301 additions and 967 deletions

View File

@ -0,0 +1,15 @@
#4387 Refactor the usage of tags (now called events) to reflect the
new ABCI events semantics:
- Move `x/{module}/tags/tags.go` => `x/{module}/types/events.go`
- Update `docs/specs`
- Refactor tags in favor of new `Event(s)` type(s)
- Update `Context` to use new `EventManager`
- (Begin|End)Blocker no longer return tags, but rather uses new `EventManager`
- Message handlers no longer return tags, but rather uses new `EventManager`
Any component (e.g. BeginBlocker, message handler, etc...) wishing to emit an event must do so
through `ctx.EventManger().EmitEvent(s)`.
To reset or wipe emitted events: `ctx = ctx.WithEventManager(sdk.NewEventManager())`
To get all emitted events: `events := ctx.EventManager().Events()`

View File

@ -627,14 +627,14 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
// the route match to see whether a handler exists.
//
// NOTE:CheckTx does not run the actual Msg handler function(s).
func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx) {
var result sdk.Result
tx, err := app.txDecoder(txBytes)
tx, err := app.txDecoder(req.Tx)
if err != nil {
result = err.Result()
} else {
result = app.runTx(runTxModeCheck, txBytes, tx)
result = app.runTx(runTxModeCheck, req.Tx, tx)
}
return abci.ResponseCheckTx{
@ -643,19 +643,19 @@ func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
Log: result.Log,
GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints?
Tags: result.Tags,
Events: result.Events.ToABCIEvents(),
}
}
// DeliverTx implements the ABCI interface.
func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) {
var result sdk.Result
tx, err := app.txDecoder(txBytes)
tx, err := app.txDecoder(req.Tx)
if err != nil {
result = err.Result()
} else {
result = app.runTx(runTxModeDeliver, txBytes, tx)
result = app.runTx(runTxModeDeliver, req.Tx, tx)
}
return abci.ResponseDeliverTx{
@ -665,7 +665,7 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
Log: result.Log,
GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints?
Tags: result.Tags,
Events: result.Events.ToABCIEvents(),
}
}
@ -705,11 +705,15 @@ func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Con
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) {
idxLogs := make([]sdk.ABCIMessageLog, 0, len(msgs)) // a list of JSON-encoded logs with msg index
var data []byte // NOTE: we just append them all (?!)
var tags sdk.Tags // also just append them all
var code sdk.CodeType
var codespace sdk.CodespaceType
var (
data []byte
code sdk.CodeType
codespace sdk.CodespaceType
)
events := sdk.EmptyEvents()
// NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter.
for msgIdx, msg := range msgs {
// match message route
msgRoute := msg.Route()
@ -725,12 +729,13 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
msgResult = handler(ctx, msg)
}
// NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter.
// Result.Data must be length prefixed in order to separate each result
// Each message result's Data must be length prefixed in order to separate
// each result.
data = append(data, msgResult.Data...)
tags = append(tags, sdk.MakeTag(sdk.TagAction, msg.Type()))
tags = append(tags, msgResult.Tags...)
// append events from the message's execution and a message action event
events = events.AppendEvent(sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())))
events = events.AppendEvents(msgResult.Events)
idxLog := sdk.ABCIMessageLog{MsgIndex: uint16(msgIdx), Log: msgResult.Log}
@ -755,7 +760,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
Data: data,
Log: strings.TrimSpace(string(logJSON)),
GasUsed: ctx.GasMeter().GasConsumed(),
Tags: tags,
Events: events,
}
return result

View File

@ -552,7 +552,7 @@ func TestCheckTx(t *testing.T) {
tx := newTxCounter(i, 0)
txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
r := app.CheckTx(txBytes)
r := app.CheckTx(abci.RequestCheckTx{Tx: txBytes})
assert.True(t, r.IsOK(), fmt.Sprintf("%v", r))
}
@ -607,7 +607,7 @@ func TestDeliverTx(t *testing.T) {
txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
}
@ -650,7 +650,7 @@ func TestMultiMsgDeliverTx(t *testing.T) {
tx := newTxCounter(0, 0, 1, 2)
txBytes, err := codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
store := app.deliverState.ctx.KVStore(capKey1)
@ -670,7 +670,7 @@ func TestMultiMsgDeliverTx(t *testing.T) {
tx.Msgs = append(tx.Msgs, msgCounter2{1})
txBytes, err = codec.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res = app.DeliverTx(txBytes)
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
store = app.deliverState.ctx.KVStore(capKey1)
@ -836,7 +836,7 @@ func TestRunInvalidTransaction(t *testing.T) {
txBytes, err := newCdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.EqualValues(t, sdk.CodeTxDecode, res.Code)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)
}
@ -1055,7 +1055,7 @@ func TestBaseAppAnteHandler(t *testing.T) {
tx.setFailOnAnte(true)
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
ctx := app.getState(runTxModeDeliver).ctx
@ -1070,7 +1070,7 @@ func TestBaseAppAnteHandler(t *testing.T) {
txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res = app.DeliverTx(txBytes)
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
ctx = app.getState(runTxModeDeliver).ctx
@ -1085,7 +1085,7 @@ func TestBaseAppAnteHandler(t *testing.T) {
txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res = app.DeliverTx(txBytes)
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
ctx = app.getState(runTxModeDeliver).ctx
@ -1161,7 +1161,7 @@ func TestGasConsumptionBadTx(t *testing.T) {
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
// require next tx to fail due to black gas limit
@ -1169,7 +1169,7 @@ func TestGasConsumptionBadTx(t *testing.T) {
txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res = app.DeliverTx(txBytes)
res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
}

View File

@ -0,0 +1,23 @@
# Events
The bank module emits the following events:
## Handlers
### MsgSend
| Type | Attribute Key | Attribute Value |
|----------|---------------|--------------------|
| transfer | recipient | {recipientAddress} |
| message | module | bank |
| message | action | send |
| message | sender | {senderAddress} |
### MsgMultiSend
| Type | Attribute Key | Attribute Value |
|----------|---------------|--------------------|
| transfer | recipient | {recipientAddress} |
| message | module | bank |
| message | action | multisend |
| message | sender | {senderAddress} |

View File

@ -1,23 +0,0 @@
# Tags
The bank module emits the following events/tags:
## Handlers
### MsgSend
| Key | Value |
|-------------|---------------------------|
| `action` | `send` |
| `category` | `bank` |
| `sender` | {senderAccountAddress} |
| `recipient` | {recipientAccountAddress} |
### MsgMultiSend
| Key | Value |
|-------------|---------------------------|
| `action` | `multisend` |
| `category` | `bank` |
| `sender` | {senderAccountAddress} |
| `recipient` | {recipientAccountAddress} |

View File

@ -22,6 +22,6 @@ This module will be used in the Cosmos Hub.
- [ViewKeeper](02_keepers.md#viewkeeper)
3. **[Messages](03_messages.md)**
- [MsgSend](03_messages.md#msgsend)
4. **[Tags](04_tags.md)**
- [Handlers](04_tags.md#handlers)
4. **[Events](04_events.md)**
- [Handlers](04_events.md#handlers)
5. **[Parameters](05_params.md)**

View File

@ -0,0 +1,14 @@
# Events
The crisis module emits the following events:
## Handlers
### MsgVerifyInvariance
| Type | Attribute Key | Attribute Value |
|-----------|---------------|------------------|
| invariant | route | {invariantRoute} |
| message | module | crisis |
| message | action | verify_invariant |
| message | sender | {senderAddress} |

View File

@ -1,14 +0,0 @@
# Tags
The crisis module emits the following events/tags:
## Handlers
### MsgVerifyInvariance
| Key | Value |
|-------------|--------------------|
| `action` | `verify_invariant` |
| `category` | `crisis` |
| `sender` | {message-sender} |
| `invariant` | {invariant-route} |

View File

@ -12,6 +12,6 @@ application initialization process.
- [ConstantFee](01_state.md#constantfee)
2. **[Messages](02_messages.md)**
- [MsgVerifyInvariant](02_messages.md#msgverifyinvariant)
3. **[Tags](03_tags.md)**
- [Handlers](03_tags.md#handlers)
3. **[Events](03_events.md)**
- [Handlers](03_events.md#handlers)
4. **[Parameters](04_params.md)**

View File

@ -0,0 +1,44 @@
# Events
The distribution module emits the following events:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|-----------------|---------------|--------------------|
| proposer_reward | validator | {validatorAddress} |
| proposer_reward | reward | {proposerReward} |
| commission | amount | {commissionAmount} |
| commission | validator | {validatorAddress} |
| rewards | amount | {rewardAmount} |
| rewards | validator | {validatorAddress} |
## Handlers
### MsgSetWithdrawAddress
| Type | Attribute Key | Attribute Value |
|----------------------|------------------|----------------------|
| set_withdraw_address | withdraw_address | {withdrawAddress} |
| message | module | distribution |
| message | action | set_withdraw_address |
| message | sender | {senderAddress} |
### MsgWithdrawDelegatorReward
| Type | Attribute Key | Attribute Value |
|---------|---------------|---------------------------|
| withdraw_rewards | amount | {rewardAmount} |
| withdraw_rewards | validator | {validatorAddress} |
| message | module | distribution |
| message | action | withdraw_delegator_reward |
| message | sender | {senderAddress} |
### MsgWithdrawValidatorCommission
| Type | Attribute Key | Attribute Value |
|------------|---------------|-------------------------------|
| withdraw_commission | amount | {commissionAmount} |
| message | module | distribution |
| message | action | withdraw_validator_commission |
| message | sender | {senderAddress} |

View File

@ -1,32 +0,0 @@
# Tags
The distribution module emits the following events/tags:
## Handlers
### MsgSetWithdrawAddress
| Key | Value |
|------------|---------------------------|
| `action` | `set_withdraw_address` |
| `category` | `distribution` |
| `sender` | {delegatorAccountAddress} |
### MsgWithdrawDelegatorReward
| Key | Value |
|--------------------|-----------------------------|
| `action` | `withdraw_delegator_reward` |
| `category` | `distribution` |
| `rewards` | {rewards} |
| `sender` | {delegatorAccountAddress} |
| `source-validator` | {srcOperatorAddress} |
### MsgWithdrawValidatorCommission
| Key | Value |
|--------------|---------------------------------|
| `action` | `withdraw_validator_commission` |
| `category` | `distribution` |
| `commission` | {commission} |
| `sender` | {srcOperatorAddress} |

View File

@ -90,6 +90,7 @@ to set up a script to periodically withdraw and rebond rewards.
- [Create or modify delegation distribution](05_hooks.md#create-or-modify-delegation-distribution)
- [Commission rate change](05_hooks.md#commission-rate-change)
- [Change in Validator State](05_hooks.md#change-in-validator-state)
6. **[Tags](06_tags.md)**
- [Handlers](06_tags.md#handlers)
6. **[Events](06_events.md)**
- [BeginBlocker](06_events.md#beginblocker)
- [Handlers](06_events.md#handlers)
7. **[Parameters](07_params.md)**

View File

@ -0,0 +1,51 @@
# Events
The governance module emits the following events:
## EndBlocker
| Type | Attribute Key | Attribute Value |
|-------------------|-----------------|------------------|
| inactive_proposal | proposal_id | {proposalID} |
| inactive_proposal | proposal_result | {proposalResult} |
| active_proposal | proposal_id | {proposalID} |
| active_proposal | proposal_result | {proposalResult} |
## Handlers
### MsgSubmitProposal
| Type | Attribute Key | Attribute Value |
|---------------------|---------------------|-----------------|
| submit_proposal | proposal_id | {proposalID} |
| submit_proposal [0] | voting_period_start | {proposalID} |
| proposal_deposit | amount | {depositAmount} |
| proposal_deposit | proposal_id | {proposalID} |
| message | module | governance |
| message | action | submit_proposal |
| message | sender | {senderAddress} |
* [0] Event only emitted if the voting period starts during the submission.
### MsgVote
| Type | Attribute Key | Attribute Value |
|---------------|---------------|-----------------|
| proposal_vote | option | {voteOption} |
| proposal_vote | proposal_id | {proposalID} |
| message | module | governance |
| message | action | vote |
| message | sender | {senderAddress} |
### MsgDeposit
| Type | Attribute Key | Attribute Value |
|----------------------|---------------------|-----------------|
| proposal_deposit | amount | {depositAmount} |
| proposal_deposit | proposal_id | {proposalID} |
| proposal_deposit [0] | voting_period_start | {proposalID} |
| message | module | governance |
| message | action | deposit |
| message | sender | {senderAddress} |
* [0] Event only emitted if the voting period starts during the submission.

View File

@ -1,41 +0,0 @@
# Tags
The governance module emits the following events/tags:
## EndBlocker
| Key | Value |
|-------------------|------------------------------------------------------------|
| `proposal-result` | `proposal-passed`\|`proposal-rejected`\|`proposal-dropped` |
## Handlers
### MsgSubmitProposal
| Key | Value |
|---------------------------|--------------------------|
| `action` | `submit_proposal` |
| `category` | `governance` |
| `sender` | {proposerAccountAddress} |
| `proposal-id` | {proposalID} |
| `voting-period-start` [0] | {proposalID} |
* [0] Tag only emitted if the voting period starts during the submission.
### MsgVote
| Key | Value |
|---------------|-----------------------|
| `action` | `vote` |
| `category` | `governance` |
| `sender` | {voterAccountAddress} |
| `proposal-id` | {proposalID} |
### MsgDeposit
| Key | Value |
|---------------|---------------------------|
| `action` | `deposit` |
| `category` | `governance` |
| `sender` | {depositorAccountAddress} |
| `proposal-id` | {proposalID} |

View File

@ -43,8 +43,8 @@ staking token of the chain.
- [Proposal Submission](03_messages.md#proposal-submission)
- [Deposit](03_messages.md#deposit)
- [Vote](03_messages.md#vote)
4. **[Tags](04_tags.md)**
- [EndBlocker](04_tags.md#endblocker)
- [Handlers](04_tags.md#handlers)
4. **[Events](04_events.md)**
- [EndBlocker](04_events.md#endblocker)
- [Handlers](04_events.md#handlers)
5. **[Future Improvements](05_future_improvements.md)**
6. **[Parameters](06_params.md)**

View File

@ -0,0 +1,12 @@
# Events
The minting module emits the following events:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|------|-------------------|--------------------|
| mint | bonded_ratio | {bondedRatio} |
| mint | inflation | {inflation} |
| mint | annual_provisions | {annualProvisions} |
| mint | amount | {amount} |

View File

@ -11,4 +11,6 @@
- [NextAnnualProvisions](03_begin_block.md#nextannualprovisions)
- [BlockProvision](03_begin_block.md#blockprovision)
4. **[Parameters](04_params.md)**
5. **[Events](05_events.md)**
- [BeginBlocker](05_events.md#beginblocker)

View File

@ -0,0 +1,24 @@
# Tags
The slashing module emits the following events/tags:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|-------|---------------|-----------------------------|
| slash | address | {validatorConsensusAddress} |
| slash | power | {validatorPower} |
| slash | reason | {slashReason} |
| slash | jailed [0] | {validatorConsensusAddress} |
- [0] Only included if the validator is jailed.
## Handlers
### MsgUnjail
| Type | Attribute Key | Attribute Value |
|---------|---------------|-----------------|
| message | module | slashing |
| message | action | unjail |
| message | sender | {senderAddress} |

View File

@ -1,13 +0,0 @@
# Tags
The slashing module emits the following events/tags:
## Handlers
### MsgUnjail
| Key | Value |
|------------|----------------------------|
| `action` | `unjail` |
| `category` | `slashing` |
| `sender` | {validatorOperatorAddress} |

View File

@ -29,8 +29,9 @@ This module will be used by the Cosmos Hub, the first hub in the Cosmos ecosyste
- [Uptime tracking](04_begin_block.md#uptime-tracking)
5. **[05_hooks.md](05_hooks.md)**
- [Hooks](05_hooks.md#hooks)
6. **[Tags](06_tags.md)**
- [Handlers](06_tags.md#handlers)
6. **[Events](06_events.md)**
- [BeginBlocker](06_events.md#beginblocker)
- [Handlers](06_events.md#handlers)
7. **[Staking Tombstone](07_tombstone.md)**
- [Abstract](07_tombstone.md#abstract)
8. **[Parameters](08_params.md)**

View File

@ -0,0 +1,72 @@
# Events
The staking module emits the following events:
## EndBlocker
| Type | Attribute Key | Attribute Value |
|-----------------------|-----------------------|-----------------------|
| complete_unbonding | validator | {validatorAddress} |
| complete_unbonding | delegator | {delegatorAddress} |
| complete_redelegation | source_validator | {srcValidatorAddress} |
| complete_redelegation | destination_validator | {dstValidatorAddress} |
| complete_redelegation | delegator | {delegatorAddress} |
## Handlers
### MsgCreateValidator
| Type | Attribute Key | Attribute Value |
|------------------|---------------|--------------------|
| create_validator | validator | {validatorAddress} |
| create_validator | amount | {delegationAmount} |
| message | module | staking |
| message | action | create_validator |
| message | sender | {senderAddress} |
### MsgEditValidator
| Type | Attribute Key | Attribute Value |
|----------------|---------------------|---------------------|
| edit_validator | commission_rate | {commissionRate} |
| edit_validator | min_self_delegation | {minSelfDelegation} |
| message | module | staking |
| message | action | edit_validator |
| message | sender | {senderAddress} |
### MsgDelegate
| Type | Attribute Key | Attribute Value |
|----------|---------------|--------------------|
| delegate | validator | {validatorAddress} |
| delegate | amount | {delegationAmount} |
| message | module | staking |
| message | action | delegate |
| message | sender | {senderAddress} |
### MsgUndelegate
| Type | Attribute Key | Attribute Value |
|---------|---------------------|--------------------|
| unbond | validator | {validatorAddress} |
| unbond | amount | {unbondAmount} |
| unbond | completion_time [0] | {completionTime} |
| message | module | staking |
| message | action | begin_unbonding |
| message | sender | {senderAddress} |
* [0] Time is formatted in the RFC3339 standard
### MsgBeginRedelegate
| Type | Attribute Key | Attribute Value |
|------------|-----------------------|-----------------------|
| redelegate | source_validator | {srcValidatorAddress} |
| redelegate | destination_validator | {dstValidatorAddress} |
| redelegate | amount | {unbondAmount} |
| redelegate | completion_time [0] | {completionTime} |
| message | module | staking |
| message | action | begin_redelegate |
| message | sender | {senderAddress} |
* [0] Time is formatted in the RFC3339 standard

View File

@ -1,65 +0,0 @@
# Tags
The staking module emits the following events/tags:
## EndBlocker
| Key | Value |
|-------------------------|-----------------------------------------------|
| `action` | `complete-unbonding`\|`complete-redelegation` |
| `category` | `staking` |
| `delegator` | {delegatorAccountAddress} |
| `source-validator` | {srcOperatorAddress} |
| `destination-validator` | {dstOperatorAddress} |
## Handlers
### MsgCreateValidator
| Key | Value |
|------------|----------------------|
| `action` | `create_validator` |
| `category` | `staking` |
| `sender` | {dstOperatorAddress} |
### MsgEditValidator
| Key | Value |
|------------|----------------------|
| `action` | `edit_validator` |
| `category` | `staking` |
| `sender` | {dstOperatorAddress} |
### MsgDelegate
| Key | Value |
|-------------------------|---------------------------|
| `action` | `delegate` |
| `category` | `staking` |
| `sender` | {delegatorAccountAddress} |
| `destination-validator` | {dstOperatorAddress} |
### MsgBeginRedelegate
| Key | Value |
|-------------------------|---------------------------|
| `action` | `begin_redelegate` |
| `category` | `staking` |
| `sender` | {delegatorAccountAddress} |
| `source-validator` | {srcOperatorAddress} |
| `destination-validator` | {dstOperatorAddress} |
| `end-time` [0] | {delegationFinishTime} |
* [0] Time is formatted in the RFC3339 standard
### MsgUndelegate
| Key | Value |
|--------------------|---------------------------|
| `action` | `begin_unbonding` |
| `category` | `staking` |
| `sender` | {delegatorAccountAddress} |
| `source-validator` | {srcOperatorAddress} |
| `end-time` [0] | {delegationFinishTime} |
* [0] Time is formatted in the RFC3339 standard

View File

@ -39,7 +39,7 @@ network.
- [Validator Set Changes](04_end_block.md#validator-set-changes)
- [Queues ](04_end_block.md#queues-)
5. **[Hooks](05_hooks.md)**
6. **[Tags](06_tags.md)**
- [EndBlocker](06_tags.md#endblocker)
- [Handlers](06_tags.md#handlers)
6. **[Events](06_events.md)**
- [EndBlocker](06_events.md#endblocker)
- [Handlers](06_events.md#handlers)
7. **[Parameters](07_params.md)**

15
go.mod
View File

@ -1,25 +1,21 @@
module github.com/cosmos/cosmos-sdk
require (
github.com/VividCortex/gohistogram v1.0.0 // indirect
github.com/aws/aws-lambda-go v1.11.1
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d
github.com/bgentry/speakeasy v0.1.0
github.com/bradleyfalzon/ghinstallation v0.1.2
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d
github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8
github.com/cosmos/ledger-cosmos-go v0.10.3
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/fortytw2/leaktest v1.3.0 // indirect
github.com/go-logfmt/logfmt v0.4.0 // indirect
github.com/gogo/protobuf v1.1.1
github.com/gogo/protobuf v1.2.1
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129
github.com/golang/protobuf v1.3.0
github.com/golang/snappy v0.0.1 // indirect
github.com/google/go-github/v26 v26.0.2
github.com/gorilla/mux v1.7.0
github.com/gorilla/websocket v1.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect
github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018 // indirect
github.com/mattn/go-isatty v0.0.6
github.com/nlopes/slack v0.5.0
github.com/pelletier/go-toml v1.2.0
@ -29,19 +25,16 @@ require (
github.com/prometheus/common v0.2.0 // indirect
github.com/prometheus/procfs v0.0.0-20190227231451-bbced9601137 // indirect
github.com/rakyll/statik v0.1.4
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 // indirect
github.com/rs/cors v1.6.0 // indirect
github.com/spf13/afero v1.2.1 // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.3.2
github.com/stretchr/testify v1.3.0
github.com/syndtr/goleveldb v0.0.0-20180708030551-c4c61651e9e3 // indirect
github.com/tendermint/btcd v0.1.1
github.com/tendermint/go-amino v0.15.0
github.com/tendermint/iavl v0.12.2
github.com/tendermint/tendermint v0.31.5
github.com/tendermint/tendermint v0.32.0
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
google.golang.org/grpc v1.19.0 // indirect
gopkg.in/yaml.v2 v2.2.2

60
go.sum
View File

@ -6,8 +6,6 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aws/aws-lambda-go v1.11.1 h1:wuOnhS5aqzPOWns71FO35PtbtBKHr4MYsPVt5qXLSfI=
github.com/aws/aws-lambda-go v1.11.1/go.mod h1:Rr2SMTLeSMKgD45uep9V/NP8tnbCcySgu04cx0k/6cw=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8=
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk=
@ -15,8 +13,6 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLM
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bradleyfalzon/ghinstallation v0.1.2 h1:9fdqVadlvEX/EUts5/aIGvx2ujKnGNIMcuCuUrM6s6Q=
github.com/bradleyfalzon/ghinstallation v0.1.2/go.mod h1:VQsLlCoNa54/CNXcc2DuCfNZrZxqQcyPeqKUugF/2h8=
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d h1:xG8Pj6Y6J760xwETNmMzmlt38QSwz0BLp1cZ09g27uw=
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
@ -27,7 +23,6 @@ github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVa
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@ -43,12 +38,14 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/etcd-io/bbolt v1.3.2 h1:RLRQ0TKLX7DlBRXAJHvbmXL17Q3KNnTBtZ9B6Qo+/Y0=
github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -56,28 +53,26 @@ github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80n
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 h1:tT8iWCYw4uOem71yYA3htfH+LNopJvcqZQshm56G5L4=
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-github/v26 v26.0.2 h1:tiPWJNapF2n6Mxbmue/g0uDkSuWf34nzlsNp4Ym7qb8=
github.com/google/go-github/v26 v26.0.2/go.mod h1:v6/FmX9au22j4CtYxnMhJJkP+JfOQDXALk7hI+MPDNM=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@ -86,16 +81,21 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 h1:AsEBgzv3DhuYHI/GiQh2HxvTP71HCCE9E/tzGUzGdtU=
github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0=
github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018 h1:MNApn+Z+fIT4NPZopPfCc1obT6aY3SVM6DOctz1A9ZU=
github.com/lusis/slack-test v0.0.0-20190426140909-c40012f20018/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-isatty v0.0.6 h1:SrwhHcpV4nWrMGdNcC2kXpMfcBVYGDuTArqyhocJgvA=
@ -115,7 +115,6 @@ github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -127,6 +126,7 @@ github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@ -147,6 +147,7 @@ github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M=
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@ -154,45 +155,44 @@ github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmq
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syndtr/goleveldb v0.0.0-20180708030551-c4c61651e9e3 h1:sAlSBRDl4psFR3ysKXRSE8ss6Mt90+ma1zRTroTNBJA=
github.com/syndtr/goleveldb v0.0.0-20180708030551-c4c61651e9e3/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v0.0.0-20181012014443-6b91fda63f2e h1:91EeXI4y4ShkyzkMqZ7QP/ZTIqwXp3RuDu5WFzxcFAs=
github.com/syndtr/goleveldb v0.0.0-20181012014443-6b91fda63f2e/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s=
github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U=
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 h1:u8i49c+BxloX3XQ55cvzFNXplizZP/q00i+IlttUjAU=
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
github.com/tendermint/go-amino v0.15.0 h1:TC4e66P59W7ML9+bxio17CPKnxW3nKIRAYskntMAoRk=
github.com/tendermint/go-amino v0.15.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/iavl v0.12.2 h1:Ls5p5VINCM1HRT9g5Vvs2zmDOCU/CCIvIHzd/pZ8P0E=
github.com/tendermint/iavl v0.12.2/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM=
github.com/tendermint/tendermint v0.31.5 h1:vTet8tCq3B9/J9Yo11dNZ8pOB7NtSy++bVSfkP4KzR4=
github.com/tendermint/tendermint v0.31.5/go.mod h1:ymcPyWblXCplCPQjbOYbrF1fWnpslATMVqiGgWbZrlc=
github.com/tendermint/tendermint v0.32.0 h1:9MAnZpWjuA3DnAXWqjYxrBXOYC0Xk8zZJgV6IO3LdBw=
github.com/tendermint/tendermint v0.32.0/go.mod h1:/5wKhXBcO1eS9qfBs2X4OcNys07c7ls+O11iODzCRhE=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -205,14 +205,15 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpbl
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b h1:qMK98NmNCRVDIYFycQ5yVRkvgDUFfdP8Ip4KqmDEB7g=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2 h1:67iHsV9djwGdZpdZNbLuQj6FOzCaZe3w+vhLjn5AcFA=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@ -222,7 +223,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -62,7 +62,7 @@ func TestDeliverTx(t *testing.T) {
Height: 1,
}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
dres := app.DeliverTx(txBytes)
dres := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.Equal(t, uint32(0), dres.Code, dres.Log)
app.EndBlock(abci.RequestEndBlock{})
cres := app.Commit()

View File

@ -41,6 +41,7 @@ func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Lo
pst: newThePast(),
gen: 0,
}
c = c.WithMultiStore(ms)
c = c.WithBlockHeader(header)
c = c.WithChainID(header.ChainID)
@ -51,6 +52,8 @@ func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, logger log.Lo
c = c.WithGasMeter(stypes.NewInfiniteGasMeter())
c = c.WithMinGasPrices(DecCoins{})
c = c.WithConsensusParams(nil)
c = c.WithEventManager(NewEventManager())
return c
}
@ -59,8 +62,26 @@ func (c Context) IsZero() bool {
return c.Context == nil
}
//----------------------------------------
// Getting a value
// ----------------------------------------------------------------------------
// Getters
// ----------------------------------------------------------------------------
type contextKey int // local to the context module
const (
contextKeyMultiStore contextKey = iota
contextKeyBlockHeader
contextKeyChainID
contextKeyIsCheckTx
contextKeyTxBytes
contextKeyLogger
contextKeyVoteInfos
contextKeyGasMeter
contextKeyBlockGasMeter
contextKeyMinGasPrices
contextKeyConsensusParams
contextKeyEventManager
)
// context value for the provided key
func (c Context) Value(key interface{}) interface{} {
@ -74,20 +95,42 @@ func (c Context) Value(key interface{}) interface{} {
return value
}
// KVStore fetches a KVStore from the MultiStore.
func (c Context) KVStore(key StoreKey) KVStore {
return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig())
func (c Context) MultiStore() MultiStore {
return c.Value(contextKeyMultiStore).(MultiStore)
}
// TransientStore fetches a TransientStore from the MultiStore.
func (c Context) TransientStore(key StoreKey) KVStore {
return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig())
func (c Context) BlockHeader() abci.Header { return c.Value(contextKeyBlockHeader).(abci.Header) }
func (c Context) BlockHeight() int64 { return c.BlockHeader().Height }
func (c Context) ChainID() string { return c.Value(contextKeyChainID).(string) }
func (c Context) TxBytes() []byte { return c.Value(contextKeyTxBytes).([]byte) }
func (c Context) Logger() log.Logger { return c.Value(contextKeyLogger).(log.Logger) }
func (c Context) VoteInfos() []abci.VoteInfo {
return c.Value(contextKeyVoteInfos).([]abci.VoteInfo)
}
//----------------------------------------
// With* (setting a value)
func (c Context) GasMeter() GasMeter { return c.Value(contextKeyGasMeter).(GasMeter) }
func (c Context) BlockGasMeter() GasMeter { return c.Value(contextKeyBlockGasMeter).(GasMeter) }
func (c Context) IsCheckTx() bool { return c.Value(contextKeyIsCheckTx).(bool) }
func (c Context) MinGasPrices() DecCoins { return c.Value(contextKeyMinGasPrices).(DecCoins) }
func (c Context) ConsensusParams() *abci.ConsensusParams {
return c.Value(contextKeyConsensusParams).(*abci.ConsensusParams)
}
func (c Context) EventManager() *EventManager { return c.Value(contextKeyEventManager).(*EventManager) }
// ----------------------------------------------------------------------------
// Setters
// ----------------------------------------------------------------------------
// nolint
func (c Context) WithValue(key interface{}, value interface{}) Context {
return c.withValue(key, value)
}
@ -127,55 +170,6 @@ func (c Context) withValue(key interface{}, value interface{}) Context {
}
}
//----------------------------------------
// Values that require no key.
type contextKey int // local to the context module
const (
contextKeyMultiStore contextKey = iota
contextKeyBlockHeader
contextKeyChainID
contextKeyIsCheckTx
contextKeyTxBytes
contextKeyLogger
contextKeyVoteInfos
contextKeyGasMeter
contextKeyBlockGasMeter
contextKeyMinGasPrices
contextKeyConsensusParams
)
func (c Context) MultiStore() MultiStore {
return c.Value(contextKeyMultiStore).(MultiStore)
}
func (c Context) BlockHeader() abci.Header { return c.Value(contextKeyBlockHeader).(abci.Header) }
func (c Context) BlockHeight() int64 { return c.BlockHeader().Height }
func (c Context) ChainID() string { return c.Value(contextKeyChainID).(string) }
func (c Context) TxBytes() []byte { return c.Value(contextKeyTxBytes).([]byte) }
func (c Context) Logger() log.Logger { return c.Value(contextKeyLogger).(log.Logger) }
func (c Context) VoteInfos() []abci.VoteInfo {
return c.Value(contextKeyVoteInfos).([]abci.VoteInfo)
}
func (c Context) GasMeter() GasMeter { return c.Value(contextKeyGasMeter).(GasMeter) }
func (c Context) BlockGasMeter() GasMeter { return c.Value(contextKeyBlockGasMeter).(GasMeter) }
func (c Context) IsCheckTx() bool { return c.Value(contextKeyIsCheckTx).(bool) }
func (c Context) MinGasPrices() DecCoins { return c.Value(contextKeyMinGasPrices).(DecCoins) }
func (c Context) ConsensusParams() *abci.ConsensusParams {
return c.Value(contextKeyConsensusParams).(*abci.ConsensusParams)
}
func (c Context) WithMultiStore(ms MultiStore) Context {
return c.withValue(contextKeyMultiStore, ms)
}
@ -231,6 +225,24 @@ func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
return c.withValue(contextKeyConsensusParams, params)
}
func (c Context) WithEventManager(em *EventManager) Context {
return c.WithValue(contextKeyEventManager, em)
}
// ----------------------------------------------------------------------------
// Store / Caching
// ----------------------------------------------------------------------------
// KVStore fetches a KVStore from the MultiStore.
func (c Context) KVStore(key StoreKey) KVStore {
return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.KVGasConfig())
}
// TransientStore fetches a TransientStore from the MultiStore.
func (c Context) TransientStore(key StoreKey) KVStore {
return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), stypes.TransientGasConfig())
}
// Cache the multistore and return a new cached context. The cached context is
// written to the context when writeCache is called.
func (c Context) CacheContext() (cc Context, writeCache func()) {
@ -299,4 +311,4 @@ func (pst *thePast) getOp(ver int64) (Op, bool) {
return Op{}, false
}
return pst.ops[ver-1], true
}
}

192
types/events.go Normal file
View File

@ -0,0 +1,192 @@
package types
import (
"fmt"
"strings"
abci "github.com/tendermint/tendermint/abci/types"
cmn "github.com/tendermint/tendermint/libs/common"
)
// ----------------------------------------------------------------------------
// Event Manager
// ----------------------------------------------------------------------------
// EventManager implements a simple wrapper around a slice of Event objects that
// can be emitted from.
type EventManager struct {
events Events
}
func NewEventManager() *EventManager {
return &EventManager{EmptyEvents()}
}
func (em *EventManager) Events() Events { return em.events }
// EmitEvent stores a single Event object.
func (em *EventManager) EmitEvent(event Event) {
em.events = em.events.AppendEvent(event)
}
// EmitEvents stores a series of Event objects.
func (em *EventManager) EmitEvents(events Events) {
em.events = em.events.AppendEvents(events)
}
// ABCIEvents returns all stored Event objects as abci.Event objects.
func (em EventManager) ABCIEvents() []abci.Event {
return em.events.ToABCIEvents()
}
// ----------------------------------------------------------------------------
// Events
// ----------------------------------------------------------------------------
type (
// Event is a type alias for an ABCI Event
Event abci.Event
// Attribute defines an attribute wrapper where the key and value are
// strings instead of raw bytes.
Attribute struct {
Key string `json:"key"`
Value string `json:"value,omitempty"`
}
// Events defines a slice of Event objects
Events []Event
)
// NewEvent creates a new Event object with a given type and slice of one or more
// attributes.
func NewEvent(ty string, attrs ...Attribute) Event {
e := Event{Type: ty}
for _, attr := range attrs {
e.Attributes = append(e.Attributes, NewAttribute(attr.Key, attr.Value).ToKVPair())
}
return e
}
// NewAttribute returns a new key/value Attribute object.
func NewAttribute(k, v string) Attribute {
return Attribute{k, v}
}
// EmptyEvents returns an empty slice of events.
func EmptyEvents() Events {
return make(Events, 0)
}
func (a Attribute) String() string {
return fmt.Sprintf("%s: %s", a.Key, a.Value)
}
// ToKVPair converts an Attribute object into a Tendermint key/value pair.
func (a Attribute) ToKVPair() cmn.KVPair {
return cmn.KVPair{Key: toBytes(a.Key), Value: toBytes(a.Value)}
}
// AppendAttributes adds one or more attributes to an Event.
func (e Event) AppendAttributes(attrs ...Attribute) Event {
for _, attr := range attrs {
e.Attributes = append(e.Attributes, attr.ToKVPair())
}
return e
}
// AppendEvent adds an Event to a slice of events.
func (e Events) AppendEvent(event Event) Events {
return append(e, event)
}
// AppendEvents adds a slice of Event objects to an exist slice of Event objects.
func (e Events) AppendEvents(events Events) Events {
return append(e, events...)
}
// ToABCIEvents converts a slice of Event objects to a slice of abci.Event
// objects.
func (e Events) ToABCIEvents() []abci.Event {
res := make([]abci.Event, len(e), len(e))
for i, ev := range e {
res[i] = abci.Event{Type: ev.Type, Attributes: ev.Attributes}
}
return res
}
func toBytes(i interface{}) []byte {
switch x := i.(type) {
case []uint8:
return x
case string:
return []byte(x)
default:
panic(i)
}
}
// Common event types and attribute keys
var (
EventTypeMessage = "message"
AttributeKeyAction = "action"
AttributeKeyModule = "module"
AttributeKeySender = "sender"
)
type (
// StringAttribute defines en Event object wrapper where all the attributes
// contain key/value pairs that are strings instead of raw bytes.
StringEvent struct {
Type string `json:"type,omitempty"`
Attributes []Attribute `json:"attributes,omitempty"`
}
// StringAttributes defines a slice of StringEvents objects.
StringEvents []StringEvent
)
func (se StringEvents) String() string {
var sb strings.Builder
for _, e := range se {
sb.WriteString(fmt.Sprintf("\t\t- %s\n", e.Type))
for _, attr := range e.Attributes {
sb.WriteString(fmt.Sprintf("\t\t\t- %s\n", attr.String()))
}
}
return strings.TrimRight(sb.String(), "\n")
}
// StringifyEvent converts an Event object to a StringEvent object.
func StringifyEvent(e abci.Event) StringEvent {
res := StringEvent{}
res.Type = e.Type
for _, attr := range e.Attributes {
res.Attributes = append(
res.Attributes,
Attribute{string(attr.Key), string(attr.Value)},
)
}
return res
}
// StringifyEvents converts a slice of Event objects into a slice of StringEvent
// objects.
func StringifyEvents(events []abci.Event) StringEvents {
var res StringEvents
for _, e := range events {
res = append(res, StringifyEvent(e))
}
return res
}

53
types/events_test.go Normal file
View File

@ -0,0 +1,53 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestAppendEvents(t *testing.T) {
e1 := NewEvent("transfer", NewAttribute("sender", "foo"))
e2 := NewEvent("transfer", NewAttribute("sender", "bar"))
a := Events{e1}
b := Events{e2}
c := a.AppendEvents(b)
require.Equal(t, c, Events{e1, e2})
require.Equal(t, c, Events{e1}.AppendEvent(NewEvent("transfer", NewAttribute("sender", "bar"))))
require.Equal(t, c, Events{e1}.AppendEvents(Events{e2}))
}
func TestAppendAttributes(t *testing.T) {
e := NewEvent("transfer", NewAttribute("sender", "foo"))
e = e.AppendAttributes(NewAttribute("recipient", "bar"))
require.Len(t, e.Attributes, 2)
require.Equal(t, e, NewEvent("transfer", NewAttribute("sender", "foo"), NewAttribute("recipient", "bar")))
}
func TestEmptyEvents(t *testing.T) {
require.Equal(t, EmptyEvents(), Events{})
}
func TestAttributeString(t *testing.T) {
require.Equal(t, "foo: bar", NewAttribute("foo", "bar").String())
}
func TestToABCIEvents(t *testing.T) {
e := Events{NewEvent("transfer", NewAttribute("sender", "foo"))}
abciEvents := e.ToABCIEvents()
require.Len(t, abciEvents, 1)
require.Equal(t, abciEvents[0].Type, e[0].Type)
require.Equal(t, abciEvents[0].Attributes, e[0].Attributes)
}
func TestEventManager(t *testing.T) {
em := NewEventManager()
event := NewEvent("reward", NewAttribute("x", "y"))
events := Events{NewEvent("transfer", NewAttribute("sender", "foo"))}
em.EmitEvents(events)
em.EmitEvent(event)
require.Len(t, em.Events(), 2)
require.Equal(t, em.Events(), events.AppendEvent(event))
}

View File

@ -139,8 +139,8 @@ type AppModule interface {
QuerierRoute() string
NewQuerierHandler() sdk.Querier
BeginBlock(sdk.Context, abci.RequestBeginBlock) sdk.Tags
EndBlock(sdk.Context, abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags)
BeginBlock(sdk.Context, abci.RequestBeginBlock)
EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
}
//___________________________
@ -172,13 +172,11 @@ func (GenesisOnlyAppModule) QuerierRoute() string { return "" }
func (gam GenesisOnlyAppModule) NewQuerierHandler() sdk.Querier { return nil }
// module begin-block
func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) sdk.Tags {
return sdk.EmptyTags()
}
func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
// module end-block
func (GenesisOnlyAppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
func (GenesisOnlyAppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}
//____________________________________________________________________________
@ -282,26 +280,30 @@ func (m *Manager) ExportGenesis(ctx sdk.Context) map[string]json.RawMessage {
return genesisData
}
// perform begin block functionality for modules
// BeginBlock performs begin block functionality for all modules. It creates a
// child context with an event manager to aggregate events emitted from all
// modules.
func (m *Manager) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
tags := sdk.EmptyTags()
ctx = ctx.WithEventManager(sdk.NewEventManager())
for _, moduleName := range m.OrderBeginBlockers {
moduleTags := m.Modules[moduleName].BeginBlock(ctx, req)
tags = tags.AppendTags(moduleTags)
m.Modules[moduleName].BeginBlock(ctx, req)
}
return abci.ResponseBeginBlock{
Tags: tags.ToKVPairs(),
Events: ctx.EventManager().ABCIEvents(),
}
}
// perform end block functionality for modules
// EndBlock performs end block functionality for all modules. It creates a
// child context with an event manager to aggregate events emitted from all
// modules.
func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
ctx = ctx.WithEventManager(sdk.NewEventManager())
validatorUpdates := []abci.ValidatorUpdate{}
tags := sdk.EmptyTags()
for _, moduleName := range m.OrderEndBlockers {
moduleValUpdates, moduleTags := m.Modules[moduleName].EndBlock(ctx, req)
tags = tags.AppendTags(moduleTags)
moduleValUpdates := m.Modules[moduleName].EndBlock(ctx, req)
// use these validator updates if provided, the module manager assumes
// only one module will update the validator set
@ -309,13 +311,14 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo
if len(validatorUpdates) > 0 {
panic("validator EndBlock updates already set by a previous module")
}
validatorUpdates = moduleValUpdates
}
}
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Tags: tags,
Events: ctx.EventManager().ABCIEvents(),
}
}

View File

@ -32,8 +32,9 @@ type Result struct {
// GasUsed is the amount of gas actually consumed. NOTE: unimplemented
GasUsed uint64
// Tags are used for transaction indexing and pubsub.
Tags Tags
// Events contains a slice of Event objects that were emitted during some
// execution.
Events Events
}
// TODO: In the future, more codes may be OK.
@ -75,7 +76,7 @@ type TxResponse struct {
Info string `json:"info,omitempty"`
GasWanted int64 `json:"gas_wanted,omitempty"`
GasUsed int64 `json:"gas_used,omitempty"`
Tags StringTags `json:"tags,omitempty"`
Events StringEvents `json:"events,omitempty"`
Codespace string `json:"codespace,omitempty"`
Tx Tx `json:"tx,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
@ -99,7 +100,7 @@ func NewResponseResultTx(res *ctypes.ResultTx, tx Tx, timestamp string) TxRespon
Info: res.TxResult.Info,
GasWanted: res.TxResult.GasWanted,
GasUsed: res.TxResult.GasUsed,
Tags: TagsToStringTags(res.TxResult.Tags),
Events: StringifyEvents(res.TxResult.Events),
Tx: tx,
Timestamp: timestamp,
}
@ -141,7 +142,7 @@ func newTxResponseCheckTx(res *ctypes.ResultBroadcastTxCommit) TxResponse {
Info: res.CheckTx.Info,
GasWanted: res.CheckTx.GasWanted,
GasUsed: res.CheckTx.GasUsed,
Tags: TagsToStringTags(res.CheckTx.Tags),
Events: StringifyEvents(res.CheckTx.Events),
Codespace: res.CheckTx.Codespace,
}
}
@ -168,7 +169,7 @@ func newTxResponseDeliverTx(res *ctypes.ResultBroadcastTxCommit) TxResponse {
Info: res.DeliverTx.Info,
GasWanted: res.DeliverTx.GasWanted,
GasUsed: res.DeliverTx.GasUsed,
Tags: TagsToStringTags(res.DeliverTx.Tags),
Events: StringifyEvents(res.DeliverTx.Events),
Codespace: res.DeliverTx.Codespace,
}
}
@ -238,8 +239,8 @@ func (r TxResponse) String() string {
sb.WriteString(fmt.Sprintf(" Timestamp: %s\n", r.Timestamp))
}
if len(r.Tags) > 0 {
sb.WriteString(fmt.Sprintf(" Tags: \n%s\n", r.Tags.String()))
if len(r.Events) > 0 {
sb.WriteString(fmt.Sprintf(" Tags: \n%s\n", r.Events.String()))
}
return strings.TrimSpace(sb.String())

View File

@ -1,118 +0,0 @@
package types
import (
"fmt"
"strings"
cmn "github.com/tendermint/tendermint/libs/common"
)
// Type synonym for convenience
type Tag = cmn.KVPair
// Type synonym for convenience
type Tags cmn.KVPairs
// New empty tags
func EmptyTags() Tags {
return make(Tags, 0)
}
// Append a single tag
func (t Tags) AppendTag(k string, v string) Tags {
return append(t, MakeTag(k, v))
}
// Append two lists of tags
func (t Tags) AppendTags(tags Tags) Tags {
return append(t, tags...)
}
// Turn tags into KVPair list
func (t Tags) ToKVPairs() []cmn.KVPair {
return []cmn.KVPair(t)
}
// New variadic tags, must be k string, v []byte repeating
func NewTags(tags ...interface{}) Tags {
var ret Tags
if len(tags)%2 != 0 {
panic("must specify key-value pairs as varargs")
}
i := 0
for {
if i == len(tags) {
break
}
ret = append(ret, Tag{Key: toBytes(tags[i]), Value: toBytes(tags[i+1])})
i += 2
}
return ret
}
func toBytes(i interface{}) []byte {
switch x := i.(type) {
case []uint8:
return x
case string:
return []byte(x)
default:
panic(i)
}
}
// Make a tag from a key and a value
func MakeTag(k string, v string) Tag {
return Tag{Key: []byte(k), Value: []byte(v)}
}
//__________________________________________________
// common tags
var (
TagAction = "action"
TagCategory = "category"
TagSender = "sender"
TagSrcValidator = "source-validator"
TagDstValidator = "destination-validator"
TagDelegator = "delegator"
)
// A KVPair where the Key and Value are both strings, rather than []byte
type StringTag struct {
Key string `json:"key"`
Value string `json:"value,omitempty"`
}
func (st StringTag) String() string {
return fmt.Sprintf("%s = %s", st.Key, st.Value)
}
// A slice of StringTag
type StringTags []StringTag
func (st StringTags) String() string {
var sb strings.Builder
for _, t := range st {
sb.WriteString(fmt.Sprintf(" - %s\n", t.String()))
}
return strings.TrimRight(sb.String(), "\n")
}
// Conversion function from a []byte tag to a string tag
func TagToStringTag(tag Tag) StringTag {
return StringTag{
Key: string(tag.Key),
Value: string(tag.Value),
}
}
// Conversion function from Tags to a StringTags
func TagsToStringTags(tags Tags) StringTags {
var stringTags StringTags
for _, tag := range tags {
stringTags = append(stringTags, TagToStringTag(tag))
}
return stringTags
}

View File

@ -1,35 +0,0 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestAppendTags(t *testing.T) {
a := NewTags("a", "1")
b := NewTags("b", "2")
c := a.AppendTags(b)
require.Equal(t, c, Tags{MakeTag("a", "1"), MakeTag("b", "2")})
require.Equal(t, c, Tags{MakeTag("a", "1")}.AppendTag("b", "2"))
}
func TestEmptyTags(t *testing.T) {
a := EmptyTags()
require.Equal(t, a, Tags{})
}
func TestNewTags(t *testing.T) {
b := NewTags("a", "1")
require.Equal(t, b, Tags{MakeTag("a", "1")})
require.Panics(t, func() { NewTags("a", "1", "b") })
require.Panics(t, func() { NewTags("a", 1) })
require.Panics(t, func() { NewTags(1, 1) })
require.Panics(t, func() { NewTags(true, false) })
}
func TestKVPairTags(t *testing.T) {
a := NewTags("a", "1")
require.Equal(t, a, Tags(a.ToKVPairs()))
}

View File

@ -121,11 +121,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags {
return sdk.EmptyTags()
}
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -11,6 +11,8 @@ import (
// NewHandler returns a handler for "bank" type messages.
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case types.MsgSend:
return handleMsgSend(ctx, k, msg)
@ -30,20 +32,20 @@ func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) sdk.Resu
if !k.GetSendEnabled(ctx) {
return types.ErrSendDisabled(k.Codespace()).Result()
}
err := k.SendCoins(ctx, msg.FromAddress, msg.ToAddress, msg.Amount)
if err != nil {
return err.Result()
}
resTags := sdk.NewTags(
types.Category, types.TxCategory,
types.Sender, msg.FromAddress.String(),
types.Recipient, msg.ToAddress.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return sdk.Result{
Tags: resTags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}
// Handle MsgMultiSend.
@ -52,13 +54,18 @@ func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend
if !k.GetSendEnabled(ctx) {
return types.ErrSendDisabled(k.Codespace()).Result()
}
resTags, err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs)
err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs)
if err != nil {
return err.Result()
}
resTags = resTags.AppendTag(types.Category, types.TxCategory)
return sdk.Result{
Tags: resTags,
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
}

View File

@ -5,6 +5,7 @@ import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/stretchr/testify/require"
)
@ -12,7 +13,7 @@ import (
func TestInvalidMsg(t *testing.T) {
h := NewHandler(nil)
res := h(sdk.Context{}, sdk.NewTestMsg())
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized bank message type"))
}

View File

@ -20,10 +20,10 @@ type Keeper interface {
SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error)
AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error)
InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) (sdk.Tags, sdk.Error)
InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) sdk.Error
DelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error)
UndelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error)
DelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
UndelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
}
// BaseKeeper manages transfers between accounts. It implements the Keeper interface.
@ -81,22 +81,16 @@ func (keeper BaseKeeper) AddCoins(
}
// InputOutputCoins handles a list of inputs and outputs
func (keeper BaseKeeper) InputOutputCoins(
ctx sdk.Context, inputs []types.Input, outputs []types.Output,
) (sdk.Tags, sdk.Error) {
func (keeper BaseKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) sdk.Error {
return inputOutputCoins(ctx, keeper.ak, inputs, outputs)
}
// DelegateCoins performs delegation by deducting amt coins from an account with
// address addr. For vesting accounts, delegations amounts are tracked for both
// vesting and vested coins.
func (keeper BaseKeeper) DelegateCoins(
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
) (sdk.Tags, sdk.Error) {
func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
return sdk.ErrInvalidCoins(amt.String())
}
return delegateCoins(ctx, keeper.ak, addr, amt)
}
@ -105,12 +99,9 @@ func (keeper BaseKeeper) DelegateCoins(
// address addr. For vesting accounts, undelegation amounts are tracked for both
// vesting and vested coins.
// If any of the undelegation amounts are negative, an error is returned.
func (keeper BaseKeeper) UndelegateCoins(
ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins,
) (sdk.Tags, sdk.Error) {
func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
return sdk.ErrInvalidCoins(amt.String())
}
return undelegateCoins(ctx, keeper.ak, addr, amt)
}
@ -156,6 +147,18 @@ func (keeper BaseSendKeeper) SendCoins(
if !amt.IsValid() {
return sdk.ErrInvalidCoins(amt.String())
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeTransfer,
sdk.NewAttribute(types.AttributeKeyRecipient, toAddr.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(types.AttributeKeySender, fromAddr.String()),
),
})
return sendCoins(ctx, keeper.ak, fromAddr, toAddr, amt)
}
@ -209,34 +212,37 @@ func (keeper BaseViewKeeper) Codespace() sdk.CodespaceType {
return keeper.codespace
}
func getCoins(ctx sdk.Context, am types.AccountKeeper, addr sdk.AccAddress) sdk.Coins {
acc := am.GetAccount(ctx, addr)
func getCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress) sdk.Coins {
acc := ak.GetAccount(ctx, addr)
if acc == nil {
return sdk.NewCoins()
}
return acc.GetCoins()
}
func setCoins(ctx sdk.Context, am types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func setCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
if !amt.IsValid() {
return sdk.ErrInvalidCoins(amt.String())
}
acc := am.GetAccount(ctx, addr)
acc := ak.GetAccount(ctx, addr)
if acc == nil {
acc = am.NewAccountWithAddress(ctx, addr)
acc = ak.NewAccountWithAddress(ctx, addr)
}
err := acc.SetCoins(amt)
if err != nil {
// Handle w/ #870
panic(err)
}
am.SetAccount(ctx, acc)
ak.SetAccount(ctx, acc)
return nil
}
// HasCoins returns whether or not an account has at least amt coins.
func hasCoins(ctx sdk.Context, am types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) bool {
return getCoins(ctx, am, addr).IsAllGTE(amt)
func hasCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) bool {
return getCoins(ctx, ak, addr).IsAllGTE(amt)
}
func getAccount(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress) exported.Account {
@ -251,7 +257,6 @@ func setAccount(ctx sdk.Context, ak types.AccountKeeper, acc exported.Account) {
//
// CONTRACT: If the account is a vesting account, the amount has to be spendable.
func subtractCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
}
@ -280,13 +285,12 @@ func subtractCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress,
}
// AddCoins adds amt to the coins at the addr.
func addCoins(ctx sdk.Context, am types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func addCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
}
oldCoins := getCoins(ctx, am, addr)
oldCoins := getCoins(ctx, ak, addr)
newCoins := oldCoins.Add(amt)
if newCoins.IsAnyNegative() {
@ -295,25 +299,25 @@ func addCoins(ctx sdk.Context, am types.AccountKeeper, addr sdk.AccAddress, amt
)
}
err := setCoins(ctx, am, addr, newCoins)
err := setCoins(ctx, ak, addr, newCoins)
return newCoins, err
}
// SendCoins moves coins from one account to another
// Returns ErrInvalidCoins if amt is invalid.
func sendCoins(ctx sdk.Context, am types.AccountKeeper, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func sendCoins(ctx sdk.Context, ak types.AccountKeeper, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
// Safety check ensuring that when sending coins the keeper must maintain the
if !amt.IsValid() {
return sdk.ErrInvalidCoins(amt.String())
}
_, err := subtractCoins(ctx, am, fromAddr, amt)
_, err := subtractCoins(ctx, ak, fromAddr, amt)
if err != nil {
return err
}
_, err = addCoins(ctx, am, toAddr, amt)
_, err = addCoins(ctx, ak, toAddr, amt)
if err != nil {
return err
}
@ -323,96 +327,87 @@ func sendCoins(ctx sdk.Context, am types.AccountKeeper, fromAddr sdk.AccAddress,
// 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 types.AccountKeeper, inputs []types.Input, outputs []types.Output) (sdk.Tags, sdk.Error) {
func inputOutputCoins(ctx sdk.Context, ak types.AccountKeeper, inputs []types.Input, outputs []types.Output) sdk.Error {
// Safety check ensuring that when sending coins the keeper must maintain the
// Check supply invariant and validity of Coins.
if err := types.ValidateInputsOutputs(inputs, outputs); err != nil {
return nil, err
return err
}
allTags := sdk.EmptyTags()
for _, in := range inputs {
_, err := subtractCoins(ctx, am, in.Address, in.Coins)
_, err := subtractCoins(ctx, ak, in.Address, in.Coins)
if err != nil {
return nil, err
return err
}
allTags = allTags.AppendTag(
types.Sender, in.Address.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(types.AttributeKeySender, in.Address.String()),
),
)
}
for _, out := range outputs {
_, err := addCoins(ctx, am, out.Address, out.Coins)
_, err := addCoins(ctx, ak, out.Address, out.Coins)
if err != nil {
return nil, err
return err
}
allTags = allTags.AppendTag(
types.Recipient, out.Address.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeTransfer,
sdk.NewAttribute(types.AttributeKeyRecipient, out.Address.String()),
),
)
}
return allTags, nil
return nil
}
func delegateCoins(
ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins,
) (sdk.Tags, sdk.Error) {
func delegateCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
return sdk.ErrInvalidCoins(amt.String())
}
acc := getAccount(ctx, ak, addr)
if acc == nil {
return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
return sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
}
oldCoins := acc.GetCoins()
_, hasNeg := oldCoins.SafeSub(amt)
if hasNeg {
return nil, sdk.ErrInsufficientCoins(
return sdk.ErrInsufficientCoins(
fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt),
)
}
if err := trackDelegation(acc, ctx.BlockHeader().Time, amt); err != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("failed to track delegation: %v", err))
return sdk.ErrInternal(fmt.Sprintf("failed to track delegation: %v", err))
}
setAccount(ctx, ak, acc)
return sdk.NewTags(
sdk.TagAction, types.ActionDelegateCoins,
sdk.TagDelegator, addr.String(),
), nil
return nil
}
func undelegateCoins(
ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins,
) (sdk.Tags, sdk.Error) {
func undelegateCoins(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
return sdk.ErrInvalidCoins(amt.String())
}
acc := getAccount(ctx, ak, addr)
if acc == nil {
return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
return sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
}
if err := trackUndelegation(acc, amt); err != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("failed to track undelegation: %v", err))
return sdk.ErrInternal(fmt.Sprintf("failed to track undelegation: %v", err))
}
setAccount(ctx, ak, acc)
return sdk.NewTags(
sdk.TagAction, types.ActionUndelegateCoins,
sdk.TagDelegator, addr.String(),
), nil
return nil
}
// CONTRACT: assumes that amt is valid.

View File

@ -295,13 +295,13 @@ func TestDelegateCoins(t *testing.T) {
ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
// require the ability for a non-vesting account to delegate
_, err := input.k.DelegateCoins(ctx, addr2, delCoins)
err := input.k.DelegateCoins(ctx, addr2, delCoins)
acc = input.ak.GetAccount(ctx, addr2)
require.NoError(t, err)
require.Equal(t, delCoins, acc.GetCoins())
// require the ability for a vesting account to delegate
_, err = input.k.DelegateCoins(ctx, addr1, delCoins)
err = input.k.DelegateCoins(ctx, addr1, delCoins)
vacc = input.ak.GetAccount(ctx, addr1).(*auth.ContinuousVestingAccount)
require.NoError(t, err)
require.Equal(t, delCoins, vacc.GetCoins())
@ -330,22 +330,22 @@ func TestUndelegateCoins(t *testing.T) {
ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
// require the ability for a non-vesting account to delegate
_, err := input.k.DelegateCoins(ctx, addr2, delCoins)
err := input.k.DelegateCoins(ctx, addr2, delCoins)
require.NoError(t, err)
// require the ability for a non-vesting account to undelegate
_, err = input.k.UndelegateCoins(ctx, addr2, delCoins)
err = input.k.UndelegateCoins(ctx, addr2, delCoins)
require.NoError(t, err)
acc = input.ak.GetAccount(ctx, addr2)
require.Equal(t, origCoins, acc.GetCoins())
// require the ability for a vesting account to delegate
_, err = input.k.DelegateCoins(ctx, addr1, delCoins)
err = input.k.DelegateCoins(ctx, addr1, delCoins)
require.NoError(t, err)
// require the ability for a vesting account to undelegate
_, err = input.k.UndelegateCoins(ctx, addr1, delCoins)
err = input.k.UndelegateCoins(ctx, addr1, delCoins)
require.NoError(t, err)
vacc = input.ak.GetAccount(ctx, addr1).(*auth.ContinuousVestingAccount)

View File

@ -0,0 +1,11 @@
package types
// Bank module event types
var (
EventTypeTransfer = "transfer"
AttributeKeyRecipient = "recipient"
AttributeKeySender = "sender"
AttributeValueCategory = ModuleName
)

View File

@ -1,17 +0,0 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Tag keys and values
var (
ActionUndelegateCoins = "undelegateCoins"
ActionDelegateCoins = "delegateCoins"
TxCategory = "bank"
Action = sdk.TagAction
Category = sdk.TagCategory
Recipient = "recipient"
Sender = "sender"
)

View File

@ -114,11 +114,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags {
return sdk.EmptyTags()
}
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -4,7 +4,6 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/crisis/tags"
"github.com/cosmos/cosmos-sdk/x/crisis/types"
)
@ -13,6 +12,8 @@ const RouterKey = ModuleName
func NewHandler(k Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case types.MsgVerifyInvariant:
return handleMsgVerifyInvariant(ctx, msg, k)
@ -25,21 +26,23 @@ func NewHandler(k Keeper) sdk.Handler {
}
func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k Keeper) sdk.Result {
// remove the constant fee
constantFee := sdk.NewCoins(k.GetConstantFee(ctx))
_, err := k.bankKeeper.SubtractCoins(ctx, msg.Sender, constantFee)
if err != nil {
return err.Result()
}
_ = k.feeCollectionKeeper.AddCollectedFees(ctx, constantFee)
// use a cached context to avoid gas costs during invariants
cacheCtx, _ := ctx.CacheContext()
found := false
var invarianceErr error
msgFullRoute := msg.FullInvariantRoute()
var invarianceErr error
for _, invarRoute := range k.routes {
if invarRoute.FullRoute() == msgFullRoute {
invarianceErr = invarRoute.Invar(cacheCtx)
@ -47,12 +50,12 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k K
break
}
}
if !found {
return types.ErrUnknownInvariant(types.DefaultCodespace).Result()
}
if invarianceErr != nil {
// NOTE currently, because the chain halts here, this transaction will never be included
// in the blockchain thus the constant fee will have never been deducted. Thus no
// refund is required.
@ -72,11 +75,17 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k K
panic(invarianceErr)
}
resTags := sdk.NewTags(
tags.Sender, msg.Sender.String(),
tags.Invariant, msg.InvariantRoute,
)
return sdk.Result{
Tags: resTags,
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeInvariant,
sdk.NewAttribute(types.AttributeKeyRoute, msg.InvariantRoute),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCrisis),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()),
),
})
return sdk.Result{Events: ctx.EventManager().Events()}
}

View File

@ -7,6 +7,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
@ -105,7 +106,7 @@ func TestInvalidMsg(t *testing.T) {
k := Keeper{}
h := NewHandler(k)
res := h(sdk.Context{}, sdk.NewTestMsg())
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized crisis message type"))
}

View File

@ -43,7 +43,7 @@ func (AppModuleBasic) DefaultGenesis() json.RawMessage {
// module validate genesis
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
//TODO
// TODO
return nil
}
@ -116,12 +116,10 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags {
return sdk.EmptyTags()
}
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
EndBlocker(ctx, am.keeper, am.logger)
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
return []abci.ValidatorUpdate{}
}

View File

@ -1,11 +0,0 @@
package tags
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Crisis module tags
var (
Sender = sdk.TagSender
Invariant = "invariant"
)

9
x/crisis/types/events.go Normal file
View File

@ -0,0 +1,9 @@
package types
// Crisis module event types
var (
EventTypeInvariant = "invariant"
AttributeValueCrisis = ModuleName
AttributeKeyRoute = "route"
)

View File

@ -10,7 +10,6 @@ import (
// set the proposer for determining distribution during endblock
// and distribute rewards for the previous block
func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) {
// determine the total power signing the block
var previousTotalPower, sumPreviousPrecommitPower int64
for _, voteInfo := range req.LastCommitInfo.GetVotes() {
@ -30,5 +29,4 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper)
// record the proposer for when we payout on the next block
consAddr := sdk.ConsAddress(req.Header.ProposerAddress)
k.SetPreviousProposerConsAddr(ctx, consAddr)
}

View File

@ -8,7 +8,6 @@ package distribution
import (
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/tags"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
@ -118,12 +117,10 @@ var (
ParamStoreKeyBonusProposerReward = keeper.ParamStoreKeyBonusProposerReward
ParamStoreKeyWithdrawAddrEnabled = keeper.ParamStoreKeyWithdrawAddrEnabled
TestAddrs = keeper.TestAddrs
Rewards = tags.Rewards
Commission = tags.Commission
TxCategory = tags.TxCategory
Validator = tags.Validator
Category = tags.Category
Sender = tags.Sender
EventTypeRewards = types.EventTypeRewards
EventTypeCommission = types.EventTypeCommission
AttributeValueCategory = types.AttributeValueCategory
AttributeKeyValidator = types.AttributeKeyValidator
ModuleCdc = types.ModuleCdc
)

View File

@ -5,14 +5,14 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/tags"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
// NOTE msg already has validate basic run
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case types.MsgSetWithdrawAddress:
return handleMsgModifyWithdrawAddress(ctx, msg, k)
@ -33,50 +33,54 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
// These functions assume everything has been authenticated (ValidateBasic passed, and signatures checked)
func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) sdk.Result {
err := k.SetWithdrawAddr(ctx, msg.DelegatorAddress, msg.WithdrawAddress)
if err != nil {
return err.Result()
}
resTags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.DelegatorAddress.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
),
)
return sdk.Result{
Tags: resTags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}
func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) sdk.Result {
rewards, err := k.WithdrawDelegationRewards(ctx, msg.DelegatorAddress, msg.ValidatorAddress)
_, err := k.WithdrawDelegationRewards(ctx, msg.DelegatorAddress, msg.ValidatorAddress)
if err != nil {
return err.Result()
}
return sdk.Result{
Tags: sdk.NewTags(
tags.Rewards, rewards.String(),
tags.Category, tags.TxCategory,
tags.Sender, msg.DelegatorAddress.String(),
tags.Validator, msg.ValidatorAddress.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
),
}
)
return sdk.Result{Events: ctx.EventManager().Events()}
}
func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdrawValidatorCommission, k keeper.Keeper) sdk.Result {
commission, err := k.WithdrawValidatorCommission(ctx, msg.ValidatorAddress)
_, err := k.WithdrawValidatorCommission(ctx, msg.ValidatorAddress)
if err != nil {
return err.Result()
}
return sdk.Result{
Tags: sdk.NewTags(
tags.Commission, commission.String(),
tags.Category, tags.TxCategory,
tags.Sender, msg.ValidatorAddress.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.ValidatorAddress.String()),
),
}
)
return sdk.Result{Events: ctx.EventManager().Events()}
}
func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler {

View File

@ -6,12 +6,15 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/staking/exported"
)
// allocate fees handles distribution of the collected fees
func (k Keeper) AllocateTokens(ctx sdk.Context, sumPreviousPrecommitPower, totalPreviousPower int64,
previousProposer sdk.ConsAddress, previousVotes []abci.VoteInfo) {
func (k Keeper) AllocateTokens(
ctx sdk.Context, sumPreviousPrecommitPower, totalPreviousPower int64,
previousProposer sdk.ConsAddress, previousVotes []abci.VoteInfo,
) {
logger := k.Logger(ctx)
@ -45,6 +48,14 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, sumPreviousPrecommitPower, total
proposerValidator := k.stakingKeeper.ValidatorByConsAddr(ctx, previousProposer)
if proposerValidator != nil {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeProposerReward,
sdk.NewAttribute(types.AttributeKeyAmount, proposerReward.String()),
sdk.NewAttribute(types.AttributeKeyValidator, proposerValidator.GetOperator().String()),
),
)
k.AllocateTokensToValidator(ctx, proposerValidator, proposerReward)
remaining = remaining.Sub(proposerReward)
} else {
@ -80,17 +91,22 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, sumPreviousPrecommitPower, total
// allocate community funding
feePool.CommunityPool = feePool.CommunityPool.Add(remaining)
k.SetFeePool(ctx, feePool)
}
// AllocateTokensToValidator allocate tokens to a particular validator, splitting according to commission
func (k Keeper) AllocateTokensToValidator(ctx sdk.Context, val exported.ValidatorI, tokens sdk.DecCoins) {
// split tokens between validator and delegators according to commission
commission := tokens.MulDec(val.GetCommission())
shared := tokens.Sub(commission)
// update current commission
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCommission,
sdk.NewAttribute(types.AttributeKeyAmount, commission.String()),
sdk.NewAttribute(types.AttributeKeyValidator, val.GetOperator().String()),
),
)
currentCommission := k.GetValidatorAccumulatedCommission(ctx, val.GetOperator())
currentCommission = currentCommission.Add(commission)
k.SetValidatorAccumulatedCommission(ctx, val.GetOperator(), currentCommission)
@ -101,6 +117,13 @@ func (k Keeper) AllocateTokensToValidator(ctx sdk.Context, val exported.Validato
k.SetValidatorCurrentRewards(ctx, val.GetOperator(), currentRewards)
// update outstanding rewards
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeRewards,
sdk.NewAttribute(types.AttributeKeyAmount, tokens.String()),
sdk.NewAttribute(types.AttributeKeyValidator, val.GetOperator().String()),
),
)
outstanding := k.GetValidatorOutstandingRewards(ctx, val.GetOperator())
outstanding = outstanding.Add(tokens)
k.SetValidatorOutstandingRewards(ctx, val.GetOperator(), outstanding)

View File

@ -46,8 +46,14 @@ func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, w
return types.ErrSetWithdrawAddrDisabled(k.codespace)
}
k.SetDelegatorWithdrawAddr(ctx, delegatorAddr, withdrawAddr)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSetWithdrawAddress,
sdk.NewAttribute(types.AttributeKeyWithdrawAddress, withdrawAddr.String()),
),
)
k.SetDelegatorWithdrawAddr(ctx, delegatorAddr, withdrawAddr)
return nil
}
@ -69,35 +75,49 @@ func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddres
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeWithdrawRewards,
sdk.NewAttribute(types.AttributeKeyAmount, rewards.String()),
sdk.NewAttribute(types.AttributeKeyValidator, valAddr.String()),
),
)
// reinitialize the delegation
k.initializeDelegation(ctx, valAddr, delAddr)
return rewards, nil
}
// withdraw validator commission
func (k Keeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, sdk.Error) {
// fetch validator accumulated commission
commission := k.GetValidatorAccumulatedCommission(ctx, valAddr)
if commission.IsZero() {
accumCommission := k.GetValidatorAccumulatedCommission(ctx, valAddr)
if accumCommission.IsZero() {
return nil, types.ErrNoValidatorCommission(k.codespace)
}
coins, remainder := commission.TruncateDecimal()
commission, remainder := accumCommission.TruncateDecimal()
k.SetValidatorAccumulatedCommission(ctx, valAddr, remainder) // leave remainder to withdraw later
// update outstanding
outstanding := k.GetValidatorOutstandingRewards(ctx, valAddr)
k.SetValidatorOutstandingRewards(ctx, valAddr, outstanding.Sub(sdk.NewDecCoins(coins)))
k.SetValidatorOutstandingRewards(ctx, valAddr, outstanding.Sub(sdk.NewDecCoins(commission)))
if !coins.IsZero() {
if !commission.IsZero() {
accAddr := sdk.AccAddress(valAddr)
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, accAddr)
if _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, coins); err != nil {
if _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, commission); err != nil {
return nil, err
}
}
return coins, nil
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeWithdrawCommission,
sdk.NewAttribute(types.AttributeKeyAmount, commission.String()),
),
)
return commission, nil
}

View File

@ -123,12 +123,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) sdk.Tags {
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)
return sdk.EmptyTags()
}
// module end-block
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -1,16 +0,0 @@
package tags
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Distribution tx tags
var (
Rewards = "rewards"
Commission = "commission"
TxCategory = "distribution"
Validator = sdk.TagSrcValidator
Category = sdk.TagCategory
Sender = sdk.TagSender
)

View File

@ -0,0 +1,17 @@
package types
// Distribution module event types
var (
EventTypeSetWithdrawAddress = "set_withdraw_address"
EventTypeRewards = "rewards"
EventTypeCommission = "commission"
EventTypeWithdrawRewards = "withdraw_rewards"
EventTypeWithdrawCommission = "withdraw_commission"
EventTypeProposerReward = "proposer_reward"
AttributeKeyWithdrawAddress = "withdraw_address"
AttributeKeyAmount = "amount"
AttributeKeyValidator = "validator"
AttributeValueCategory = ModuleName
)

View File

@ -66,7 +66,7 @@ func ValidateAccountInGenesis(appGenesisState map[string]json.RawMessage,
return nil
}
type deliverTxfn func([]byte) abci.ResponseDeliverTx
type deliverTxfn func(abci.RequestDeliverTx) abci.ResponseDeliverTx
// deliver a genesis transaction
func DeliverGenTxs(ctx sdk.Context, cdc *codec.Codec, genTxs []json.RawMessage,
@ -76,7 +76,7 @@ func DeliverGenTxs(ctx sdk.Context, cdc *codec.Codec, genTxs []json.RawMessage,
var tx auth.StdTx
cdc.MustUnmarshalJSON(genTx, &tx)
bz := cdc.MustMarshalBinaryLengthPrefixed(tx)
res := deliverTx(bz)
res := deliverTx(abci.RequestDeliverTx{Tx: bz})
if !res.IsOK() {
panic(res.Log)
}

View File

@ -4,8 +4,8 @@ import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
"github.com/cosmos/cosmos-sdk/x/gov/tags"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
@ -37,14 +37,14 @@ func (p Proposer) String() string {
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
func QueryDepositsByTxQuery(cliCtx context.CLIContext, params types.QueryProposalParams) ([]byte, error) {
tags := []string{
fmt.Sprintf("%s='%s'", tags.Action, types.MsgDeposit{}.Type()),
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit),
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
}
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
searchResult, err := utils.QueryTxsByTags(cliCtx, tags, defaultPage, defaultLimit)
searchResult, err := utils.QueryTxsByTags(cliCtx, events, defaultPage, defaultLimit)
if err != nil {
return nil, err
}
@ -79,14 +79,14 @@ func QueryDepositsByTxQuery(cliCtx context.CLIContext, params types.QueryProposa
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
func QueryVotesByTxQuery(cliCtx context.CLIContext, params types.QueryProposalParams) ([]byte, error) {
tags := []string{
fmt.Sprintf("%s='%s'", tags.Action, types.MsgVote{}.Type()),
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote),
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
}
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
searchResult, err := utils.QueryTxsByTags(cliCtx, tags, defaultPage, defaultLimit)
searchResult, err := utils.QueryTxsByTags(cliCtx, events, defaultPage, defaultLimit)
if err != nil {
return nil, err
}
@ -116,15 +116,15 @@ func QueryVotesByTxQuery(cliCtx context.CLIContext, params types.QueryProposalPa
// QueryVoteByTxQuery will query for a single vote via a direct txs tags query.
func QueryVoteByTxQuery(cliCtx context.CLIContext, params types.QueryVoteParams) ([]byte, error) {
tags := []string{
fmt.Sprintf("%s='%s'", tags.Action, types.MsgVote{}.Type()),
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
fmt.Sprintf("%s='%s'", tags.Sender, []byte(params.Voter.String())),
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgVote),
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalVote, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Voter.String())),
}
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
searchResult, err := utils.QueryTxsByTags(cliCtx, tags, defaultPage, defaultLimit)
searchResult, err := utils.QueryTxsByTags(cliCtx, events, defaultPage, defaultLimit)
if err != nil {
return nil, err
}
@ -156,15 +156,15 @@ func QueryVoteByTxQuery(cliCtx context.CLIContext, params types.QueryVoteParams)
// QueryDepositByTxQuery will query for a single deposit via a direct txs tags
// query.
func QueryDepositByTxQuery(cliCtx context.CLIContext, params types.QueryDepositParams) ([]byte, error) {
tags := []string{
fmt.Sprintf("%s='%s'", tags.Action, types.MsgDeposit{}.Type()),
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
fmt.Sprintf("%s='%s'", tags.Sender, []byte(params.Depositor.String())),
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit),
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, []byte(params.Depositor.String())),
}
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
searchResult, err := utils.QueryTxsByTags(cliCtx, tags, defaultPage, defaultLimit)
searchResult, err := utils.QueryTxsByTags(cliCtx, events, defaultPage, defaultLimit)
if err != nil {
return nil, err
}
@ -196,14 +196,14 @@ func QueryDepositByTxQuery(cliCtx context.CLIContext, params types.QueryDepositP
// QueryProposerByTxQuery will query for a proposer of a governance proposal by
// ID.
func QueryProposerByTxQuery(cliCtx context.CLIContext, proposalID uint64) (Proposer, error) {
tags := []string{
fmt.Sprintf("%s='%s'", tags.Action, types.MsgSubmitProposal{}.Type()),
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", proposalID))),
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal),
fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))),
}
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
// support configurable pagination.
searchResult, err := utils.QueryTxsByTags(cliCtx, tags, defaultPage, defaultLimit)
searchResult, err := utils.QueryTxsByTags(cliCtx, events, defaultPage, defaultLimit)
if err != nil {
return Proposer{}, err
}

View File

@ -1,6 +1,8 @@
package gov
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
@ -63,8 +65,15 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
deposit = NewDeposit(proposalID, depositorAddr, depositAmount)
}
keeper.setDeposit(ctx, proposalID, depositorAddr, deposit)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeProposalDeposit,
sdk.NewAttribute(types.AttributeKeyAmount, depositAmount.String()),
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
),
)
keeper.setDeposit(ctx, proposalID, depositorAddr, deposit)
return nil, activatedVotingPeriod
}

View File

@ -4,21 +4,25 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/tags"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
// EndBlocker called every block, process inflation, update validator set
func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags {
// EndBlocker called every block, process inflation, update validator set.
func EndBlocker(ctx sdk.Context, keeper Keeper) {
logger := keeper.Logger(ctx)
resTags := sdk.NewTags()
// delete inactive proposal from store and its deposits
keeper.IterateInactiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal Proposal) bool {
keeper.DeleteProposal(ctx, proposal.ProposalID)
keeper.DeleteDeposits(ctx, proposal.ProposalID)
resTags = resTags.AppendTag(tags.ProposalID, fmt.Sprintf("%d", proposal.ProposalID))
resTags = resTags.AppendTag(tags.ProposalResult, tags.ActionProposalDropped)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeInactiveProposal,
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ProposalID)),
sdk.NewAttribute(types.AttributeKeyProposalResult, types.AttributeValueProposalDropped),
),
)
logger.Info(
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %s (had only %s); deleted",
@ -53,19 +57,19 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags {
err := handler(cacheCtx, proposal.Content)
if err == nil {
proposal.Status = StatusPassed
tagValue = tags.ActionProposalPassed
tagValue = types.AttributeValueProposalPassed
logMsg = "passed"
// write state to the underlying multi-store
writeCache()
} else {
proposal.Status = StatusFailed
tagValue = tags.ActionProposalFailed
tagValue = types.AttributeValueProposalFailed
logMsg = fmt.Sprintf("passed, but failed on execution: %s", err.ABCILog())
}
} else {
proposal.Status = StatusRejected
tagValue = tags.ActionProposalRejected
tagValue = types.AttributeValueProposalRejected
logMsg = "rejected"
}
@ -81,11 +85,13 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags {
),
)
resTags = resTags.AppendTag(tags.ProposalID, fmt.Sprintf("%d", proposal.ProposalID))
resTags = resTags.AppendTag(tags.ProposalResult, tagValue)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeActiveProposal,
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ProposalID)),
sdk.NewAttribute(types.AttributeKeyProposalResult, tagValue),
),
)
return false
})
return resTags
}

View File

@ -9,7 +9,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/tags"
"github.com/cosmos/cosmos-sdk/x/staking"
)
@ -276,8 +275,7 @@ func TestProposalPassedEndblocker(t *testing.T) {
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod)
ctx = ctx.WithBlockHeader(newHeader)
resTags := EndBlocker(ctx, input.keeper)
require.Equal(t, sdk.MakeTag(tags.ProposalResult, tags.ActionProposalPassed), resTags[1])
EndBlocker(ctx, input.keeper)
}
func TestEndBlockerProposalHandlerFailed(t *testing.T) {
@ -323,6 +321,5 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) {
ctx = ctx.WithValue(contextKeyBadProposal, false)
// validate that the proposal fails/has been rejected
resTags := EndBlocker(ctx, input.keeper)
require.Equal(t, sdk.MakeTag(tags.ProposalResult, tags.ActionProposalFailed), resTags[1])
EndBlocker(ctx, input.keeper)
}

View File

@ -4,12 +4,14 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/tags"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
// Handle all "gov" type messages.
func NewHandler(keeper Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case MsgDeposit:
return handleMsgDeposit(ctx, keeper, msg)
@ -38,20 +40,26 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
return err.Result()
}
proposalIDStr := fmt.Sprintf("%d", proposal.ProposalID)
resTags := sdk.NewTags(
tags.ProposalID, proposalIDStr,
tags.Category, tags.TxCategory,
tags.Sender, msg.Proposer.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Proposer.String()),
),
)
if votingStarted {
resTags = resTags.AppendTag(tags.VotingPeriodStart, proposalIDStr)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitProposal,
sdk.NewAttribute(types.AttributeKeyVotingPeriodStart, fmt.Sprintf("%d", proposal.ProposalID)),
),
)
}
return sdk.Result{
Data: keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal.ProposalID),
Tags: resTags,
Data: keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal.ProposalID),
Events: ctx.EventManager().Events(),
}
}
@ -61,21 +69,24 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result
return err.Result()
}
proposalIDStr := fmt.Sprintf("%d", msg.ProposalID)
resTags := sdk.NewTags(
tags.ProposalID, proposalIDStr,
tags.Category, tags.TxCategory,
tags.Sender, msg.Depositor.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Depositor.String()),
),
)
if votingStarted {
resTags = resTags.AppendTag(tags.VotingPeriodStart, proposalIDStr)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeProposalDeposit,
sdk.NewAttribute(types.AttributeKeyVotingPeriodStart, fmt.Sprintf("%d", msg.ProposalID)),
),
)
}
return sdk.Result{
Tags: resTags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}
func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
@ -84,13 +95,14 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
return err.Result()
}
proposalIDStr := fmt.Sprintf("%d", msg.ProposalID)
return sdk.Result{
Tags: sdk.NewTags(
tags.ProposalID, proposalIDStr,
tags.Category, tags.TxCategory,
tags.Sender, msg.Voter.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Voter.String()),
),
}
)
return sdk.Result{Events: ctx.EventManager().Events()}
}

View File

@ -5,6 +5,7 @@ import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/stretchr/testify/require"
)
@ -13,7 +14,7 @@ func TestInvalidMsg(t *testing.T) {
k := Keeper{}
h := NewHandler(k)
res := h(sdk.Context{}, sdk.NewTestMsg())
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized gov message type"))
}

View File

@ -146,12 +146,10 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags {
return sdk.EmptyTags()
}
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
tags := EndBlocker(ctx, am.keeper)
return []abci.ValidatorUpdate{}, tags
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
EndBlocker(ctx, am.keeper)
return []abci.ValidatorUpdate{}
}

View File

@ -36,6 +36,13 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, content Content) (Proposal,
keeper.InsertInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
keeper.setProposalID(ctx, proposalID+1)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitProposal,
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
),
)
return proposal, nil
}

View File

@ -1,25 +0,0 @@
package tags
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Governance tags
const (
ActionProposalDropped = "proposal-dropped" // didn't meet min deposit
ActionProposalPassed = "proposal-passed" // meet vote quorum
ActionProposalRejected = "proposal-rejected" // didn't meet vote quorum
ActionProposalFailed = "proposal-failed" // error on proposal handler
TxCategory = "governance"
ProposalID = "proposal-id"
VotingPeriodStart = "voting-period-start"
ProposalResult = "proposal-result"
)
// SDK tag aliases
var (
Action = sdk.TagAction
Category = sdk.TagCategory
Sender = sdk.TagSender
)

View File

@ -80,10 +80,8 @@ func getMockApp(t *testing.T, numGenAccs int, genState GenesisState, genAccs []a
// gov and staking endblocker
func getEndBlocker(keeper Keeper) sdk.EndBlocker {
return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
tags := EndBlocker(ctx, keeper)
return abci.ResponseEndBlock{
Tags: tags,
}
EndBlocker(ctx, keeper)
return abci.ResponseEndBlock{}
}
}

21
x/gov/types/events.go Normal file
View File

@ -0,0 +1,21 @@
package types
// Governance module event types
const (
EventTypeSubmitProposal = "submit_proposal"
EventTypeProposalDeposit = "proposal_deposit"
EventTypeProposalVote = "proposal_vote"
EventTypeInactiveProposal = "inactive_proposal"
EventTypeActiveProposal = "active_proposal"
AttributeKeyProposalResult = "proposal_result"
AttributeKeyAmount = "amount"
AttributeKeyOption = "option"
AttributeKeyProposalID = "proposal_id"
AttributeKeyVotingPeriodStart = "voting_period_start"
AttributeValueCategory = "governance"
AttributeValueProposalDropped = "proposal_dropped" // didn't meet min deposit
AttributeValueProposalPassed = "proposal_passed" // met vote quorum
AttributeValueProposalRejected = "proposal_rejected" // didn't meet vote quorum
AttributeValueProposalFailed = "proposal_failed" // error on proposal handler
)

View File

@ -1,6 +1,8 @@
package gov
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
@ -22,6 +24,14 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.A
vote := NewVote(proposalID, voterAddr, option)
keeper.setVote(ctx, proposalID, voterAddr, vote)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeProposalVote,
sdk.NewAttribute(types.AttributeKeyOption, option.String()),
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
),
)
return nil
}

View File

@ -2,6 +2,7 @@ package mint
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/mint/internal/types"
)
// BeginBlocker mints new tokens for the previous block.
@ -21,4 +22,14 @@ func BeginBlocker(ctx sdk.Context, k Keeper) {
mintedCoin := minter.BlockProvision(params)
k.AddCollectedFees(ctx, sdk.Coins{mintedCoin})
k.InflateSupply(ctx, mintedCoin.Amount)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeMint,
sdk.NewAttribute(types.AttributeKeyBondedRatio, bondedRatio.String()),
sdk.NewAttribute(types.AttributeKeyInflation, minter.Inflation.String()),
sdk.NewAttribute(types.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
sdk.NewAttribute(types.AttributeKeyAmount, mintedCoin.Amount.String()),
),
)
}

View File

@ -0,0 +1,11 @@
package types
// Minting module event types
const (
EventTypeMint = ModuleName
AttributeKeyBondedRatio = "bonded_ratio"
AttributeKeyInflation = "inflation"
AttributeKeyAnnualProvisions = "annual_provisions"
AttributeKeyAmount = "amount"
)

View File

@ -116,12 +116,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) sdk.Tags {
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlocker(ctx, am.keeper)
return sdk.EmptyTags()
}
// module end-block
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -10,8 +10,7 @@ import (
)
// slashing begin block functionality
func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) sdk.Tags {
func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) {
// Iterate over all the validators which *should* have signed this block
// store whether or not they have actually signed it and slash/unbond any
// which have missed too many blocks in a row (downtime slashing)
@ -30,6 +29,4 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) sdk.Ta
sk.Logger(ctx).Error(fmt.Sprintf("ignored unknown evidence type: %s", evidence.Type))
}
}
return sdk.EmptyTags()
}

View File

@ -49,10 +49,9 @@ func getMockApp(t *testing.T) (*mock.App, staking.Keeper, Keeper) {
// staking endblocker
func getEndBlocker(keeper staking.Keeper) sdk.EndBlocker {
return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates, tags := staking.EndBlocker(ctx, keeper)
validatorUpdates := staking.EndBlocker(ctx, keeper)
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Tags: tags,
}
}
}

View File

@ -4,12 +4,13 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing/tags"
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)
func NewHandler(k Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
// NOTE msg already has validate basic run
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case MsgUnjail:
return handleMsgUnjail(ctx, msg, k)
@ -61,15 +62,15 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result {
return ErrValidatorJailed(k.codespace).Result()
}
// unjail the validator
k.sk.Unjail(ctx, consAddr)
tags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.ValidatorAddr.String(),
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.ValidatorAddr.String()),
),
)
return sdk.Result{
Tags: tags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking"
@ -127,7 +128,7 @@ func TestInvalidMsg(t *testing.T) {
k := Keeper{}
h := NewHandler(k)
res := h(sdk.Context{}, sdk.NewTestMsg())
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized slashing message type"))
}

View File

@ -109,11 +109,25 @@ func (k Keeper) HandleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
// Tendermint. This value is validator.Tokens as sent to Tendermint via
// ABCI, and now received as evidence.
// The fraction is passed in to separately to slash unbonding and rebonding delegations.
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSlash,
sdk.NewAttribute(types.AttributeKeyAddress, consAddr.String()),
sdk.NewAttribute(types.AttributeKeyPower, fmt.Sprintf("%d", power)),
sdk.NewAttribute(types.AttributeKeyReason, types.AttributeValueDoubleSign),
),
)
k.sk.Slash(ctx, consAddr, distributionHeight, power, fraction)
// Jail validator if not already jailed
// begin unbonding validator if not already unbonding (tombstone)
if !validator.IsJailed() {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSlash,
sdk.NewAttribute(types.AttributeKeyJailed, consAddr.String()),
),
)
k.sk.Jail(ctx, consAddr)
}
@ -189,8 +203,19 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
// i.e. at the end of the pre-genesis block (none) = at the beginning of the genesis block.
// That's fine since this is just used to filter unbonding delegations & redelegations.
distributionHeight := height - sdk.ValidatorUpdateDelay - 1
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSlash,
sdk.NewAttribute(types.AttributeKeyAddress, consAddr.String()),
sdk.NewAttribute(types.AttributeKeyPower, fmt.Sprintf("%d", power)),
sdk.NewAttribute(types.AttributeKeyReason, types.AttributeValueMissingSignature),
sdk.NewAttribute(types.AttributeKeyJailed, consAddr.String()),
),
)
k.sk.Slash(ctx, consAddr, distributionHeight, power, k.SlashFractionDowntime(ctx))
k.sk.Jail(ctx, consAddr)
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeJailDuration(ctx))
// We need to reset the counter & array so that the validator won't be immediately slashed for downtime upon rebonding.

View File

@ -395,7 +395,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
newAmt := sdk.TokensFromConsensusPower(101)
got = sh(ctx, NewTestMsgCreateValidator(addrs[1], pks[1], newAmt))
require.True(t, got.IsOK())
validatorUpdates, _ := staking.EndBlocker(ctx, sk)
validatorUpdates := staking.EndBlocker(ctx, sk)
require.Equal(t, 2, len(validatorUpdates))
validator, _ := sk.GetValidator(ctx, addr)
require.Equal(t, sdk.Unbonding, validator.Status)
@ -408,7 +408,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
delTokens := sdk.TokensFromConsensusPower(50)
got = sh(ctx, newTestMsgDelegate(sdk.AccAddress(addrs[2]), addrs[0], delTokens))
require.True(t, got.IsOK())
validatorUpdates, _ = staking.EndBlocker(ctx, sk)
validatorUpdates = staking.EndBlocker(ctx, sk)
require.Equal(t, 2, len(validatorUpdates))
validator, _ = sk.GetValidator(ctx, addr)
require.Equal(t, sdk.Bonded, validator.Status)

View File

@ -127,11 +127,11 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) sdk.Tags {
return BeginBlocker(ctx, req, am.keeper)
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)
}
// module end-block
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
return []abci.ValidatorUpdate{}, sdk.EmptyTags()
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -1,13 +0,0 @@
package tags
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Slashing tags
var (
TxCategory = "slashing"
Category = sdk.TagCategory
Sender = sdk.TagSender
)

View File

@ -0,0 +1,15 @@
package types
// Slashing module event types
var (
EventTypeSlash = "slash"
AttributeKeyAddress = "address"
AttributeKeyPower = "power"
AttributeKeyReason = "reason"
AttributeKeyJailed = "jailed"
AttributeValueDoubleSign = "double_sign"
AttributeValueMissingSignature = "missing_signature"
AttributeValueCategory = ModuleName
)

View File

@ -36,11 +36,10 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) {
// getEndBlocker returns a staking endblocker.
func getEndBlocker(keeper Keeper) sdk.EndBlocker {
return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates, tags := EndBlocker(ctx, keeper)
validatorUpdates := EndBlocker(ctx, keeper)
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Tags: tags,
}
}
}

View File

@ -138,20 +138,27 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
isBondTx := contains(typesQuerySlice, "bond")
isUnbondTx := contains(typesQuerySlice, "unbond")
isRedTx := contains(typesQuerySlice, "redelegate")
var txs []*sdk.SearchTxsResult
var actions []string
var (
txs []*sdk.SearchTxsResult
actions []string
)
switch {
case isBondTx:
actions = append(actions, types.MsgDelegate{}.Type())
case isUnbondTx:
actions = append(actions, types.MsgUndelegate{}.Type())
case isRedTx:
actions = append(actions, types.MsgBeginRedelegate{}.Type())
case noQuery:
actions = append(actions, types.MsgDelegate{}.Type())
actions = append(actions, types.MsgUndelegate{}.Type())
actions = append(actions, types.MsgBeginRedelegate{}.Type())
default:
w.WriteHeader(http.StatusNoContent)
return

View File

@ -10,7 +10,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
"github.com/cosmos/cosmos-sdk/x/staking/tags"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
@ -25,15 +24,15 @@ func contains(stringSlice []string, txType string) bool {
}
// queries staking txs
func queryTxs(cliCtx context.CLIContext, tag string, delegatorAddr string) (*sdk.SearchTxsResult, error) {
func queryTxs(cliCtx context.CLIContext, action string, delegatorAddr string) (*sdk.SearchTxsResult, error) {
page := 1
limit := 100
tags := []string{
fmt.Sprintf("%s='%s'", tags.Action, tag),
fmt.Sprintf("%s='%s'", tags.Sender, delegatorAddr),
events := []string{
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, action),
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, delegatorAddr),
}
return utils.QueryTxsByTags(cliCtx, tags, page, limit)
return utils.QueryTxsByTags(cliCtx, events, page, limit)
}
func queryBonds(cliCtx context.CLIContext, endpoint string) http.HandlerFunc {

View File

@ -10,13 +10,13 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/cosmos/cosmos-sdk/x/staking/tags"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
// NOTE msg already has validate basic run
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case types.MsgCreateValidator:
return handleMsgCreateValidator(ctx, msg, k)
@ -41,9 +41,7 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
}
// Called every block, update validator set
func EndBlocker(ctx sdk.Context, k keeper.Keeper) ([]abci.ValidatorUpdate, sdk.Tags) {
resTags := sdk.NewTags()
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
// Calculate validator set changes.
//
// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
@ -66,11 +64,13 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) ([]abci.ValidatorUpdate, sdk.T
continue
}
resTags = resTags.AppendTags(sdk.NewTags(
tags.Action, tags.ActionCompleteUnbonding,
tags.Delegator, dvPair.DelegatorAddress.String(),
tags.SrcValidator, dvPair.ValidatorAddress.String(),
))
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCompleteUnbonding,
sdk.NewAttribute(types.AttributeKeyValidator, dvPair.ValidatorAddress.String()),
sdk.NewAttribute(types.AttributeKeyDelegator, dvPair.DelegatorAddress.String()),
),
)
}
// Remove all mature redelegations from the red queue.
@ -82,16 +82,17 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) ([]abci.ValidatorUpdate, sdk.T
continue
}
resTags = resTags.AppendTags(sdk.NewTags(
tags.Action, tags.ActionCompleteRedelegation,
tags.Category, tags.TxCategory,
tags.Delegator, dvvTriplet.DelegatorAddress.String(),
tags.SrcValidator, dvvTriplet.ValidatorSrcAddress.String(),
tags.DstValidator, dvvTriplet.ValidatorDstAddress.String(),
))
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCompleteRedelegation,
sdk.NewAttribute(types.AttributeKeyDelegator, dvvTriplet.DelegatorAddress.String()),
sdk.NewAttribute(types.AttributeKeySrcValidator, dvvTriplet.ValidatorSrcAddress.String()),
sdk.NewAttribute(types.AttributeKeyDstValidator, dvvTriplet.ValidatorDstAddress.String()),
),
)
}
return validatorUpdates, resTags
return validatorUpdates
}
// These functions assume everything has been authenticated,
@ -150,15 +151,20 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
return err.Result()
}
resTags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.DelegatorAddress.String(),
tags.DstValidator, msg.ValidatorAddress.String(),
)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCreateValidator,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress.String()),
sdk.NewAttribute(types.AttributeKeyAmount, msg.Value.Amount.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
),
})
return sdk.Result{
Tags: resTags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}
func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keeper.Keeper) sdk.Result {
@ -200,14 +206,20 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe
k.SetValidator(ctx, validator)
resTags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.ValidatorAddress.String(),
)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeEditValidator,
sdk.NewAttribute(types.AttributeKeyCommissionRate, validator.Commission.String()),
sdk.NewAttribute(types.AttributeKeyMinSelfDelegation, validator.MinSelfDelegation.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.ValidatorAddress.String()),
),
})
return sdk.Result{
Tags: resTags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}
func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper) sdk.Result {
@ -225,15 +237,20 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper)
return err.Result()
}
resTags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.DelegatorAddress.String(),
tags.DstValidator, msg.ValidatorAddress.String(),
)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeDelegate,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress.String()),
sdk.NewAttribute(types.AttributeKeyAmount, msg.Amount.Amount.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
),
})
return sdk.Result{
Tags: resTags,
}
return sdk.Result{Events: ctx.EventManager().Events()}
}
func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keeper) sdk.Result {
@ -253,15 +270,22 @@ func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keep
return err.Result()
}
finishTime := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime)
resTags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.DelegatorAddress.String(),
tags.SrcValidator, msg.ValidatorAddress.String(),
tags.EndTime, completionTime.Format(time.RFC3339),
)
completionTimeBz := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeUnbond,
sdk.NewAttribute(types.AttributeKeyValidator, msg.ValidatorAddress.String()),
sdk.NewAttribute(types.AttributeKeyAmount, msg.Amount.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
),
})
return sdk.Result{Data: finishTime, Tags: resTags}
return sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}
}
func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k keeper.Keeper) sdk.Result {
@ -283,14 +307,21 @@ func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k k
return err.Result()
}
finishTime := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime)
resTags := sdk.NewTags(
tags.Category, tags.TxCategory,
tags.Sender, msg.DelegatorAddress.String(),
tags.SrcValidator, msg.ValidatorSrcAddress.String(),
tags.DstValidator, msg.ValidatorDstAddress.String(),
tags.EndTime, completionTime.Format(time.RFC3339),
)
completionTimeBz := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRedelegate,
sdk.NewAttribute(types.AttributeKeySrcValidator, msg.ValidatorSrcAddress.String()),
sdk.NewAttribute(types.AttributeKeyDstValidator, msg.ValidatorDstAddress.String()),
sdk.NewAttribute(types.AttributeKeyAmount, msg.Amount.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
),
})
return sdk.Result{Data: finishTime, Tags: resTags}
return sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}
}

View File

@ -1277,7 +1277,7 @@ func TestInvalidMsg(t *testing.T) {
k := keep.Keeper{}
h := NewHandler(k)
res := h(sdk.Context{}, sdk.NewTestMsg())
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized staking message type"))
}

View File

@ -469,7 +469,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.In
}
if subtractAccount {
_, err := k.bankKeeper.DelegateCoins(ctx, delegation.DelegatorAddress, sdk.Coins{sdk.NewCoin(k.GetParams(ctx).BondDenom, bondAmt)})
err := k.bankKeeper.DelegateCoins(ctx, delegation.DelegatorAddress, sdk.Coins{sdk.NewCoin(k.GetParams(ctx).BondDenom, bondAmt)})
if err != nil {
return sdk.Dec{}, err
}
@ -620,7 +620,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delAddr sdk.AccAddress,
// track undelegation only when remaining or truncated shares are non-zero
if !entry.Balance.IsZero() {
_, err := k.bankKeeper.UndelegateCoins(ctx, ubd.DelegatorAddress, sdk.Coins{sdk.NewCoin(k.GetParams(ctx).BondDenom, entry.Balance)})
err := k.bankKeeper.UndelegateCoins(ctx, ubd.DelegatorAddress, sdk.Coins{sdk.NewCoin(k.GetParams(ctx).BondDenom, entry.Balance)})
if err != nil {
return err
}

View File

@ -158,11 +158,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
}
// module begin-block
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags {
return sdk.EmptyTags()
}
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) {
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker(ctx, am.keeper)
}

View File

@ -1,20 +0,0 @@
package tags
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// staking tags
var (
ActionCompleteUnbonding = "complete-unbonding"
ActionCompleteRedelegation = "complete-redelegation"
TxCategory = "staking"
Action = sdk.TagAction
Category = sdk.TagCategory
Sender = sdk.TagSender
SrcValidator = sdk.TagSrcValidator
DstValidator = sdk.TagDstValidator
Delegator = sdk.TagDelegator
EndTime = "end-time"
)

22
x/staking/types/events.go Normal file
View File

@ -0,0 +1,22 @@
package types
// Staking module event types
var (
EventTypeCompleteUnbonding = "complete_unbonding"
EventTypeCompleteRedelegation = "complete_redelegation"
EventTypeCreateValidator = "create_validator"
EventTypeEditValidator = "edit_validator"
EventTypeDelegate = "delegate"
EventTypeUnbond = "unbond"
EventTypeRedelegate = "redelegate"
AttributeKeyValidator = "validator"
AttributeKeyCommissionRate = "commission_rate"
AttributeKeyMinSelfDelegation = "min_self_delegation"
AttributeKeySrcValidator = "source_validator"
AttributeKeyDstValidator = "destination_validator"
AttributeKeyDelegator = "delegator"
AttributeKeyAmount = "amount"
AttributeKeyCompletionTime = "completion_time"
AttributeValueCategory = ModuleName
)

View File

@ -19,8 +19,8 @@ type FeeCollectionKeeper interface {
// expected bank keeper (noalias)
type BankKeeper interface {
DelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error)
UndelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error)
DelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
UndelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
}
// AccountKeeper expected Account keeper