-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add l1 contract * rename pkg name * parse event l1Txn * add some * upgrade yu * Revert "upgrade yu" This reverts commit adf05dd. * handle StarknetLogMessageToL2 (#67) * handle StarknetLogMessageToL2 * chore: done some changes * reuse client * Use fatal to handle NewCairo error * Pass starknetrpc.StarknetRPC on NewL1 * Handle fee in convertL1TxnToBroadcastedTxn * some fix * some fix * rm sleep --------- Co-authored-by: Lawliet-Chan <[email protected]> * enable l1 * fix --------- Co-authored-by: Nordsche Sasa <[email protected]>
- Loading branch information
1 parent
d227b0d
commit 4384f35
Showing
13 changed files
with
1,456 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
Copyright 2019-2024 StarkWare Industries Ltd. | ||
Licensed under the Apache License, Version 2.0 (the "License"). | ||
You may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
https://www.starkware.co/open-source-license/ | ||
Unless required by applicable law or agreed to in writing, | ||
software distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions | ||
and limitations under the License. | ||
*/ | ||
// SPDX-License-Identifier: Apache-2.0. | ||
pragma solidity ^0.8.0; | ||
|
||
interface IStarknetMessagingEvents { | ||
// This event needs to be compatible with the one defined in Output.sol. | ||
event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload); | ||
|
||
// An event that is raised when a message is sent from L1 to L2. | ||
event LogMessageToL2( | ||
address indexed fromAddress, | ||
uint256 indexed toAddress, | ||
uint256 indexed selector, | ||
uint256[] payload, | ||
uint256 nonce, | ||
uint256 fee | ||
); | ||
|
||
// An event that is raised when a message from L2 to L1 is consumed. | ||
event ConsumedMessageToL1( | ||
uint256 indexed fromAddress, | ||
address indexed toAddress, | ||
uint256[] payload | ||
); | ||
|
||
// An event that is raised when a message from L1 to L2 is consumed. | ||
event ConsumedMessageToL2( | ||
address indexed fromAddress, | ||
uint256 indexed toAddress, | ||
uint256 indexed selector, | ||
uint256[] payload, | ||
uint256 nonce | ||
); | ||
|
||
// An event that is raised when a message from L1 to L2 Cancellation is started. | ||
event MessageToL2CancellationStarted( | ||
address indexed fromAddress, | ||
uint256 indexed toAddress, | ||
uint256 indexed selector, | ||
uint256[] payload, | ||
uint256 nonce | ||
); | ||
|
||
// An event that is raised when a message from L1 to L2 is canceled. | ||
event MessageToL2Canceled( | ||
address indexed fromAddress, | ||
uint256 indexed toAddress, | ||
uint256 indexed selector, | ||
uint256[] payload, | ||
uint256 nonce | ||
); | ||
} |
1 change: 1 addition & 0 deletions
1
cairo/l1/contract/solidity/IStarknetMessagingEvents_sol_IStarknetMessagingEvents.abi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromAddress","type":"uint256"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"payload","type":"uint256[]"}],"name":"ConsumedMessageToL1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"toAddress","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"selector","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"payload","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"ConsumedMessageToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromAddress","type":"uint256"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"payload","type":"uint256[]"}],"name":"LogMessageToL1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"toAddress","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"selector","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"payload","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"LogMessageToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"toAddress","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"selector","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"payload","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"MessageToL2Canceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"toAddress","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"selector","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"payload","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"MessageToL2CancellationStarted","type":"event"}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package l1 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"itachi/cairo/l1/contract" | ||
"math/big" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"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" | ||
) | ||
|
||
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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package l1 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/NethermindEth/juno/core/felt" | ||
"github.com/NethermindEth/juno/rpc" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/sirupsen/logrus" | ||
"github.com/yu-org/yu/core/kernel" | ||
"itachi/cairo/config" | ||
"itachi/cairo/l1/contract" | ||
"itachi/cairo/starknetrpc" | ||
"math/big" | ||
) | ||
|
||
type L1 struct { | ||
itachi *kernel.Kernel | ||
ethL1 *EthSubscriber | ||
starknetRPC *starknetrpc.StarknetRPC | ||
} | ||
|
||
func NewL1(itachi *kernel.Kernel, cfg *config.Config, s *starknetrpc.StarknetRPC) (*L1, error) { | ||
ethL1, err := NewEthSubscriber(cfg.EthClientAddress, common.HexToAddress(cfg.EthContractAddress)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &L1{ | ||
itachi: itachi, | ||
ethL1: ethL1, | ||
starknetRPC: s, | ||
}, nil | ||
} | ||
|
||
func StartupL1(itachi *kernel.Kernel, cfg *config.Config, s *starknetrpc.StarknetRPC) { | ||
if cfg.EnableL1 { | ||
l1, err := NewL1(itachi, cfg, s) | ||
if err != nil { | ||
logrus.Fatal("init L1 client failed: ", err) | ||
} | ||
err = l1.Run(context.Background()) | ||
if err != nil { | ||
logrus.Fatal("l1 client run failed: ", err) | ||
} | ||
} | ||
} | ||
|
||
func (l *L1) Run(ctx context.Context) error { | ||
msgChan := make(chan *contract.StarknetLogMessageToL2) | ||
sub, err := l.ethL1.WatchLogMessageToL2(ctx, msgChan, nil, nil, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Listen for msgChan | ||
go func() { | ||
for { | ||
select { | ||
case msg := <-msgChan: | ||
broadcastedTxn, err := convertL1TxnToBroadcastedTxn(msg) | ||
if err != nil { | ||
logrus.Errorf("Error converting L1 txn to broadcasted txn: %v", err) | ||
continue | ||
} | ||
response, jsonRpcErr := l.starknetRPC.AddTransaction(*broadcastedTxn) | ||
if jsonRpcErr != nil { | ||
logrus.Errorf("Error adding transaction: %v", err) | ||
} else { | ||
logrus.Infof("L1 Transaction added: %v", response) | ||
} | ||
case subErr := <-sub.Err(): | ||
logrus.Errorf("L1 update subscription failed: %v, Resubscribing...", subErr) | ||
sub.Unsubscribe() | ||
|
||
sub, err = l.ethL1.WatchLogMessageToL2(ctx, msgChan, nil, nil, nil) | ||
if err != nil { | ||
logrus.Errorf("Resubscribe failed: %v", err) | ||
} | ||
case <-ctx.Done(): | ||
sub.Unsubscribe() | ||
return | ||
} | ||
} | ||
}() | ||
return nil | ||
} | ||
|
||
func convertL1TxnToBroadcastedTxn(event *contract.StarknetLogMessageToL2) (*rpc.BroadcastedTransaction, error) { | ||
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) | ||
} | ||
|
||
maxU128 := new(big.Int).SetUint64(1<<64 - 1) | ||
|
||
// Check if fee exceeds u128 max value | ||
if event.Fee.Cmp(maxU128) > 0 { | ||
return nil, fmt.Errorf("fee exceeds u128 max value") | ||
} | ||
|
||
return &rpc.BroadcastedTransaction{ | ||
Transaction: rpc.Transaction{ | ||
Type: rpc.TxnL1Handler, | ||
ContractAddress: new(felt.Felt).SetBigInt(event.ToAddress), | ||
Nonce: new(felt.Felt).SetBigInt(event.Nonce), | ||
CallData: &callData, | ||
}, | ||
PaidFeeOnL1: new(felt.Felt).SetBigInt(event.Fee), | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.