From e9122fd83632612cef7afad61b74198bf0dc3e7c Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 3 Dec 2024 17:15:36 +0700 Subject: [PATCH 01/43] Add IPAddressRegistry field to Network struct --- utils/network.go | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/network.go b/utils/network.go index c0988c82f6..212fb9f981 100644 --- a/utils/network.go +++ b/utils/network.go @@ -22,6 +22,7 @@ type Network struct { L1ChainID *big.Int `json:"l1_chain_id" validate:"required"` L2ChainID string `json:"l2_chain_id" validate:"required"` CoreContractAddress common.Address `json:"core_contract_address" validate:"required"` + IPAddressRegistry *common.Address `json:"ip_address_registry"` BlockHashMetaInfo *BlockHashMetaInfo `json:"block_hash_meta_info"` } From cc87abafadd8233a74a93b2d7e658f842333df84 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 3 Dec 2024 17:18:02 +0700 Subject: [PATCH 02/43] Add IPAddressRegistry contract ABI --- l1/abi/ip_address_registry.json | 217 ++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 l1/abi/ip_address_registry.json diff --git a/l1/abi/ip_address_registry.json b/l1/abi/ip_address_registry.json new file mode 100644 index 0000000000..b46d275791 --- /dev/null +++ b/l1/abi/ip_address_registry.json @@ -0,0 +1,217 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_updater", + "type": "address" + } + ], + "name": "addAuthorizedUpdater", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_ipAddress", + "type": "string" + } + ], + "name": "addIPAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "ipAddress", + "type": "string" + } + ], + "name": "IPAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "ipAddress", + "type": "string" + } + ], + "name": "IPRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_updater", + "type": "address" + } + ], + "name": "removeAuthorizedUpdater", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "removeIPAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "updater", + "type": "address" + } + ], + "name": "UpdaterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "updater", + "type": "address" + } + ], + "name": "UpdaterRemoved", + "type": "event" + }, + { + "inputs": [], + "name": "getIPAddresses", + "outputs": [ + { + "internalType": "string[]", + "name": "", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_updater", + "type": "address" + } + ], + "name": "isAuthorizedUpdater", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] From d87c3882d1080598000db2fee657140cbe0613a5 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 3 Dec 2024 17:20:10 +0700 Subject: [PATCH 03/43] Add go generate comment for IPAddressRegistry ABI --- l1/l1.go | 1 + 1 file changed, 1 insertion(+) diff --git a/l1/l1.go b/l1/l1.go index bab31e69e8..654f7efed0 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -1,3 +1,4 @@ +//go:generate abigen --abi abi/ip_address_registry.json --pkg contract --type IPAddressRegistry --out contract/ip_address_registry.go package l1 import ( From f967248e0f516a70b5e3fe239319bbdbcf10a9b1 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 3 Dec 2024 17:20:48 +0700 Subject: [PATCH 04/43] Generate IPAddressRegistry --- l1/contract/ip_address_registry.go | 1089 ++++++++++++++++++++++++++++ 1 file changed, 1089 insertions(+) create mode 100644 l1/contract/ip_address_registry.go diff --git a/l1/contract/ip_address_registry.go b/l1/contract/ip_address_registry.go new file mode 100644 index 0000000000..56f7f0f05e --- /dev/null +++ b/l1/contract/ip_address_registry.go @@ -0,0 +1,1089 @@ +// 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 +) + +// IPAddressRegistryMetaData contains all meta data concerning the IPAddressRegistry contract. +var IPAddressRegistryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"addAuthorizedUpdater\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_ipAddress\",\"type\":\"string\"}],\"name\":\"addIPAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"ipAddress\",\"type\":\"string\"}],\"name\":\"IPAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"ipAddress\",\"type\":\"string\"}],\"name\":\"IPRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"removeAuthorizedUpdater\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"removeIPAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"}],\"name\":\"UpdaterAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updater\",\"type\":\"address\"}],\"name\":\"UpdaterRemoved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getIPAddresses\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_updater\",\"type\":\"address\"}],\"name\":\"isAuthorizedUpdater\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// IPAddressRegistryABI is the input ABI used to generate the binding from. +// Deprecated: Use IPAddressRegistryMetaData.ABI instead. +var IPAddressRegistryABI = IPAddressRegistryMetaData.ABI + +// IPAddressRegistry is an auto generated Go binding around an Ethereum contract. +type IPAddressRegistry struct { + IPAddressRegistryCaller // Read-only binding to the contract + IPAddressRegistryTransactor // Write-only binding to the contract + IPAddressRegistryFilterer // Log filterer for contract events +} + +// IPAddressRegistryCaller is an auto generated read-only Go binding around an Ethereum contract. +type IPAddressRegistryCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IPAddressRegistryTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IPAddressRegistryTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IPAddressRegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IPAddressRegistryFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IPAddressRegistrySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IPAddressRegistrySession struct { + Contract *IPAddressRegistry // 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 +} + +// IPAddressRegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IPAddressRegistryCallerSession struct { + Contract *IPAddressRegistryCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IPAddressRegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IPAddressRegistryTransactorSession struct { + Contract *IPAddressRegistryTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IPAddressRegistryRaw is an auto generated low-level Go binding around an Ethereum contract. +type IPAddressRegistryRaw struct { + Contract *IPAddressRegistry // Generic contract binding to access the raw methods on +} + +// IPAddressRegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IPAddressRegistryCallerRaw struct { + Contract *IPAddressRegistryCaller // Generic read-only contract binding to access the raw methods on +} + +// IPAddressRegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IPAddressRegistryTransactorRaw struct { + Contract *IPAddressRegistryTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIPAddressRegistry creates a new instance of IPAddressRegistry, bound to a specific deployed contract. +func NewIPAddressRegistry(address common.Address, backend bind.ContractBackend) (*IPAddressRegistry, error) { + contract, err := bindIPAddressRegistry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IPAddressRegistry{IPAddressRegistryCaller: IPAddressRegistryCaller{contract: contract}, IPAddressRegistryTransactor: IPAddressRegistryTransactor{contract: contract}, IPAddressRegistryFilterer: IPAddressRegistryFilterer{contract: contract}}, nil +} + +// NewIPAddressRegistryCaller creates a new read-only instance of IPAddressRegistry, bound to a specific deployed contract. +func NewIPAddressRegistryCaller(address common.Address, caller bind.ContractCaller) (*IPAddressRegistryCaller, error) { + contract, err := bindIPAddressRegistry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IPAddressRegistryCaller{contract: contract}, nil +} + +// NewIPAddressRegistryTransactor creates a new write-only instance of IPAddressRegistry, bound to a specific deployed contract. +func NewIPAddressRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*IPAddressRegistryTransactor, error) { + contract, err := bindIPAddressRegistry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IPAddressRegistryTransactor{contract: contract}, nil +} + +// NewIPAddressRegistryFilterer creates a new log filterer instance of IPAddressRegistry, bound to a specific deployed contract. +func NewIPAddressRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*IPAddressRegistryFilterer, error) { + contract, err := bindIPAddressRegistry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IPAddressRegistryFilterer{contract: contract}, nil +} + +// bindIPAddressRegistry binds a generic wrapper to an already deployed contract. +func bindIPAddressRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IPAddressRegistryMetaData.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 (_IPAddressRegistry *IPAddressRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IPAddressRegistry.Contract.IPAddressRegistryCaller.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 (_IPAddressRegistry *IPAddressRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.IPAddressRegistryTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IPAddressRegistry *IPAddressRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.IPAddressRegistryTransactor.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 (_IPAddressRegistry *IPAddressRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IPAddressRegistry.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 (_IPAddressRegistry *IPAddressRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IPAddressRegistry *IPAddressRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.contract.Transact(opts, method, params...) +} + +// GetIPAddresses is a free data retrieval call binding the contract method 0xd42c014a. +// +// Solidity: function getIPAddresses() view returns(string[]) +func (_IPAddressRegistry *IPAddressRegistryCaller) GetIPAddresses(opts *bind.CallOpts) ([]string, error) { + var out []interface{} + err := _IPAddressRegistry.contract.Call(opts, &out, "getIPAddresses") + + if err != nil { + return *new([]string), err + } + + out0 := *abi.ConvertType(out[0], new([]string)).(*[]string) + + return out0, err + +} + +// GetIPAddresses is a free data retrieval call binding the contract method 0xd42c014a. +// +// Solidity: function getIPAddresses() view returns(string[]) +func (_IPAddressRegistry *IPAddressRegistrySession) GetIPAddresses() ([]string, error) { + return _IPAddressRegistry.Contract.GetIPAddresses(&_IPAddressRegistry.CallOpts) +} + +// GetIPAddresses is a free data retrieval call binding the contract method 0xd42c014a. +// +// Solidity: function getIPAddresses() view returns(string[]) +func (_IPAddressRegistry *IPAddressRegistryCallerSession) GetIPAddresses() ([]string, error) { + return _IPAddressRegistry.Contract.GetIPAddresses(&_IPAddressRegistry.CallOpts) +} + +// IsAuthorizedUpdater is a free data retrieval call binding the contract method 0xb865bccc. +// +// Solidity: function isAuthorizedUpdater(address _updater) view returns(bool) +func (_IPAddressRegistry *IPAddressRegistryCaller) IsAuthorizedUpdater(opts *bind.CallOpts, _updater common.Address) (bool, error) { + var out []interface{} + err := _IPAddressRegistry.contract.Call(opts, &out, "isAuthorizedUpdater", _updater) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsAuthorizedUpdater is a free data retrieval call binding the contract method 0xb865bccc. +// +// Solidity: function isAuthorizedUpdater(address _updater) view returns(bool) +func (_IPAddressRegistry *IPAddressRegistrySession) IsAuthorizedUpdater(_updater common.Address) (bool, error) { + return _IPAddressRegistry.Contract.IsAuthorizedUpdater(&_IPAddressRegistry.CallOpts, _updater) +} + +// IsAuthorizedUpdater is a free data retrieval call binding the contract method 0xb865bccc. +// +// Solidity: function isAuthorizedUpdater(address _updater) view returns(bool) +func (_IPAddressRegistry *IPAddressRegistryCallerSession) IsAuthorizedUpdater(_updater common.Address) (bool, error) { + return _IPAddressRegistry.Contract.IsAuthorizedUpdater(&_IPAddressRegistry.CallOpts, _updater) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_IPAddressRegistry *IPAddressRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _IPAddressRegistry.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_IPAddressRegistry *IPAddressRegistrySession) Owner() (common.Address, error) { + return _IPAddressRegistry.Contract.Owner(&_IPAddressRegistry.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_IPAddressRegistry *IPAddressRegistryCallerSession) Owner() (common.Address, error) { + return _IPAddressRegistry.Contract.Owner(&_IPAddressRegistry.CallOpts) +} + +// AddAuthorizedUpdater is a paid mutator transaction binding the contract method 0x8c9b9fdc. +// +// Solidity: function addAuthorizedUpdater(address _updater) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactor) AddAuthorizedUpdater(opts *bind.TransactOpts, _updater common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.contract.Transact(opts, "addAuthorizedUpdater", _updater) +} + +// AddAuthorizedUpdater is a paid mutator transaction binding the contract method 0x8c9b9fdc. +// +// Solidity: function addAuthorizedUpdater(address _updater) returns() +func (_IPAddressRegistry *IPAddressRegistrySession) AddAuthorizedUpdater(_updater common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.AddAuthorizedUpdater(&_IPAddressRegistry.TransactOpts, _updater) +} + +// AddAuthorizedUpdater is a paid mutator transaction binding the contract method 0x8c9b9fdc. +// +// Solidity: function addAuthorizedUpdater(address _updater) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactorSession) AddAuthorizedUpdater(_updater common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.AddAuthorizedUpdater(&_IPAddressRegistry.TransactOpts, _updater) +} + +// AddIPAddress is a paid mutator transaction binding the contract method 0x90139fa0. +// +// Solidity: function addIPAddress(string _ipAddress) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactor) AddIPAddress(opts *bind.TransactOpts, _ipAddress string) (*types.Transaction, error) { + return _IPAddressRegistry.contract.Transact(opts, "addIPAddress", _ipAddress) +} + +// AddIPAddress is a paid mutator transaction binding the contract method 0x90139fa0. +// +// Solidity: function addIPAddress(string _ipAddress) returns() +func (_IPAddressRegistry *IPAddressRegistrySession) AddIPAddress(_ipAddress string) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.AddIPAddress(&_IPAddressRegistry.TransactOpts, _ipAddress) +} + +// AddIPAddress is a paid mutator transaction binding the contract method 0x90139fa0. +// +// Solidity: function addIPAddress(string _ipAddress) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactorSession) AddIPAddress(_ipAddress string) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.AddIPAddress(&_IPAddressRegistry.TransactOpts, _ipAddress) +} + +// RemoveAuthorizedUpdater is a paid mutator transaction binding the contract method 0x603cda09. +// +// Solidity: function removeAuthorizedUpdater(address _updater) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactor) RemoveAuthorizedUpdater(opts *bind.TransactOpts, _updater common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.contract.Transact(opts, "removeAuthorizedUpdater", _updater) +} + +// RemoveAuthorizedUpdater is a paid mutator transaction binding the contract method 0x603cda09. +// +// Solidity: function removeAuthorizedUpdater(address _updater) returns() +func (_IPAddressRegistry *IPAddressRegistrySession) RemoveAuthorizedUpdater(_updater common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.RemoveAuthorizedUpdater(&_IPAddressRegistry.TransactOpts, _updater) +} + +// RemoveAuthorizedUpdater is a paid mutator transaction binding the contract method 0x603cda09. +// +// Solidity: function removeAuthorizedUpdater(address _updater) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactorSession) RemoveAuthorizedUpdater(_updater common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.RemoveAuthorizedUpdater(&_IPAddressRegistry.TransactOpts, _updater) +} + +// RemoveIPAddress is a paid mutator transaction binding the contract method 0xba14bc71. +// +// Solidity: function removeIPAddress(uint256 index) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactor) RemoveIPAddress(opts *bind.TransactOpts, index *big.Int) (*types.Transaction, error) { + return _IPAddressRegistry.contract.Transact(opts, "removeIPAddress", index) +} + +// RemoveIPAddress is a paid mutator transaction binding the contract method 0xba14bc71. +// +// Solidity: function removeIPAddress(uint256 index) returns() +func (_IPAddressRegistry *IPAddressRegistrySession) RemoveIPAddress(index *big.Int) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.RemoveIPAddress(&_IPAddressRegistry.TransactOpts, index) +} + +// RemoveIPAddress is a paid mutator transaction binding the contract method 0xba14bc71. +// +// Solidity: function removeIPAddress(uint256 index) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactorSession) RemoveIPAddress(index *big.Int) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.RemoveIPAddress(&_IPAddressRegistry.TransactOpts, index) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_IPAddressRegistry *IPAddressRegistryTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IPAddressRegistry.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_IPAddressRegistry *IPAddressRegistrySession) RenounceOwnership() (*types.Transaction, error) { + return _IPAddressRegistry.Contract.RenounceOwnership(&_IPAddressRegistry.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_IPAddressRegistry *IPAddressRegistryTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _IPAddressRegistry.Contract.RenounceOwnership(&_IPAddressRegistry.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_IPAddressRegistry *IPAddressRegistrySession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.TransferOwnership(&_IPAddressRegistry.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_IPAddressRegistry *IPAddressRegistryTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _IPAddressRegistry.Contract.TransferOwnership(&_IPAddressRegistry.TransactOpts, newOwner) +} + +// IPAddressRegistryIPAddedIterator is returned from FilterIPAdded and is used to iterate over the raw logs and unpacked data for IPAdded events raised by the IPAddressRegistry contract. +type IPAddressRegistryIPAddedIterator struct { + Event *IPAddressRegistryIPAdded // 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 *IPAddressRegistryIPAddedIterator) 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(IPAddressRegistryIPAdded) + 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(IPAddressRegistryIPAdded) + 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 *IPAddressRegistryIPAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IPAddressRegistryIPAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IPAddressRegistryIPAdded represents a IPAdded event raised by the IPAddressRegistry contract. +type IPAddressRegistryIPAdded struct { + IpAddress string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterIPAdded is a free log retrieval operation binding the contract event 0xe7f7a48f1891a089b5b0418c215a3fdc894029f208c5b5930473161f39ae988b. +// +// Solidity: event IPAdded(string ipAddress) +func (_IPAddressRegistry *IPAddressRegistryFilterer) FilterIPAdded(opts *bind.FilterOpts) (*IPAddressRegistryIPAddedIterator, error) { + + logs, sub, err := _IPAddressRegistry.contract.FilterLogs(opts, "IPAdded") + if err != nil { + return nil, err + } + return &IPAddressRegistryIPAddedIterator{contract: _IPAddressRegistry.contract, event: "IPAdded", logs: logs, sub: sub}, nil +} + +// WatchIPAdded is a free log subscription operation binding the contract event 0xe7f7a48f1891a089b5b0418c215a3fdc894029f208c5b5930473161f39ae988b. +// +// Solidity: event IPAdded(string ipAddress) +func (_IPAddressRegistry *IPAddressRegistryFilterer) WatchIPAdded(opts *bind.WatchOpts, sink chan<- *IPAddressRegistryIPAdded) (event.Subscription, error) { + + logs, sub, err := _IPAddressRegistry.contract.WatchLogs(opts, "IPAdded") + 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(IPAddressRegistryIPAdded) + if err := _IPAddressRegistry.contract.UnpackLog(event, "IPAdded", 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 +} + +// ParseIPAdded is a log parse operation binding the contract event 0xe7f7a48f1891a089b5b0418c215a3fdc894029f208c5b5930473161f39ae988b. +// +// Solidity: event IPAdded(string ipAddress) +func (_IPAddressRegistry *IPAddressRegistryFilterer) ParseIPAdded(log types.Log) (*IPAddressRegistryIPAdded, error) { + event := new(IPAddressRegistryIPAdded) + if err := _IPAddressRegistry.contract.UnpackLog(event, "IPAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IPAddressRegistryIPRemovedIterator is returned from FilterIPRemoved and is used to iterate over the raw logs and unpacked data for IPRemoved events raised by the IPAddressRegistry contract. +type IPAddressRegistryIPRemovedIterator struct { + Event *IPAddressRegistryIPRemoved // 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 *IPAddressRegistryIPRemovedIterator) 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(IPAddressRegistryIPRemoved) + 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(IPAddressRegistryIPRemoved) + 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 *IPAddressRegistryIPRemovedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IPAddressRegistryIPRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IPAddressRegistryIPRemoved represents a IPRemoved event raised by the IPAddressRegistry contract. +type IPAddressRegistryIPRemoved struct { + IpAddress string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterIPRemoved is a free log retrieval operation binding the contract event 0x45fe66c64cad3093171b605f5ffe092b5333c407560ee34f49a9096c6b312c4f. +// +// Solidity: event IPRemoved(string ipAddress) +func (_IPAddressRegistry *IPAddressRegistryFilterer) FilterIPRemoved(opts *bind.FilterOpts) (*IPAddressRegistryIPRemovedIterator, error) { + + logs, sub, err := _IPAddressRegistry.contract.FilterLogs(opts, "IPRemoved") + if err != nil { + return nil, err + } + return &IPAddressRegistryIPRemovedIterator{contract: _IPAddressRegistry.contract, event: "IPRemoved", logs: logs, sub: sub}, nil +} + +// WatchIPRemoved is a free log subscription operation binding the contract event 0x45fe66c64cad3093171b605f5ffe092b5333c407560ee34f49a9096c6b312c4f. +// +// Solidity: event IPRemoved(string ipAddress) +func (_IPAddressRegistry *IPAddressRegistryFilterer) WatchIPRemoved(opts *bind.WatchOpts, sink chan<- *IPAddressRegistryIPRemoved) (event.Subscription, error) { + + logs, sub, err := _IPAddressRegistry.contract.WatchLogs(opts, "IPRemoved") + 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(IPAddressRegistryIPRemoved) + if err := _IPAddressRegistry.contract.UnpackLog(event, "IPRemoved", 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 +} + +// ParseIPRemoved is a log parse operation binding the contract event 0x45fe66c64cad3093171b605f5ffe092b5333c407560ee34f49a9096c6b312c4f. +// +// Solidity: event IPRemoved(string ipAddress) +func (_IPAddressRegistry *IPAddressRegistryFilterer) ParseIPRemoved(log types.Log) (*IPAddressRegistryIPRemoved, error) { + event := new(IPAddressRegistryIPRemoved) + if err := _IPAddressRegistry.contract.UnpackLog(event, "IPRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IPAddressRegistryOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the IPAddressRegistry contract. +type IPAddressRegistryOwnershipTransferredIterator struct { + Event *IPAddressRegistryOwnershipTransferred // 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 *IPAddressRegistryOwnershipTransferredIterator) 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(IPAddressRegistryOwnershipTransferred) + 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(IPAddressRegistryOwnershipTransferred) + 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 *IPAddressRegistryOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IPAddressRegistryOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IPAddressRegistryOwnershipTransferred represents a OwnershipTransferred event raised by the IPAddressRegistry contract. +type IPAddressRegistryOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_IPAddressRegistry *IPAddressRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*IPAddressRegistryOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _IPAddressRegistry.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &IPAddressRegistryOwnershipTransferredIterator{contract: _IPAddressRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_IPAddressRegistry *IPAddressRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *IPAddressRegistryOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _IPAddressRegistry.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(IPAddressRegistryOwnershipTransferred) + if err := _IPAddressRegistry.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_IPAddressRegistry *IPAddressRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*IPAddressRegistryOwnershipTransferred, error) { + event := new(IPAddressRegistryOwnershipTransferred) + if err := _IPAddressRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IPAddressRegistryUpdaterAddedIterator is returned from FilterUpdaterAdded and is used to iterate over the raw logs and unpacked data for UpdaterAdded events raised by the IPAddressRegistry contract. +type IPAddressRegistryUpdaterAddedIterator struct { + Event *IPAddressRegistryUpdaterAdded // 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 *IPAddressRegistryUpdaterAddedIterator) 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(IPAddressRegistryUpdaterAdded) + 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(IPAddressRegistryUpdaterAdded) + 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 *IPAddressRegistryUpdaterAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IPAddressRegistryUpdaterAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IPAddressRegistryUpdaterAdded represents a UpdaterAdded event raised by the IPAddressRegistry contract. +type IPAddressRegistryUpdaterAdded struct { + Updater common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdaterAdded is a free log retrieval operation binding the contract event 0x23a38f89c31ff6329bf86f3863cfa2ad8fc1462c40dbf907dbbebb8f9cb237ec. +// +// Solidity: event UpdaterAdded(address updater) +func (_IPAddressRegistry *IPAddressRegistryFilterer) FilterUpdaterAdded(opts *bind.FilterOpts) (*IPAddressRegistryUpdaterAddedIterator, error) { + + logs, sub, err := _IPAddressRegistry.contract.FilterLogs(opts, "UpdaterAdded") + if err != nil { + return nil, err + } + return &IPAddressRegistryUpdaterAddedIterator{contract: _IPAddressRegistry.contract, event: "UpdaterAdded", logs: logs, sub: sub}, nil +} + +// WatchUpdaterAdded is a free log subscription operation binding the contract event 0x23a38f89c31ff6329bf86f3863cfa2ad8fc1462c40dbf907dbbebb8f9cb237ec. +// +// Solidity: event UpdaterAdded(address updater) +func (_IPAddressRegistry *IPAddressRegistryFilterer) WatchUpdaterAdded(opts *bind.WatchOpts, sink chan<- *IPAddressRegistryUpdaterAdded) (event.Subscription, error) { + + logs, sub, err := _IPAddressRegistry.contract.WatchLogs(opts, "UpdaterAdded") + 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(IPAddressRegistryUpdaterAdded) + if err := _IPAddressRegistry.contract.UnpackLog(event, "UpdaterAdded", 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 +} + +// ParseUpdaterAdded is a log parse operation binding the contract event 0x23a38f89c31ff6329bf86f3863cfa2ad8fc1462c40dbf907dbbebb8f9cb237ec. +// +// Solidity: event UpdaterAdded(address updater) +func (_IPAddressRegistry *IPAddressRegistryFilterer) ParseUpdaterAdded(log types.Log) (*IPAddressRegistryUpdaterAdded, error) { + event := new(IPAddressRegistryUpdaterAdded) + if err := _IPAddressRegistry.contract.UnpackLog(event, "UpdaterAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IPAddressRegistryUpdaterRemovedIterator is returned from FilterUpdaterRemoved and is used to iterate over the raw logs and unpacked data for UpdaterRemoved events raised by the IPAddressRegistry contract. +type IPAddressRegistryUpdaterRemovedIterator struct { + Event *IPAddressRegistryUpdaterRemoved // 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 *IPAddressRegistryUpdaterRemovedIterator) 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(IPAddressRegistryUpdaterRemoved) + 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(IPAddressRegistryUpdaterRemoved) + 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 *IPAddressRegistryUpdaterRemovedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IPAddressRegistryUpdaterRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IPAddressRegistryUpdaterRemoved represents a UpdaterRemoved event raised by the IPAddressRegistry contract. +type IPAddressRegistryUpdaterRemoved struct { + Updater common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdaterRemoved is a free log retrieval operation binding the contract event 0x209d819a9ec655e89f2b2b9d65c8a78879b45a8f20d1941d69c5fe6dc21bcb62. +// +// Solidity: event UpdaterRemoved(address updater) +func (_IPAddressRegistry *IPAddressRegistryFilterer) FilterUpdaterRemoved(opts *bind.FilterOpts) (*IPAddressRegistryUpdaterRemovedIterator, error) { + + logs, sub, err := _IPAddressRegistry.contract.FilterLogs(opts, "UpdaterRemoved") + if err != nil { + return nil, err + } + return &IPAddressRegistryUpdaterRemovedIterator{contract: _IPAddressRegistry.contract, event: "UpdaterRemoved", logs: logs, sub: sub}, nil +} + +// WatchUpdaterRemoved is a free log subscription operation binding the contract event 0x209d819a9ec655e89f2b2b9d65c8a78879b45a8f20d1941d69c5fe6dc21bcb62. +// +// Solidity: event UpdaterRemoved(address updater) +func (_IPAddressRegistry *IPAddressRegistryFilterer) WatchUpdaterRemoved(opts *bind.WatchOpts, sink chan<- *IPAddressRegistryUpdaterRemoved) (event.Subscription, error) { + + logs, sub, err := _IPAddressRegistry.contract.WatchLogs(opts, "UpdaterRemoved") + 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(IPAddressRegistryUpdaterRemoved) + if err := _IPAddressRegistry.contract.UnpackLog(event, "UpdaterRemoved", 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 +} + +// ParseUpdaterRemoved is a log parse operation binding the contract event 0x209d819a9ec655e89f2b2b9d65c8a78879b45a8f20d1941d69c5fe6dc21bcb62. +// +// Solidity: event UpdaterRemoved(address updater) +func (_IPAddressRegistry *IPAddressRegistryFilterer) ParseUpdaterRemoved(log types.Log) (*IPAddressRegistryUpdaterRemoved, error) { + event := new(IPAddressRegistryUpdaterRemoved) + if err := _IPAddressRegistry.contract.UnpackLog(event, "UpdaterRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} From 2511a586e9dde363723d5412ec327fc32526326e Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 4 Dec 2024 13:22:23 +0700 Subject: [PATCH 05/43] Add prefix check --- p2p/p2p.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/p2p/p2p.go b/p2p/p2p.go index f0b54c3381..3d60ed378e 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -1,6 +1,7 @@ package p2p import ( + "bytes" "context" "encoding/hex" "errors" @@ -360,9 +361,13 @@ func loadPeers(database db.DB) ([]peer.AddrInfo, error) { defer it.Close() prefix := db.Peer.Key() + var peerIDBytes []byte for it.Seek(prefix); it.Valid(); it.Next() { - peerIDBytes := it.Key()[len(prefix):] - peerID, err := peer.IDFromBytes(peerIDBytes) + peerIDBytes = it.Key() + if !bytes.HasPrefix(peerIDBytes, prefix) { + break + } + peerID, err := peer.IDFromBytes(peerIDBytes[len(prefix):]) if err != nil { return fmt.Errorf("decode peer ID: %w", err) } From 95f9c1df58cc4f661d384e1e816c93ac2754ff73 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 4 Dec 2024 19:46:10 +0700 Subject: [PATCH 06/43] Add a channel to get IPs from l1 and handler for that --- p2p/p2p.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/p2p/p2p.go b/p2p/p2p.go index 3d60ed378e..201467f03d 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -35,6 +35,18 @@ const ( clientName = "juno" ) +type IPAddressEvent uint8 + +const ( + Add IPAddressEvent = iota + Remove +) + +type IPAddressRegistryEvent struct { + EventType IPAddressEvent + IP string +} + type Service struct { host host.Host @@ -50,6 +62,8 @@ type Service struct { feederNode bool database db.DB + + l1events <-chan IPAddressRegistryEvent } func New(addr, publicAddr, version, peers, privKeyStr string, feederNode bool, bc *blockchain.Blockchain, snNetwork *utils.Network, @@ -208,6 +222,8 @@ func (s *Service) Run(ctx context.Context) error { } }() + go s.listenForL1Events(ctx) + err := s.dht.Bootstrap(ctx) if err != nil { return err @@ -249,6 +265,25 @@ func (s *Service) Run(ctx context.Context) error { return nil } +func (s *Service) listenForL1Events(ctx context.Context) { + for event := range s.l1events { + switch event.EventType { + case Add: + if err := s.host.Connect(ctx, peer.AddrInfo{ID: peer.ID(event.IP)}); err != nil { + s.log.Warnw("Failed to connect to peer", "peer", event.IP, "err", err) + } else { + s.log.Infow("Connected to peer", "peer", event.IP) + } + case Remove: + if err := s.host.Network().ClosePeer(peer.ID(event.IP)); err != nil { + s.log.Warnw("Failed to disconnect from peer", "peer", event.IP, "err", err) + } else { + s.log.Infow("Disconnected from peer", "peer", event.IP) + } + } + } +} + func (s *Service) setProtocolHandlers() { s.SetProtocolHandler(starknet.HeadersPID(), s.handler.HeadersHandler) s.SetProtocolHandler(starknet.EventsPID(), s.handler.EventsHandler) From e0baa58a4f0b9f766eb9d3cf70b160ce9dca9600 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 4 Dec 2024 19:47:29 +0700 Subject: [PATCH 07/43] Add a channel to send IPs to P2P and handlers for that --- l1/eth_subscriber.go | 53 +++++++++++++++++----- l1/l1.go | 102 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 142 insertions(+), 13 deletions(-) diff --git a/l1/eth_subscriber.go b/l1/eth_subscriber.go index a9490d283e..f60c9f5ecd 100644 --- a/l1/eth_subscriber.go +++ b/l1/eth_subscriber.go @@ -8,6 +8,7 @@ import ( "time" "github.com/NethermindEth/juno/l1/contract" + "github.com/NethermindEth/juno/utils" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -17,15 +18,17 @@ import ( ) type EthSubscriber struct { - ethClient *ethclient.Client - client *rpc.Client - filterer *contract.StarknetFilterer - listener EventListener + ethClient *ethclient.Client + client *rpc.Client + filterer *contract.StarknetFilterer + listener EventListener + ipAddressRegistry *contract.IPAddressRegistry + ipAddressRegistryFilterer *contract.IPAddressRegistryFilterer } var _ Subscriber = (*EthSubscriber)(nil) -func NewEthSubscriber(ethClientAddress string, coreContractAddress common.Address) (*EthSubscriber, error) { +func NewEthSubscriber(ethClientAddress string, network *utils.Network) (*EthSubscriber, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -34,15 +37,33 @@ func NewEthSubscriber(ethClientAddress string, coreContractAddress common.Addres return nil, err } ethClient := ethclient.NewClient(client) - filterer, err := contract.NewStarknetFilterer(coreContractAddress, ethClient) + filterer, err := contract.NewStarknetFilterer(network.CoreContractAddress, ethClient) if err != nil { return nil, err } + + var ( + ipAddressRegistry *contract.IPAddressRegistry + ipAddressRegistryFilterer *contract.IPAddressRegistryFilterer + ) + if network.IPAddressRegistry != nil { + ipAddressRegistry, err = contract.NewIPAddressRegistry(*network.IPAddressRegistry, ethClient) + if err != nil { + return nil, err + } + ipAddressRegistryFilterer, err = contract.NewIPAddressRegistryFilterer(*network.IPAddressRegistry, ethClient) + if err != nil { + return nil, err + } + } + return &EthSubscriber{ - ethClient: ethClient, - client: client, - filterer: filterer, - listener: SelectiveListener{}, + ethClient: ethClient, + client: client, + filterer: filterer, + listener: SelectiveListener{}, + ipAddressRegistry: ipAddressRegistry, + ipAddressRegistryFilterer: ipAddressRegistryFilterer, }, nil } @@ -50,6 +71,18 @@ func (s *EthSubscriber) WatchLogStateUpdate(ctx context.Context, sink chan<- *co return s.filterer.WatchLogStateUpdate(&bind.WatchOpts{Context: ctx}, sink) } +func (s *EthSubscriber) WatchIPAdded(ctx context.Context, sink chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) { + return s.ipAddressRegistryFilterer.WatchIPAdded(&bind.WatchOpts{Context: ctx}, sink) +} + +func (s *EthSubscriber) WatchIPRemoved(ctx context.Context, sink chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) { + return s.ipAddressRegistryFilterer.WatchIPRemoved(&bind.WatchOpts{Context: ctx}, sink) +} + +func (s *EthSubscriber) GetIPAddresses(ctx context.Context, ip common.Address) ([]string, error) { + return s.ipAddressRegistry.GetIPAddresses(&bind.CallOpts{Context: ctx}) +} + func (s *EthSubscriber) ChainID(ctx context.Context) (*big.Int, error) { reqTimer := time.Now() chainID, err := s.ethClient.ChainID(ctx) diff --git a/l1/l1.go b/l1/l1.go index 654f7efed0..40db4a7541 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -11,6 +11,7 @@ import ( "github.com/NethermindEth/juno/core" "github.com/NethermindEth/juno/core/felt" "github.com/NethermindEth/juno/l1/contract" + "github.com/NethermindEth/juno/p2p" "github.com/NethermindEth/juno/service" "github.com/NethermindEth/juno/utils" "github.com/ethereum/go-ethereum/common" @@ -22,6 +23,9 @@ import ( type Subscriber interface { FinalisedHeight(ctx context.Context) (uint64, error) WatchLogStateUpdate(ctx context.Context, sink chan<- *contract.StarknetLogStateUpdate) (event.Subscription, error) + WatchIPAdded(ctx context.Context, sink chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) + WatchIPRemoved(ctx context.Context, sink chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) + GetIPAddresses(ctx context.Context, ip common.Address) ([]string, error) ChainID(ctx context.Context) (*big.Int, error) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) @@ -37,11 +41,12 @@ type Client struct { pollFinalisedInterval time.Duration nonFinalisedLogs map[uint64]*contract.StarknetLogStateUpdate listener EventListener + eventsToP2P chan<- p2p.IPAddressRegistryEvent } var _ service.Service = (*Client)(nil) -func NewClient(l1 Subscriber, chain *blockchain.Blockchain, log utils.SimpleLogger) *Client { +func NewClient(l1 Subscriber, chain *blockchain.Blockchain, log utils.SimpleLogger, eventsToP2P chan<- p2p.IPAddressEvent) *Client { return &Client{ l1: l1, l2Chain: chain, @@ -51,6 +56,7 @@ func NewClient(l1 Subscriber, chain *blockchain.Blockchain, log utils.SimpleLogg pollFinalisedInterval: time.Minute, nonFinalisedLogs: make(map[uint64]*contract.StarknetLogStateUpdate, 0), listener: SelectiveListener{}, + eventsToP2P: eventsToP2P, } } @@ -86,6 +92,38 @@ func (c *Client) subscribeToUpdates(ctx context.Context, updateChan chan *contra } } +func (c *Client) subscribeToIPAddressAddition(ctx context.Context, updateChan chan *contract.IPAddressRegistryIPAdded) (event.Subscription, error) { + for { + select { + case <-ctx.Done(): + return nil, fmt.Errorf("context canceled before resubscribe was successful: %w", ctx.Err()) + default: + updateSub, err := c.l1.WatchIPAdded(ctx, updateChan) + if err == nil { + return updateSub, nil + } + c.log.Debugw("Failed to subscribe to L1 IP address additions", "tryAgainIn", c.resubscribeDelay, "err", err) + time.Sleep(c.resubscribeDelay) + } + } +} + +func (c *Client) subscribeToIPAddressRemoval(ctx context.Context, updateChan chan *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) { + for { + select { + case <-ctx.Done(): + return nil, fmt.Errorf("context canceled before resubscribe was successful: %w", ctx.Err()) + default: + updateSub, err := c.l1.WatchIPRemoved(ctx, updateChan) + if err == nil { + return updateSub, nil + } + c.log.Debugw("Failed to subscribe to L1 IP address removals", "tryAgainIn", c.resubscribeDelay, "err", err) + time.Sleep(c.resubscribeDelay) + } + } +} + func (c *Client) checkChainID(ctx context.Context) error { gotChainID, err := c.l1.ChainID(ctx) if err != nil { @@ -108,19 +146,46 @@ func (c *Client) Run(ctx context.Context) error { return err } + addresses, err := c.l1.GetIPAddresses(ctx, *c.network.IPAddressRegistry) + if err != nil { + return err + } + for _, address := range addresses { + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Add, + IP: address, + } + } + buffer := 128 c.log.Infow("Subscribing to L1 updates...") - updateChan := make(chan *contract.StarknetLogStateUpdate, buffer) updateSub, err := c.subscribeToUpdates(ctx, updateChan) if err != nil { return err } defer updateSub.Unsubscribe() - c.log.Infow("Subscribed to L1 updates") + c.log.Debugw("Subscribing to L1 IP address additions...") + addedChan := make(chan *contract.IPAddressRegistryIPAdded, buffer) + addedSub, err := c.subscribeToIPAddressAddition(ctx, addedChan) + if err != nil { + return err + } + defer addedSub.Unsubscribe() + c.log.Debugw("Subscribed to L1 IP address additions") + + c.log.Debugw("Subscribing to L1 IP address removals...") + removedChan := make(chan *contract.IPAddressRegistryIPRemoved, buffer) + removedSub, err := c.subscribeToIPAddressRemoval(ctx, removedChan) + if err != nil { + return err + } + defer removedSub.Unsubscribe() + c.log.Debugw("Subscribed to L1 IP address removals") + ticker := time.NewTicker(c.pollFinalisedInterval) defer ticker.Stop() for { @@ -159,6 +224,37 @@ func (c *Client) Run(ctx context.Context) error { } else { c.nonFinalisedLogs[logStateUpdate.Raw.BlockNumber] = logStateUpdate } + case err := <-addedSub.Err(): + c.log.Debugw("IP address addition subscription failed, resubscribing", "error", err) + addedSub.Unsubscribe() + + addedSub, err = c.subscribeToIPAddressAddition(ctx, addedChan) + if err != nil { + return err + } + defer addedSub.Unsubscribe() //nolint:gocritic + case err := <-removedSub.Err(): + c.log.Debugw("IP address removal subscription failed, resubscribing", "error", err) + removedSub.Unsubscribe() + + removedSub, err = c.subscribeToIPAddressRemoval(ctx, removedChan) + if err != nil { + return err + } + defer removedSub.Unsubscribe() //nolint:gocritic + case added := <-addedChan: + c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Add, + IP: added.IpAddress, + } + case removed := <-removedChan: + c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Remove, + IP: removed.IpAddress, + } + default: break Outer } From 2e863e6a95d45570f31cf2c968e808e7ff7adc0a Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 4 Dec 2024 19:48:40 +0700 Subject: [PATCH 08/43] Add a channel for l1 and P2P communication and change the order of services initialization --- node/node.go | 61 ++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/node/node.go b/node/node.go index 586876b4ee..cbae81b2ba 100644 --- a/node/node.go +++ b/node/node.go @@ -170,6 +170,34 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen services = append(services, plugin.NewService(p)) } + throttledVM := NewThrottledVM(vm.New(false, log), cfg.MaxVMs, int32(cfg.MaxVMQueue)) + + var syncReader sync.Reader = &sync.NoopSynchronizer{} + if synchronizer != nil { + syncReader = synchronizer + } + + rpcHandler := rpc.New(chain, syncReader, throttledVM, version, log).WithGateway(gatewayClient).WithFeeder(client) + rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) + services = append(services, rpcHandler) + + l1ToP2P := make(chan p2p.IPAddressEvent, 128) + + if !cfg.DisableL1Verification { + // Due to mutually exclusive flag we can do the following. + if cfg.EthNode == "" { + return nil, fmt.Errorf("ethereum node address not found; Use --disable-l1-verification flag if L1 verification is not required") + } + + var l1Client *l1.Client + l1Client, err = newL1Client(cfg.EthNode, cfg.Metrics, chain, log, l1ToP2P) + if err != nil { + return nil, fmt.Errorf("create L1 client: %w", err) + } + services = append(services, l1Client) + rpcHandler.WithL1Client(l1Client.L1()) + } + var p2pService *p2p.Service if cfg.P2P { if cfg.Network == utils.Mainnet { @@ -192,17 +220,6 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen if synchronizer != nil { services = append(services, synchronizer) } - - throttledVM := NewThrottledVM(vm.New(false, log), cfg.MaxVMs, int32(cfg.MaxVMQueue)) - - var syncReader sync.Reader = &sync.NoopSynchronizer{} - if synchronizer != nil { - syncReader = synchronizer - } - - rpcHandler := rpc.New(chain, syncReader, throttledVM, version, log).WithGateway(gatewayClient).WithFeeder(client) - rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) - services = append(services, rpcHandler) // to improve RPC throughput we double GOMAXPROCS maxGoroutines := 2 * runtime.GOMAXPROCS(0) jsonrpcServer := jsonrpc.NewServer(maxGoroutines, log).WithValidator(validator.Validator()) @@ -274,21 +291,6 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen metricsService: metricsService, } - if !n.cfg.DisableL1Verification { - // Due to mutually exclusive flag we can do the following. - if n.cfg.EthNode == "" { - return nil, fmt.Errorf("ethereum node address not found; Use --disable-l1-verification flag if L1 verification is not required") - } - - var l1Client *l1.Client - l1Client, err = newL1Client(cfg.EthNode, cfg.Metrics, n.blockchain, n.log) - if err != nil { - return nil, fmt.Errorf("create L1 client: %w", err) - } - n.services = append(n.services, l1Client) - rpcHandler.WithL1Client(l1Client.L1()) - } - if semversion, err := semver.NewVersion(version); err == nil { ug := upgrader.NewUpgrader(semversion, githubAPIUrl, latestReleaseURL, upgraderDelay, n.log) n.services = append(n.services, ug) @@ -299,7 +301,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen return n, nil } -func newL1Client(ethNode string, includeMetrics bool, chain *blockchain.Blockchain, log utils.SimpleLogger) (*l1.Client, error) { +func newL1Client(ethNode string, includeMetrics bool, chain *blockchain.Blockchain, log utils.SimpleLogger, l1ToP2P chan p2p.IPAddressEvent) (*l1.Client, error) { ethNodeURL, err := url.Parse(ethNode) if err != nil { return nil, fmt.Errorf("parse Ethereum node URL: %w", err) @@ -310,13 +312,12 @@ func newL1Client(ethNode string, includeMetrics bool, chain *blockchain.Blockcha network := chain.Network() - var ethSubscriber *l1.EthSubscriber - ethSubscriber, err = l1.NewEthSubscriber(ethNode, network.CoreContractAddress) + ethSubscriber, err := l1.NewEthSubscriber(ethNode, network) if err != nil { return nil, fmt.Errorf("set up ethSubscriber: %w", err) } - l1Client := l1.NewClient(ethSubscriber, chain, log) + l1Client := l1.NewClient(ethSubscriber, chain, log, l1ToP2P) if includeMetrics { l1Client.WithEventListener(makeL1Metrics()) From 4a66b164e7379811942dee1a6da37a438ba3d023 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 11:22:25 +0700 Subject: [PATCH 09/43] Separate subscription creation --- l1/l1.go | 150 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 64 deletions(-) diff --git a/l1/l1.go b/l1/l1.go index 40db4a7541..145fd9d833 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" + "golang.org/x/sync/errgroup" ) //go:generate mockgen -destination=../mocks/mock_subscriber.go -package=mocks github.com/NethermindEth/juno/l1 Subscriber @@ -46,7 +47,7 @@ type Client struct { var _ service.Service = (*Client)(nil) -func NewClient(l1 Subscriber, chain *blockchain.Blockchain, log utils.SimpleLogger, eventsToP2P chan<- p2p.IPAddressEvent) *Client { +func NewClient(l1 Subscriber, chain *blockchain.Blockchain, log utils.SimpleLogger, eventsToP2P chan<- p2p.IPAddressRegistryEvent) *Client { return &Client{ l1: l1, l2Chain: chain, @@ -146,19 +147,22 @@ func (c *Client) Run(ctx context.Context) error { return err } - addresses, err := c.l1.GetIPAddresses(ctx, *c.network.IPAddressRegistry) - if err != nil { - return err - } - for _, address := range addresses { - c.eventsToP2P <- p2p.IPAddressRegistryEvent{ - EventType: p2p.Add, - IP: address, - } - } - buffer := 128 + ticker := time.NewTicker(c.pollFinalisedInterval) + defer ticker.Stop() + errs, ctx := errgroup.WithContext(ctx) + errs.Go(func() error { + return c.makeSubscriptionToStateUpdates(ctx, ticker, buffer) + }) + if c.network.IPAddressRegistry != nil { + errs.Go(func() error { + return c.makeSubscribtionsToIPAddresses(ctx, ticker, buffer) + }) + } + return errs.Wait() +} +func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, ticker *time.Ticker, buffer int) error { c.log.Infow("Subscribing to L1 updates...") updateChan := make(chan *contract.StarknetLogStateUpdate, buffer) updateSub, err := c.subscribeToUpdates(ctx, updateChan) @@ -167,27 +171,6 @@ func (c *Client) Run(ctx context.Context) error { } defer updateSub.Unsubscribe() c.log.Infow("Subscribed to L1 updates") - - c.log.Debugw("Subscribing to L1 IP address additions...") - addedChan := make(chan *contract.IPAddressRegistryIPAdded, buffer) - addedSub, err := c.subscribeToIPAddressAddition(ctx, addedChan) - if err != nil { - return err - } - defer addedSub.Unsubscribe() - c.log.Debugw("Subscribed to L1 IP address additions") - - c.log.Debugw("Subscribing to L1 IP address removals...") - removedChan := make(chan *contract.IPAddressRegistryIPRemoved, buffer) - removedSub, err := c.subscribeToIPAddressRemoval(ctx, removedChan) - if err != nil { - return err - } - defer removedSub.Unsubscribe() - c.log.Debugw("Subscribed to L1 IP address removals") - - ticker := time.NewTicker(c.pollFinalisedInterval) - defer ticker.Stop() for { select { case <-ctx.Done(): @@ -224,37 +207,6 @@ func (c *Client) Run(ctx context.Context) error { } else { c.nonFinalisedLogs[logStateUpdate.Raw.BlockNumber] = logStateUpdate } - case err := <-addedSub.Err(): - c.log.Debugw("IP address addition subscription failed, resubscribing", "error", err) - addedSub.Unsubscribe() - - addedSub, err = c.subscribeToIPAddressAddition(ctx, addedChan) - if err != nil { - return err - } - defer addedSub.Unsubscribe() //nolint:gocritic - case err := <-removedSub.Err(): - c.log.Debugw("IP address removal subscription failed, resubscribing", "error", err) - removedSub.Unsubscribe() - - removedSub, err = c.subscribeToIPAddressRemoval(ctx, removedChan) - if err != nil { - return err - } - defer removedSub.Unsubscribe() //nolint:gocritic - case added := <-addedChan: - c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) - c.eventsToP2P <- p2p.IPAddressRegistryEvent{ - EventType: p2p.Add, - IP: added.IpAddress, - } - case removed := <-removedChan: - c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) - c.eventsToP2P <- p2p.IPAddressRegistryEvent{ - EventType: p2p.Remove, - IP: removed.IpAddress, - } - default: break Outer } @@ -267,6 +219,76 @@ func (c *Client) Run(ctx context.Context) error { } } +func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, ticker *time.Ticker, buffer int) error { + addresses, err := c.l1.GetIPAddresses(ctx, *c.network.IPAddressRegistry) + if err != nil { + return err + } + for _, address := range addresses { + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Add, + IP: address, + } + } + c.log.Debugw("Subscribing to L1 IP address additions...") + addedChan := make(chan *contract.IPAddressRegistryIPAdded, buffer) + addedSub, err := c.subscribeToIPAddressAddition(ctx, addedChan) + if err != nil { + return err + } + defer addedSub.Unsubscribe() + c.log.Debugw("Subscribed to L1 IP address additions") + + c.log.Debugw("Subscribing to L1 IP address removals...") + removedChan := make(chan *contract.IPAddressRegistryIPRemoved, buffer) + removedSub, err := c.subscribeToIPAddressRemoval(ctx, removedChan) + if err != nil { + return err + } + defer removedSub.Unsubscribe() + c.log.Debugw("Subscribed to L1 IP address removals") + for { + select { + case <-ctx.Done(): + return nil + case <-ticker.C: + select { + case err := <-addedSub.Err(): + fmt.Println("err", err) + c.log.Debugw("IP address addition subscription failed, resubscribing", "error", err) + addedSub.Unsubscribe() + + addedSub, err = c.subscribeToIPAddressAddition(ctx, addedChan) + if err != nil { + return err + } + defer addedSub.Unsubscribe() //nolint:gocritic + case err := <-removedSub.Err(): + c.log.Debugw("IP address removal subscription failed, resubscribing", "error", err) + removedSub.Unsubscribe() + + removedSub, err = c.subscribeToIPAddressRemoval(ctx, removedChan) + if err != nil { + return err + } + defer removedSub.Unsubscribe() //nolint:gocritic + case added := <-addedChan: + c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Add, + IP: added.IpAddress, + } + case removed := <-removedChan: + c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Remove, + IP: removed.IpAddress, + } + } + } + } +} + func (c *Client) finalisedHeight(ctx context.Context) uint64 { for { select { From eb8d5a1184ff405e0219e72201e6abc3323594fc Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 11:22:55 +0700 Subject: [PATCH 10/43] Regenerate mock --- mocks/mock_subscriber.go | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/mocks/mock_subscriber.go b/mocks/mock_subscriber.go index 103c988fa2..c0d1a651df 100644 --- a/mocks/mock_subscriber.go +++ b/mocks/mock_subscriber.go @@ -87,6 +87,21 @@ func (mr *MockSubscriberMockRecorder) FinalisedHeight(ctx any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FinalisedHeight", reflect.TypeOf((*MockSubscriber)(nil).FinalisedHeight), ctx) } +// GetIPAddresses mocks base method. +func (m *MockSubscriber) GetIPAddresses(ctx context.Context, ip common.Address) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetIPAddresses", ctx, ip) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetIPAddresses indicates an expected call of GetIPAddresses. +func (mr *MockSubscriberMockRecorder) GetIPAddresses(ctx, ip any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIPAddresses", reflect.TypeOf((*MockSubscriber)(nil).GetIPAddresses), ctx, ip) +} + // TransactionReceipt mocks base method. func (m *MockSubscriber) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { m.ctrl.T.Helper() @@ -102,6 +117,36 @@ func (mr *MockSubscriberMockRecorder) TransactionReceipt(ctx, txHash any) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransactionReceipt", reflect.TypeOf((*MockSubscriber)(nil).TransactionReceipt), ctx, txHash) } +// WatchIPAdded mocks base method. +func (m *MockSubscriber) WatchIPAdded(ctx context.Context, sink chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WatchIPAdded", ctx, sink) + ret0, _ := ret[0].(event.Subscription) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WatchIPAdded indicates an expected call of WatchIPAdded. +func (mr *MockSubscriberMockRecorder) WatchIPAdded(ctx, sink any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WatchIPAdded", reflect.TypeOf((*MockSubscriber)(nil).WatchIPAdded), ctx, sink) +} + +// WatchIPRemoved mocks base method. +func (m *MockSubscriber) WatchIPRemoved(ctx context.Context, sink chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WatchIPRemoved", ctx, sink) + ret0, _ := ret[0].(event.Subscription) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WatchIPRemoved indicates an expected call of WatchIPRemoved. +func (mr *MockSubscriberMockRecorder) WatchIPRemoved(ctx, sink any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WatchIPRemoved", reflect.TypeOf((*MockSubscriber)(nil).WatchIPRemoved), ctx, sink) +} + // WatchLogStateUpdate mocks base method. func (m *MockSubscriber) WatchLogStateUpdate(ctx context.Context, sink chan<- *contract.StarknetLogStateUpdate) (event.Subscription, error) { m.ctrl.T.Helper() From 4c6b87000803fff1f37ceab698c711313aa6dd7d Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 11:23:27 +0700 Subject: [PATCH 11/43] Update tests --- l1/l1_pkg_test.go | 5 +++-- l1/l1_test.go | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index 4d8f9f0bce..22ba730855 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -13,6 +13,7 @@ import ( "github.com/NethermindEth/juno/db/pebble" "github.com/NethermindEth/juno/l1/contract" "github.com/NethermindEth/juno/mocks" + "github.com/NethermindEth/juno/p2p" "github.com/NethermindEth/juno/utils" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" @@ -338,7 +339,7 @@ func TestClient(t *testing.T) { network := utils.Mainnet chain := blockchain.New(pebble.NewMemTest(t), &network, nil) - client := NewClient(nil, chain, nopLog).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := NewClient(nil, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) // We loop over each block and check that the state agrees with our expectations. for _, block := range tt.blocks { @@ -398,7 +399,7 @@ func TestUnreliableSubscription(t *testing.T) { nopLog := utils.NewNopZapLogger() network := utils.Mainnet chain := blockchain.New(pebble.NewMemTest(t), &network, nil) - client := NewClient(nil, chain, nopLog).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := NewClient(nil, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) err := errors.New("test err") for _, block := range longSequenceOfBlocks { diff --git a/l1/l1_test.go b/l1/l1_test.go index bb14cc711a..f748ef29cc 100644 --- a/l1/l1_test.go +++ b/l1/l1_test.go @@ -16,6 +16,7 @@ import ( "github.com/NethermindEth/juno/l1" "github.com/NethermindEth/juno/l1/contract" "github.com/NethermindEth/juno/mocks" + "github.com/NethermindEth/juno/p2p" "github.com/NethermindEth/juno/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -72,7 +73,7 @@ func TestFailToCreateSubscription(t *testing.T) { subscriber.EXPECT().Close().Times(1) - client := l1.NewClient(subscriber, chain, nopLog).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) ctx, cancel := context.WithTimeout(context.Background(), time.Second) require.ErrorContains(t, client.Run(ctx), "context canceled before resubscribe was successful") @@ -96,7 +97,7 @@ func TestMismatchedChainID(t *testing.T) { Return(new(big.Int), nil). Times(1) - client := l1.NewClient(subscriber, chain, nopLog).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) ctx, cancel := context.WithTimeout(context.Background(), time.Second) t.Cleanup(cancel) @@ -141,7 +142,7 @@ func TestEventListener(t *testing.T) { subscriber.EXPECT().Close().Times(1) var got *core.L1Head - client := l1.NewClient(subscriber, chain, nopLog). + client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)). WithResubscribeDelay(0). WithPollFinalisedInterval(time.Nanosecond). WithEventListener(l1.SelectiveListener{ @@ -247,7 +248,7 @@ func TestEthSubscriber_FinalisedHeight(t *testing.T) { server, listener := startServer("127.0.0.1:0", test.service) defer server.Stop() - subscriber, err := l1.NewEthSubscriber("ws://"+listener.Addr().String(), common.Address{}) + subscriber, err := l1.NewEthSubscriber("ws://"+listener.Addr().String(), &utils.Network{}) require.NoError(t, err) defer subscriber.Close() From fb1be0aa0507c7b30a906d13ec824408103149eb Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 11:24:43 +0700 Subject: [PATCH 12/43] Fix arg --- node/node.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/node.go b/node/node.go index cbae81b2ba..69e751db27 100644 --- a/node/node.go +++ b/node/node.go @@ -181,7 +181,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) services = append(services, rpcHandler) - l1ToP2P := make(chan p2p.IPAddressEvent, 128) + l1ToP2P := make(chan p2p.IPAddressRegistryEvent, 128) //nolin:gomnd if !cfg.DisableL1Verification { // Due to mutually exclusive flag we can do the following. @@ -301,7 +301,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen return n, nil } -func newL1Client(ethNode string, includeMetrics bool, chain *blockchain.Blockchain, log utils.SimpleLogger, l1ToP2P chan p2p.IPAddressEvent) (*l1.Client, error) { +func newL1Client(ethNode string, includeMetrics bool, chain *blockchain.Blockchain, log utils.SimpleLogger, l1ToP2P chan p2p.IPAddressRegistryEvent) (*l1.Client, error) { ethNodeURL, err := url.Parse(ethNode) if err != nil { return nil, fmt.Errorf("parse Ethereum node URL: %w", err) From e8586c90a9cabc7dc86cf362d319e910f9ebb177 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 13:34:45 +0700 Subject: [PATCH 13/43] Remove ticker from params --- l1/l1.go | 79 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/l1/l1.go b/l1/l1.go index 145fd9d833..41324ce263 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -148,21 +148,22 @@ func (c *Client) Run(ctx context.Context) error { } buffer := 128 - ticker := time.NewTicker(c.pollFinalisedInterval) - defer ticker.Stop() + errs, ctx := errgroup.WithContext(ctx) errs.Go(func() error { - return c.makeSubscriptionToStateUpdates(ctx, ticker, buffer) + return c.makeSubscriptionToStateUpdates(ctx, buffer) }) if c.network.IPAddressRegistry != nil { errs.Go(func() error { - return c.makeSubscribtionsToIPAddresses(ctx, ticker, buffer) + return c.makeSubscribtionsToIPAddresses(ctx, buffer) }) } return errs.Wait() } -func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, ticker *time.Ticker, buffer int) error { +func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, buffer int) error { + ticker := time.NewTicker(c.pollFinalisedInterval) + defer ticker.Stop() c.log.Infow("Subscribing to L1 updates...") updateChan := make(chan *contract.StarknetLogStateUpdate, buffer) updateSub, err := c.subscribeToUpdates(ctx, updateChan) @@ -219,12 +220,13 @@ func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, ticker *tim } } -func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, ticker *time.Ticker, buffer int) error { +func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) error { addresses, err := c.l1.GetIPAddresses(ctx, *c.network.IPAddressRegistry) if err != nil { return err } for _, address := range addresses { + fmt.Println("added", address) c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Add, IP: address, @@ -251,39 +253,38 @@ func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, ticker *tim select { case <-ctx.Done(): return nil - case <-ticker.C: - select { - case err := <-addedSub.Err(): - fmt.Println("err", err) - c.log.Debugw("IP address addition subscription failed, resubscribing", "error", err) - addedSub.Unsubscribe() - - addedSub, err = c.subscribeToIPAddressAddition(ctx, addedChan) - if err != nil { - return err - } - defer addedSub.Unsubscribe() //nolint:gocritic - case err := <-removedSub.Err(): - c.log.Debugw("IP address removal subscription failed, resubscribing", "error", err) - removedSub.Unsubscribe() - - removedSub, err = c.subscribeToIPAddressRemoval(ctx, removedChan) - if err != nil { - return err - } - defer removedSub.Unsubscribe() //nolint:gocritic - case added := <-addedChan: - c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) - c.eventsToP2P <- p2p.IPAddressRegistryEvent{ - EventType: p2p.Add, - IP: added.IpAddress, - } - case removed := <-removedChan: - c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) - c.eventsToP2P <- p2p.IPAddressRegistryEvent{ - EventType: p2p.Remove, - IP: removed.IpAddress, - } + case err := <-addedSub.Err(): + fmt.Println("err", err) + c.log.Debugw("IP address addition subscription failed, resubscribing", "error", err) + addedSub.Unsubscribe() + + addedSub, err = c.subscribeToIPAddressAddition(ctx, addedChan) + if err != nil { + return err + } + defer addedSub.Unsubscribe() //nolint:gocritic + case err := <-removedSub.Err(): + c.log.Debugw("IP address removal subscription failed, resubscribing", "error", err) + removedSub.Unsubscribe() + + removedSub, err = c.subscribeToIPAddressRemoval(ctx, removedChan) + if err != nil { + return err + } + defer removedSub.Unsubscribe() //nolint:gocritic + case added := <-addedChan: + c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) + fmt.Println("added", added.IpAddress) + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Add, + IP: added.IpAddress, + } + case removed := <-removedChan: + fmt.Println("removed", removed.IpAddress) + c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) + c.eventsToP2P <- p2p.IPAddressRegistryEvent{ + EventType: p2p.Remove, + IP: removed.IpAddress, } } } From 6d7da991563b438a8ec7cb78e7ba1e7f4efedb50 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 13:36:19 +0700 Subject: [PATCH 14/43] Add TestMakeSubscribtionsToIPAddresses --- l1/l1_pkg_test.go | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index 22ba730855..ff7b5c9246 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -15,6 +15,7 @@ import ( "github.com/NethermindEth/juno/mocks" "github.com/NethermindEth/juno/p2p" "github.com/NethermindEth/juno/utils" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -467,3 +468,76 @@ func TestUnreliableSubscription(t *testing.T) { } } } + +func TestMakeSubscribtionsToIPAddresses(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + nopLog := utils.NewNopZapLogger() + network := utils.Mainnet + address := common.HexToAddress("0x1234") + network.IPAddressRegistry = &address + eventsChan := make(chan p2p.IPAddressRegistryEvent, 10) + chain := blockchain.New(pebble.NewMemTest(t), &network) + client := NewClient(nil, chain, nopLog, eventsChan).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + + storedAddresses := []string{"0x1", "0x2", "0x3"} + addressesToAdd := []string{"0x4", "0x5", "0x6"} + addressToRemove := []string{"0x2", "0x5"} + + subscriber := mocks.NewMockSubscriber(ctrl) + client.l1 = subscriber + + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(addressesToAdd[:2], nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()). + DoAndReturn(func(_ context.Context, sink chan<- *contract.IPAddressRegistryIPAdded) (*fakeSubscription, error) { + go func() { + for _, addr := range addressesToAdd { + sink <- &contract.IPAddressRegistryIPAdded{IpAddress: addr} + } + }() + return newFakeSubscription(), nil + }). + Times(1) + + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()). + DoAndReturn(func(_ context.Context, sink chan<- *contract.IPAddressRegistryIPRemoved) (*fakeSubscription, error) { + go func() { + for _, addr := range addressToRemove { + sink <- &contract.IPAddressRegistryIPRemoved{IpAddress: addr} + } + }() + return newFakeSubscription(), nil + }). + Times(1) + + require.NoError(t, client.makeSubscribtionsToIPAddresses(ctx, 1)) + + expectedAddressesToAdd := make(map[string]struct{}, len(addressesToAdd)+len(storedAddresses)) + for _, addr := range addressesToAdd { + expectedAddressesToAdd[addr] = struct{}{} + } + for _, addr := range storedAddresses { + expectedAddressesToAdd[addr] = struct{}{} + } + expectedAddressesToRemove := make(map[string]struct{}, len(addressToRemove)) + for _, addr := range addressToRemove { + expectedAddressesToRemove[addr] = struct{}{} + } + select { + case event := <-eventsChan: + switch event.EventType { + case p2p.Add: + assert.Contains(t, expectedAddressesToAdd, event.IP) + delete(expectedAddressesToAdd, event.IP) + case p2p.Remove: + assert.Contains(t, expectedAddressesToRemove, event.IP) + delete(expectedAddressesToRemove, event.IP) + } + case <-time.After(100 * time.Millisecond): + t.Fatal("Expected IP address addition event") + } +} From 9648a50ef9126d38c769fdb3f1223583eafcebeb Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 15:00:53 +0700 Subject: [PATCH 15/43] Remove debug logs --- l1/l1.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/l1/l1.go b/l1/l1.go index 41324ce263..8b8930c55a 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -226,7 +226,6 @@ func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) return err } for _, address := range addresses { - fmt.Println("added", address) c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Add, IP: address, @@ -254,7 +253,6 @@ func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) case <-ctx.Done(): return nil case err := <-addedSub.Err(): - fmt.Println("err", err) c.log.Debugw("IP address addition subscription failed, resubscribing", "error", err) addedSub.Unsubscribe() @@ -274,13 +272,11 @@ func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) defer removedSub.Unsubscribe() //nolint:gocritic case added := <-addedChan: c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) - fmt.Println("added", added.IpAddress) c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Add, IP: added.IpAddress, } case removed := <-removedChan: - fmt.Println("removed", removed.IpAddress) c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Remove, From 639b4c2b2590d6af768f281f209f50d1ad2ca55e Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 5 Dec 2024 15:41:55 +0700 Subject: [PATCH 16/43] Add TestUnreliableSubscriptionToIPAddresses --- l1/l1_pkg_test.go | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index ff7b5c9246..f14011f7bd 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -541,3 +541,96 @@ func TestMakeSubscribtionsToIPAddresses(t *testing.T) { t.Fatal("Expected IP address addition event") } } + +func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { + t.Parallel() + address := common.HexToAddress("0x1234") + network := utils.Mainnet + network.IPAddressRegistry = &address + chain := blockchain.New(pebble.NewMemTest(t), &network) + nopLog := utils.NewNopZapLogger() + err := errors.New("test err") + + testCases := []struct { + name string + setupMock func(subscriber *mocks.MockSubscriber) + expectedErr error + }{ + { + name: "GetIPAddresses error", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, err).Times(1) + }, + expectedErr: err, + }, + { + name: "WatchIPAdded error", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(nil, err).Times(1) + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + }, + expectedErr: nil, + }, + { + name: "WatchIPRemoved error", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(nil, err).Times(1) + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + }, + expectedErr: nil, + }, + { + name: "Addition subscription error", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(err), nil).Times(1) + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + }, + expectedErr: nil, + }, + { + name: "Removal subscription error", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(err), nil).Times(1) + subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) + }, + expectedErr: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + eventsChan := make(chan p2p.IPAddressRegistryEvent, 10) + client := Client{ + l1: nil, + l2Chain: chain, + log: nopLog, + network: chain.Network(), + resubscribeDelay: 0, + nonFinalisedLogs: make(map[uint64]*contract.StarknetLogStateUpdate, 0), + listener: SelectiveListener{}, + eventsToP2P: eventsChan, + } + + subscriber := mocks.NewMockSubscriber(ctrl) + client.l1 = subscriber + tc.setupMock(subscriber) + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + err := client.makeSubscribtionsToIPAddresses(ctx, 1) + require.ErrorIs(t, err, tc.expectedErr) + }) + } +} From cf245be905f9094ce1b4f76976f4efbb72d33b2a Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 15:40:53 +0700 Subject: [PATCH 17/43] Set chan to nil --- p2p/p2p_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/p2p/p2p_test.go b/p2p/p2p_test.go index 54b19d5900..b5a5f69d6f 100644 --- a/p2p/p2p_test.go +++ b/p2p/p2p_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestInvalidKey(t *testing.T) { _, err := p2p.New( "/ip4/127.0.0.1/tcp/30301", "", @@ -24,6 +23,7 @@ func TestInvalidKey(t *testing.T) { &utils.Integration, utils.NewNopZapLogger(), nil, + nil, ) require.Error(t, err) @@ -61,6 +61,7 @@ func TestLoadAndPersistPeers(t *testing.T) { &utils.Integration, utils.NewNopZapLogger(), testDB, + nil, ) require.NoError(t, err) } From 22e6d4e1e29809142476e4793ebb9e2bc42945b6 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 15:41:56 +0700 Subject: [PATCH 18/43] Add TestListenForL1Events --- p2p/p2p_pkg_test.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 p2p/p2p_pkg_test.go diff --git a/p2p/p2p_pkg_test.go b/p2p/p2p_pkg_test.go new file mode 100644 index 0000000000..63d9d022b0 --- /dev/null +++ b/p2p/p2p_pkg_test.go @@ -0,0 +1,46 @@ +package p2p + +import ( + "context" + "testing" + "time" + + "github.com/NethermindEth/juno/db/pebble" + "github.com/NethermindEth/juno/utils" + "github.com/libp2p/go-libp2p/core/peer" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/stretchr/testify/require" +) + +func TestListenForL1Events(t *testing.T) { + eventChan := make(chan IPAddressRegistryEvent, 8) + ctx, cancel := context.WithCancel(context.Background()) + defer func() { + cancel() + close(eventChan) + }() + + net, err := mocknet.FullMeshLinked(2) + require.NoError(t, err) + peerHosts := net.Hosts() + require.Len(t, peerHosts, 2) + testDB := pebble.NewMemTest(t) + + peerA, err := NewWithHost(peerHosts[0], "", false, nil, &utils.Integration, utils.NewNopZapLogger(), testDB, eventChan) + require.NoError(t, err) + + go peerA.listenForL1Events(ctx) + + peerB, err := NewWithHost(peerHosts[1], "", false, nil, &utils.Integration, utils.NewNopZapLogger(), testDB, nil) + require.NoError(t, err) + + addr, err := peerB.ListenAddrs() + require.NoError(t, err) + addrStr := addr[0].String() + + eventChan <- IPAddressRegistryEvent{Add, addrStr} + time.Sleep(100 * time.Millisecond) + require.Equal(t, peer.IDSlice{peerHosts[0].ID(), peerHosts[1].ID()}, peerA.host.Peerstore().Peers()) + + // TODO: test remove event, find a way to remove peer from peerstore +} From 18d91120ccebfc6498527fc945d5ac9f2212fa31 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 15:42:34 +0700 Subject: [PATCH 19/43] Fix listenForL1Events --- p2p/p2p.go | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/p2p/p2p.go b/p2p/p2p.go index 201467f03d..9501799ae9 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -67,7 +67,7 @@ type Service struct { } func New(addr, publicAddr, version, peers, privKeyStr string, feederNode bool, bc *blockchain.Blockchain, snNetwork *utils.Network, - log utils.SimpleLogger, database db.DB, + log utils.SimpleLogger, database db.DB, l1events <-chan IPAddressRegistryEvent, ) (*Service, error) { if addr == "" { // 0.0.0.0/tcp/0 will listen on any interface device and assing a free port. @@ -124,11 +124,11 @@ func New(addr, publicAddr, version, peers, privKeyStr string, feederNode bool, b // Todo: try to understand what will happen if user passes a multiaddr with p2p public and a private key which doesn't match. // For example, a user passes the following multiaddr: --p2p-addr=/ip4/0.0.0.0/tcp/7778/p2p/(SomePublicKey) and also passes a // --p2p-private-key="SomePrivateKey". However, the private public key pair don't match, in this case what will happen? - return NewWithHost(p2pHost, peers, feederNode, bc, snNetwork, log, database) + return NewWithHost(p2pHost, peers, feederNode, bc, snNetwork, log, database, l1events) } func NewWithHost(p2phost host.Host, peers string, feederNode bool, bc *blockchain.Blockchain, snNetwork *utils.Network, - log utils.SimpleLogger, database db.DB, + log utils.SimpleLogger, database db.DB, l1events <-chan IPAddressRegistryEvent, ) (*Service, error) { var ( peersAddrInfoS []peer.AddrInfo @@ -170,6 +170,7 @@ func NewWithHost(p2phost host.Host, peers string, feederNode bool, bc *blockchai feederNode: feederNode, handler: starknet.NewHandler(bc, log), database: database, + l1events: l1events, } return s, nil } @@ -266,19 +267,37 @@ func (s *Service) Run(ctx context.Context) error { } func (s *Service) listenForL1Events(ctx context.Context) { - for event := range s.l1events { - switch event.EventType { - case Add: - if err := s.host.Connect(ctx, peer.AddrInfo{ID: peer.ID(event.IP)}); err != nil { - s.log.Warnw("Failed to connect to peer", "peer", event.IP, "err", err) - } else { - s.log.Infow("Connected to peer", "peer", event.IP) + for { + select { + case <-ctx.Done(): + return + case registryEvent, ok := <-s.l1events: + if !ok { + s.log.Debugw("L1 events channel closed") + return } - case Remove: - if err := s.host.Network().ClosePeer(peer.ID(event.IP)); err != nil { - s.log.Warnw("Failed to disconnect from peer", "peer", event.IP, "err", err) - } else { - s.log.Infow("Disconnected from peer", "peer", event.IP) + peerInfo, err := peer.AddrInfoFromP2pAddr(multiaddr.StringCast(registryEvent.IP)) + if err != nil { + s.log.Warnw("Failed to parse peer address", "peer", registryEvent.IP, "err", err) + continue + } + switch registryEvent.EventType { + case Add: + if err := s.host.Connect(ctx, *peerInfo); err != nil { + s.log.Warnw("Failed to connect to peer", "peer", registryEvent.IP, "err", err) + } else { + s.log.Debugw("Connected to peer", "peer", registryEvent.IP) + } + case Remove: + if err := s.host.Network().ClosePeer(peerInfo.ID); err != nil { + s.log.Warnw("Failed to disconnect from peer", "peer", registryEvent.IP, "err", err) + } else { + s.log.Debugw("Disconnected from peer", "peer", registryEvent.IP) + } + s.host.Peerstore().RemovePeer(peerInfo.ID) + s.log.Debugw("Removed peer from peerstore", "peer", peerInfo.ID) + s.dht.RoutingTable().RemovePeer(peerInfo.ID) + s.log.Debugw("Removed peer from routing table", "peer", peerInfo.ID) } } } From e44d6da978d8ff012ca3e6b129339d2d715462b3 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 15:51:34 +0700 Subject: [PATCH 20/43] Fix minor erorrs and linter issues --- l1/l1.go | 14 +++++++++----- l1/l1_pkg_test.go | 8 ++++---- node/node.go | 15 +++++++++------ p2p/p2p.go | 14 +++++++------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/l1/l1.go b/l1/l1.go index 8b8930c55a..5556649867 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -93,7 +93,9 @@ func (c *Client) subscribeToUpdates(ctx context.Context, updateChan chan *contra } } -func (c *Client) subscribeToIPAddressAddition(ctx context.Context, updateChan chan *contract.IPAddressRegistryIPAdded) (event.Subscription, error) { +func (c *Client) subscribeToIPAddressAddition( + ctx context.Context, updateChan chan *contract.IPAddressRegistryIPAdded, +) (event.Subscription, error) { for { select { case <-ctx.Done(): @@ -109,7 +111,9 @@ func (c *Client) subscribeToIPAddressAddition(ctx context.Context, updateChan ch } } -func (c *Client) subscribeToIPAddressRemoval(ctx context.Context, updateChan chan *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) { +func (c *Client) subscribeToIPAddressRemoval( + ctx context.Context, updateChan chan *contract.IPAddressRegistryIPRemoved, +) (event.Subscription, error) { for { select { case <-ctx.Done(): @@ -228,7 +232,7 @@ func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) for _, address := range addresses { c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Add, - IP: address, + Address: address, } } c.log.Debugw("Subscribing to L1 IP address additions...") @@ -274,13 +278,13 @@ func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) c.log.Debugw("Received L1 IP address addition", "ip", added.IpAddress) c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Add, - IP: added.IpAddress, + Address: added.IpAddress, } case removed := <-removedChan: c.log.Debugw("Received L1 IP address removal", "ip", removed.IpAddress) c.eventsToP2P <- p2p.IPAddressRegistryEvent{ EventType: p2p.Remove, - IP: removed.IpAddress, + Address: removed.IpAddress, } } } diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index f14011f7bd..f31786b863 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -531,11 +531,11 @@ func TestMakeSubscribtionsToIPAddresses(t *testing.T) { case event := <-eventsChan: switch event.EventType { case p2p.Add: - assert.Contains(t, expectedAddressesToAdd, event.IP) - delete(expectedAddressesToAdd, event.IP) + assert.Contains(t, expectedAddressesToAdd, event.Address) + delete(expectedAddressesToAdd, event.Address) case p2p.Remove: - assert.Contains(t, expectedAddressesToRemove, event.IP) - delete(expectedAddressesToRemove, event.IP) + assert.Contains(t, expectedAddressesToRemove, event.Address) + delete(expectedAddressesToRemove, event.Address) } case <-time.After(100 * time.Millisecond): t.Fatal("Expected IP address addition event") diff --git a/node/node.go b/node/node.go index 69e751db27..963d3faae1 100644 --- a/node/node.go +++ b/node/node.go @@ -39,9 +39,10 @@ import ( ) const ( - upgraderDelay = 5 * time.Minute - githubAPIUrl = "https://api.github.com/repos/NethermindEth/juno/releases/latest" - latestReleaseURL = "https://github.com/NethermindEth/juno/releases/latest" + upgraderDelay = 5 * time.Minute + githubAPIUrl = "https://api.github.com/repos/NethermindEth/juno/releases/latest" + latestReleaseURL = "https://github.com/NethermindEth/juno/releases/latest" + l1ToP2PChannelBuffer = 128 ) // Config is the top-level juno configuration. @@ -181,7 +182,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) services = append(services, rpcHandler) - l1ToP2P := make(chan p2p.IPAddressRegistryEvent, 128) //nolin:gomnd + l1ToP2P := make(chan p2p.IPAddressRegistryEvent, l1ToP2PChannelBuffer) //nolin:mnd if !cfg.DisableL1Verification { // Due to mutually exclusive flag we can do the following. @@ -210,7 +211,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen synchronizer = nil } p2pService, err = p2p.New(cfg.P2PAddr, cfg.P2PPublicAddr, version, cfg.P2PPeers, cfg.P2PPrivateKey, cfg.P2PFeederNode, - chain, &cfg.Network, log, database) + chain, &cfg.Network, log, database, l1ToP2P) if err != nil { return nil, fmt.Errorf("set up p2p service: %w", err) } @@ -301,7 +302,9 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen return n, nil } -func newL1Client(ethNode string, includeMetrics bool, chain *blockchain.Blockchain, log utils.SimpleLogger, l1ToP2P chan p2p.IPAddressRegistryEvent) (*l1.Client, error) { +func newL1Client( + ethNode string, includeMetrics bool, chain *blockchain.Blockchain, log utils.SimpleLogger, l1ToP2P chan p2p.IPAddressRegistryEvent, +) (*l1.Client, error) { ethNodeURL, err := url.Parse(ethNode) if err != nil { return nil, fmt.Errorf("parse Ethereum node URL: %w", err) diff --git a/p2p/p2p.go b/p2p/p2p.go index 9501799ae9..829f26e99f 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -44,7 +44,7 @@ const ( type IPAddressRegistryEvent struct { EventType IPAddressEvent - IP string + Address string } type Service struct { @@ -276,23 +276,23 @@ func (s *Service) listenForL1Events(ctx context.Context) { s.log.Debugw("L1 events channel closed") return } - peerInfo, err := peer.AddrInfoFromP2pAddr(multiaddr.StringCast(registryEvent.IP)) + peerInfo, err := peer.AddrInfoFromP2pAddr(multiaddr.StringCast(registryEvent.Address)) if err != nil { - s.log.Warnw("Failed to parse peer address", "peer", registryEvent.IP, "err", err) + s.log.Warnw("Failed to parse peer address", "peer", registryEvent.Address, "err", err) continue } switch registryEvent.EventType { case Add: if err := s.host.Connect(ctx, *peerInfo); err != nil { - s.log.Warnw("Failed to connect to peer", "peer", registryEvent.IP, "err", err) + s.log.Warnw("Failed to connect to peer", "peer", registryEvent.Address, "err", err) } else { - s.log.Debugw("Connected to peer", "peer", registryEvent.IP) + s.log.Debugw("Connected to peer", "peer", registryEvent.Address) } case Remove: if err := s.host.Network().ClosePeer(peerInfo.ID); err != nil { - s.log.Warnw("Failed to disconnect from peer", "peer", registryEvent.IP, "err", err) + s.log.Warnw("Failed to disconnect from peer", "peer", registryEvent.Address, "err", err) } else { - s.log.Debugw("Disconnected from peer", "peer", registryEvent.IP) + s.log.Debugw("Disconnected from peer", "peer", registryEvent.Address) } s.host.Peerstore().RemovePeer(peerInfo.ID) s.log.Debugw("Removed peer from peerstore", "peer", peerInfo.ID) From 1701daeb55480ec3a7a4772d4582f9891668a219 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 15:54:54 +0700 Subject: [PATCH 21/43] Move ticker closer to its usage --- l1/l1.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/l1/l1.go b/l1/l1.go index 5556649867..75679da76d 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -166,8 +166,6 @@ func (c *Client) Run(ctx context.Context) error { } func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, buffer int) error { - ticker := time.NewTicker(c.pollFinalisedInterval) - defer ticker.Stop() c.log.Infow("Subscribing to L1 updates...") updateChan := make(chan *contract.StarknetLogStateUpdate, buffer) updateSub, err := c.subscribeToUpdates(ctx, updateChan) @@ -175,7 +173,12 @@ func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, buffer int) return err } defer updateSub.Unsubscribe() + c.log.Infow("Subscribed to L1 updates") + + ticker := time.NewTicker(c.pollFinalisedInterval) + defer ticker.Stop() + for { select { case <-ctx.Done(): From 124697e89fee097b51389f7cb506c19cbc7a3fe6 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 16:01:15 +0700 Subject: [PATCH 22/43] Set chans to nil --- l1/l1_pkg_test.go | 4 ++-- l1/l1_test.go | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index f31786b863..7c339f7789 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -340,7 +340,7 @@ func TestClient(t *testing.T) { network := utils.Mainnet chain := blockchain.New(pebble.NewMemTest(t), &network, nil) - client := NewClient(nil, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := NewClient(nil, chain, nopLog, nil).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) // We loop over each block and check that the state agrees with our expectations. for _, block := range tt.blocks { @@ -400,7 +400,7 @@ func TestUnreliableSubscription(t *testing.T) { nopLog := utils.NewNopZapLogger() network := utils.Mainnet chain := blockchain.New(pebble.NewMemTest(t), &network, nil) - client := NewClient(nil, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := NewClient(nil, chain, nopLog, nil).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) err := errors.New("test err") for _, block := range longSequenceOfBlocks { diff --git a/l1/l1_test.go b/l1/l1_test.go index f748ef29cc..d8fdc2221a 100644 --- a/l1/l1_test.go +++ b/l1/l1_test.go @@ -16,7 +16,6 @@ import ( "github.com/NethermindEth/juno/l1" "github.com/NethermindEth/juno/l1/contract" "github.com/NethermindEth/juno/mocks" - "github.com/NethermindEth/juno/p2p" "github.com/NethermindEth/juno/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -73,7 +72,7 @@ func TestFailToCreateSubscription(t *testing.T) { subscriber.EXPECT().Close().Times(1) - client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := l1.NewClient(subscriber, chain, nopLog, nil).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) ctx, cancel := context.WithTimeout(context.Background(), time.Second) require.ErrorContains(t, client.Run(ctx), "context canceled before resubscribe was successful") @@ -97,7 +96,7 @@ func TestMismatchedChainID(t *testing.T) { Return(new(big.Int), nil). Times(1) - client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) + client := l1.NewClient(subscriber, chain, nopLog, nil).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) ctx, cancel := context.WithTimeout(context.Background(), time.Second) t.Cleanup(cancel) @@ -142,7 +141,7 @@ func TestEventListener(t *testing.T) { subscriber.EXPECT().Close().Times(1) var got *core.L1Head - client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)). + client := l1.NewClient(subscriber, chain, nopLog, nil). WithResubscribeDelay(0). WithPollFinalisedInterval(time.Nanosecond). WithEventListener(l1.SelectiveListener{ From 3220329c90f26e5266ddc4d16902dddb02d0d9ee Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 6 Dec 2024 16:05:10 +0700 Subject: [PATCH 23/43] Fix test to pass when peer order change --- p2p/p2p_pkg_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/p2p/p2p_pkg_test.go b/p2p/p2p_pkg_test.go index 63d9d022b0..c56126fa00 100644 --- a/p2p/p2p_pkg_test.go +++ b/p2p/p2p_pkg_test.go @@ -40,7 +40,14 @@ func TestListenForL1Events(t *testing.T) { eventChan <- IPAddressRegistryEvent{Add, addrStr} time.Sleep(100 * time.Millisecond) - require.Equal(t, peer.IDSlice{peerHosts[0].ID(), peerHosts[1].ID()}, peerA.host.Peerstore().Peers()) + expectedPeers := map[peer.ID]struct{}{ + peerHosts[0].ID(): {}, + peerHosts[1].ID(): {}, + } + + for _, peer := range peerA.host.Peerstore().Peers() { + require.Contains(t, expectedPeers, peer) + } // TODO: test remove event, find a way to remove peer from peerstore } From 3e8661f13ea8fba93f76047e85f495dbcae852e7 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Tue, 10 Dec 2024 09:22:02 +0700 Subject: [PATCH 24/43] Set sepolia SC address --- utils/network.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/network.go b/utils/network.go index 212fb9f981..267b2f54fd 100644 --- a/utils/network.go +++ b/utils/network.go @@ -39,8 +39,9 @@ var ( fallBackSequencerAddressMainnet, _ = new(felt.Felt).SetString("0x021f4b90b0377c82bf330b7b5295820769e72d79d8acd0effa0ebde6e9988bc5") fallBackSequencerAddress, _ = new(felt.Felt).SetString("0x046a89ae102987331d369645031b49c27738ed096f2789c24449966da4c6de6b") // The following are necessary for Cobra and Viper, respectively, to unmarshal log level CLI/config parameters properly. - _ pflag.Value = (*Network)(nil) - _ encoding.TextUnmarshaler = (*Network)(nil) + _ pflag.Value = (*Network)(nil) + _ encoding.TextUnmarshaler = (*Network)(nil) + ipAddressRegistry = common.HexToAddress("0xa2499F2a3Fb071fd99f921038d043eF31B446883") // The docs states the addresses for each network: https://docs.starknet.io/tools/important-addresses/ Mainnet = Network{ @@ -108,6 +109,7 @@ var ( First07Block: 0, FallBackSequencerAddress: fallBackSequencerAddress, }, + IPAddressRegistry: &ipAddressRegistry, } SepoliaIntegration = Network{ Name: "sepolia-integration", From 249a9f9de15687bebd8dbb22c8479be9b26115d0 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 18 Dec 2024 16:56:52 +0700 Subject: [PATCH 25/43] Fix rebase issues --- l1/l1_pkg_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index 7c339f7789..11cf75ad73 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -478,7 +478,7 @@ func TestMakeSubscribtionsToIPAddresses(t *testing.T) { address := common.HexToAddress("0x1234") network.IPAddressRegistry = &address eventsChan := make(chan p2p.IPAddressRegistryEvent, 10) - chain := blockchain.New(pebble.NewMemTest(t), &network) + chain := blockchain.New(pebble.NewMemTest(t), &network, nil) client := NewClient(nil, chain, nopLog, eventsChan).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) @@ -547,7 +547,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { address := common.HexToAddress("0x1234") network := utils.Mainnet network.IPAddressRegistry = &address - chain := blockchain.New(pebble.NewMemTest(t), &network) + chain := blockchain.New(pebble.NewMemTest(t), &network, nil) nopLog := utils.NewNopZapLogger() err := errors.New("test err") From b22aa539e9aa967d478b348c02099f69f8efde48 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 18 Dec 2024 16:57:10 +0700 Subject: [PATCH 26/43] Fix rebase issues --- p2p/p2p_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/p2p/p2p_test.go b/p2p/p2p_test.go index b5a5f69d6f..444ed5f34a 100644 --- a/p2p/p2p_test.go +++ b/p2p/p2p_test.go @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/require" ) + +func TestInvalidKey(t *testing.T) { _, err := p2p.New( "/ip4/127.0.0.1/tcp/30301", "", From 2261edfe55e3067451d80db4fa861023929f7068 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 18 Dec 2024 16:57:33 +0700 Subject: [PATCH 27/43] Fix chan usage --- l1/l1.go | 1 + node/node.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/l1/l1.go b/l1/l1.go index 75679da76d..8da096dd07 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -228,6 +228,7 @@ func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, buffer int) } func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) error { + defer close(c.eventsToP2P) addresses, err := c.l1.GetIPAddresses(ctx, *c.network.IPAddressRegistry) if err != nil { return err diff --git a/node/node.go b/node/node.go index 963d3faae1..5279d98d56 100644 --- a/node/node.go +++ b/node/node.go @@ -39,10 +39,9 @@ import ( ) const ( - upgraderDelay = 5 * time.Minute - githubAPIUrl = "https://api.github.com/repos/NethermindEth/juno/releases/latest" - latestReleaseURL = "https://github.com/NethermindEth/juno/releases/latest" - l1ToP2PChannelBuffer = 128 + upgraderDelay * time.Minute + githubAPIUrl = "https://api.github.com/repos/NethermindEth/juno/releases/latest" + latestReleaseURLhttps://github.com/NethermindEth/juno/releases/latest" ) // Config is the top-level juno configuration. @@ -182,8 +181,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) services = append(services, rpcHandler) - l1ToP2P := make(chan p2p.IPAddressRegistryEvent, l1ToP2PChannelBuffer) //nolin:mnd - + l1ToP2P := make(chan p2p.IPAddressRegistryEvent) if !cfg.DisableL1Verification { // Due to mutually exclusive flag we can do the following. if cfg.EthNode == "" { @@ -197,6 +195,8 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen } services = append(services, l1Client) rpcHandler.WithL1Client(l1Client.L1()) + } else { + close(l1ToP2P) } var p2pService *p2p.Service From d6202df99710d83011c931af0660e6fae25ea6a4 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 18 Dec 2024 19:30:53 +0700 Subject: [PATCH 28/43] Fix minor issues --- node/node.go | 8 ++++---- p2p/p2p_test.go | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/node/node.go b/node/node.go index 5279d98d56..35a775ee82 100644 --- a/node/node.go +++ b/node/node.go @@ -39,9 +39,9 @@ import ( ) const ( - upgraderDelay * time.Minute - githubAPIUrl = "https://api.github.com/repos/NethermindEth/juno/releases/latest" - latestReleaseURLhttps://github.com/NethermindEth/juno/releases/latest" + upgraderDelay = 5 * time.Minute + githubAPIUrl = "https://api.github.com/repos/NethermindEth/juno/releases/latest" + latestReleaseURL = "https://github.com/NethermindEth/juno/releases/latest" ) // Config is the top-level juno configuration. @@ -181,7 +181,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) services = append(services, rpcHandler) - l1ToP2P := make(chan p2p.IPAddressRegistryEvent) + l1ToP2P := make(chan p2p.IPAddressRegistryEvent) if !cfg.DisableL1Verification { // Due to mutually exclusive flag we can do the following. if cfg.EthNode == "" { diff --git a/p2p/p2p_test.go b/p2p/p2p_test.go index 444ed5f34a..d5bd377fe1 100644 --- a/p2p/p2p_test.go +++ b/p2p/p2p_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" ) - func TestInvalidKey(t *testing.T) { _, err := p2p.New( "/ip4/127.0.0.1/tcp/30301", From 09367b3c62a2efee958c7ccc6deabcafc83d05ea Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 30 Dec 2024 18:53:51 +0900 Subject: [PATCH 29/43] Add test cases --- l1/l1_pkg_test.go | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index 11cf75ad73..995542b8c3 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -554,6 +554,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { testCases := []struct { name string setupMock func(subscriber *mocks.MockSubscriber) + timeOut time.Duration expectedErr error }{ { @@ -561,6 +562,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { setupMock: func(subscriber *mocks.MockSubscriber) { subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, err).Times(1) }, + timeOut: 50 * time.Millisecond, expectedErr: err, }, { @@ -571,7 +573,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) }, - expectedErr: nil, + timeOut: 50 * time.Millisecond, }, { name: "WatchIPRemoved error", @@ -581,7 +583,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(nil, err).Times(1) subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) }, - expectedErr: nil, + timeOut: 50 * time.Millisecond, }, { name: "Addition subscription error", @@ -591,7 +593,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) }, - expectedErr: nil, + timeOut: 50 * time.Millisecond, }, { name: "Removal subscription error", @@ -601,7 +603,34 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(err), nil).Times(1) subscriber.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(newFakeSubscription(), nil).Times(1) }, - expectedErr: nil, + timeOut: 50 * time.Millisecond, + }, + { + name: "Addition subscription expires", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).DoAndReturn( + func(_ context.Context, _ common.Address) ([]string, error) { + time.Sleep(100 * time.Millisecond) + return nil, nil + }, + ).Times(1) + }, + expectedErr: context.DeadlineExceeded, + timeOut: 50 * time.Millisecond, + }, + { + name: "Removal subscription expires", + setupMock: func(subscriber *mocks.MockSubscriber) { + subscriber.EXPECT().GetIPAddresses(gomock.Any(), address).Return(nil, nil).Times(1) + subscriber.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).DoAndReturn( + func(_ context.Context, sink chan<- *contract.IPAddressRegistryIPAdded) (*fakeSubscription, error) { + time.Sleep(100 * time.Millisecond) + return newFakeSubscription(), nil + }, + ).Times(1) + }, + timeOut: 50 * time.Millisecond, + expectedErr: context.DeadlineExceeded, }, } @@ -627,7 +656,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { client.l1 = subscriber tc.setupMock(subscriber) - ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + ctx, cancel := context.WithTimeout(context.Background(), tc.timeOut) defer cancel() err := client.makeSubscribtionsToIPAddresses(ctx, 1) require.ErrorIs(t, err, tc.expectedErr) From c59ac72b5cbe5ea59aa08be8b1ae6fa52be63188 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 30 Dec 2024 21:19:58 +0900 Subject: [PATCH 30/43] Add interfaces --- l1/eth_subscriber.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/l1/eth_subscriber.go b/l1/eth_subscriber.go index f60c9f5ecd..9d60d6fa3c 100644 --- a/l1/eth_subscriber.go +++ b/l1/eth_subscriber.go @@ -17,13 +17,24 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +//go:generate mockgen -destination=../mocks/mock_getter.go -package=mocks github.com/NethermindEth/juno/l1 IPAddressGetter +type IPAddressGetter interface { + GetIPAddresses(*bind.CallOpts) ([]string, error) +} + +//go:generate mockgen -destination=../mocks/mock_watcher.go -package=mocks github.com/NethermindEth/juno/l1 IPWatcher +type IPWatcher interface { + WatchIPAdded(*bind.WatchOpts, chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) + WatchIPRemoved(*bind.WatchOpts, chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) +} + type EthSubscriber struct { ethClient *ethclient.Client client *rpc.Client filterer *contract.StarknetFilterer listener EventListener - ipAddressRegistry *contract.IPAddressRegistry - ipAddressRegistryFilterer *contract.IPAddressRegistryFilterer + ipAddressRegistry IPAddressGetter + ipAddressRegistryFilterer IPWatcher } var _ Subscriber = (*EthSubscriber)(nil) From d68c1ce42688241056c5d48520d6ae9a21d8560a Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 30 Dec 2024 21:20:17 +0900 Subject: [PATCH 31/43] Generate mocks --- mocks/mock_getter.go | 56 +++++++++++++++++++++++++++++++++ mocks/mock_watcher.go | 73 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 mocks/mock_getter.go create mode 100644 mocks/mock_watcher.go diff --git a/mocks/mock_getter.go b/mocks/mock_getter.go new file mode 100644 index 0000000000..cb37c8d9aa --- /dev/null +++ b/mocks/mock_getter.go @@ -0,0 +1,56 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/NethermindEth/juno/l1 (interfaces: IPAddressGetter) +// +// Generated by this command: +// +// mockgen -destination=../mocks/mock_getter.go -package=mocks github.com/NethermindEth/juno/l1 IPAddressGetter +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + reflect "reflect" + + bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + gomock "go.uber.org/mock/gomock" +) + +// MockIPAddressGetter is a mock of IPAddressGetter interface. +type MockIPAddressGetter struct { + ctrl *gomock.Controller + recorder *MockIPAddressGetterMockRecorder + isgomock struct{} +} + +// MockIPAddressGetterMockRecorder is the mock recorder for MockIPAddressGetter. +type MockIPAddressGetterMockRecorder struct { + mock *MockIPAddressGetter +} + +// NewMockIPAddressGetter creates a new mock instance. +func NewMockIPAddressGetter(ctrl *gomock.Controller) *MockIPAddressGetter { + mock := &MockIPAddressGetter{ctrl: ctrl} + mock.recorder = &MockIPAddressGetterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIPAddressGetter) EXPECT() *MockIPAddressGetterMockRecorder { + return m.recorder +} + +// GetIPAddresses mocks base method. +func (m *MockIPAddressGetter) GetIPAddresses(arg0 *bind.CallOpts) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetIPAddresses", arg0) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetIPAddresses indicates an expected call of GetIPAddresses. +func (mr *MockIPAddressGetterMockRecorder) GetIPAddresses(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIPAddresses", reflect.TypeOf((*MockIPAddressGetter)(nil).GetIPAddresses), arg0) +} diff --git a/mocks/mock_watcher.go b/mocks/mock_watcher.go new file mode 100644 index 0000000000..46f3fd19b0 --- /dev/null +++ b/mocks/mock_watcher.go @@ -0,0 +1,73 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/NethermindEth/juno/l1 (interfaces: IPWatcher) +// +// Generated by this command: +// +// mockgen -destination=../mocks/mock_watcher.go -package=mocks github.com/NethermindEth/juno/l1 IPWatcher +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + reflect "reflect" + + contract "github.com/NethermindEth/juno/l1/contract" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + event "github.com/ethereum/go-ethereum/event" + gomock "go.uber.org/mock/gomock" +) + +// MockIPWatcher is a mock of IPWatcher interface. +type MockIPWatcher struct { + ctrl *gomock.Controller + recorder *MockIPWatcherMockRecorder + isgomock struct{} +} + +// MockIPWatcherMockRecorder is the mock recorder for MockIPWatcher. +type MockIPWatcherMockRecorder struct { + mock *MockIPWatcher +} + +// NewMockIPWatcher creates a new mock instance. +func NewMockIPWatcher(ctrl *gomock.Controller) *MockIPWatcher { + mock := &MockIPWatcher{ctrl: ctrl} + mock.recorder = &MockIPWatcherMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIPWatcher) EXPECT() *MockIPWatcherMockRecorder { + return m.recorder +} + +// WatchIPAdded mocks base method. +func (m *MockIPWatcher) WatchIPAdded(arg0 *bind.WatchOpts, arg1 chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WatchIPAdded", arg0, arg1) + ret0, _ := ret[0].(event.Subscription) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WatchIPAdded indicates an expected call of WatchIPAdded. +func (mr *MockIPWatcherMockRecorder) WatchIPAdded(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WatchIPAdded", reflect.TypeOf((*MockIPWatcher)(nil).WatchIPAdded), arg0, arg1) +} + +// WatchIPRemoved mocks base method. +func (m *MockIPWatcher) WatchIPRemoved(arg0 *bind.WatchOpts, arg1 chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WatchIPRemoved", arg0, arg1) + ret0, _ := ret[0].(event.Subscription) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WatchIPRemoved indicates an expected call of WatchIPRemoved. +func (mr *MockIPWatcherMockRecorder) WatchIPRemoved(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WatchIPRemoved", reflect.TypeOf((*MockIPWatcher)(nil).WatchIPRemoved), arg0, arg1) +} From c6ed9ddb34affeb5e616d6e8d8443ceea397dcff Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 30 Dec 2024 21:20:29 +0900 Subject: [PATCH 32/43] Add tests --- l1/eth_subscriber_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 l1/eth_subscriber_test.go diff --git a/l1/eth_subscriber_test.go b/l1/eth_subscriber_test.go new file mode 100644 index 0000000000..902ce777f3 --- /dev/null +++ b/l1/eth_subscriber_test.go @@ -0,0 +1,36 @@ +package l1 + +import ( + "context" + "testing" + + "github.com/NethermindEth/juno/mocks" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" +) + +func TestIPAddressRegistry(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockIPAddressGetter := mocks.NewMockIPAddressGetter(ctrl) + mockIPAddressGetter.EXPECT().GetIPAddresses(gomock.Any()).Return([]string{}, nil).Times(1) + + mockIPWatcher := mocks.NewMockIPWatcher(ctrl) + mockIPWatcher.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(nil, nil).Times(1) + mockIPWatcher.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(nil, nil).Times(1) + + subscriber := &EthSubscriber{ + ipAddressRegistry: mockIPAddressGetter, + ipAddressRegistryFilterer: mockIPWatcher, + } + + _, err := subscriber.GetIPAddresses(context.Background(), common.Address{}) + require.NoError(t, err) + _, err = subscriber.WatchIPAdded(context.Background(), nil) + require.NoError(t, err) + _, err = subscriber.WatchIPRemoved(context.Background(), nil) +} From 472720947542dc11727ea86f4f6d8c36fdbd3ad1 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Mon, 30 Dec 2024 21:21:56 +0900 Subject: [PATCH 33/43] Fix test --- l1/eth_subscriber_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/l1/eth_subscriber_test.go b/l1/eth_subscriber_test.go index 902ce777f3..54f184c8f2 100644 --- a/l1/eth_subscriber_test.go +++ b/l1/eth_subscriber_test.go @@ -33,4 +33,5 @@ func TestIPAddressRegistry(t *testing.T) { _, err = subscriber.WatchIPAdded(context.Background(), nil) require.NoError(t, err) _, err = subscriber.WatchIPRemoved(context.Background(), nil) + require.NoError(t, err) } From d1397f08ad2b3ea1f25d282f3ad75f4733868331 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 1 Jan 2025 11:48:13 +0900 Subject: [PATCH 34/43] Add IPAddressRegistry field to test --- l1/l1_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/l1/l1_test.go b/l1/l1_test.go index d8fdc2221a..26599d4555 100644 --- a/l1/l1_test.go +++ b/l1/l1_test.go @@ -247,7 +247,8 @@ func TestEthSubscriber_FinalisedHeight(t *testing.T) { server, listener := startServer("127.0.0.1:0", test.service) defer server.Stop() - subscriber, err := l1.NewEthSubscriber("ws://"+listener.Addr().String(), &utils.Network{}) + subscriber, err := l1.NewEthSubscriber("ws://"+listener.Addr().String(), + &utils.Network{IPAddressRegistry: &common.Address{}}) require.NoError(t, err) defer subscriber.Close() From 06a746061cd16ce9e273547a1f07a10ec0611ee0 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 1 Jan 2025 11:56:29 +0900 Subject: [PATCH 35/43] Add IPAddressRegistry field to test --- l1/l1_test.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/l1/l1_test.go b/l1/l1_test.go index 26599d4555..f76cec9e39 100644 --- a/l1/l1_test.go +++ b/l1/l1_test.go @@ -16,6 +16,7 @@ import ( "github.com/NethermindEth/juno/l1" "github.com/NethermindEth/juno/l1/contract" "github.com/NethermindEth/juno/mocks" + "github.com/NethermindEth/juno/p2p" "github.com/NethermindEth/juno/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -110,6 +111,7 @@ func TestEventListener(t *testing.T) { ctrl := gomock.NewController(t) nopLog := utils.NewNopZapLogger() network := utils.Mainnet + network.IPAddressRegistry = &common.Address{} chain := blockchain.New(pebble.NewMemTest(t), &network, nil) subscriber := mocks.NewMockSubscriber(ctrl) @@ -126,6 +128,24 @@ func TestEventListener(t *testing.T) { Return(newFakeSubscription(), nil). Times(1) + subscriber. + EXPECT(). + GetIPAddresses(gomock.Any(), gomock.Any()). + Return([]string{}, nil). + Times(1) + + subscriber. + EXPECT(). + WatchIPAdded(gomock.Any(), gomock.Any()). + Return(newFakeSubscription(), nil). + Times(1) + + subscriber. + EXPECT(). + WatchIPRemoved(gomock.Any(), gomock.Any()). + Return(newFakeSubscription(), nil). + Times(1) + subscriber. EXPECT(). FinalisedHeight(gomock.Any()). @@ -141,7 +161,7 @@ func TestEventListener(t *testing.T) { subscriber.EXPECT().Close().Times(1) var got *core.L1Head - client := l1.NewClient(subscriber, chain, nopLog, nil). + client := l1.NewClient(subscriber, chain, nopLog, make(chan<- p2p.IPAddressRegistryEvent)). WithResubscribeDelay(0). WithPollFinalisedInterval(time.Nanosecond). WithEventListener(l1.SelectiveListener{ From a425c3c594f0a37759680eaf2b531dc3c3145cee Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 1 Jan 2025 17:17:28 +0900 Subject: [PATCH 36/43] Add TestNodeWithL1Verification tests --- node/node_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/node/node_test.go b/node/node_test.go index fb3d208593..f48a48cdf8 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -2,6 +2,8 @@ package node_test import ( "context" + "net" + "net/http" "testing" "time" @@ -12,6 +14,7 @@ import ( adaptfeeder "github.com/NethermindEth/juno/starknetdata/feeder" "github.com/NethermindEth/juno/sync" "github.com/NethermindEth/juno/utils" + "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" ) @@ -90,3 +93,59 @@ func TestNetworkVerificationOnNonEmptyDB(t *testing.T) { }) } } + +func TestNodeWithL1Verification(t *testing.T) { + server := rpc.NewServer() + require.NoError(t, server.RegisterName("eth", &testEmptyService{})) + listener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + go func() { + _ = http.Serve(listener, server.WebsocketHandler([]string{"*"})) + }() + defer server.Stop() + _, err = node.New(&node.Config{ + Network: utils.Network{}, + EthNode: "ws://" + listener.Addr().String(), + DatabasePath: t.TempDir(), + DisableL1Verification: false, + }, "v0.1") + require.NoError(t, err) +} + +func TestNodeWithL1VerificationError(t *testing.T) { + tests := []struct { + name string + cfg *node.Config + err string + }{ + { + name: "no network", + cfg: &node.Config{ + DatabasePath: t.TempDir(), + DisableL1Verification: false, + }, + err: "ethereum node address not found", + }, + { + name: "parce URL error", + cfg: &node.Config{ + DatabasePath: t.TempDir(), + DisableL1Verification: false, + EthNode: string([]byte{0x7f}), + }, + err: "parse Ethereum node URL", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := node.New(tt.cfg, "v0.1") + require.ErrorContains(t, err, tt.err) + }) + } +} + +type testEmptyService struct{} + +func (testEmptyService) GetBlockByNumber(ctx context.Context, number string, fullTx bool) (interface{}, error) { + return nil, nil +} From 276aedd000698315469076734c3f52ecd0ca5a9f Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 1 Jan 2025 17:33:51 +0900 Subject: [PATCH 37/43] Ignore l1/contract in codecov --- .github/codecov.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/codecov.yml b/.github/codecov.yml index 8a1bf7a4e9..39daabcee8 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -10,11 +10,11 @@ coverage: only_pulls: true ignore: - mocks - - l1/internal/contract/starknet.go + - l1/contract/* - grpc/gen/* - vm - p2p - adapters/core2p2p - adapters/p2p2core - docs - - "**/*_enumer.go" \ No newline at end of file + - "**/*_enumer.go" From c78d5366f9a0a0c02c0587a8efd273463cd1c039 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Wed, 1 Jan 2025 17:42:06 +0900 Subject: [PATCH 38/43] Remove interfaces --- l1/eth_subscriber.go | 15 ++------ l1/eth_subscriber_test.go | 37 -------------------- mocks/mock_getter.go | 56 ------------------------------ mocks/mock_watcher.go | 73 --------------------------------------- 4 files changed, 2 insertions(+), 179 deletions(-) delete mode 100644 l1/eth_subscriber_test.go delete mode 100644 mocks/mock_getter.go delete mode 100644 mocks/mock_watcher.go diff --git a/l1/eth_subscriber.go b/l1/eth_subscriber.go index 9d60d6fa3c..f60c9f5ecd 100644 --- a/l1/eth_subscriber.go +++ b/l1/eth_subscriber.go @@ -17,24 +17,13 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) -//go:generate mockgen -destination=../mocks/mock_getter.go -package=mocks github.com/NethermindEth/juno/l1 IPAddressGetter -type IPAddressGetter interface { - GetIPAddresses(*bind.CallOpts) ([]string, error) -} - -//go:generate mockgen -destination=../mocks/mock_watcher.go -package=mocks github.com/NethermindEth/juno/l1 IPWatcher -type IPWatcher interface { - WatchIPAdded(*bind.WatchOpts, chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) - WatchIPRemoved(*bind.WatchOpts, chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) -} - type EthSubscriber struct { ethClient *ethclient.Client client *rpc.Client filterer *contract.StarknetFilterer listener EventListener - ipAddressRegistry IPAddressGetter - ipAddressRegistryFilterer IPWatcher + ipAddressRegistry *contract.IPAddressRegistry + ipAddressRegistryFilterer *contract.IPAddressRegistryFilterer } var _ Subscriber = (*EthSubscriber)(nil) diff --git a/l1/eth_subscriber_test.go b/l1/eth_subscriber_test.go deleted file mode 100644 index 54f184c8f2..0000000000 --- a/l1/eth_subscriber_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package l1 - -import ( - "context" - "testing" - - "github.com/NethermindEth/juno/mocks" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "go.uber.org/mock/gomock" -) - -func TestIPAddressRegistry(t *testing.T) { - t.Parallel() - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockIPAddressGetter := mocks.NewMockIPAddressGetter(ctrl) - mockIPAddressGetter.EXPECT().GetIPAddresses(gomock.Any()).Return([]string{}, nil).Times(1) - - mockIPWatcher := mocks.NewMockIPWatcher(ctrl) - mockIPWatcher.EXPECT().WatchIPAdded(gomock.Any(), gomock.Any()).Return(nil, nil).Times(1) - mockIPWatcher.EXPECT().WatchIPRemoved(gomock.Any(), gomock.Any()).Return(nil, nil).Times(1) - - subscriber := &EthSubscriber{ - ipAddressRegistry: mockIPAddressGetter, - ipAddressRegistryFilterer: mockIPWatcher, - } - - _, err := subscriber.GetIPAddresses(context.Background(), common.Address{}) - require.NoError(t, err) - _, err = subscriber.WatchIPAdded(context.Background(), nil) - require.NoError(t, err) - _, err = subscriber.WatchIPRemoved(context.Background(), nil) - require.NoError(t, err) -} diff --git a/mocks/mock_getter.go b/mocks/mock_getter.go deleted file mode 100644 index cb37c8d9aa..0000000000 --- a/mocks/mock_getter.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/NethermindEth/juno/l1 (interfaces: IPAddressGetter) -// -// Generated by this command: -// -// mockgen -destination=../mocks/mock_getter.go -package=mocks github.com/NethermindEth/juno/l1 IPAddressGetter -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - gomock "go.uber.org/mock/gomock" -) - -// MockIPAddressGetter is a mock of IPAddressGetter interface. -type MockIPAddressGetter struct { - ctrl *gomock.Controller - recorder *MockIPAddressGetterMockRecorder - isgomock struct{} -} - -// MockIPAddressGetterMockRecorder is the mock recorder for MockIPAddressGetter. -type MockIPAddressGetterMockRecorder struct { - mock *MockIPAddressGetter -} - -// NewMockIPAddressGetter creates a new mock instance. -func NewMockIPAddressGetter(ctrl *gomock.Controller) *MockIPAddressGetter { - mock := &MockIPAddressGetter{ctrl: ctrl} - mock.recorder = &MockIPAddressGetterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIPAddressGetter) EXPECT() *MockIPAddressGetterMockRecorder { - return m.recorder -} - -// GetIPAddresses mocks base method. -func (m *MockIPAddressGetter) GetIPAddresses(arg0 *bind.CallOpts) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetIPAddresses", arg0) - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetIPAddresses indicates an expected call of GetIPAddresses. -func (mr *MockIPAddressGetterMockRecorder) GetIPAddresses(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIPAddresses", reflect.TypeOf((*MockIPAddressGetter)(nil).GetIPAddresses), arg0) -} diff --git a/mocks/mock_watcher.go b/mocks/mock_watcher.go deleted file mode 100644 index 46f3fd19b0..0000000000 --- a/mocks/mock_watcher.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/NethermindEth/juno/l1 (interfaces: IPWatcher) -// -// Generated by this command: -// -// mockgen -destination=../mocks/mock_watcher.go -package=mocks github.com/NethermindEth/juno/l1 IPWatcher -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - contract "github.com/NethermindEth/juno/l1/contract" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - event "github.com/ethereum/go-ethereum/event" - gomock "go.uber.org/mock/gomock" -) - -// MockIPWatcher is a mock of IPWatcher interface. -type MockIPWatcher struct { - ctrl *gomock.Controller - recorder *MockIPWatcherMockRecorder - isgomock struct{} -} - -// MockIPWatcherMockRecorder is the mock recorder for MockIPWatcher. -type MockIPWatcherMockRecorder struct { - mock *MockIPWatcher -} - -// NewMockIPWatcher creates a new mock instance. -func NewMockIPWatcher(ctrl *gomock.Controller) *MockIPWatcher { - mock := &MockIPWatcher{ctrl: ctrl} - mock.recorder = &MockIPWatcherMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIPWatcher) EXPECT() *MockIPWatcherMockRecorder { - return m.recorder -} - -// WatchIPAdded mocks base method. -func (m *MockIPWatcher) WatchIPAdded(arg0 *bind.WatchOpts, arg1 chan<- *contract.IPAddressRegistryIPAdded) (event.Subscription, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WatchIPAdded", arg0, arg1) - ret0, _ := ret[0].(event.Subscription) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// WatchIPAdded indicates an expected call of WatchIPAdded. -func (mr *MockIPWatcherMockRecorder) WatchIPAdded(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WatchIPAdded", reflect.TypeOf((*MockIPWatcher)(nil).WatchIPAdded), arg0, arg1) -} - -// WatchIPRemoved mocks base method. -func (m *MockIPWatcher) WatchIPRemoved(arg0 *bind.WatchOpts, arg1 chan<- *contract.IPAddressRegistryIPRemoved) (event.Subscription, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WatchIPRemoved", arg0, arg1) - ret0, _ := ret[0].(event.Subscription) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// WatchIPRemoved indicates an expected call of WatchIPRemoved. -func (mr *MockIPWatcherMockRecorder) WatchIPRemoved(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WatchIPRemoved", reflect.TypeOf((*MockIPWatcher)(nil).WatchIPRemoved), arg0, arg1) -} From 4a300ffa32dcbbef16f2ca819178865b115e3bb0 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 2 Jan 2025 10:45:40 +0900 Subject: [PATCH 39/43] Rename IPAddressRegistry to BootnodeRegistry --- l1/eth_subscriber.go | 6 +++--- l1/l1.go | 4 ++-- l1/l1_pkg_test.go | 4 ++-- l1/l1_test.go | 4 ++-- utils/network.go | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/l1/eth_subscriber.go b/l1/eth_subscriber.go index f60c9f5ecd..a0b9b54bb1 100644 --- a/l1/eth_subscriber.go +++ b/l1/eth_subscriber.go @@ -46,12 +46,12 @@ func NewEthSubscriber(ethClientAddress string, network *utils.Network) (*EthSubs ipAddressRegistry *contract.IPAddressRegistry ipAddressRegistryFilterer *contract.IPAddressRegistryFilterer ) - if network.IPAddressRegistry != nil { - ipAddressRegistry, err = contract.NewIPAddressRegistry(*network.IPAddressRegistry, ethClient) + if network.BootnodeRegistry != nil { + ipAddressRegistry, err = contract.NewIPAddressRegistry(network.BootnodeRegistry, ethClient) if err != nil { return nil, err } - ipAddressRegistryFilterer, err = contract.NewIPAddressRegistryFilterer(*network.IPAddressRegistry, ethClient) + ipAddressRegistryFilterer, err = contract.NewIPAddressRegistryFilterer(network.BootnodeRegistry, ethClient) if err != nil { return nil, err } diff --git a/l1/l1.go b/l1/l1.go index 8da096dd07..e012fd6a58 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -157,7 +157,7 @@ func (c *Client) Run(ctx context.Context) error { errs.Go(func() error { return c.makeSubscriptionToStateUpdates(ctx, buffer) }) - if c.network.IPAddressRegistry != nil { + if c.network.BootnodeRegistry != nil { errs.Go(func() error { return c.makeSubscribtionsToIPAddresses(ctx, buffer) }) @@ -229,7 +229,7 @@ func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, buffer int) func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) error { defer close(c.eventsToP2P) - addresses, err := c.l1.GetIPAddresses(ctx, *c.network.IPAddressRegistry) + addresses, err := c.l1.GetIPAddresses(ctx, *c.network.BootnodeRegistry) if err != nil { return err } diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index 995542b8c3..f48628885b 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -476,7 +476,7 @@ func TestMakeSubscribtionsToIPAddresses(t *testing.T) { nopLog := utils.NewNopZapLogger() network := utils.Mainnet address := common.HexToAddress("0x1234") - network.IPAddressRegistry = &address + network.BootnodeRegistry = &address eventsChan := make(chan p2p.IPAddressRegistryEvent, 10) chain := blockchain.New(pebble.NewMemTest(t), &network, nil) client := NewClient(nil, chain, nopLog, eventsChan).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) @@ -546,7 +546,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { t.Parallel() address := common.HexToAddress("0x1234") network := utils.Mainnet - network.IPAddressRegistry = &address + network.BootnodeRegistry = &address chain := blockchain.New(pebble.NewMemTest(t), &network, nil) nopLog := utils.NewNopZapLogger() err := errors.New("test err") diff --git a/l1/l1_test.go b/l1/l1_test.go index f76cec9e39..899851294b 100644 --- a/l1/l1_test.go +++ b/l1/l1_test.go @@ -111,7 +111,7 @@ func TestEventListener(t *testing.T) { ctrl := gomock.NewController(t) nopLog := utils.NewNopZapLogger() network := utils.Mainnet - network.IPAddressRegistry = &common.Address{} + network.BootnodeRegistry = &common.Address{} chain := blockchain.New(pebble.NewMemTest(t), &network, nil) subscriber := mocks.NewMockSubscriber(ctrl) @@ -268,7 +268,7 @@ func TestEthSubscriber_FinalisedHeight(t *testing.T) { defer server.Stop() subscriber, err := l1.NewEthSubscriber("ws://"+listener.Addr().String(), - &utils.Network{IPAddressRegistry: &common.Address{}}) + &utils.Network{BootnodeRegistry: &common.Address{}}) require.NoError(t, err) defer subscriber.Close() diff --git a/utils/network.go b/utils/network.go index 267b2f54fd..8ddf0180ef 100644 --- a/utils/network.go +++ b/utils/network.go @@ -22,7 +22,7 @@ type Network struct { L1ChainID *big.Int `json:"l1_chain_id" validate:"required"` L2ChainID string `json:"l2_chain_id" validate:"required"` CoreContractAddress common.Address `json:"core_contract_address" validate:"required"` - IPAddressRegistry *common.Address `json:"ip_address_registry"` + BootnodeRegistry *common.Address `json:"ip_address_registry"` BlockHashMetaInfo *BlockHashMetaInfo `json:"block_hash_meta_info"` } @@ -109,7 +109,7 @@ var ( First07Block: 0, FallBackSequencerAddress: fallBackSequencerAddress, }, - IPAddressRegistry: &ipAddressRegistry, + BootnodeRegistry: &ipAddressRegistry, } SepoliaIntegration = Network{ Name: "sepolia-integration", From 4f66c6d4e993a4c6d0e51230b47214cd86e4431f Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 2 Jan 2025 10:47:18 +0900 Subject: [PATCH 40/43] Change pointer to value --- l1/eth_subscriber.go | 3 ++- l1/l1.go | 6 ++++-- l1/l1_pkg_test.go | 4 ++-- l1/l1_test.go | 4 ++-- utils/network.go | 9 ++++----- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/l1/eth_subscriber.go b/l1/eth_subscriber.go index a0b9b54bb1..d2d969d30a 100644 --- a/l1/eth_subscriber.go +++ b/l1/eth_subscriber.go @@ -46,7 +46,8 @@ func NewEthSubscriber(ethClientAddress string, network *utils.Network) (*EthSubs ipAddressRegistry *contract.IPAddressRegistry ipAddressRegistryFilterer *contract.IPAddressRegistryFilterer ) - if network.BootnodeRegistry != nil { + if network.BootnodeRegistry != emptyIPAddressRegistry { + fmt.Println("Bootnode registry is not empty") ipAddressRegistry, err = contract.NewIPAddressRegistry(network.BootnodeRegistry, ethClient) if err != nil { return nil, err diff --git a/l1/l1.go b/l1/l1.go index e012fd6a58..6295eac44b 100644 --- a/l1/l1.go +++ b/l1/l1.go @@ -20,6 +20,8 @@ import ( "golang.org/x/sync/errgroup" ) +var emptyIPAddressRegistry = common.Address{} + //go:generate mockgen -destination=../mocks/mock_subscriber.go -package=mocks github.com/NethermindEth/juno/l1 Subscriber type Subscriber interface { FinalisedHeight(ctx context.Context) (uint64, error) @@ -157,7 +159,7 @@ func (c *Client) Run(ctx context.Context) error { errs.Go(func() error { return c.makeSubscriptionToStateUpdates(ctx, buffer) }) - if c.network.BootnodeRegistry != nil { + if c.network.BootnodeRegistry != emptyIPAddressRegistry { errs.Go(func() error { return c.makeSubscribtionsToIPAddresses(ctx, buffer) }) @@ -229,7 +231,7 @@ func (c *Client) makeSubscriptionToStateUpdates(ctx context.Context, buffer int) func (c *Client) makeSubscribtionsToIPAddresses(ctx context.Context, buffer int) error { defer close(c.eventsToP2P) - addresses, err := c.l1.GetIPAddresses(ctx, *c.network.BootnodeRegistry) + addresses, err := c.l1.GetIPAddresses(ctx, c.network.BootnodeRegistry) if err != nil { return err } diff --git a/l1/l1_pkg_test.go b/l1/l1_pkg_test.go index f48628885b..08d89dcb6a 100644 --- a/l1/l1_pkg_test.go +++ b/l1/l1_pkg_test.go @@ -476,7 +476,7 @@ func TestMakeSubscribtionsToIPAddresses(t *testing.T) { nopLog := utils.NewNopZapLogger() network := utils.Mainnet address := common.HexToAddress("0x1234") - network.BootnodeRegistry = &address + network.BootnodeRegistry = address eventsChan := make(chan p2p.IPAddressRegistryEvent, 10) chain := blockchain.New(pebble.NewMemTest(t), &network, nil) client := NewClient(nil, chain, nopLog, eventsChan).WithResubscribeDelay(0).WithPollFinalisedInterval(time.Nanosecond) @@ -546,7 +546,7 @@ func TestUnreliableSubscriptionToIPAddresses(t *testing.T) { t.Parallel() address := common.HexToAddress("0x1234") network := utils.Mainnet - network.BootnodeRegistry = &address + network.BootnodeRegistry = address chain := blockchain.New(pebble.NewMemTest(t), &network, nil) nopLog := utils.NewNopZapLogger() err := errors.New("test err") diff --git a/l1/l1_test.go b/l1/l1_test.go index 899851294b..4a9d174931 100644 --- a/l1/l1_test.go +++ b/l1/l1_test.go @@ -111,7 +111,7 @@ func TestEventListener(t *testing.T) { ctrl := gomock.NewController(t) nopLog := utils.NewNopZapLogger() network := utils.Mainnet - network.BootnodeRegistry = &common.Address{} + network.BootnodeRegistry = common.HexToAddress("0x1234") chain := blockchain.New(pebble.NewMemTest(t), &network, nil) subscriber := mocks.NewMockSubscriber(ctrl) @@ -268,7 +268,7 @@ func TestEthSubscriber_FinalisedHeight(t *testing.T) { defer server.Stop() subscriber, err := l1.NewEthSubscriber("ws://"+listener.Addr().String(), - &utils.Network{BootnodeRegistry: &common.Address{}}) + &utils.Network{BootnodeRegistry: common.Address{}}) require.NoError(t, err) defer subscriber.Close() diff --git a/utils/network.go b/utils/network.go index 8ddf0180ef..47b9265d50 100644 --- a/utils/network.go +++ b/utils/network.go @@ -22,7 +22,7 @@ type Network struct { L1ChainID *big.Int `json:"l1_chain_id" validate:"required"` L2ChainID string `json:"l2_chain_id" validate:"required"` CoreContractAddress common.Address `json:"core_contract_address" validate:"required"` - BootnodeRegistry *common.Address `json:"ip_address_registry"` + BootnodeRegistry common.Address `json:"ip_address_registry"` BlockHashMetaInfo *BlockHashMetaInfo `json:"block_hash_meta_info"` } @@ -39,9 +39,8 @@ var ( fallBackSequencerAddressMainnet, _ = new(felt.Felt).SetString("0x021f4b90b0377c82bf330b7b5295820769e72d79d8acd0effa0ebde6e9988bc5") fallBackSequencerAddress, _ = new(felt.Felt).SetString("0x046a89ae102987331d369645031b49c27738ed096f2789c24449966da4c6de6b") // The following are necessary for Cobra and Viper, respectively, to unmarshal log level CLI/config parameters properly. - _ pflag.Value = (*Network)(nil) - _ encoding.TextUnmarshaler = (*Network)(nil) - ipAddressRegistry = common.HexToAddress("0xa2499F2a3Fb071fd99f921038d043eF31B446883") + _ pflag.Value = (*Network)(nil) + _ encoding.TextUnmarshaler = (*Network)(nil) // The docs states the addresses for each network: https://docs.starknet.io/tools/important-addresses/ Mainnet = Network{ @@ -109,7 +108,7 @@ var ( First07Block: 0, FallBackSequencerAddress: fallBackSequencerAddress, }, - BootnodeRegistry: &ipAddressRegistry, + BootnodeRegistry: common.HexToAddress("0xa2499F2a3Fb071fd99f921038d043eF31B446883"), } SepoliaIntegration = Network{ Name: "sepolia-integration", From 26957c09bf77551f5e98564abb294a87c37c84f7 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 2 Jan 2025 10:47:49 +0900 Subject: [PATCH 41/43] Change channel initialization --- node/node.go | 8 +++----- p2p/p2p.go | 4 +++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/node/node.go b/node/node.go index 35a775ee82..c91d4c08a5 100644 --- a/node/node.go +++ b/node/node.go @@ -181,22 +181,20 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen rpcHandler = rpcHandler.WithFilterLimit(cfg.RPCMaxBlockScan).WithCallMaxSteps(uint64(cfg.RPCCallMaxSteps)) services = append(services, rpcHandler) - l1ToP2P := make(chan p2p.IPAddressRegistryEvent) + var l1ToP2P chan p2p.IPAddressRegistryEvent if !cfg.DisableL1Verification { // Due to mutually exclusive flag we can do the following. if cfg.EthNode == "" { return nil, fmt.Errorf("ethereum node address not found; Use --disable-l1-verification flag if L1 verification is not required") } - var l1Client *l1.Client - l1Client, err = newL1Client(cfg.EthNode, cfg.Metrics, chain, log, l1ToP2P) + l1ToP2P = make(chan p2p.IPAddressRegistryEvent) + l1Client, err := newL1Client(cfg.EthNode, cfg.Metrics, chain, log, l1ToP2P) if err != nil { return nil, fmt.Errorf("create L1 client: %w", err) } services = append(services, l1Client) rpcHandler.WithL1Client(l1Client.L1()) - } else { - close(l1ToP2P) } var p2pService *p2p.Service diff --git a/p2p/p2p.go b/p2p/p2p.go index 829f26e99f..a02b152b56 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -223,7 +223,9 @@ func (s *Service) Run(ctx context.Context) error { } }() - go s.listenForL1Events(ctx) + if s.l1events != nil { + go s.listenForL1Events(ctx) + } err := s.dht.Bootstrap(ctx) if err != nil { From 1f1be6286764cba71e5ffd4bd9d7d0d994c9f5d2 Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Thu, 2 Jan 2025 10:53:24 +0900 Subject: [PATCH 42/43] Specify that the peer removal is specifically from L1 events --- p2p/p2p.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/p2p/p2p.go b/p2p/p2p.go index a02b152b56..629a6062c8 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -297,9 +297,9 @@ func (s *Service) listenForL1Events(ctx context.Context) { s.log.Debugw("Disconnected from peer", "peer", registryEvent.Address) } s.host.Peerstore().RemovePeer(peerInfo.ID) - s.log.Debugw("Removed peer from peerstore", "peer", peerInfo.ID) + s.log.Debugw("L1 event: Removed peer from routing table", "peer", peerInfo.ID) s.dht.RoutingTable().RemovePeer(peerInfo.ID) - s.log.Debugw("Removed peer from routing table", "peer", peerInfo.ID) + s.log.Debugw("L1 event: Removed peer from DHT", "peer", peerInfo.ID) } } } From 478e8cd923adeb81ac2ee7ed701a953a5e7cd2ed Mon Sep 17 00:00:00 2001 From: AnkushinDaniil Date: Fri, 3 Jan 2025 10:57:49 +0900 Subject: [PATCH 43/43] Remove prefix check --- p2p/p2p.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/p2p/p2p.go b/p2p/p2p.go index 629a6062c8..c248a8dd86 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -1,7 +1,6 @@ package p2p import ( - "bytes" "context" "encoding/hex" "errors" @@ -420,9 +419,6 @@ func loadPeers(database db.DB) ([]peer.AddrInfo, error) { var peerIDBytes []byte for it.Seek(prefix); it.Valid(); it.Next() { peerIDBytes = it.Key() - if !bytes.HasPrefix(peerIDBytes, prefix) { - break - } peerID, err := peer.IDFromBytes(peerIDBytes[len(prefix):]) if err != nil { return fmt.Errorf("decode peer ID: %w", err)