diff --git a/.pending/breaking/sdk/4387-Refactor-the-us b/.pending/breaking/sdk/4387-Refactor-the-us new file mode 100644 index 0000000000..0d868640ce --- /dev/null +++ b/.pending/breaking/sdk/4387-Refactor-the-us @@ -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()` diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index c35d79175b..d421a4f076 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -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 diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index c552ed4d64..a706bead0c 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -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)) } diff --git a/docs/spec/bank/04_events.md b/docs/spec/bank/04_events.md new file mode 100644 index 0000000000..bacc531d39 --- /dev/null +++ b/docs/spec/bank/04_events.md @@ -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} | diff --git a/docs/spec/bank/04_tags.md b/docs/spec/bank/04_tags.md deleted file mode 100644 index 0a7f382c2a..0000000000 --- a/docs/spec/bank/04_tags.md +++ /dev/null @@ -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} | diff --git a/docs/spec/bank/README.md b/docs/spec/bank/README.md index cd32692101..f4c583af98 100644 --- a/docs/spec/bank/README.md +++ b/docs/spec/bank/README.md @@ -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)** diff --git a/docs/spec/crisis/03_events.md b/docs/spec/crisis/03_events.md new file mode 100644 index 0000000000..f645e823b7 --- /dev/null +++ b/docs/spec/crisis/03_events.md @@ -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} | diff --git a/docs/spec/crisis/03_tags.md b/docs/spec/crisis/03_tags.md deleted file mode 100644 index a6a4a738ca..0000000000 --- a/docs/spec/crisis/03_tags.md +++ /dev/null @@ -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} | diff --git a/docs/spec/crisis/README.md b/docs/spec/crisis/README.md index 2031788002..6fae6fe52e 100644 --- a/docs/spec/crisis/README.md +++ b/docs/spec/crisis/README.md @@ -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)** diff --git a/docs/spec/distribution/06_events.md b/docs/spec/distribution/06_events.md new file mode 100644 index 0000000000..08a22b660f --- /dev/null +++ b/docs/spec/distribution/06_events.md @@ -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} | diff --git a/docs/spec/distribution/06_tags.md b/docs/spec/distribution/06_tags.md deleted file mode 100644 index 12a5687093..0000000000 --- a/docs/spec/distribution/06_tags.md +++ /dev/null @@ -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} | diff --git a/docs/spec/distribution/README.md b/docs/spec/distribution/README.md index 506ba9f488..cf306c4e45 100644 --- a/docs/spec/distribution/README.md +++ b/docs/spec/distribution/README.md @@ -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)** diff --git a/docs/spec/governance/04_events.md b/docs/spec/governance/04_events.md new file mode 100644 index 0000000000..b2dd73490d --- /dev/null +++ b/docs/spec/governance/04_events.md @@ -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. diff --git a/docs/spec/governance/04_tags.md b/docs/spec/governance/04_tags.md deleted file mode 100644 index fb547e0ee8..0000000000 --- a/docs/spec/governance/04_tags.md +++ /dev/null @@ -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} | diff --git a/docs/spec/governance/README.md b/docs/spec/governance/README.md index 769ba03ec8..5f9ebc31ca 100644 --- a/docs/spec/governance/README.md +++ b/docs/spec/governance/README.md @@ -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)** diff --git a/docs/spec/mint/05_events.md b/docs/spec/mint/05_events.md new file mode 100644 index 0000000000..a98d8db73d --- /dev/null +++ b/docs/spec/mint/05_events.md @@ -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} | diff --git a/docs/spec/mint/README.md b/docs/spec/mint/README.md index d0feb6b5fe..b9f9bc8c1e 100644 --- a/docs/spec/mint/README.md +++ b/docs/spec/mint/README.md @@ -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) diff --git a/docs/spec/slashing/06_events.md b/docs/spec/slashing/06_events.md new file mode 100644 index 0000000000..a98e6529d1 --- /dev/null +++ b/docs/spec/slashing/06_events.md @@ -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} | diff --git a/docs/spec/slashing/06_tags.md b/docs/spec/slashing/06_tags.md deleted file mode 100644 index 8ba7e1db98..0000000000 --- a/docs/spec/slashing/06_tags.md +++ /dev/null @@ -1,13 +0,0 @@ -# Tags - -The slashing module emits the following events/tags: - -## Handlers - -### MsgUnjail - -| Key | Value | -|------------|----------------------------| -| `action` | `unjail` | -| `category` | `slashing` | -| `sender` | {validatorOperatorAddress} | diff --git a/docs/spec/slashing/README.md b/docs/spec/slashing/README.md index c7b7a04be8..fbcb704fff 100644 --- a/docs/spec/slashing/README.md +++ b/docs/spec/slashing/README.md @@ -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)** diff --git a/docs/spec/staking/06_events.md b/docs/spec/staking/06_events.md new file mode 100644 index 0000000000..85b498bc37 --- /dev/null +++ b/docs/spec/staking/06_events.md @@ -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 diff --git a/docs/spec/staking/06_tags.md b/docs/spec/staking/06_tags.md deleted file mode 100644 index bf64b9d560..0000000000 --- a/docs/spec/staking/06_tags.md +++ /dev/null @@ -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 diff --git a/docs/spec/staking/README.md b/docs/spec/staking/README.md index 4265e75a32..a34274b7a1 100644 --- a/docs/spec/staking/README.md +++ b/docs/spec/staking/README.md @@ -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)** diff --git a/go.mod b/go.mod index 613d7b2268..6c9013094e 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 9948cade88..f9ed61b070 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/server/mock/app_test.go b/server/mock/app_test.go index 707c22c85e..3dd451970c 100644 --- a/server/mock/app_test.go +++ b/server/mock/app_test.go @@ -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() diff --git a/types/context.go b/types/context.go index de426bfe7e..32486d4842 100644 --- a/types/context.go +++ b/types/context.go @@ -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 -} +} \ No newline at end of file diff --git a/types/events.go b/types/events.go new file mode 100644 index 0000000000..a105c8d066 --- /dev/null +++ b/types/events.go @@ -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 +} diff --git a/types/events_test.go b/types/events_test.go new file mode 100644 index 0000000000..538f1ed8bd --- /dev/null +++ b/types/events_test.go @@ -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)) +} diff --git a/types/module/module.go b/types/module/module.go index ca2f0ed3ff..f6083882d9 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -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(), } } diff --git a/types/result.go b/types/result.go index b5ebc38c13..31986f48ba 100644 --- a/types/result.go +++ b/types/result.go @@ -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()) diff --git a/types/tags.go b/types/tags.go deleted file mode 100644 index ebfdfc8f27..0000000000 --- a/types/tags.go +++ /dev/null @@ -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 -} diff --git a/types/tags_test.go b/types/tags_test.go deleted file mode 100644 index 9ce59cf7fc..0000000000 --- a/types/tags_test.go +++ /dev/null @@ -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())) -} diff --git a/x/auth/module.go b/x/auth/module.go index e9bdf61d72..a5852e2625 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -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{} } diff --git a/x/bank/handler.go b/x/bank/handler.go index a1c4f2adf4..4bdabaf575 100644 --- a/x/bank/handler.go +++ b/x/bank/handler.go @@ -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()} } diff --git a/x/bank/handler_test.go b/x/bank/handler_test.go index 69021d30b4..da97e547f5 100644 --- a/x/bank/handler_test.go +++ b/x/bank/handler_test.go @@ -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")) } diff --git a/x/bank/internal/keeper/keeper.go b/x/bank/internal/keeper/keeper.go index 5d7abfc901..2ae5b9f7e6 100644 --- a/x/bank/internal/keeper/keeper.go +++ b/x/bank/internal/keeper/keeper.go @@ -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. diff --git a/x/bank/internal/keeper/keeper_test.go b/x/bank/internal/keeper/keeper_test.go index 8758af817b..cd46b22ef1 100644 --- a/x/bank/internal/keeper/keeper_test.go +++ b/x/bank/internal/keeper/keeper_test.go @@ -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) diff --git a/x/bank/internal/types/events.go b/x/bank/internal/types/events.go new file mode 100644 index 0000000000..db831a297f --- /dev/null +++ b/x/bank/internal/types/events.go @@ -0,0 +1,11 @@ +package types + +// Bank module event types +var ( + EventTypeTransfer = "transfer" + + AttributeKeyRecipient = "recipient" + AttributeKeySender = "sender" + + AttributeValueCategory = ModuleName +) diff --git a/x/bank/internal/types/tags.go b/x/bank/internal/types/tags.go deleted file mode 100644 index 9877d75915..0000000000 --- a/x/bank/internal/types/tags.go +++ /dev/null @@ -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" -) diff --git a/x/bank/module.go b/x/bank/module.go index bcb415a906..bd0a8d54db 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -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{} } diff --git a/x/crisis/handler.go b/x/crisis/handler.go index 012b82edde..867d3203a3 100644 --- a/x/crisis/handler.go +++ b/x/crisis/handler.go @@ -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()} } diff --git a/x/crisis/handler_test.go b/x/crisis/handler_test.go index 9632ebc52d..6e8a0941a2 100644 --- a/x/crisis/handler_test.go +++ b/x/crisis/handler_test.go @@ -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")) } diff --git a/x/crisis/module.go b/x/crisis/module.go index c3dd7a41f5..cecf816d73 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -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{} } diff --git a/x/crisis/tags/tags.go b/x/crisis/tags/tags.go deleted file mode 100644 index da3c667936..0000000000 --- a/x/crisis/tags/tags.go +++ /dev/null @@ -1,11 +0,0 @@ -package tags - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// Crisis module tags -var ( - Sender = sdk.TagSender - Invariant = "invariant" -) diff --git a/x/crisis/types/events.go b/x/crisis/types/events.go new file mode 100644 index 0000000000..5f05cf9e72 --- /dev/null +++ b/x/crisis/types/events.go @@ -0,0 +1,9 @@ +package types + +// Crisis module event types +var ( + EventTypeInvariant = "invariant" + + AttributeValueCrisis = ModuleName + AttributeKeyRoute = "route" +) diff --git a/x/distribution/abci.go b/x/distribution/abci.go index 237145c2e3..de7df339e2 100644 --- a/x/distribution/abci.go +++ b/x/distribution/abci.go @@ -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) - } diff --git a/x/distribution/alias.go b/x/distribution/alias.go index c44dfaab25..7cb5afe96a 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -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 ) diff --git a/x/distribution/handler.go b/x/distribution/handler.go index 3602bfabb3..ca047cec36 100644 --- a/x/distribution/handler.go +++ b/x/distribution/handler.go @@ -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 { diff --git a/x/distribution/keeper/allocation.go b/x/distribution/keeper/allocation.go index 73ed04f60a..6da5d6d805 100644 --- a/x/distribution/keeper/allocation.go +++ b/x/distribution/keeper/allocation.go @@ -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) diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 37ce7b859d..7c29dbfb8d 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -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 } diff --git a/x/distribution/module.go b/x/distribution/module.go index a915c49b89..4fb6ccba61 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -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{} } diff --git a/x/distribution/tags/tags.go b/x/distribution/tags/tags.go deleted file mode 100644 index 96dadacd74..0000000000 --- a/x/distribution/tags/tags.go +++ /dev/null @@ -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 -) diff --git a/x/distribution/types/events.go b/x/distribution/types/events.go new file mode 100644 index 0000000000..c5fb7c826e --- /dev/null +++ b/x/distribution/types/events.go @@ -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 +) diff --git a/x/genutil/gentx.go b/x/genutil/gentx.go index 82c89f2db9..0dc14de225 100644 --- a/x/genutil/gentx.go +++ b/x/genutil/gentx.go @@ -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) } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index d1605b801f..878083df2e 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -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 } diff --git a/x/gov/deposit.go b/x/gov/deposit.go index 292d12012d..bbaf3efdb3 100644 --- a/x/gov/deposit.go +++ b/x/gov/deposit.go @@ -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 } diff --git a/x/gov/endblocker.go b/x/gov/endblocker.go index a3fe512e58..d9d7933e05 100644 --- a/x/gov/endblocker.go +++ b/x/gov/endblocker.go @@ -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 } diff --git a/x/gov/endblocker_test.go b/x/gov/endblocker_test.go index 24bbb939cc..4936f4ad65 100644 --- a/x/gov/endblocker_test.go +++ b/x/gov/endblocker_test.go @@ -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) } diff --git a/x/gov/handler.go b/x/gov/handler.go index 15b7b75078..11011baff6 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -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()} + } diff --git a/x/gov/handler_test.go b/x/gov/handler_test.go index 8b8ad17cb5..1a655611a6 100644 --- a/x/gov/handler_test.go +++ b/x/gov/handler_test.go @@ -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")) } diff --git a/x/gov/module.go b/x/gov/module.go index 73db7cdeb2..cc53f4e1b8 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -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{} } diff --git a/x/gov/proposal.go b/x/gov/proposal.go index cdba45bbf3..ef9b7e89e2 100644 --- a/x/gov/proposal.go +++ b/x/gov/proposal.go @@ -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 } diff --git a/x/gov/tags/tags.go b/x/gov/tags/tags.go deleted file mode 100644 index 56fec9c449..0000000000 --- a/x/gov/tags/tags.go +++ /dev/null @@ -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 -) diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 861e9f66bf..ef329a39f4 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -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{} } } diff --git a/x/gov/types/events.go b/x/gov/types/events.go new file mode 100644 index 0000000000..b823d4daca --- /dev/null +++ b/x/gov/types/events.go @@ -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 +) diff --git a/x/gov/vote.go b/x/gov/vote.go index a92e24af4d..7ebb352cc7 100644 --- a/x/gov/vote.go +++ b/x/gov/vote.go @@ -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 } diff --git a/x/mint/abci.go b/x/mint/abci.go index dee058e696..6e38198be0 100644 --- a/x/mint/abci.go +++ b/x/mint/abci.go @@ -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()), + ), + ) } diff --git a/x/mint/internal/types/events.go b/x/mint/internal/types/events.go new file mode 100644 index 0000000000..678def7bfc --- /dev/null +++ b/x/mint/internal/types/events.go @@ -0,0 +1,11 @@ +package types + +// Minting module event types +const ( + EventTypeMint = ModuleName + + AttributeKeyBondedRatio = "bonded_ratio" + AttributeKeyInflation = "inflation" + AttributeKeyAnnualProvisions = "annual_provisions" + AttributeKeyAmount = "amount" +) diff --git a/x/mint/module.go b/x/mint/module.go index 41a47ac41c..e8e07d94ef 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -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{} } diff --git a/x/slashing/abci.go b/x/slashing/abci.go index c9ca3116ba..ef21e4477e 100644 --- a/x/slashing/abci.go +++ b/x/slashing/abci.go @@ -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() } diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index c3745175c2..44a89daae6 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -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, } } } diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 919279a6f1..be7885885a 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -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()} } diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index dce7dd2136..bd3ab2f30a 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -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")) } diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 3fdd1f1ae9..fe6fde2f1d 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -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. diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 01f44b8eb3..98a2043429 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -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) diff --git a/x/slashing/module.go b/x/slashing/module.go index 8ac01d9ef5..3538f96d65 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -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{} } diff --git a/x/slashing/tags/tags.go b/x/slashing/tags/tags.go deleted file mode 100644 index 48e5bcba2f..0000000000 --- a/x/slashing/tags/tags.go +++ /dev/null @@ -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 -) diff --git a/x/slashing/types/events.go b/x/slashing/types/events.go new file mode 100644 index 0000000000..08e2daaa70 --- /dev/null +++ b/x/slashing/types/events.go @@ -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 +) diff --git a/x/staking/app_test.go b/x/staking/app_test.go index 41fb081c16..9dd0ed47eb 100644 --- a/x/staking/app_test.go +++ b/x/staking/app_test.go @@ -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, } } } diff --git a/x/staking/client/rest/query.go b/x/staking/client/rest/query.go index 3a10eb42d3..271406c02c 100644 --- a/x/staking/client/rest/query.go +++ b/x/staking/client/rest/query.go @@ -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 diff --git a/x/staking/client/rest/utils.go b/x/staking/client/rest/utils.go index 1d07c04a2e..726133b573 100644 --- a/x/staking/client/rest/utils.go +++ b/x/staking/client/rest/utils.go @@ -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 { diff --git a/x/staking/handler.go b/x/staking/handler.go index be96d94a5d..3bedb34e62 100644 --- a/x/staking/handler.go +++ b/x/staking/handler.go @@ -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()} } diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index 5d020ecb30..6aea3541c3 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -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")) } diff --git a/x/staking/keeper/delegation.go b/x/staking/keeper/delegation.go index 6005be3744..8dd85e3acb 100644 --- a/x/staking/keeper/delegation.go +++ b/x/staking/keeper/delegation.go @@ -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 } diff --git a/x/staking/module.go b/x/staking/module.go index 0c4e9a61a5..49cfbf605e 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -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) } diff --git a/x/staking/tags/tags.go b/x/staking/tags/tags.go deleted file mode 100644 index 8468748dbb..0000000000 --- a/x/staking/tags/tags.go +++ /dev/null @@ -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" -) diff --git a/x/staking/types/events.go b/x/staking/types/events.go new file mode 100644 index 0000000000..f0155fda1a --- /dev/null +++ b/x/staking/types/events.go @@ -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 +) diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 4470daba89..ffbd6c58fa 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -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