github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/types/events.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  
     8  	abci "github.com/ari-anchor/sei-tendermint/abci/types"
     9  	"github.com/ari-anchor/sei-tendermint/internal/jsontypes"
    10  	tmquery "github.com/ari-anchor/sei-tendermint/internal/pubsub/query"
    11  	"github.com/ari-anchor/sei-tendermint/proto/tendermint/types"
    12  )
    13  
    14  // Reserved event types (alphabetically sorted).
    15  const (
    16  	// Block level events for mass consumption by users.
    17  	// These events are triggered from the state package,
    18  	// after a block has been committed.
    19  	// These are also used by the tx indexer for async indexing.
    20  	// All of this data can be fetched through the rpc.
    21  	EventNewBlockValue            = "NewBlock"
    22  	EventNewBlockHeaderValue      = "NewBlockHeader"
    23  	EventNewEvidenceValue         = "NewEvidence"
    24  	EventTxValue                  = "Tx"
    25  	EventValidatorSetUpdatesValue = "ValidatorSetUpdates"
    26  
    27  	// Internal consensus events.
    28  	// These are used for testing the consensus state machine.
    29  	// They can also be used to build real-time consensus visualizers.
    30  	EventCompleteProposalValue = "CompleteProposal"
    31  	// The BlockSyncStatus event will be emitted when the node switching
    32  	// state sync mechanism between the consensus reactor and the blocksync reactor.
    33  	EventBlockSyncStatusValue = "BlockSyncStatus"
    34  	EventLockValue            = "Lock"
    35  	EventNewRoundValue        = "NewRound"
    36  	EventNewRoundStepValue    = "NewRoundStep"
    37  	EventPolkaValue           = "Polka"
    38  	EventRelockValue          = "Relock"
    39  	EventStateSyncStatusValue = "StateSyncStatus"
    40  	EventTimeoutProposeValue  = "TimeoutPropose"
    41  	EventTimeoutWaitValue     = "TimeoutWait"
    42  	EventValidBlockValue      = "ValidBlock"
    43  	EventVoteValue            = "Vote"
    44  
    45  	// Events emitted by the evidence reactor when evidence is validated
    46  	// and before it is committed
    47  	EventEvidenceValidatedValue = "EvidenceValidated"
    48  )
    49  
    50  // Pre-populated ABCI Tendermint-reserved events
    51  var (
    52  	EventNewBlock = abci.Event{
    53  		Type: strings.Split(EventTypeKey, ".")[0],
    54  		Attributes: []abci.EventAttribute{
    55  			{
    56  				Key:   []byte(strings.Split(EventTypeKey, ".")[1]),
    57  				Value: []byte(EventNewBlockValue),
    58  			},
    59  		},
    60  	}
    61  
    62  	EventNewBlockHeader = abci.Event{
    63  		Type: strings.Split(EventTypeKey, ".")[0],
    64  		Attributes: []abci.EventAttribute{
    65  			{
    66  				Key:   []byte(strings.Split(EventTypeKey, ".")[1]),
    67  				Value: []byte(EventNewBlockHeaderValue),
    68  			},
    69  		},
    70  	}
    71  
    72  	EventNewEvidence = abci.Event{
    73  		Type: strings.Split(EventTypeKey, ".")[0],
    74  		Attributes: []abci.EventAttribute{
    75  			{
    76  				Key:   []byte(strings.Split(EventTypeKey, ".")[1]),
    77  				Value: []byte(EventNewEvidenceValue),
    78  			},
    79  		},
    80  	}
    81  
    82  	EventTx = abci.Event{
    83  		Type: strings.Split(EventTypeKey, ".")[0],
    84  		Attributes: []abci.EventAttribute{
    85  			{
    86  				Key:   []byte(strings.Split(EventTypeKey, ".")[1]),
    87  				Value: []byte(EventTxValue),
    88  			},
    89  		},
    90  	}
    91  )
    92  
    93  // ENCODING / DECODING
    94  
    95  // EventData is satisfied by types that can be published as event data.
    96  //
    97  // Implementations of this interface that contain ABCI event metadata should
    98  // also implement the eventlog.ABCIEventer extension interface to expose those
    99  // metadata to the event log machinery. Event data that do not contain ABCI
   100  // metadata can safely omit this.
   101  type EventData interface {
   102  	// The value must support encoding as a type-tagged JSON object.
   103  	jsontypes.Tagged
   104  	ToLegacy() LegacyEventData
   105  }
   106  
   107  type LegacyEventData interface {
   108  	jsontypes.Tagged
   109  }
   110  
   111  func init() {
   112  	jsontypes.MustRegister(EventDataBlockSyncStatus{})
   113  	jsontypes.MustRegister(EventDataCompleteProposal{})
   114  	jsontypes.MustRegister(EventDataNewBlock{})
   115  	jsontypes.MustRegister(EventDataNewBlockHeader{})
   116  	jsontypes.MustRegister(EventDataNewEvidence{})
   117  	jsontypes.MustRegister(EventDataNewRound{})
   118  	jsontypes.MustRegister(EventDataRoundState{})
   119  	jsontypes.MustRegister(EventDataStateSyncStatus{})
   120  	jsontypes.MustRegister(EventDataTx{})
   121  	jsontypes.MustRegister(EventDataValidatorSetUpdates{})
   122  	jsontypes.MustRegister(EventDataVote{})
   123  	jsontypes.MustRegister(EventDataEvidenceValidated{})
   124  	jsontypes.MustRegister(LegacyEventDataNewBlock{})
   125  	jsontypes.MustRegister(LegacyEventDataTx{})
   126  	jsontypes.MustRegister(EventDataString(""))
   127  }
   128  
   129  // Most event messages are basic types (a block, a transaction)
   130  // but some (an input to a call tx or a receive) are more exotic
   131  
   132  type EventDataNewBlock struct {
   133  	Block   *Block  `json:"block"`
   134  	BlockID BlockID `json:"block_id"`
   135  
   136  	ResultFinalizeBlock abci.ResponseFinalizeBlock `json:"result_finalize_block"`
   137  }
   138  
   139  // TypeTag implements the required method of jsontypes.Tagged.
   140  func (EventDataNewBlock) TypeTag() string { return "tendermint/event/NewBlock_new" }
   141  
   142  // ABCIEvents implements the eventlog.ABCIEventer interface.
   143  func (e EventDataNewBlock) ABCIEvents() []abci.Event {
   144  	base := []abci.Event{eventWithAttr(BlockHeightKey, fmt.Sprint(e.Block.Header.Height))}
   145  	return append(base, e.ResultFinalizeBlock.Events...)
   146  }
   147  
   148  type LegacyEventDataNewBlock struct {
   149  	Block            *LegacyBlock            `json:"block"`
   150  	ResultBeginBlock abci.ResponseBeginBlock `json:"result_begin_block"`
   151  	ResultEndBlock   LegacyResponseEndBlock  `json:"result_end_block"`
   152  }
   153  
   154  func (LegacyEventDataNewBlock) TypeTag() string { return "tendermint/event/NewBlock" }
   155  
   156  type LegacyEvidence struct {
   157  	Evidence EvidenceList `json:"evidence"`
   158  }
   159  
   160  type LegacyBlock struct {
   161  	Header     `json:"header"`
   162  	Data       `json:"data"`
   163  	Evidence   LegacyEvidence `json:"evidence"`
   164  	LastCommit *Commit        `json:"last_commit"`
   165  }
   166  
   167  type LegacyResponseEndBlock struct {
   168  	ValidatorUpdates      []abci.ValidatorUpdate `json:"validator_updates"`
   169  	ConsensusParamUpdates *LegacyConsensusParams `json:"consensus_param_updates,omitempty"`
   170  	Events                []abci.Event           `json:"events,omitempty"`
   171  }
   172  
   173  type LegacyConsensusParams struct {
   174  	Block     *LegacyBlockParams     `json:"block,omitempty"`
   175  	Evidence  *LegacyEvidenceParams  `json:"evidence,omitempty"`
   176  	Validator *types.ValidatorParams `json:"validator,omitempty"`
   177  	Version   *LegacyVersionParams   `json:"version,omitempty"`
   178  }
   179  
   180  type LegacyBlockParams struct {
   181  	MaxBytes string `json:"max_bytes,omitempty"`
   182  	MaxGas   string `json:"max_gas,omitempty"`
   183  }
   184  
   185  type LegacyEvidenceParams struct {
   186  	MaxAgeNumBlocks string `json:"max_age_num_blocks,omitempty"`
   187  	MaxAgeDuration  string `json:"max_age_duration"`
   188  	MaxBytes        string `json:"max_bytes,omitempty"`
   189  }
   190  
   191  type LegacyVersionParams struct {
   192  	AppVersion string `json:"app_version,omitempty"`
   193  }
   194  
   195  func (e EventDataNewBlock) ToLegacy() LegacyEventData {
   196  	block := &LegacyBlock{}
   197  	if e.Block != nil {
   198  		block = &LegacyBlock{
   199  			Header:     e.Block.Header,
   200  			Data:       e.Block.Data,
   201  			Evidence:   LegacyEvidence{Evidence: e.Block.Evidence},
   202  			LastCommit: e.Block.LastCommit,
   203  		}
   204  	}
   205  	consensusParamUpdates := &LegacyConsensusParams{}
   206  	if e.ResultFinalizeBlock.ConsensusParamUpdates != nil {
   207  		if e.ResultFinalizeBlock.ConsensusParamUpdates.Block != nil {
   208  			consensusParamUpdates.Block = &LegacyBlockParams{
   209  				MaxBytes: fmt.Sprintf("%d", e.ResultFinalizeBlock.ConsensusParamUpdates.Block.MaxBytes),
   210  				MaxGas:   fmt.Sprintf("%d", e.ResultFinalizeBlock.ConsensusParamUpdates.Block.MaxGas),
   211  			}
   212  		}
   213  		if e.ResultFinalizeBlock.ConsensusParamUpdates.Evidence != nil {
   214  			consensusParamUpdates.Evidence = &LegacyEvidenceParams{
   215  				MaxAgeNumBlocks: fmt.Sprintf("%d", e.ResultFinalizeBlock.ConsensusParamUpdates.Evidence.MaxAgeNumBlocks),
   216  				MaxAgeDuration:  fmt.Sprintf("%d", e.ResultFinalizeBlock.ConsensusParamUpdates.Evidence.MaxAgeDuration),
   217  				MaxBytes:        fmt.Sprintf("%d", e.ResultFinalizeBlock.ConsensusParamUpdates.Evidence.MaxBytes),
   218  			}
   219  		}
   220  		if e.ResultFinalizeBlock.ConsensusParamUpdates.Validator != nil {
   221  			consensusParamUpdates.Validator = &types.ValidatorParams{
   222  				PubKeyTypes: e.ResultFinalizeBlock.ConsensusParamUpdates.Validator.PubKeyTypes,
   223  			}
   224  		}
   225  		if e.ResultFinalizeBlock.ConsensusParamUpdates.Version != nil {
   226  			consensusParamUpdates.Version = &LegacyVersionParams{
   227  				AppVersion: fmt.Sprintf("%d", e.ResultFinalizeBlock.ConsensusParamUpdates.Version.AppVersion),
   228  			}
   229  		}
   230  	}
   231  	return &LegacyEventDataNewBlock{
   232  		Block:            block,
   233  		ResultBeginBlock: abci.ResponseBeginBlock{Events: e.ResultFinalizeBlock.Events},
   234  		ResultEndBlock: LegacyResponseEndBlock{
   235  			ValidatorUpdates:      e.ResultFinalizeBlock.ValidatorUpdates,
   236  			Events:                []abci.Event{},
   237  			ConsensusParamUpdates: consensusParamUpdates,
   238  		},
   239  	}
   240  }
   241  
   242  type EventDataNewBlockHeader struct {
   243  	Header Header `json:"header"`
   244  
   245  	NumTxs              int64                      `json:"num_txs,string"` // Number of txs in a block
   246  	ResultFinalizeBlock abci.ResponseFinalizeBlock `json:"result_finalize_block"`
   247  }
   248  
   249  // TypeTag implements the required method of jsontypes.Tagged.
   250  func (EventDataNewBlockHeader) TypeTag() string { return "tendermint/event/NewBlockHeader" }
   251  
   252  // ABCIEvents implements the eventlog.ABCIEventer interface.
   253  func (e EventDataNewBlockHeader) ABCIEvents() []abci.Event {
   254  	base := []abci.Event{eventWithAttr(BlockHeightKey, fmt.Sprint(e.Header.Height))}
   255  	return append(base, e.ResultFinalizeBlock.Events...)
   256  }
   257  
   258  func (e EventDataNewBlockHeader) ToLegacy() LegacyEventData {
   259  	return e
   260  }
   261  
   262  type EventDataNewEvidence struct {
   263  	Evidence Evidence `json:"evidence"`
   264  
   265  	Height int64 `json:"height,string"`
   266  }
   267  
   268  // TypeTag implements the required method of jsontypes.Tagged.
   269  func (EventDataNewEvidence) TypeTag() string { return "tendermint/event/NewEvidence" }
   270  
   271  func (e EventDataNewEvidence) ToLegacy() LegacyEventData {
   272  	return e
   273  }
   274  
   275  // All txs fire EventDataTx
   276  type EventDataTx struct {
   277  	abci.TxResult
   278  }
   279  
   280  // TypeTag implements the required method of jsontypes.Tagged.
   281  func (EventDataTx) TypeTag() string { return "tendermint/event/Tx_new" }
   282  
   283  // ABCIEvents implements the eventlog.ABCIEventer interface.
   284  func (e EventDataTx) ABCIEvents() []abci.Event {
   285  	base := []abci.Event{
   286  		eventWithAttr(TxHashKey, fmt.Sprintf("%X", Tx(e.Tx).Hash())),
   287  		eventWithAttr(TxHeightKey, fmt.Sprintf("%d", e.Height)),
   288  	}
   289  	return append(base, e.Result.Events...)
   290  }
   291  
   292  type LegacyEventDataTx struct {
   293  	TxResult LegacyTxResult `json:"TxResult"`
   294  }
   295  
   296  type LegacyTxResult struct {
   297  	Height string       `json:"height,omitempty"`
   298  	Index  uint32       `json:"index,omitempty"`
   299  	Tx     []byte       `json:"tx,omitempty"`
   300  	Result LegacyResult `json:"result"`
   301  }
   302  
   303  type LegacyResult struct {
   304  	Log       string       `json:"log,omitempty"`
   305  	GasWanted string       `json:"gas_wanted,omitempty"`
   306  	GasUsed   string       `json:"gas_used,omitempty"`
   307  	Events    []abci.Event `json:"events,omitempty"`
   308  }
   309  
   310  func (LegacyEventDataTx) TypeTag() string {
   311  	return "tendermint/event/Tx"
   312  }
   313  
   314  func (e EventDataTx) ToLegacy() LegacyEventData {
   315  	return LegacyEventDataTx{
   316  		TxResult: LegacyTxResult{
   317  			Height: fmt.Sprintf("%d", e.Height),
   318  			Index:  e.Index,
   319  			Tx:     e.Tx,
   320  			Result: LegacyResult{
   321  				Log:       e.Result.Log,
   322  				GasWanted: fmt.Sprintf("%d", e.Result.GasWanted),
   323  				GasUsed:   fmt.Sprintf("%d", e.Result.GasUsed),
   324  				Events:    e.Result.Events,
   325  			},
   326  		},
   327  	}
   328  }
   329  
   330  // NOTE: This goes into the replay WAL
   331  type EventDataRoundState struct {
   332  	Height int64  `json:"height,string"`
   333  	Round  int32  `json:"round"`
   334  	Step   string `json:"step"`
   335  }
   336  
   337  // TypeTag implements the required method of jsontypes.Tagged.
   338  func (EventDataRoundState) TypeTag() string { return "tendermint/event/RoundState" }
   339  
   340  func (e EventDataRoundState) ToLegacy() LegacyEventData {
   341  	return e
   342  }
   343  
   344  type ValidatorInfo struct {
   345  	Address Address `json:"address"`
   346  	Index   int32   `json:"index"`
   347  }
   348  
   349  type EventDataNewRound struct {
   350  	Height int64  `json:"height,string"`
   351  	Round  int32  `json:"round"`
   352  	Step   string `json:"step"`
   353  
   354  	Proposer ValidatorInfo `json:"proposer"`
   355  }
   356  
   357  // TypeTag implements the required method of jsontypes.Tagged.
   358  func (EventDataNewRound) TypeTag() string { return "tendermint/event/NewRound" }
   359  
   360  func (e EventDataNewRound) ToLegacy() LegacyEventData {
   361  	return e
   362  }
   363  
   364  type EventDataCompleteProposal struct {
   365  	Height int64  `json:"height,string"`
   366  	Round  int32  `json:"round"`
   367  	Step   string `json:"step"`
   368  
   369  	BlockID BlockID `json:"block_id"`
   370  }
   371  
   372  // TypeTag implements the required method of jsontypes.Tagged.
   373  func (EventDataCompleteProposal) TypeTag() string { return "tendermint/event/CompleteProposal" }
   374  
   375  func (e EventDataCompleteProposal) ToLegacy() LegacyEventData {
   376  	return e
   377  }
   378  
   379  type EventDataVote struct {
   380  	Vote *Vote
   381  }
   382  
   383  // TypeTag implements the required method of jsontypes.Tagged.
   384  func (EventDataVote) TypeTag() string { return "tendermint/event/Vote" }
   385  
   386  func (e EventDataVote) ToLegacy() LegacyEventData {
   387  	return e
   388  }
   389  
   390  type EventDataString string
   391  
   392  // TypeTag implements the required method of jsontypes.Tagged.
   393  func (EventDataString) TypeTag() string { return "tendermint/event/ProposalString" }
   394  
   395  func (e EventDataString) ToLegacy() LegacyEventData {
   396  	return e
   397  }
   398  
   399  type EventDataValidatorSetUpdates struct {
   400  	ValidatorUpdates []*Validator `json:"validator_updates"`
   401  }
   402  
   403  // TypeTag implements the required method of jsontypes.Tagged.
   404  func (EventDataValidatorSetUpdates) TypeTag() string { return "tendermint/event/ValidatorSetUpdates" }
   405  
   406  func (e EventDataValidatorSetUpdates) ToLegacy() LegacyEventData {
   407  	return e
   408  }
   409  
   410  // EventDataBlockSyncStatus shows the fastsync status and the
   411  // height when the node state sync mechanism changes.
   412  type EventDataBlockSyncStatus struct {
   413  	Complete bool  `json:"complete"`
   414  	Height   int64 `json:"height,string"`
   415  }
   416  
   417  // TypeTag implements the required method of jsontypes.Tagged.
   418  func (EventDataBlockSyncStatus) TypeTag() string { return "tendermint/event/FastSyncStatus" }
   419  
   420  func (e EventDataBlockSyncStatus) ToLegacy() LegacyEventData {
   421  	return e
   422  }
   423  
   424  // EventDataStateSyncStatus shows the statesync status and the
   425  // height when the node state sync mechanism changes.
   426  type EventDataStateSyncStatus struct {
   427  	Complete bool  `json:"complete"`
   428  	Height   int64 `json:"height,string"`
   429  }
   430  
   431  // TypeTag implements the required method of jsontypes.Tagged.
   432  func (EventDataStateSyncStatus) TypeTag() string { return "tendermint/event/StateSyncStatus" }
   433  
   434  func (e EventDataStateSyncStatus) ToLegacy() LegacyEventData {
   435  	return e
   436  }
   437  
   438  type EventDataEvidenceValidated struct {
   439  	Evidence Evidence `json:"evidence"`
   440  
   441  	Height int64 `json:"height,string"`
   442  }
   443  
   444  // TypeTag implements the required method of jsontypes.Tagged.
   445  func (EventDataEvidenceValidated) TypeTag() string { return "tendermint/event/EvidenceValidated" }
   446  
   447  func (e EventDataEvidenceValidated) ToLegacy() LegacyEventData {
   448  	return e
   449  }
   450  
   451  // PUBSUB
   452  
   453  const (
   454  	// EventTypeKey is a reserved composite key for event name.
   455  	EventTypeKey = "tm.event"
   456  
   457  	// TxHashKey is a reserved key, used to specify transaction's hash.
   458  	// see EventBus#PublishEventTx
   459  	TxHashKey = "tx.hash"
   460  
   461  	// TxHeightKey is a reserved key, used to specify transaction block's height.
   462  	// see EventBus#PublishEventTx
   463  	TxHeightKey = "tx.height"
   464  
   465  	// BlockHeightKey is a reserved key used for indexing FinalizeBlock events.
   466  	BlockHeightKey = "block.height"
   467  )
   468  
   469  var (
   470  	EventQueryCompleteProposal    = QueryForEvent(EventCompleteProposalValue)
   471  	EventQueryLock                = QueryForEvent(EventLockValue)
   472  	EventQueryNewBlock            = QueryForEvent(EventNewBlockValue)
   473  	EventQueryNewBlockHeader      = QueryForEvent(EventNewBlockHeaderValue)
   474  	EventQueryNewEvidence         = QueryForEvent(EventNewEvidenceValue)
   475  	EventQueryNewRound            = QueryForEvent(EventNewRoundValue)
   476  	EventQueryNewRoundStep        = QueryForEvent(EventNewRoundStepValue)
   477  	EventQueryPolka               = QueryForEvent(EventPolkaValue)
   478  	EventQueryRelock              = QueryForEvent(EventRelockValue)
   479  	EventQueryTimeoutPropose      = QueryForEvent(EventTimeoutProposeValue)
   480  	EventQueryTimeoutWait         = QueryForEvent(EventTimeoutWaitValue)
   481  	EventQueryTx                  = QueryForEvent(EventTxValue)
   482  	EventQueryValidatorSetUpdates = QueryForEvent(EventValidatorSetUpdatesValue)
   483  	EventQueryValidBlock          = QueryForEvent(EventValidBlockValue)
   484  	EventQueryVote                = QueryForEvent(EventVoteValue)
   485  	EventQueryBlockSyncStatus     = QueryForEvent(EventBlockSyncStatusValue)
   486  	EventQueryStateSyncStatus     = QueryForEvent(EventStateSyncStatusValue)
   487  	EventQueryEvidenceValidated   = QueryForEvent(EventEvidenceValidatedValue)
   488  )
   489  
   490  func EventQueryTxFor(tx Tx) *tmquery.Query {
   491  	return tmquery.MustCompile(fmt.Sprintf("%s='%s' AND %s='%X'", EventTypeKey, EventTxValue, TxHashKey, tx.Hash()))
   492  }
   493  
   494  func QueryForEvent(eventValue string) *tmquery.Query {
   495  	return tmquery.MustCompile(fmt.Sprintf("%s='%s'", EventTypeKey, eventValue))
   496  }
   497  
   498  // BlockEventPublisher publishes all block related events
   499  type BlockEventPublisher interface {
   500  	PublishEventNewBlock(EventDataNewBlock) error
   501  	PublishEventNewBlockHeader(EventDataNewBlockHeader) error
   502  	PublishEventNewEvidence(EventDataNewEvidence) error
   503  	PublishEventTx(EventDataTx) error
   504  	PublishEventValidatorSetUpdates(EventDataValidatorSetUpdates) error
   505  }
   506  
   507  type TxEventPublisher interface {
   508  	PublishEventTx(EventDataTx) error
   509  }
   510  
   511  // eventWithAttr constructs a single abci.Event with a single attribute.
   512  // The type of the event and the name of the attribute are obtained by
   513  // splitting the event type on period (e.g., "foo.bar").
   514  func eventWithAttr(etype, value string) abci.Event {
   515  	parts := strings.SplitN(etype, ".", 2)
   516  	return abci.Event{
   517  		Type: parts[0],
   518  		Attributes: []abci.EventAttribute{{
   519  			Key: []byte(parts[1]), Value: []byte(value),
   520  		}},
   521  	}
   522  }
   523  
   524  func TryUnmarshalEventData(data json.RawMessage) (EventData, error) {
   525  	var eventData EventData
   526  	err := jsontypes.Unmarshal(data, &eventData)
   527  	if err != nil {
   528  		return nil, err
   529  	}
   530  	return eventData, nil
   531  }