diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e118e5..91e237c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: jobs: build: - name: Build Test + name: Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/cairo/cairo.go b/cairo/cairo.go index 9848f4f..45a0a69 100644 --- a/cairo/cairo.go +++ b/cairo/cairo.go @@ -2,6 +2,9 @@ package cairo import ( "encoding/hex" + "itachi/cairo/config" + "net/http" + junostate "github.com/NethermindEth/juno/blockchain" "github.com/NethermindEth/juno/core" "github.com/NethermindEth/juno/core/felt" @@ -16,8 +19,6 @@ import ( "github.com/yu-org/yu/core/context" "github.com/yu-org/yu/core/tripod" "github.com/yu-org/yu/core/types" - "itachi/cairo/config" - "net/http" ) type Cairo struct { diff --git a/cairo/config/config.go b/cairo/config/config.go index f4e30b4..2b75182 100644 --- a/cairo/config/config.go +++ b/cairo/config/config.go @@ -39,10 +39,16 @@ type Config struct { GenesisContracts map[string]string `toml:"genesis_contracts"` GenesisStorages []*GenesisStorage `toml:"genesis_storages"` + // RPC configs EnableStarknetRPC bool `toml:"enable_starknet_rpc"` StarknetHost string `toml:"starknet_host"` StarknetPort string `toml:"starknet_port"` + // L1 configs + EnableL1 bool `toml:"enable_l1"` + EthClientAddress string `toml:"eth_client_address"` + EthContractAddress string `toml:"eth_contract_address"` + EnablePprof bool `toml:"enable_pprof"` PprofAddr string `toml:"pprof_addr"` } diff --git a/cairo/l1/contract/l1.go b/cairo/l1/contract/l1.go new file mode 100644 index 0000000..1262b47 --- /dev/null +++ b/cairo/l1/contract/l1.go @@ -0,0 +1,1146 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contract + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// StarknetMetaData contains all meta data concerning the Starknet contract. +var StarknetMetaData = &bind.MetaData{ + ABI: "[{\"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\"}]", +} + +// StarknetABI is the input ABI used to generate the binding from. +// Deprecated: Use StarknetMetaData.ABI instead. +var StarknetABI = StarknetMetaData.ABI + +// Starknet is an auto generated Go binding around an Ethereum contract. +type Starknet struct { + StarknetCaller // Read-only binding to the contract + StarknetTransactor // Write-only binding to the contract + StarknetFilterer // Log filterer for contract events +} + +// StarknetCaller is an auto generated read-only Go binding around an Ethereum contract. +type StarknetCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StarknetTransactor is an auto generated write-only Go binding around an Ethereum contract. +type StarknetTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StarknetFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type StarknetFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// StarknetSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type StarknetSession struct { + Contract *Starknet // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StarknetCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type StarknetCallerSession struct { + Contract *StarknetCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// StarknetTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type StarknetTransactorSession struct { + Contract *StarknetTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// StarknetRaw is an auto generated low-level Go binding around an Ethereum contract. +type StarknetRaw struct { + Contract *Starknet // Generic contract binding to access the raw methods on +} + +// StarknetCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type StarknetCallerRaw struct { + Contract *StarknetCaller // Generic read-only contract binding to access the raw methods on +} + +// StarknetTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type StarknetTransactorRaw struct { + Contract *StarknetTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewStarknet creates a new instance of Starknet, bound to a specific deployed contract. +func NewStarknet(address common.Address, backend bind.ContractBackend) (*Starknet, error) { + contract, err := bindStarknet(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Starknet{StarknetCaller: StarknetCaller{contract: contract}, StarknetTransactor: StarknetTransactor{contract: contract}, StarknetFilterer: StarknetFilterer{contract: contract}}, nil +} + +// NewStarknetCaller creates a new read-only instance of Starknet, bound to a specific deployed contract. +func NewStarknetCaller(address common.Address, caller bind.ContractCaller) (*StarknetCaller, error) { + contract, err := bindStarknet(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &StarknetCaller{contract: contract}, nil +} + +// NewStarknetTransactor creates a new write-only instance of Starknet, bound to a specific deployed contract. +func NewStarknetTransactor(address common.Address, transactor bind.ContractTransactor) (*StarknetTransactor, error) { + contract, err := bindStarknet(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &StarknetTransactor{contract: contract}, nil +} + +// NewStarknetFilterer creates a new log filterer instance of Starknet, bound to a specific deployed contract. +func NewStarknetFilterer(address common.Address, filterer bind.ContractFilterer) (*StarknetFilterer, error) { + contract, err := bindStarknet(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &StarknetFilterer{contract: contract}, nil +} + +// bindStarknet binds a generic wrapper to an already deployed contract. +func bindStarknet(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := StarknetMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Starknet *StarknetRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Starknet.Contract.StarknetCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Starknet *StarknetRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Starknet.Contract.StarknetTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Starknet *StarknetRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Starknet.Contract.StarknetTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Starknet *StarknetCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Starknet.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Starknet *StarknetTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Starknet.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Starknet *StarknetTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Starknet.Contract.contract.Transact(opts, method, params...) +} + +// StarknetConsumedMessageToL1Iterator is returned from FilterConsumedMessageToL1 and is used to iterate over the raw logs and unpacked data for ConsumedMessageToL1 events raised by the Starknet contract. +type StarknetConsumedMessageToL1Iterator struct { + Event *StarknetConsumedMessageToL1 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StarknetConsumedMessageToL1Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StarknetConsumedMessageToL1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StarknetConsumedMessageToL1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StarknetConsumedMessageToL1Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StarknetConsumedMessageToL1Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StarknetConsumedMessageToL1 represents a ConsumedMessageToL1 event raised by the Starknet contract. +type StarknetConsumedMessageToL1 struct { + FromAddress *big.Int + ToAddress common.Address + Payload []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterConsumedMessageToL1 is a free log retrieval operation binding the contract event 0x7a06c571aa77f34d9706c51e5d8122b5595aebeaa34233bfe866f22befb973b1. +// +// Solidity: event ConsumedMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload) +func (_Starknet *StarknetFilterer) FilterConsumedMessageToL1(opts *bind.FilterOpts, fromAddress []*big.Int, toAddress []common.Address) (*StarknetConsumedMessageToL1Iterator, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + + logs, sub, err := _Starknet.contract.FilterLogs(opts, "ConsumedMessageToL1", fromAddressRule, toAddressRule) + if err != nil { + return nil, err + } + return &StarknetConsumedMessageToL1Iterator{contract: _Starknet.contract, event: "ConsumedMessageToL1", logs: logs, sub: sub}, nil +} + +// WatchConsumedMessageToL1 is a free log subscription operation binding the contract event 0x7a06c571aa77f34d9706c51e5d8122b5595aebeaa34233bfe866f22befb973b1. +// +// Solidity: event ConsumedMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload) +func (_Starknet *StarknetFilterer) WatchConsumedMessageToL1(opts *bind.WatchOpts, sink chan<- *StarknetConsumedMessageToL1, fromAddress []*big.Int, toAddress []common.Address) (event.Subscription, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + + logs, sub, err := _Starknet.contract.WatchLogs(opts, "ConsumedMessageToL1", fromAddressRule, toAddressRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StarknetConsumedMessageToL1) + if err := _Starknet.contract.UnpackLog(event, "ConsumedMessageToL1", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseConsumedMessageToL1 is a log parse operation binding the contract event 0x7a06c571aa77f34d9706c51e5d8122b5595aebeaa34233bfe866f22befb973b1. +// +// Solidity: event ConsumedMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload) +func (_Starknet *StarknetFilterer) ParseConsumedMessageToL1(log types.Log) (*StarknetConsumedMessageToL1, error) { + event := new(StarknetConsumedMessageToL1) + if err := _Starknet.contract.UnpackLog(event, "ConsumedMessageToL1", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StarknetConsumedMessageToL2Iterator is returned from FilterConsumedMessageToL2 and is used to iterate over the raw logs and unpacked data for ConsumedMessageToL2 events raised by the Starknet contract. +type StarknetConsumedMessageToL2Iterator struct { + Event *StarknetConsumedMessageToL2 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StarknetConsumedMessageToL2Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StarknetConsumedMessageToL2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StarknetConsumedMessageToL2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StarknetConsumedMessageToL2Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StarknetConsumedMessageToL2Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StarknetConsumedMessageToL2 represents a ConsumedMessageToL2 event raised by the Starknet contract. +type StarknetConsumedMessageToL2 struct { + FromAddress common.Address + ToAddress *big.Int + Selector *big.Int + Payload []*big.Int + Nonce *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterConsumedMessageToL2 is a free log retrieval operation binding the contract event 0x9592d37825c744e33fa80c469683bbd04d336241bb600b574758efd182abe26a. +// +// Solidity: event ConsumedMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) FilterConsumedMessageToL2(opts *bind.FilterOpts, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (*StarknetConsumedMessageToL2Iterator, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.FilterLogs(opts, "ConsumedMessageToL2", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return &StarknetConsumedMessageToL2Iterator{contract: _Starknet.contract, event: "ConsumedMessageToL2", logs: logs, sub: sub}, nil +} + +// WatchConsumedMessageToL2 is a free log subscription operation binding the contract event 0x9592d37825c744e33fa80c469683bbd04d336241bb600b574758efd182abe26a. +// +// Solidity: event ConsumedMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) WatchConsumedMessageToL2(opts *bind.WatchOpts, sink chan<- *StarknetConsumedMessageToL2, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (event.Subscription, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.WatchLogs(opts, "ConsumedMessageToL2", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StarknetConsumedMessageToL2) + if err := _Starknet.contract.UnpackLog(event, "ConsumedMessageToL2", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseConsumedMessageToL2 is a log parse operation binding the contract event 0x9592d37825c744e33fa80c469683bbd04d336241bb600b574758efd182abe26a. +// +// Solidity: event ConsumedMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) ParseConsumedMessageToL2(log types.Log) (*StarknetConsumedMessageToL2, error) { + event := new(StarknetConsumedMessageToL2) + if err := _Starknet.contract.UnpackLog(event, "ConsumedMessageToL2", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StarknetLogMessageToL1Iterator is returned from FilterLogMessageToL1 and is used to iterate over the raw logs and unpacked data for LogMessageToL1 events raised by the Starknet contract. +type StarknetLogMessageToL1Iterator struct { + Event *StarknetLogMessageToL1 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StarknetLogMessageToL1Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StarknetLogMessageToL1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StarknetLogMessageToL1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StarknetLogMessageToL1Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StarknetLogMessageToL1Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StarknetLogMessageToL1 represents a LogMessageToL1 event raised by the Starknet contract. +type StarknetLogMessageToL1 struct { + FromAddress *big.Int + ToAddress common.Address + Payload []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogMessageToL1 is a free log retrieval operation binding the contract event 0x4264ac208b5fde633ccdd42e0f12c3d6d443a4f3779bbf886925b94665b63a22. +// +// Solidity: event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload) +func (_Starknet *StarknetFilterer) FilterLogMessageToL1(opts *bind.FilterOpts, fromAddress []*big.Int, toAddress []common.Address) (*StarknetLogMessageToL1Iterator, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + + logs, sub, err := _Starknet.contract.FilterLogs(opts, "LogMessageToL1", fromAddressRule, toAddressRule) + if err != nil { + return nil, err + } + return &StarknetLogMessageToL1Iterator{contract: _Starknet.contract, event: "LogMessageToL1", logs: logs, sub: sub}, nil +} + +// WatchLogMessageToL1 is a free log subscription operation binding the contract event 0x4264ac208b5fde633ccdd42e0f12c3d6d443a4f3779bbf886925b94665b63a22. +// +// Solidity: event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload) +func (_Starknet *StarknetFilterer) WatchLogMessageToL1(opts *bind.WatchOpts, sink chan<- *StarknetLogMessageToL1, fromAddress []*big.Int, toAddress []common.Address) (event.Subscription, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + + logs, sub, err := _Starknet.contract.WatchLogs(opts, "LogMessageToL1", fromAddressRule, toAddressRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StarknetLogMessageToL1) + if err := _Starknet.contract.UnpackLog(event, "LogMessageToL1", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogMessageToL1 is a log parse operation binding the contract event 0x4264ac208b5fde633ccdd42e0f12c3d6d443a4f3779bbf886925b94665b63a22. +// +// Solidity: event LogMessageToL1(uint256 indexed fromAddress, address indexed toAddress, uint256[] payload) +func (_Starknet *StarknetFilterer) ParseLogMessageToL1(log types.Log) (*StarknetLogMessageToL1, error) { + event := new(StarknetLogMessageToL1) + if err := _Starknet.contract.UnpackLog(event, "LogMessageToL1", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StarknetLogMessageToL2Iterator is returned from FilterLogMessageToL2 and is used to iterate over the raw logs and unpacked data for LogMessageToL2 events raised by the Starknet contract. +type StarknetLogMessageToL2Iterator struct { + Event *StarknetLogMessageToL2 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StarknetLogMessageToL2Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StarknetLogMessageToL2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StarknetLogMessageToL2) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StarknetLogMessageToL2Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StarknetLogMessageToL2Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StarknetLogMessageToL2 represents a LogMessageToL2 event raised by the Starknet contract. +type StarknetLogMessageToL2 struct { + FromAddress common.Address + ToAddress *big.Int + Selector *big.Int + Payload []*big.Int + Nonce *big.Int + Fee *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogMessageToL2 is a free log retrieval operation binding the contract event 0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b. +// +// Solidity: event LogMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce, uint256 fee) +func (_Starknet *StarknetFilterer) FilterLogMessageToL2(opts *bind.FilterOpts, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (*StarknetLogMessageToL2Iterator, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.FilterLogs(opts, "LogMessageToL2", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return &StarknetLogMessageToL2Iterator{contract: _Starknet.contract, event: "LogMessageToL2", logs: logs, sub: sub}, nil +} + +// WatchLogMessageToL2 is a free log subscription operation binding the contract event 0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b. +// +// Solidity: event LogMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce, uint256 fee) +func (_Starknet *StarknetFilterer) WatchLogMessageToL2(opts *bind.WatchOpts, sink chan<- *StarknetLogMessageToL2, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (event.Subscription, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.WatchLogs(opts, "LogMessageToL2", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StarknetLogMessageToL2) + if err := _Starknet.contract.UnpackLog(event, "LogMessageToL2", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogMessageToL2 is a log parse operation binding the contract event 0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b. +// +// Solidity: event LogMessageToL2(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce, uint256 fee) +func (_Starknet *StarknetFilterer) ParseLogMessageToL2(log types.Log) (*StarknetLogMessageToL2, error) { + event := new(StarknetLogMessageToL2) + if err := _Starknet.contract.UnpackLog(event, "LogMessageToL2", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StarknetMessageToL2CanceledIterator is returned from FilterMessageToL2Canceled and is used to iterate over the raw logs and unpacked data for MessageToL2Canceled events raised by the Starknet contract. +type StarknetMessageToL2CanceledIterator struct { + Event *StarknetMessageToL2Canceled // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StarknetMessageToL2CanceledIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StarknetMessageToL2Canceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StarknetMessageToL2Canceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StarknetMessageToL2CanceledIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StarknetMessageToL2CanceledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StarknetMessageToL2Canceled represents a MessageToL2Canceled event raised by the Starknet contract. +type StarknetMessageToL2Canceled struct { + FromAddress common.Address + ToAddress *big.Int + Selector *big.Int + Payload []*big.Int + Nonce *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMessageToL2Canceled is a free log retrieval operation binding the contract event 0x8abd2ec2e0a10c82f5b60ea00455fa96c41fd144f225fcc52b8d83d94f803ed8. +// +// Solidity: event MessageToL2Canceled(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) FilterMessageToL2Canceled(opts *bind.FilterOpts, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (*StarknetMessageToL2CanceledIterator, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.FilterLogs(opts, "MessageToL2Canceled", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return &StarknetMessageToL2CanceledIterator{contract: _Starknet.contract, event: "MessageToL2Canceled", logs: logs, sub: sub}, nil +} + +// WatchMessageToL2Canceled is a free log subscription operation binding the contract event 0x8abd2ec2e0a10c82f5b60ea00455fa96c41fd144f225fcc52b8d83d94f803ed8. +// +// Solidity: event MessageToL2Canceled(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) WatchMessageToL2Canceled(opts *bind.WatchOpts, sink chan<- *StarknetMessageToL2Canceled, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (event.Subscription, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.WatchLogs(opts, "MessageToL2Canceled", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StarknetMessageToL2Canceled) + if err := _Starknet.contract.UnpackLog(event, "MessageToL2Canceled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMessageToL2Canceled is a log parse operation binding the contract event 0x8abd2ec2e0a10c82f5b60ea00455fa96c41fd144f225fcc52b8d83d94f803ed8. +// +// Solidity: event MessageToL2Canceled(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) ParseMessageToL2Canceled(log types.Log) (*StarknetMessageToL2Canceled, error) { + event := new(StarknetMessageToL2Canceled) + if err := _Starknet.contract.UnpackLog(event, "MessageToL2Canceled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// StarknetMessageToL2CancellationStartedIterator is returned from FilterMessageToL2CancellationStarted and is used to iterate over the raw logs and unpacked data for MessageToL2CancellationStarted events raised by the Starknet contract. +type StarknetMessageToL2CancellationStartedIterator struct { + Event *StarknetMessageToL2CancellationStarted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *StarknetMessageToL2CancellationStartedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(StarknetMessageToL2CancellationStarted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(StarknetMessageToL2CancellationStarted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *StarknetMessageToL2CancellationStartedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *StarknetMessageToL2CancellationStartedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// StarknetMessageToL2CancellationStarted represents a MessageToL2CancellationStarted event raised by the Starknet contract. +type StarknetMessageToL2CancellationStarted struct { + FromAddress common.Address + ToAddress *big.Int + Selector *big.Int + Payload []*big.Int + Nonce *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMessageToL2CancellationStarted is a free log retrieval operation binding the contract event 0x2e00dccd686fd6823ec7dc3e125582aa82881b6ff5f6b5a73856e1ea8338a3be. +// +// Solidity: event MessageToL2CancellationStarted(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) FilterMessageToL2CancellationStarted(opts *bind.FilterOpts, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (*StarknetMessageToL2CancellationStartedIterator, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.FilterLogs(opts, "MessageToL2CancellationStarted", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return &StarknetMessageToL2CancellationStartedIterator{contract: _Starknet.contract, event: "MessageToL2CancellationStarted", logs: logs, sub: sub}, nil +} + +// WatchMessageToL2CancellationStarted is a free log subscription operation binding the contract event 0x2e00dccd686fd6823ec7dc3e125582aa82881b6ff5f6b5a73856e1ea8338a3be. +// +// Solidity: event MessageToL2CancellationStarted(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) WatchMessageToL2CancellationStarted(opts *bind.WatchOpts, sink chan<- *StarknetMessageToL2CancellationStarted, fromAddress []common.Address, toAddress []*big.Int, selector []*big.Int) (event.Subscription, error) { + + var fromAddressRule []interface{} + for _, fromAddressItem := range fromAddress { + fromAddressRule = append(fromAddressRule, fromAddressItem) + } + var toAddressRule []interface{} + for _, toAddressItem := range toAddress { + toAddressRule = append(toAddressRule, toAddressItem) + } + var selectorRule []interface{} + for _, selectorItem := range selector { + selectorRule = append(selectorRule, selectorItem) + } + + logs, sub, err := _Starknet.contract.WatchLogs(opts, "MessageToL2CancellationStarted", fromAddressRule, toAddressRule, selectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(StarknetMessageToL2CancellationStarted) + if err := _Starknet.contract.UnpackLog(event, "MessageToL2CancellationStarted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMessageToL2CancellationStarted is a log parse operation binding the contract event 0x2e00dccd686fd6823ec7dc3e125582aa82881b6ff5f6b5a73856e1ea8338a3be. +// +// Solidity: event MessageToL2CancellationStarted(address indexed fromAddress, uint256 indexed toAddress, uint256 indexed selector, uint256[] payload, uint256 nonce) +func (_Starknet *StarknetFilterer) ParseMessageToL2CancellationStarted(log types.Log) (*StarknetMessageToL2CancellationStarted, error) { + event := new(StarknetMessageToL2CancellationStarted) + if err := _Starknet.contract.UnpackLog(event, "MessageToL2CancellationStarted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/cairo/l1/contract/solidity/IStarknetMessagingEvents.sol b/cairo/l1/contract/solidity/IStarknetMessagingEvents.sol new file mode 100644 index 0000000..8acdfe5 --- /dev/null +++ b/cairo/l1/contract/solidity/IStarknetMessagingEvents.sol @@ -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 + ); +} \ No newline at end of file diff --git a/cairo/l1/contract/solidity/IStarknetMessagingEvents_sol_IStarknetMessagingEvents.abi b/cairo/l1/contract/solidity/IStarknetMessagingEvents_sol_IStarknetMessagingEvents.abi new file mode 100644 index 0000000..e006d98 --- /dev/null +++ b/cairo/l1/contract/solidity/IStarknetMessagingEvents_sol_IStarknetMessagingEvents.abi @@ -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"}] \ No newline at end of file diff --git a/cairo/l1/eth_sub.go b/cairo/l1/eth_sub.go new file mode 100644 index 0000000..4518c49 --- /dev/null +++ b/cairo/l1/eth_sub.go @@ -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() +} diff --git a/cairo/l1/l1.go b/cairo/l1/l1.go new file mode 100644 index 0000000..c9397a7 --- /dev/null +++ b/cairo/l1/l1.go @@ -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 +} diff --git a/cairo/starknetrpc/rpc.go b/cairo/starknetrpc/rpc.go index c75a7e3..8edd153 100644 --- a/cairo/starknetrpc/rpc.go +++ b/cairo/starknetrpc/rpc.go @@ -3,13 +3,14 @@ package starknetrpc import ( "context" "errors" - "github.com/sirupsen/logrus" "itachi/cairo/config" "net" "net/http" "runtime" "time" + "github.com/sirupsen/logrus" + "github.com/NethermindEth/juno/jsonrpc" "github.com/NethermindEth/juno/utils" "github.com/NethermindEth/juno/validator" @@ -92,7 +93,7 @@ func (s *StarknetRPC) Serve(ctx context.Context) error { } } -func StartUpStarknetRPC(chain *kernel.Kernel, cfg *config.Config) { +func StartUpStarknetRPC(chain *kernel.Kernel, cfg *config.Config) *StarknetRPC { if cfg.EnableStarknetRPC { rpcSrv, err := NewStarknetRPC(chain, cfg) if err != nil { @@ -106,7 +107,9 @@ func StartUpStarknetRPC(chain *kernel.Kernel, cfg *config.Config) { logrus.Errorf("starknetRPC serves failed, %v", err) } }() + return rpcSrv } + return nil } func exactPathServer(path string, handler http.Handler) http.HandlerFunc { diff --git a/cmd/node/app/app.go b/cmd/node/app/app.go index 580bbf5..106d515 100644 --- a/cmd/node/app/app.go +++ b/cmd/node/app/app.go @@ -1,23 +1,32 @@ package app import ( - "github.com/common-nighthawk/go-figure" - "github.com/yu-org/yu/apps/poa" - "github.com/yu-org/yu/core/kernel" - "github.com/yu-org/yu/core/startup" "itachi/cairo" "itachi/cairo/config" + "itachi/cairo/l1" "itachi/cairo/starknetrpc" "itachi/utils" + + "github.com/common-nighthawk/go-figure" + "github.com/yu-org/yu/apps/poa" + "github.com/yu-org/yu/core/kernel" + "github.com/yu-org/yu/core/startup" ) func StartUpChain(poaCfg *poa.PoaConfig, crCfg *config.Config) { figure.NewColorFigure("Itachi", "big", "green", false).Print() chain := InitItachi(poaCfg, crCfg) - starknetrpc.StartUpStarknetRPC(chain, crCfg) + + // Starknet RPC server + rpcSrv := starknetrpc.StartUpStarknetRPC(chain, crCfg) + + // Subscribe to L1 + l1.StartupL1(chain, crCfg, rpcSrv) + utils.StartUpPprof(crCfg) chain.Startup() + } func InitItachi(poaCfg *poa.PoaConfig, crCfg *config.Config) *kernel.Kernel { diff --git a/cmd/node/main.go b/cmd/node/main.go index 5f18c02..bfa99a3 100644 --- a/cmd/node/main.go +++ b/cmd/node/main.go @@ -1,10 +1,11 @@ package main import ( - "github.com/yu-org/yu/apps/poa" - "github.com/yu-org/yu/core/startup" "itachi/cairo/config" "itachi/cmd/node/app" + + "github.com/yu-org/yu/apps/poa" + "github.com/yu-org/yu/core/startup" ) func main() { diff --git a/conf/cairo_cfg.toml b/conf/cairo_cfg.toml index e587b99..2620187 100644 --- a/conf/cairo_cfg.toml +++ b/conf/cairo_cfg.toml @@ -11,6 +11,10 @@ max_vm_queue = 1000000 log_level = 1 colour = true +# ETH L1 +enable_l1 = false +eth_client_address = "https://sepolia.infura.io/v3/" + sequencer_addr = "0x46a89ae102987331d369645031b49c27738ed096f2789c24449966da4c6de6b" skip_charge_fee = true skip_validate = false diff --git a/integration-test/integration_test.go b/integration-test/integration_test.go index 0633d9f..0dfa0e9 100644 --- a/integration-test/integration_test.go +++ b/integration-test/integration_test.go @@ -3,6 +3,13 @@ package integration_test import ( "encoding/json" "fmt" + "itachi/cairo" + "itachi/cairo/config" + "itachi/cmd/node/app" + "sync" + "testing" + "time" + "github.com/NethermindEth/juno/core" "github.com/NethermindEth/juno/core/felt" "github.com/NethermindEth/juno/rpc" @@ -13,12 +20,6 @@ import ( "github.com/yu-org/yu/core/kernel" "github.com/yu-org/yu/core/startup" "github.com/yu-org/yu/example/client/callchain" - "itachi/cairo" - "itachi/cairo/config" - "itachi/cmd/node/app" - "sync" - "testing" - "time" ) var chain *kernel.Kernel @@ -28,7 +29,7 @@ func init() { poaCfg := poa.DefaultCfg(0) crCfg := config.DefaultCfg() - chain = app.InitItachi(poaCfg, crCfg) + chain, _ = app.InitItachi(poaCfg, crCfg) } func TestIntegration(t *testing.T) {