2022-02-08 12:42:15 -08:00
|
|
|
package ethereum
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"github.com/certusone/wormhole/node/pkg/common"
|
|
|
|
"github.com/certusone/wormhole/node/pkg/ethereum/abi"
|
|
|
|
"github.com/certusone/wormhole/node/pkg/vaa"
|
|
|
|
eth_common "github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// SECURITY: Hardcoded ABI identifier for the LogMessagePublished topic. When using the watcher, we don't need this
|
|
|
|
// since the node will only hand us pre-filtered events. In this case, we need to manually verify it
|
|
|
|
// since ParseLogMessagePublished will only verify whether it parses.
|
|
|
|
logMessagePublishedTopic = eth_common.HexToHash("0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2")
|
|
|
|
)
|
|
|
|
|
2022-02-08 14:16:43 -08:00
|
|
|
// MessageEventsForTransaction returns the lockup events for a given transaction.
|
|
|
|
// Returns the block number and a list of MessagePublication events.
|
2022-02-08 12:42:15 -08:00
|
|
|
func MessageEventsForTransaction(
|
|
|
|
ctx context.Context,
|
|
|
|
c *ethclient.Client,
|
|
|
|
contract eth_common.Address,
|
|
|
|
chainId vaa.ChainID,
|
2022-02-08 14:16:43 -08:00
|
|
|
tx eth_common.Hash) (uint64, []*common.MessagePublication, error) {
|
2022-02-08 12:42:15 -08:00
|
|
|
|
|
|
|
f, err := abi.NewAbiFilterer(contract, c)
|
|
|
|
if err != nil {
|
2022-02-08 14:16:43 -08:00
|
|
|
return 0, nil, fmt.Errorf("failed to create ABI filterer: %w", err)
|
2022-02-08 12:42:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get transactions logs from transaction
|
|
|
|
receipt, err := c.TransactionReceipt(ctx, tx)
|
|
|
|
if err != nil {
|
2022-02-08 14:16:43 -08:00
|
|
|
return 0, nil, fmt.Errorf("failed to get transaction receipt: %w", err)
|
2022-02-08 12:42:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get block
|
|
|
|
block, err := c.BlockByHash(ctx, receipt.BlockHash)
|
|
|
|
if err != nil {
|
2022-02-08 14:16:43 -08:00
|
|
|
return 0, nil, fmt.Errorf("failed to get block: %w", err)
|
2022-02-08 12:42:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
msgs := make([]*common.MessagePublication, 0, len(receipt.Logs))
|
|
|
|
|
|
|
|
// Extract logs
|
|
|
|
for _, l := range receipt.Logs {
|
|
|
|
// SECURITY: Skip logs not produced by our contract.
|
|
|
|
if l.Address != contract {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if l == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if l.Topics[0] != logMessagePublishedTopic {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
ev, err := f.ParseLogMessagePublished(*l)
|
|
|
|
if err != nil {
|
2022-02-08 14:16:43 -08:00
|
|
|
return 0, nil, fmt.Errorf("failed to parse log: %w", err)
|
2022-02-08 12:42:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
message := &common.MessagePublication{
|
|
|
|
TxHash: ev.Raw.TxHash,
|
|
|
|
Timestamp: time.Unix(int64(block.Time()), 0),
|
|
|
|
Nonce: ev.Nonce,
|
|
|
|
Sequence: ev.Sequence,
|
|
|
|
EmitterChain: chainId,
|
|
|
|
EmitterAddress: PadAddress(ev.Sender),
|
|
|
|
Payload: ev.Payload,
|
|
|
|
ConsistencyLevel: ev.ConsistencyLevel,
|
|
|
|
}
|
|
|
|
|
|
|
|
msgs = append(msgs, message)
|
|
|
|
}
|
|
|
|
|
2022-02-08 14:16:43 -08:00
|
|
|
return receipt.BlockNumber.Uint64(), msgs, nil
|
2022-02-08 12:42:15 -08:00
|
|
|
}
|