From ded3110d384fc15326eacaa6aff2a385003458ea Mon Sep 17 00:00:00 2001 From: Lawliet-Chan <1576710154@qq.com> Date: Wed, 15 May 2024 13:42:04 +0800 Subject: [PATCH] parse event l1Txn --- cairo/l1/eth_sub.go | 86 +++++++++++++++++++++++++++++++++++++++++++++ cairo/l1/l1.go | 23 ++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 cairo/l1/eth_sub.go create mode 100644 cairo/l1/l1.go diff --git a/cairo/l1/eth_sub.go b/cairo/l1/eth_sub.go new file mode 100644 index 0000000..c8727c2 --- /dev/null +++ b/cairo/l1/eth_sub.go @@ -0,0 +1,86 @@ +package l1 + +import ( + "context" + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/rpc" + "itachi/cairo/l1/contract" + "math/big" + "strconv" + "strings" + "time" +) + +type EthSubscriber struct { + ethClient *ethclient.Client + client *rpc.Client + filterer *contract.StarknetFilterer +} + +func NewEthSubscriber(ethClientAddress string, coreContractAddress common.Address) (*EthSubscriber, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + // TODO replace with our own client once we have one. + // Geth pulls in a lot of dependencies that we don't use. + client, err := rpc.DialContext(ctx, ethClientAddress) + if err != nil { + return nil, err + } + ethClient := ethclient.NewClient(client) + filterer, err := contract.NewStarknetFilterer(coreContractAddress, ethClient) + if err != nil { + return nil, err + } + return &EthSubscriber{ + ethClient: ethClient, + client: client, + filterer: filterer, + }, nil +} + +func (s *EthSubscriber) WatchLogMessageToL2( + ctx context.Context, + sink chan<- *contract.StarknetLogMessageToL2, + fromAddress []common.Address, + toAddress []*big.Int, + selector []*big.Int, +) (event.Subscription, error) { + return s.filterer.WatchLogMessageToL2(&bind.WatchOpts{Context: ctx}, sink, fromAddress, toAddress, selector) +} + +func (s *EthSubscriber) ChainID(ctx context.Context) (*big.Int, error) { + return s.ethClient.ChainID(ctx) +} + +func (s *EthSubscriber) FinalisedHeight(ctx context.Context) (uint64, error) { + finalisedBlock := make(map[string]any, 0) + if err := s.client.CallContext(ctx, &finalisedBlock, "eth_getBlockByNumber", "finalized", false); err != nil { //nolint:misspell + return 0, fmt.Errorf("get finalised Ethereum block: %w", err) + } + + number, ok := finalisedBlock["number"] //nolint:gosec + if !ok { + return 0, fmt.Errorf("number field not present in Ethereum block") + } + + numberString, ok := number.(string) + if !ok { + return 0, fmt.Errorf("block number is not a string: %v", number) + } + + numberString = strings.TrimPrefix(numberString, "0x") + numberUint, err := strconv.ParseUint(numberString, 16, 64) + if err != nil { + return 0, fmt.Errorf("parse block number: %s", numberString) + } + + return numberUint, nil +} + +func (s *EthSubscriber) Close() { + s.ethClient.Close() +} diff --git a/cairo/l1/l1.go b/cairo/l1/l1.go new file mode 100644 index 0000000..c83cc7f --- /dev/null +++ b/cairo/l1/l1.go @@ -0,0 +1,23 @@ +package l1 + +import ( + "github.com/NethermindEth/juno/core" + "github.com/NethermindEth/juno/core/felt" + "itachi/cairo/l1/contract" +) + +func parseEventToL1Txn(event *contract.StarknetLogMessageToL2) *core.L1HandlerTransaction { + callData := make([]*felt.Felt, 0) + callData = append(callData, new(felt.Felt).SetBigInt(event.FromAddress.Big())) + for _, payload := range event.Payload { + data := new(felt.Felt).SetBigInt(payload) + callData = append(callData, data) + } + return &core.L1HandlerTransaction{ + ContractAddress: new(felt.Felt).SetBigInt(event.ToAddress), + EntryPointSelector: new(felt.Felt).SetBigInt(event.Selector), + Nonce: new(felt.Felt).SetBigInt(event.Nonce), + CallData: callData, + Version: new(core.TransactionVersion), + } +}