github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/types/events.go (about) 1 package types 2 3 import ( 4 "encoding/hex" 5 6 "github.com/onflow/cadence/runtime/common" 7 gethCommon "github.com/onflow/go-ethereum/common" 8 "github.com/onflow/go-ethereum/rlp" 9 10 "github.com/onflow/cadence" 11 12 "github.com/onflow/flow-go/model/flow" 13 ) 14 15 const ( 16 EventTypeBlockExecuted flow.EventType = "EVM.BlockExecuted" 17 EventTypeTransactionExecuted flow.EventType = "EVM.TransactionExecuted" 18 ) 19 20 type EventPayload interface { 21 // ToCadence converts the event to Cadence event 22 ToCadence(location common.Location) (cadence.Event, error) 23 } 24 25 type Event struct { 26 Etype flow.EventType 27 Payload EventPayload 28 } 29 30 // todo we might have to break this event into two (tx included /tx executed) if size becomes an issue 31 32 type transactionEvent struct { 33 Payload []byte // transaction RLP-encoded payload 34 Result *Result // transaction execution result 35 BlockHeight uint64 36 BlockHash gethCommon.Hash 37 } 38 39 // NewTransactionEvent creates a new transaction event with the given parameters 40 // - result: the result of the transaction execution 41 // - payload: the RLP-encoded payload of the transaction 42 // - blockHeight: the height of the block where the transaction is included 43 // - blockHash: the hash of the block where the transaction is included 44 func NewTransactionEvent( 45 result *Result, 46 payload []byte, 47 blockHeight uint64, 48 blockHash gethCommon.Hash, 49 ) *Event { 50 return &Event{ 51 Etype: EventTypeTransactionExecuted, 52 Payload: &transactionEvent{ 53 BlockHeight: blockHeight, 54 BlockHash: blockHash, 55 Payload: payload, 56 Result: result, 57 }, 58 } 59 } 60 61 func (p *transactionEvent) ToCadence(location common.Location) (cadence.Event, error) { 62 var encodedLogs []byte 63 var err error 64 if len(p.Result.Logs) > 0 { 65 encodedLogs, err = rlp.EncodeToBytes(p.Result.Logs) 66 if err != nil { 67 return cadence.Event{}, err 68 } 69 } 70 71 deployedAddress := cadence.String("") 72 if p.Result.DeployedContractAddress != nil { 73 deployedAddress = cadence.String(p.Result.DeployedContractAddress.String()) 74 } 75 76 eventType := cadence.NewEventType( 77 location, 78 string(EventTypeTransactionExecuted), 79 []cadence.Field{ 80 cadence.NewField("hash", cadence.StringType), 81 cadence.NewField("index", cadence.UInt16Type), 82 cadence.NewField("type", cadence.UInt8Type), 83 cadence.NewField("payload", cadence.StringType), 84 cadence.NewField("errorCode", cadence.UInt16Type), 85 cadence.NewField("gasConsumed", cadence.UInt64Type), 86 cadence.NewField("contractAddress", cadence.StringType), 87 cadence.NewField("logs", cadence.StringType), 88 cadence.NewField("blockHeight", cadence.UInt64Type), 89 // todo we can remove hash and just reference block by height (evm-gateway dependency) 90 cadence.NewField("blockHash", cadence.StringType), 91 }, 92 nil, 93 ) 94 95 return cadence.NewEvent([]cadence.Value{ 96 cadence.String(p.Result.TxHash.String()), 97 cadence.NewUInt16(p.Result.Index), 98 cadence.NewUInt8(p.Result.TxType), 99 cadence.String(hex.EncodeToString(p.Payload)), 100 cadence.NewUInt16(uint16(p.Result.ResultSummary().ErrorCode)), 101 cadence.NewUInt64(p.Result.GasConsumed), 102 deployedAddress, 103 cadence.String(hex.EncodeToString(encodedLogs)), 104 cadence.NewUInt64(p.BlockHeight), 105 cadence.String(p.BlockHash.String()), 106 }).WithType(eventType), nil 107 } 108 109 type blockEvent struct { 110 *Block 111 } 112 113 // NewBlockEvent creates a new block event with the given block as payload. 114 func NewBlockEvent(block *Block) *Event { 115 return &Event{ 116 Etype: EventTypeBlockExecuted, 117 Payload: &blockEvent{block}, 118 } 119 } 120 121 func (p *blockEvent) ToCadence(location common.Location) (cadence.Event, error) { 122 hashes := make([]cadence.Value, len(p.TransactionHashes)) 123 for i, hash := range p.TransactionHashes { 124 hashes[i] = cadence.String(hash.String()) 125 } 126 127 blockHash, err := p.Hash() 128 if err != nil { 129 return cadence.Event{}, err 130 } 131 132 eventType := cadence.NewEventType( 133 location, 134 string(EventTypeBlockExecuted), 135 []cadence.Field{ 136 cadence.NewField("height", cadence.UInt64Type), 137 cadence.NewField("hash", cadence.StringType), 138 cadence.NewField("timestamp", cadence.UInt64Type), 139 cadence.NewField("totalSupply", cadence.IntType), 140 cadence.NewField("totalGasUsed", cadence.UInt64Type), 141 cadence.NewField("parentHash", cadence.StringType), 142 cadence.NewField("receiptRoot", cadence.StringType), 143 cadence.NewField( 144 "transactionHashes", 145 cadence.NewVariableSizedArrayType(cadence.StringType), 146 ), 147 }, 148 nil, 149 ) 150 151 return cadence.NewEvent([]cadence.Value{ 152 cadence.NewUInt64(p.Height), 153 cadence.String(blockHash.String()), 154 cadence.NewUInt64(p.Timestamp), 155 cadence.NewIntFromBig(p.TotalSupply), 156 cadence.NewUInt64(p.TotalGasUsed), 157 cadence.String(p.ParentBlockHash.String()), 158 cadence.String(p.ReceiptRoot.String()), 159 cadence.NewArray(hashes).WithType(cadence.NewVariableSizedArrayType(cadence.StringType)), 160 }).WithType(eventType), nil 161 } 162 163 type BlockEventPayload struct { 164 Height uint64 `cadence:"height"` 165 Hash string `cadence:"hash"` 166 Timestamp uint64 `cadence:"timestamp"` 167 TotalSupply cadence.Int `cadence:"totalSupply"` 168 TotalGasUsed uint64 `cadence:"totalGasUsed"` 169 ParentBlockHash string `cadence:"parentHash"` 170 ReceiptRoot string `cadence:"receiptRoot"` 171 TransactionHashes []cadence.String `cadence:"transactionHashes"` 172 } 173 174 // DecodeBlockEventPayload decodes Cadence event into block event payload. 175 func DecodeBlockEventPayload(event cadence.Event) (*BlockEventPayload, error) { 176 var block BlockEventPayload 177 err := cadence.DecodeFields(event, &block) 178 return &block, err 179 } 180 181 type TransactionEventPayload struct { 182 Hash string `cadence:"hash"` 183 Index uint16 `cadence:"index"` 184 TransactionType uint8 `cadence:"type"` 185 Payload string `cadence:"payload"` 186 ErrorCode uint16 `cadence:"errorCode"` 187 GasConsumed uint64 `cadence:"gasConsumed"` 188 ContractAddress string `cadence:"contractAddress"` 189 Logs string `cadence:"logs"` 190 BlockHeight uint64 `cadence:"blockHeight"` 191 BlockHash string `cadence:"blockHash"` 192 } 193 194 // DecodeTransactionEventPayload decodes Cadence event into transaction event payload. 195 func DecodeTransactionEventPayload(event cadence.Event) (*TransactionEventPayload, error) { 196 var tx TransactionEventPayload 197 err := cadence.DecodeFields(event, &tx) 198 return &tx, err 199 }