Skip to content

Commit

Permalink
Aggregate and expose EVM-related event payloads
Browse files Browse the repository at this point in the history
  • Loading branch information
m-Peter committed Oct 25, 2024
1 parent e95b413 commit ecdb6ac
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 23 deletions.
6 changes: 3 additions & 3 deletions models/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ func (b *Block) Hash() (gethCommon.Hash, error) {

// decodeBlockEvent takes a cadence event that contains executed block payload and
// decodes it into the Block type.
func decodeBlockEvent(event cadence.Event) (*Block, error) {
func decodeBlockEvent(event cadence.Event) (*Block, *events.BlockEventPayload, error) {
payload, err := events.DecodeBlockEventPayload(event)
if err != nil {
return nil, fmt.Errorf(
return nil, nil, fmt.Errorf(
"failed to Cadence-decode EVM block event [%s]: %w",
event.String(),
err,
Expand Down Expand Up @@ -102,7 +102,7 @@ func decodeBlockEvent(event cadence.Event) (*Block, error) {
PrevRandao: payload.PrevRandao,
},
FixedHash: fixedHash,
}, nil
}, payload, nil
}

// blockV0 is the block format, prior to adding the PrevRandao field.
Expand Down
4 changes: 2 additions & 2 deletions models/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func Test_DecodeBlockExecutedEvent(t *testing.T) {
encEv, err := ev.Payload.ToCadence(flowGo.Previewnet)
require.NoError(t, err)

decBlock, err := decodeBlockEvent(encEv)
decBlock, _, err := decodeBlockEvent(encEv)
require.NoError(t, err)

assert.Equal(t, decBlock, block)
Expand Down Expand Up @@ -150,7 +150,7 @@ func Test_DecodingLegacyBlockExecutedEvent(t *testing.T) {
hashToCadenceArrayValue(block.TransactionHashRoot),
}).WithType(eventType)

b, err := decodeBlockEvent(legacyEvent)
b, _, err := decodeBlockEvent(legacyEvent)
require.NoError(t, err)

require.Equal(t, block.ParentBlockHash, b.ParentBlockHash)
Expand Down
29 changes: 23 additions & 6 deletions models/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ func isTransactionExecutedEvent(event cadence.Event) bool {
// CadenceEvents contains Flow emitted events containing one or zero evm block executed event,
// and multiple or zero evm transaction events.
type CadenceEvents struct {
events flow.BlockEvents // Flow events for a specific flow block
block *Block // EVM block (at most one per Flow block)
transactions []Transaction // transactions in the EVM block
receipts []*Receipt // receipts for transactions
events flow.BlockEvents // Flow events for a specific flow block
block *Block // EVM block (at most one per Flow block)
blockEventPayload *events.BlockEventPayload // EVM.BlockExecuted event payload (at most one per Flow block)
transactions []Transaction // transactions in the EVM block
txEventPayloads []events.TransactionEventPayload // EVM.TransactionExecuted event payloads
receipts []*Receipt // receipts for transactions
}

// NewCadenceEvents decodes the events into evm types.
Expand Down Expand Up @@ -111,22 +113,24 @@ func decodeCadenceEvents(events flow.BlockEvents) (*CadenceEvents, error) {
return nil, fmt.Errorf("EVM block was already set for Flow block: %d", events.Height)
}

block, err := decodeBlockEvent(val)
block, blockEventPayload, err := decodeBlockEvent(val)
if err != nil {
return nil, err
}

e.block = block
e.blockEventPayload = blockEventPayload
continue
}

if isTransactionExecutedEvent(val) {
tx, receipt, err := decodeTransactionEvent(val)
tx, receipt, txEventPayload, err := decodeTransactionEvent(val)
if err != nil {
return nil, err
}

e.transactions = append(e.transactions, tx)
e.txEventPayloads = append(e.txEventPayloads, *txEventPayload)
e.receipts = append(e.receipts, receipt)
}
}
Expand Down Expand Up @@ -162,12 +166,25 @@ func (c *CadenceEvents) Block() *Block {
return c.block
}

// BlockEventPayload returns the EVM.BlockExecuted event payload. If the Flow block
// events do not contain an EVM block, the return value is nil.
func (c *CadenceEvents) BlockEventPayload() *events.BlockEventPayload {
return c.blockEventPayload
}

// Transactions included in the EVM block, if event doesn't
// contain EVM transactions the return value is nil.
func (c *CadenceEvents) Transactions() []Transaction {
return c.transactions
}

// TxEventPayloads returns the EVM.TransactionExecuted event payloads for the
// current EVM block. If the Flow block events do not contain any EVM transactions
// the return value is nil.
func (c *CadenceEvents) TxEventPayloads() []events.TransactionEventPayload {
return c.txEventPayloads
}

// Receipts included in the EVM block, if event doesn't
// contain EVM transactions the return value is nil.
func (c *CadenceEvents) Receipts() []*Receipt {
Expand Down
14 changes: 13 additions & 1 deletion models/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func TestCadenceEvents_Block(t *testing.T) {
}

// generate single block
_, blockEvent, err := newBlock(1, hashes)
block, blockEvent, err := newBlock(1, hashes)
require.NoError(t, err)
blockEvent.TransactionIndex = 4
blockEvent.EventIndex = 0
Expand All @@ -216,13 +216,25 @@ func TestCadenceEvents_Block(t *testing.T) {
cdcEvents.events.Events,
)

// assert we have collected the EVM.BlockExecuted event payload
blockEventPayload := cdcEvents.blockEventPayload
blockHash, err := block.Hash()
require.NoError(t, err)
assert.Equal(t, blockHash, blockEventPayload.Hash)

// assert that EVM transactions & receipts are sorted by their
// TransactionIndex field
for i := 0; i < txCount; i++ {
tx := cdcEvents.transactions[i]
receipt := cdcEvents.receipts[i]
assert.Equal(t, tx.Hash(), receipt.TxHash)
assert.Equal(t, uint(i), receipt.TransactionIndex)

// assert we have collected the EVM.TransactionExecuted event payloads
// in their correct order.
txEventPayload := cdcEvents.TxEventPayloads()[i]
assert.Equal(t, tx.Hash(), txEventPayload.Hash)
assert.Equal(t, blockEventPayload.Height, txEventPayload.BlockHeight)
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion models/receipt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func Test_DecodeReceipts(t *testing.T) {
cdcEv, rec := createTestEvent(t, evmTxBinary)

_, receipt, err := decodeTransactionEvent(cdcEv)
_, receipt, _, err := decodeTransactionEvent(cdcEv)
require.NoError(t, err)

for i, l := range rec.Logs {
Expand Down
29 changes: 23 additions & 6 deletions models/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,19 @@ func (tc TransactionCall) MarshalBinary() ([]byte, error) {
// decodeTransactionEvent takes a cadence event for transaction executed
// and decodes its payload into a Transaction interface and a Receipt.
// The concrete type will be either a TransactionCall or a DirectCall.
func decodeTransactionEvent(event cadence.Event) (Transaction, *Receipt, error) {
func decodeTransactionEvent(event cadence.Event) (
Transaction,
*Receipt,
*events.TransactionEventPayload,
error,
) {
txEvent, err := events.DecodeTransactionEventPayload(event)
if err != nil {
return nil, nil, fmt.Errorf("failed to Cadence decode transaction event [%s]: %w", event.String(), err)
return nil, nil, nil, fmt.Errorf(
"failed to Cadence decode transaction event [%s]: %w",
event.String(),
err,
)
}

gethReceipt := &gethTypes.Receipt{
Expand All @@ -186,7 +195,7 @@ func decodeTransactionEvent(event cadence.Event) (Transaction, *Receipt, error)
if len(txEvent.Logs) > 0 {
err = rlp.Decode(bytes.NewReader(txEvent.Logs), &gethReceipt.Logs)
if err != nil {
return nil, nil, fmt.Errorf("failed to RLP-decode logs: %w", err)
return nil, nil, nil, fmt.Errorf("failed to RLP-decode logs: %w", err)
}
}

Expand All @@ -211,19 +220,27 @@ func decodeTransactionEvent(event cadence.Event) (Transaction, *Receipt, error)
if txEvent.TransactionType == types.DirectCallTxType {
directCall, err := types.DirectCallFromEncoded(txEvent.Payload)
if err != nil {
return nil, nil, fmt.Errorf("failed to RLP-decode direct call [%x]: %w", txEvent.Payload, err)
return nil, nil, nil, fmt.Errorf(
"failed to RLP-decode direct call [%x]: %w",
txEvent.Payload,
err,
)
}
tx = DirectCall{DirectCall: directCall}
} else {
gethTx := &gethTypes.Transaction{}
if err := gethTx.UnmarshalBinary(txEvent.Payload); err != nil {
return nil, nil, fmt.Errorf("failed to RLP-decode transaction [%x]: %w", txEvent.Payload, err)
return nil, nil, nil, fmt.Errorf(
"failed to RLP-decode transaction [%x]: %w",
txEvent.Payload,
err,
)
}
receipt.EffectiveGasPrice = gethTx.EffectiveGasTipValue(nil)
tx = TransactionCall{Transaction: gethTx}
}

return tx, receipt, nil
return tx, receipt, txEvent, nil
}

func UnmarshalTransaction(value []byte) (Transaction, error) {
Expand Down
8 changes: 4 additions & 4 deletions models/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func createTestEvent(t *testing.T, txBinary string) (cadence.Event, *types.Resul
func Test_DecodeEVMTransaction(t *testing.T) {
cdcEv, _ := createTestEvent(t, evmTxBinary)

decTx, _, err := decodeTransactionEvent(cdcEv)
decTx, _, _, err := decodeTransactionEvent(cdcEv)
require.NoError(t, err)
require.IsType(t, TransactionCall{}, decTx)

Expand Down Expand Up @@ -131,7 +131,7 @@ func Test_DecodeEVMTransaction(t *testing.T) {
func Test_DecodeDirectCall(t *testing.T) {
cdcEv, _ := createTestEvent(t, directCallBinary)

decTx, _, err := decodeTransactionEvent(cdcEv)
decTx, _, _, err := decodeTransactionEvent(cdcEv)
require.NoError(t, err)
require.IsType(t, DirectCall{}, decTx)

Expand Down Expand Up @@ -179,7 +179,7 @@ func Test_UnmarshalTransaction(t *testing.T) {

cdcEv, _ := createTestEvent(t, evmTxBinary)

tx, _, err := decodeTransactionEvent(cdcEv)
tx, _, _, err := decodeTransactionEvent(cdcEv)
require.NoError(t, err)

encodedTx, err := tx.MarshalBinary()
Expand Down Expand Up @@ -233,7 +233,7 @@ func Test_UnmarshalTransaction(t *testing.T) {

cdcEv, _ := createTestEvent(t, directCallBinary)

tx, _, err := decodeTransactionEvent(cdcEv)
tx, _, _, err := decodeTransactionEvent(cdcEv)
require.NoError(t, err)

encodedTx, err := tx.MarshalBinary()
Expand Down

0 comments on commit ecdb6ac

Please sign in to comment.