From d3ead5502e90b48dc0a7fe0cc7d5e88ac934b73b Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Thu, 12 Sep 2024 16:29:04 +0000 Subject: [PATCH 01/34] feat: Add contract bindings for VEBO Lido contract --- internal/lido/contracts/vebo/VEBO.abi | 1 + internal/lido/contracts/vebo/VEBO.bin | 1 + internal/lido/contracts/vebo/VEBO.go | 3357 +++++++++++++++++++++++++ 3 files changed, 3359 insertions(+) create mode 100644 internal/lido/contracts/vebo/VEBO.abi create mode 100644 internal/lido/contracts/vebo/VEBO.bin create mode 100644 internal/lido/contracts/vebo/VEBO.go diff --git a/internal/lido/contracts/vebo/VEBO.abi b/internal/lido/contracts/vebo/VEBO.abi new file mode 100644 index 00000000..9c30845b --- /dev/null +++ b/internal/lido/contracts/vebo/VEBO.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"address","name":"lidoLocator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ArgumentOutOfBounds","type":"error"},{"inputs":[],"name":"HashCannotBeZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[],"name":"NoConsensusReportToProcess","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"PauseUntilMustBeInFuture","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[],"name":"RefSlotAlreadyProcessing","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"SecondsPerSlotCannotBeZero","type":"error"},{"inputs":[],"name":"SenderIsNotTheConsensusContract","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[],"name":"UnexpectedRequestsDataLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedRequestsDataFormat","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ReportDiscarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"validatorIndex","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ValidatorExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsCount","type":"uint256"}],"name":"WarnDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"discardConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256[]","name":"nodeOpIds","type":"uint256[]"}],"name":"getLastRequestedValidatorIndices","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bool","name":"dataSubmitted","type":"bool"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"requestsSubmitted","type":"uint256"}],"internalType":"struct ValidatorsExitBusOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRequestsProcessed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ValidatorsExitBusOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/internal/lido/contracts/vebo/VEBO.bin b/internal/lido/contracts/vebo/VEBO.bin new file mode 100644 index 00000000..c6be32be --- /dev/null +++ b/internal/lido/contracts/vebo/VEBO.bin @@ -0,0 +1 @@ +0x608060405234801561001057600080fd5b50600436106102275760003560e01c80638f7797c211610130578063c469c307116100b8578063e2793e721161007c578063e2793e7214610538578063eb990c5914610540578063ef9bf37e14610553578063f288246114610573578063f3f449c71461059a57600080fd5b8063c469c307146104e4578063ca15c873146104f7578063d43812171461050a578063d547741f1461051d578063e271b7741461053057600080fd5b8063a217fddf116100ff578063a217fddf14610491578063a302ee3814610499578063abe9cfc8146104a2578063ad5cac4e146104b5578063b187bd26146104dc57600080fd5b80638f7797c2146103e45780639010d07c1461044457806391d14854146104575780639cc23c791461046a57600080fd5b806336568abe116101b35780635be20425116101825780635be204251461037757806360d64d381461037f5780638aa10435146103a95780638d591474146103b15780638f55b571146103c457600080fd5b806336568abe1461030e578063389ed2671461032157806346e1f57614610348578063589ff76c1461036f57600080fd5b8063294492c8116101fa578063294492c8146102925780632de03aa1146102a55780632f2ff15d146102cc578063304b9071146102df5780633584d59c1461030657600080fd5b806301ffc9a71461022c578063046f7da214610254578063063f36ad1461025e578063248a9ca314610271575b600080fd5b61023f61023a3660046126d4565b6105ad565b60405190151581526020015b60405180910390f35b61025c6105d8565b005b61025c61026c3660046126fe565b610616565b61028461027f36600461272a565b61080e565b60405190815260200161024b565b61025c6102a0366004612743565b610830565b6102847f2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c781565b61025c6102da3660046127a1565b610898565b6102847f000000000000000000000000000000000000000000000000000000000000000c81565b6102846108ba565b61025c61031c3660046127a1565b6108d7565b6102847f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d81565b6102847f65fa0c17458517c727737e4153dd477fa3e328cf706640b0f68b1a285c5990da81565b610284610951565b610284610969565b610387610981565b604080519485526020850193909352918301521515606082015260800161024b565b610284610a29565b61025c6103bf36600461272a565b610a53565b6103cc610a87565b6040516001600160a01b03909116815260200161024b565b6103ec610a9f565b60405161024b9190600060e0820190508251825260208301516020830152604083015160408301526060830151151560608301526080830151608083015260a083015160a083015260c083015160c083015292915050565b6103cc6104523660046127d1565b610c36565b61023f6104653660046127a1565b610c62565b6102847fc31b1e4b732c5173dc51d519dfa432bad95550ecc4b0f9a61c2a558a2a8e434181565b610284600081565b61028460001981565b61025c6104b036600461272a565b610c9a565b6102847f04a0afbbd09d5ad397fc858789da4f8edd59f5ca5098d70faa490babee945c3b81565b61023f610cce565b61025c6104f23660046127f3565b610ced565b61028461050536600461272a565b610d37565b61025c61051836600461272a565b610d5b565b61025c61052b3660046127a1565b610e9e565b610284600181565b610284610ebb565b61025c61054e366004612810565b610ee5565b610566610561366004612856565b610f33565b60405161024b91906128d4565b6102847f0000000000000000000000000000000000000000000000000000000065156ac081565b61025c6105a836600461272a565b611093565b60006001600160e01b03198216635a05180f60e01b14806105d257506105d2826110cb565b92915050565b6105e0611100565b7f2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c761060b8133611127565b61061361118b565b50565b61061e6111cf565b600080516020612db0833981519152546001600160401b0316808310156106675760405163431d301760e11b815260048101849052602481018290526044015b60405180910390fd5b600061067f600080516020612d708339815191525490565b90508084116106ab576040516360a41e4960e01b8152600481018590526024810182905260440161065e565b824211156106cf5760405163537bacdf60e11b81526004810184905260240161065e565b8184141580156106df5750818114155b156107105760405182907f800b849c8bf80718cf786c99d1091c079fe2c5e420a3ba7ba9b0ef8179ef2c3890600090a25b8461072e57604051635b18a69f60e11b815260040160405180910390fd5b604080518681526020810185905285917faed7d1a7a1831158dcda1e4214f5862f450bd3eb5721a5f322bf8c9fe1790b0a910160405180910390a26000604051806060016040528087815260200161078587611210565b6001600160401b0316815260200161079c86611210565b6001600160401b039081169091528151600080516020612cd0833981519152556020820151600080516020612db0833981519152805460408501518416600160401b026001600160801b03199091169290931691909117919091179055905061080681848461127c565b505050505050565b6000908152600080516020612d50833981519152602052604090206001015490565b610838611366565b61084061138c565b610849816113e8565b61088282602001358360000135846040516020016108679190612941565b6040516020818303038152906040528051906020012061141e565b61088a61151d565b5061089482611643565b5050565b6108a18261080e565b6108ab8133611127565b6108b58383611947565b505050565b60006108d2600080516020612d708339815191525490565b905090565b6001600160a01b03811633146109475760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b606482015260840161065e565b6108948282611976565b60006108d2600080516020612d908339815191525490565b60006108d2600080516020612dd08339815191525490565b600080808080600080516020612cd083398151915260408051606081018252825481526001909201546001600160401b038082166020850152600160401b9091041690820152905060006109e1600080516020612d708339815191525490565b82516020840151604085015192935090918215801590610a0d57508385602001516001600160401b0316145b92996001600160401b0392831699509116965090945092505050565b60006108d27f4dd0f6662ba1d6b081f08b350f5e9a6a7b15cf586926ba66f753594928fa64a65490565b7fc31b1e4b732c5173dc51d519dfa432bad95550ecc4b0f9a61c2a558a2a8e4341610a7e8133611127565b610894826119a5565b60006108d2600080516020612d108339815191525490565b610ae46040518060e001604052806000815260200160008152602001600080191681526020016000151581526020016000815260200160008152602001600081525090565b60408051606081018252600080516020612cd0833981519152548152600080516020612db0833981519152546001600160401b038082166020840152600160401b9091041691810191909152610b38611a28565b825280511580610b59575080602001516001600160401b0316826000015114155b15610b62575090565b6040818101516001600160401b0316602084015281519083015260007ff54f01aac0787b485340ed16cefe4fba326c1674376c8dcd7c2a644b4643792f6040805160808101825291546001600160401b03808216808552600160401b830482166020860152600160801b830490911692840192909252600160c01b900461ffff166060808401919091528551909114908501819052909150610c0357505090565b606081015161ffff16608084015260208101516001600160401b0390811660a08501526040909101511660c08301525090565b6000828152600080516020612d3083398151915260205260408120610c5b9083611abd565b9392505050565b6000918252600080516020612d50833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b7f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d610cc58133611127565b61089482611ac9565b6000610ce6600080516020612d908339815191525490565b4210905090565b7f04a0afbbd09d5ad397fc858789da4f8edd59f5ca5098d70faa490babee945c3b610d188133611127565b61089482610d32600080516020612d708339815191525490565b611b1d565b6000818152600080516020612d30833981519152602052604081206105d290611d76565b610d636111cf565b60408051606081018252600080516020612cd0833981519152548152600080516020612db0833981519152546001600160401b0380821660208401819052600160401b909204169282019290925290821015610dea57602081015160405163431d301760e11b8152600481018490526001600160401b03909116602482015260440161065e565b80602001516001600160401b0316821115610e03575050565b6000610e1b600080516020612d708339815191525490565b9050808311610e3c576040516252e2c960e41b815260040160405180910390fd5b6000600080516020612cd08339815191525581602001516001600160401b03167fe21266bc27ee721ac10034efaf7fd724656ef471c75b8402cd8f07850af6b6768360000151604051610e9191815260200190565b60405180910390a2505050565b610ea78261080e565b610eb18133611127565b6108b58383611976565b60006108d27f423c0a70d629d0b16eb0cfb674ba25f8352fe47057f0f4af829a850a22c6cc4a5490565b6001600160a01b038416610f0c57604051636b35b1b760e01b815260040160405180910390fd5b610f17600085611d80565b610f22600019611d8a565b610f2d838383611dda565b50505050565b606062ffffff841115610f5957604051632de932e560e01b815260040160405180910390fd5b6000826001600160401b03811115610f7357610f736129ca565b604051908082528060200260200182016040528015610f9c578160200160208202803683370190505b50905060005b8381101561108a576000858583818110610fbe57610fbe6129e0565b90506020020135905064ffffffffff8016811115610fef57604051632de932e560e01b815260040160405180910390fd5b602887901b81176000818152600080516020612cf0833981519152602090815260409182902082518084019093525460ff811615158084526101009091046001600160401b03169183019190915261104957600019611058565b80602001516001600160401b03165b85858151811061106a5761106a6129e0565b6020026020010181815250505050508061108390612a0c565b9050610fa2565b50949350505050565b7f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d6110be8133611127565b61089482611d8a565b9055565b60006001600160e01b03198216637965db0b60e01b14806105d257506301ffc9a760e01b6001600160e01b03198316146105d2565b611108610cce565b6111255760405163b047186b60e01b815260040160405180910390fd5b565b6111318282610c62565b61089457611149816001600160a01b03166014611e4d565b611154836020611e4d565b604051602001611165929190612a53565b60408051601f198184030181529082905262461bcd60e51b825261065e91600401612ac8565b611193611100565b42600080516020612d90833981519152556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f990600090a1565b600080516020612d10833981519152546001600160a01b0316336001600160a01b0316146111255760405163fef4d83160e01b815260040160405180910390fd5b60006001600160401b038211156112785760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b606482015260840161065e565b5090565b604080516080810182527ff54f01aac0787b485340ed16cefe4fba326c1674376c8dcd7c2a644b4643792f546001600160401b03808216808452600160401b830482166020850152600160801b830490911693830193909352600160c01b900461ffff166060820152908214801561130d575080602001516001600160401b031681604001516001600160401b0316105b15610f2d5760408082015160208084015183516001600160401b03938416815292169082015283917fefc67aab43195093a8d8ed25d52281d96de480748ece2787888c586e8e1e79b4910160405180910390a250505050565b61136e610cce565b1561112557604051630286f07360e31b815260040160405180910390fd5b336113b77f65fa0c17458517c727737e4153dd477fa3e328cf706640b0f68b1a285c5990da82610c62565b1580156113ca57506113c881611fe8565b155b15610613576040516323dada5360e01b815260040160405180910390fd5b60006113f2610a29565b9050808214610894576040516303abe78360e21b8152600481018290526024810183905260440161065e565b60408051606081018252600080516020612cd0833981519152548152600080516020612db0833981519152546001600160401b0380821660208401819052600160401b90920416928201929092529084146114a457602081015160405163490b8d4560e11b81526001600160401b0390911660048201526024810185905260440161065e565b60006114bc600080516020612dd08339815191525490565b90508084146114e857604051632a37dd3d60e11b8152600481018290526024810185905260440161065e565b8151831461151657815160405163642c75c760e11b815260048101919091526024810184905260440161065e565b5050505050565b60408051606081018252600080516020612cd083398151915254808252600080516020612db0833981519152546001600160401b038082166020850152600160401b909104169282019290925260009161158a576040516364dfc18f60e01b815260040160405180910390fd5b6115a081604001516001600160401b031661207e565b60006115b8600080516020612d708339815191525490565b905081602001516001600160401b03168114156115e7576040516252e2c960e41b815260040160405180910390fd5b6020828101516001600160401b0316600080516020612d70833981519152819055835160405190815290917ff73febded7d4502284718948a3e1d75406151c6326bde069424a584a4f6af87a910160405180910390a292915050565b600181606001351461166e57604051630f542bef60e21b81526060820135600482015260240161065e565b604061167d6080830183612afb565b611688929150612b5e565b156116a657604051630260e4e160e41b815260040160405180910390fd5b7f00000000000000000000000028fab2059c713a7f9d8c86db49f9bb0e96af1ef86001600160a01b031663f5e6d50f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ff57600080fd5b505afa158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190612b72565b6001600160a01b0316633e0865dd82604001356040518263ffffffff1660e01b815260040161176891815260200190565b60006040518083038186803b15801561178057600080fd5b505afa158015611794573d6000803e3d6000fd5b50505060408083013591506117ac6080840184612afb565b6117b7929150612b8f565b146117d55760405163f34afee160e01b815260040160405180910390fd5b6117ea6117e56080830183612afb565b6120a2565b60405180608001604052806118028360200135611210565b6001600160401b0316815260200161181d8360400135611210565b6001600160401b031681526020016118388360400135611210565b6001600160401b0316815260016020909101527ff54f01aac0787b485340ed16cefe4fba326c1674376c8dcd7c2a644b4643792f81518154602084015160408086015160609096015161ffff16600160c01b0261ffff60c01b196001600160401b03978816600160801b021669ffffffffffffffffffff60801b19938816600160401b026001600160801b031990951697909516969096179290921716919091179290921790558101356118e95750565b61061381604001356119197f423c0a70d629d0b16eb0cfb674ba25f8352fe47057f0f4af829a850a22c6cc4a5490565b6119239190612ba3565b7f423c0a70d629d0b16eb0cfb674ba25f8352fe47057f0f4af829a850a22c6cc4a55565b6119518282612339565b6000828152600080516020612d30833981519152602052604090206108b590826123af565b61198082826123c4565b6000828152600080516020612d30833981519152602052604090206108b59082612438565b60006119bd600080516020612dd08339815191525490565b9050808214156119e057604051631d7c761b60e21b815260040160405180910390fd5b6119f7600080516020612dd0833981519152839055565b604051819083907ffa5304972d4ec3e3207f0bbf91155a49d0dfa62488f9529403a2a49e4b29a89590600090a35050565b600080611a41600080516020612d108339815191525490565b90506000816001600160a01b03166372f79b136040518163ffffffff1660e01b8152600401604080518083038186803b158015611a7d57600080fd5b505afa158015611a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab59190612bbb565b509392505050565b6000610c5b838361244d565b611ad1611366565b42811015611af2576040516339e2ec5360e11b815260040160405180910390fd5b60006000198214611b0f57611b08826001612ba3565b9050611b14565b506000195b61089481612477565b6001600160a01b038216611b44576040516303988b8160e61b815260040160405180910390fd5b6000611b5c600080516020612d108339815191525490565b9050806001600160a01b0316836001600160a01b03161415611b91576040516321a55ce160e11b815260040160405180910390fd5b600080846001600160a01b031663606c0c946040518163ffffffff1660e01b815260040160606040518083038186803b158015611bcd57600080fd5b505afa158015611be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c059190612bdf565b92509250507f000000000000000000000000000000000000000000000000000000000000000c82141580611c5957507f0000000000000000000000000000000000000000000000000000000065156ac08114155b15611c7757604051635401d0a160e11b815260040160405180910390fd5b6000856001600160a01b0316636095012f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cb257600080fd5b505afa158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea9190612c0d565b905084811015611d1757604051631e779ad160e11b8152600481018290526024810186905260440161065e565b611d2e600080516020612d10833981519152879055565b836001600160a01b0316866001600160a01b03167f25421480fb7f52d18947876279a213696b58d7e0e5416ce5e2c9f9942661c34c60405160405180910390a3505050505050565b60006105d2825490565b6108948282611947565b611d92611366565b80611db05760405163ad58bfc760e01b815260040160405180910390fd5b6000600019821415611dc55750600019611b14565b611dcf8242612ba3565b905061089481612477565b611de4600161250a565b611dee8382611b1d565b611df7826119a5565b611e0e600080516020612d70833981519152829055565b611e1781611210565b600080516020612cd0833981519152600101805467ffffffffffffffff19166001600160401b0392909216919091179055505050565b60606000611e5c836002612c26565b611e67906002612ba3565b6001600160401b03811115611e7e57611e7e6129ca565b6040519080825280601f01601f191660200182016040528015611ea8576020820181803683370190505b509050600360fc1b81600081518110611ec357611ec36129e0565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611ef257611ef26129e0565b60200101906001600160f81b031916908160001a9053506000611f16846002612c26565b611f21906001612ba3565b90505b6001811115611f99576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611f5557611f556129e0565b1a60f81b828281518110611f6b57611f6b6129e0565b60200101906001600160f81b031916908160001a90535060049490941c93611f9281612c45565b9050611f24565b508315610c5b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161065e565b600080612001600080516020612d108339815191525490565b604051631951c03760e01b81526001600160a01b03858116600483015291925090821690631951c0379060240160206040518083038186803b15801561204657600080fd5b505afa15801561205a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5b9190612c5c565b804211156106135760405163537bacdf60e11b81526004810182905260240161065e565b60408051808201909152600080825260208201819052839183830191908190366030425b868810156122cb5760408801976010810193503560801c8681116120fd576040516362851b8960e01b815260040160405180910390fd5b8064ffffffffff604082901c1662ffffff606883901c1680612132576040516370180ea960e01b815260040160405180910390fd5b602881901b82178981146121eb5789156121a25788600080516020612cf083398151915260008c81526020918252604090208251815493909201516001600160401b03166101000268ffffffffffffffff00199215159290921668ffffffffffffffffff19909316929092171790555b6000818152600080516020612cf0833981519152602090815260409182902082518084019093525460ff81161515835261010090046001600160401b0316908201529099509750885b8851801561220f575088602001516001600160401b0316846001600160401b031611155b1561225457602089015160405163d4bb585960e01b815260048101849052602481018590526001600160401b039182166044820152908516606482015260840161065e565b6040518060400160405280600115158152602001856001600160401b03168152509850849a50836001600160401b031683837f96395f55c4997466e5035d777f0e1ba82b8cae217aaad05cf07839eb7c75bcf28b8b8b6040516122b993929190612c7e565b60405180910390a450505050506120c6565b841561232d5783600080516020612cf083398151915260008781526020918252604090208251815493909201516001600160401b03166101000268ffffffffffffffff00199215159290921668ffffffffffffffffff19909316929092171790555b50505050505050505050565b6123438282610c62565b610894576000828152600080516020612d50833981519152602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b6000610c5b836001600160a01b038416612539565b6123ce8282610c62565b15610894576000828152600080516020612d50833981519152602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610c5b836001600160a01b038416612588565b6000826000018281548110612464576124646129e0565b9060005260206000200154905092915050565b61248e600080516020612d90833981519152829055565b6000198114156124d15760405160001981527f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e906020015b60405180910390a150565b7f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e6124fc4283612ca2565b6040519081526020016124c6565b612512610a29565b156125305760405163184e52a160e21b815260040160405180910390fd5b6106138161267b565b6000818152600183016020526040812054612580575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d2565b5060006105d2565b600081815260018301602052604081205480156126715760006125ac600183612ca2565b85549091506000906125c090600190612ca2565b90508181146126255760008660000182815481106125e0576125e06129e0565b9060005260206000200154905080876000018481548110612603576126036129e0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061263657612636612cb9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d2565b60009150506105d2565b6126a47f4dd0f6662ba1d6b081f08b350f5e9a6a7b15cf586926ba66f753594928fa64a6829055565b6040518181527ffddcded6b4f4730c226821172046b48372d3cd963c159701ae1b7c3bcac541bb906020016124c6565b6000602082840312156126e657600080fd5b81356001600160e01b031981168114610c5b57600080fd5b60008060006060848603121561271357600080fd5b505081359360208301359350604090920135919050565b60006020828403121561273c57600080fd5b5035919050565b6000806040838503121561275657600080fd5b82356001600160401b0381111561276c57600080fd5b830160a0818603121561277e57600080fd5b946020939093013593505050565b6001600160a01b038116811461061357600080fd5b600080604083850312156127b457600080fd5b8235915060208301356127c68161278c565b809150509250929050565b600080604083850312156127e457600080fd5b50508035926020909101359150565b60006020828403121561280557600080fd5b8135610c5b8161278c565b6000806000806080858703121561282657600080fd5b84356128318161278c565b935060208501356128418161278c565b93969395505050506040820135916060013590565b60008060006040848603121561286b57600080fd5b8335925060208401356001600160401b038082111561288957600080fd5b818601915086601f83011261289d57600080fd5b8135818111156128ac57600080fd5b8760208260051b85010111156128c157600080fd5b6020830194508093505050509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561290c578351835292840192918401916001016128f0565b50909695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081528135602082015260208201356040820152604082013560608201526060820135608082015260006080830135601e1984360301811261298357600080fd5b830180356001600160401b0381111561299b57600080fd5b8036038513156129aa57600080fd5b60a0808501526129c160c085018260208501612918565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612a2057612a206129f6565b5060010190565b60005b83811015612a42578181015183820152602001612a2a565b83811115610f2d5750506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612a8b816017850160208801612a27565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612abc816028840160208801612a27565b01602801949350505050565b6020815260008251806020840152612ae7816040850160208701612a27565b601f01601f19169190910160400192915050565b6000808335601e19843603018112612b1257600080fd5b8301803591506001600160401b03821115612b2c57600080fd5b602001915036819003821315612b4157600080fd5b9250929050565b634e487b7160e01b600052601260045260246000fd5b600082612b6d57612b6d612b48565b500690565b600060208284031215612b8457600080fd5b8151610c5b8161278c565b600082612b9e57612b9e612b48565b500490565b60008219821115612bb657612bb66129f6565b500190565b60008060408385031215612bce57600080fd5b505080516020909101519092909150565b600080600060608486031215612bf457600080fd5b8351925060208401519150604084015190509250925092565b600060208284031215612c1f57600080fd5b5051919050565b6000816000190483118215151615612c4057612c406129f6565b500290565b600081612c5457612c546129f6565b506000190190565b600060208284031215612c6e57600080fd5b81518015158114610c5b57600080fd5b604081526000612c92604083018587612918565b9050826020830152949350505050565b600082821015612cb457612cb46129f6565b500390565b634e487b7160e01b600052603160045260246000fdfe9d565e483b8608dc09e04eff85533859683d2eeaa6ebc28af53a92d7dba3eea6bd6f8054a60057d34b01ac26cf9ceebc52adc698c27460513794fb003b6529d6b0e01b719c2c32a677822ce1584cb6a66e576ee3c2c506b9621dbe626355aa658f8c450dae5029cd48cd91dd9db65da48fb742893edfc7941250f6721d93cbbe9a627a5d4aa7c17f87ff26e3fe9a42c2b6c559e8b41a42282d0ecebb17c0e4d3c9bdcd6eb2e956ecf03d8d27bee4c163f9b5c078aa69020d618e76513b5d0a94e8b012900cb200ee5dfc3b895a32791b67d12891b09f117814f167a237783a029d565e483b8608dc09e04eff85533859683d2eeaa6ebc28af53a92d7dba3eea72767d6892477f8d2750fb44e817c9aed93d34d3c6be4101ed58bcac692c99e9ca2646970667358221220ba9315d71daa9272447d2e1f7230a93aee14c04d44e36c5966ac2469f188463e64736f6c63430008090033 diff --git a/internal/lido/contracts/vebo/VEBO.go b/internal/lido/contracts/vebo/VEBO.go new file mode 100644 index 00000000..141c23f4 --- /dev/null +++ b/internal/lido/contracts/vebo/VEBO.go @@ -0,0 +1,3357 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vebo + +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 +) + +// ValidatorsExitBusOracleProcessingState is an auto generated low-level Go binding around an user-defined struct. +type ValidatorsExitBusOracleProcessingState struct { + CurrentFrameRefSlot *big.Int + ProcessingDeadlineTime *big.Int + DataHash [32]byte + DataSubmitted bool + DataFormat *big.Int + RequestsCount *big.Int + RequestsSubmitted *big.Int +} + +// ValidatorsExitBusOracleReportData is an auto generated low-level Go binding around an user-defined struct. +type ValidatorsExitBusOracleReportData struct { + ConsensusVersion *big.Int + RefSlot *big.Int + RequestsCount *big.Int + DataFormat *big.Int + Data []byte +} + +// VeboMetaData contains all meta data concerning the Vebo contract. +var VeboMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"secondsPerSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"genesisTime\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"lidoLocator\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AddressCannotBeSame\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AdminCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArgumentOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"initialRefSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"processingRefSlot\",\"type\":\"uint256\"}],\"name\":\"InitialRefSlotCannotBeLessThanProcessingOne\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContractVersionIncrement\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequestsData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequestsDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRequestsDataSortOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoConsensusReportToProcess\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"moduleId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nodeOpId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevRequestedValidatorIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedValidatorIndex\",\"type\":\"uint256\"}],\"name\":\"NodeOpValidatorIndexMustIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonZeroContractVersionOnInit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PauseUntilMustBeInFuture\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PausedExpected\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"ProcessingDeadlineMissed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RefSlotAlreadyProcessing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevRefSlot\",\"type\":\"uint256\"}],\"name\":\"RefSlotCannotDecrease\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"processingRefSlot\",\"type\":\"uint256\"}],\"name\":\"RefSlotMustBeGreaterThanProcessingOne\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ResumedExpected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SecondsPerSlotCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIsNotTheConsensusContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedVersion\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedVersion\",\"type\":\"uint256\"}],\"name\":\"UnexpectedConsensusVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"UnexpectedContractVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"consensusHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"receivedHash\",\"type\":\"bytes32\"}],\"name\":\"UnexpectedDataHash\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"consensusRefSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataRefSlot\",\"type\":\"uint256\"}],\"name\":\"UnexpectedRefSlot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedRequestsDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"format\",\"type\":\"uint256\"}],\"name\":\"UnsupportedRequestsDataFormat\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VersionCannotBeSame\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroPauseDuration\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"prevAddr\",\"type\":\"address\"}],\"name\":\"ConsensusHashContractSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"prevVersion\",\"type\":\"uint256\"}],\"name\":\"ConsensusVersionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"ContractVersionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"ProcessingStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"ReportDiscarded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"processingDeadlineTime\",\"type\":\"uint256\"}],\"name\":\"ReportSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Resumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"stakingModuleId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"validatorIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"validatorPubkey\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"ValidatorExitRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestsProcessed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestsCount\",\"type\":\"uint256\"}],\"name\":\"WarnDataIncompleteProcessing\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"}],\"name\":\"WarnProcessingMissed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DATA_FORMAT_LIST\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GENESIS_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MANAGE_CONSENSUS_CONTRACT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MANAGE_CONSENSUS_VERSION_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PAUSE_INFINITELY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PAUSE_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RESUME_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SECONDS_PER_SLOT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMIT_DATA_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"}],\"name\":\"discardConsensusReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusReport\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"processingDeadlineTime\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"processingStarted\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getContractVersion\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastProcessingRefSlot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"moduleId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"nodeOpIds\",\"type\":\"uint256[]\"}],\"name\":\"getLastRequestedValidatorIndices\",\"outputs\":[{\"internalType\":\"int256[]\",\"name\":\"\",\"type\":\"int256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getProcessingState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"currentFrameRefSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"processingDeadlineTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"dataSubmitted\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"dataFormat\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestsCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestsSubmitted\",\"type\":\"uint256\"}],\"internalType\":\"structValidatorsExitBusOracle.ProcessingState\",\"name\":\"result\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getResumeSinceTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalRequestsProcessed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensusContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"consensusVersion\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lastProcessingRefSlot\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_duration\",\"type\":\"uint256\"}],\"name\":\"pauseFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_pauseUntilInclusive\",\"type\":\"uint256\"}],\"name\":\"pauseUntil\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setConsensusContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"setConsensusVersion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"reportHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"submitConsensusReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"consensusVersion\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"refSlot\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestsCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataFormat\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structValidatorsExitBusOracle.ReportData\",\"name\":\"data\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"contractVersion\",\"type\":\"uint256\"}],\"name\":\"submitReportData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50600436106102275760003560e01c80638f7797c211610130578063c469c307116100b8578063e2793e721161007c578063e2793e7214610538578063eb990c5914610540578063ef9bf37e14610553578063f288246114610573578063f3f449c71461059a57600080fd5b8063c469c307146104e4578063ca15c873146104f7578063d43812171461050a578063d547741f1461051d578063e271b7741461053057600080fd5b8063a217fddf116100ff578063a217fddf14610491578063a302ee3814610499578063abe9cfc8146104a2578063ad5cac4e146104b5578063b187bd26146104dc57600080fd5b80638f7797c2146103e45780639010d07c1461044457806391d14854146104575780639cc23c791461046a57600080fd5b806336568abe116101b35780635be20425116101825780635be204251461037757806360d64d381461037f5780638aa10435146103a95780638d591474146103b15780638f55b571146103c457600080fd5b806336568abe1461030e578063389ed2671461032157806346e1f57614610348578063589ff76c1461036f57600080fd5b8063294492c8116101fa578063294492c8146102925780632de03aa1146102a55780632f2ff15d146102cc578063304b9071146102df5780633584d59c1461030657600080fd5b806301ffc9a71461022c578063046f7da214610254578063063f36ad1461025e578063248a9ca314610271575b600080fd5b61023f61023a3660046126d4565b6105ad565b60405190151581526020015b60405180910390f35b61025c6105d8565b005b61025c61026c3660046126fe565b610616565b61028461027f36600461272a565b61080e565b60405190815260200161024b565b61025c6102a0366004612743565b610830565b6102847f2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c781565b61025c6102da3660046127a1565b610898565b6102847f000000000000000000000000000000000000000000000000000000000000000c81565b6102846108ba565b61025c61031c3660046127a1565b6108d7565b6102847f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d81565b6102847f65fa0c17458517c727737e4153dd477fa3e328cf706640b0f68b1a285c5990da81565b610284610951565b610284610969565b610387610981565b604080519485526020850193909352918301521515606082015260800161024b565b610284610a29565b61025c6103bf36600461272a565b610a53565b6103cc610a87565b6040516001600160a01b03909116815260200161024b565b6103ec610a9f565b60405161024b9190600060e0820190508251825260208301516020830152604083015160408301526060830151151560608301526080830151608083015260a083015160a083015260c083015160c083015292915050565b6103cc6104523660046127d1565b610c36565b61023f6104653660046127a1565b610c62565b6102847fc31b1e4b732c5173dc51d519dfa432bad95550ecc4b0f9a61c2a558a2a8e434181565b610284600081565b61028460001981565b61025c6104b036600461272a565b610c9a565b6102847f04a0afbbd09d5ad397fc858789da4f8edd59f5ca5098d70faa490babee945c3b81565b61023f610cce565b61025c6104f23660046127f3565b610ced565b61028461050536600461272a565b610d37565b61025c61051836600461272a565b610d5b565b61025c61052b3660046127a1565b610e9e565b610284600181565b610284610ebb565b61025c61054e366004612810565b610ee5565b610566610561366004612856565b610f33565b60405161024b91906128d4565b6102847f0000000000000000000000000000000000000000000000000000000065156ac081565b61025c6105a836600461272a565b611093565b60006001600160e01b03198216635a05180f60e01b14806105d257506105d2826110cb565b92915050565b6105e0611100565b7f2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c761060b8133611127565b61061361118b565b50565b61061e6111cf565b600080516020612db0833981519152546001600160401b0316808310156106675760405163431d301760e11b815260048101849052602481018290526044015b60405180910390fd5b600061067f600080516020612d708339815191525490565b90508084116106ab576040516360a41e4960e01b8152600481018590526024810182905260440161065e565b824211156106cf5760405163537bacdf60e11b81526004810184905260240161065e565b8184141580156106df5750818114155b156107105760405182907f800b849c8bf80718cf786c99d1091c079fe2c5e420a3ba7ba9b0ef8179ef2c3890600090a25b8461072e57604051635b18a69f60e11b815260040160405180910390fd5b604080518681526020810185905285917faed7d1a7a1831158dcda1e4214f5862f450bd3eb5721a5f322bf8c9fe1790b0a910160405180910390a26000604051806060016040528087815260200161078587611210565b6001600160401b0316815260200161079c86611210565b6001600160401b039081169091528151600080516020612cd0833981519152556020820151600080516020612db0833981519152805460408501518416600160401b026001600160801b03199091169290931691909117919091179055905061080681848461127c565b505050505050565b6000908152600080516020612d50833981519152602052604090206001015490565b610838611366565b61084061138c565b610849816113e8565b61088282602001358360000135846040516020016108679190612941565b6040516020818303038152906040528051906020012061141e565b61088a61151d565b5061089482611643565b5050565b6108a18261080e565b6108ab8133611127565b6108b58383611947565b505050565b60006108d2600080516020612d708339815191525490565b905090565b6001600160a01b03811633146109475760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b606482015260840161065e565b6108948282611976565b60006108d2600080516020612d908339815191525490565b60006108d2600080516020612dd08339815191525490565b600080808080600080516020612cd083398151915260408051606081018252825481526001909201546001600160401b038082166020850152600160401b9091041690820152905060006109e1600080516020612d708339815191525490565b82516020840151604085015192935090918215801590610a0d57508385602001516001600160401b0316145b92996001600160401b0392831699509116965090945092505050565b60006108d27f4dd0f6662ba1d6b081f08b350f5e9a6a7b15cf586926ba66f753594928fa64a65490565b7fc31b1e4b732c5173dc51d519dfa432bad95550ecc4b0f9a61c2a558a2a8e4341610a7e8133611127565b610894826119a5565b60006108d2600080516020612d108339815191525490565b610ae46040518060e001604052806000815260200160008152602001600080191681526020016000151581526020016000815260200160008152602001600081525090565b60408051606081018252600080516020612cd0833981519152548152600080516020612db0833981519152546001600160401b038082166020840152600160401b9091041691810191909152610b38611a28565b825280511580610b59575080602001516001600160401b0316826000015114155b15610b62575090565b6040818101516001600160401b0316602084015281519083015260007ff54f01aac0787b485340ed16cefe4fba326c1674376c8dcd7c2a644b4643792f6040805160808101825291546001600160401b03808216808552600160401b830482166020860152600160801b830490911692840192909252600160c01b900461ffff166060808401919091528551909114908501819052909150610c0357505090565b606081015161ffff16608084015260208101516001600160401b0390811660a08501526040909101511660c08301525090565b6000828152600080516020612d3083398151915260205260408120610c5b9083611abd565b9392505050565b6000918252600080516020612d50833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b7f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d610cc58133611127565b61089482611ac9565b6000610ce6600080516020612d908339815191525490565b4210905090565b7f04a0afbbd09d5ad397fc858789da4f8edd59f5ca5098d70faa490babee945c3b610d188133611127565b61089482610d32600080516020612d708339815191525490565b611b1d565b6000818152600080516020612d30833981519152602052604081206105d290611d76565b610d636111cf565b60408051606081018252600080516020612cd0833981519152548152600080516020612db0833981519152546001600160401b0380821660208401819052600160401b909204169282019290925290821015610dea57602081015160405163431d301760e11b8152600481018490526001600160401b03909116602482015260440161065e565b80602001516001600160401b0316821115610e03575050565b6000610e1b600080516020612d708339815191525490565b9050808311610e3c576040516252e2c960e41b815260040160405180910390fd5b6000600080516020612cd08339815191525581602001516001600160401b03167fe21266bc27ee721ac10034efaf7fd724656ef471c75b8402cd8f07850af6b6768360000151604051610e9191815260200190565b60405180910390a2505050565b610ea78261080e565b610eb18133611127565b6108b58383611976565b60006108d27f423c0a70d629d0b16eb0cfb674ba25f8352fe47057f0f4af829a850a22c6cc4a5490565b6001600160a01b038416610f0c57604051636b35b1b760e01b815260040160405180910390fd5b610f17600085611d80565b610f22600019611d8a565b610f2d838383611dda565b50505050565b606062ffffff841115610f5957604051632de932e560e01b815260040160405180910390fd5b6000826001600160401b03811115610f7357610f736129ca565b604051908082528060200260200182016040528015610f9c578160200160208202803683370190505b50905060005b8381101561108a576000858583818110610fbe57610fbe6129e0565b90506020020135905064ffffffffff8016811115610fef57604051632de932e560e01b815260040160405180910390fd5b602887901b81176000818152600080516020612cf0833981519152602090815260409182902082518084019093525460ff811615158084526101009091046001600160401b03169183019190915261104957600019611058565b80602001516001600160401b03165b85858151811061106a5761106a6129e0565b6020026020010181815250505050508061108390612a0c565b9050610fa2565b50949350505050565b7f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d6110be8133611127565b61089482611d8a565b9055565b60006001600160e01b03198216637965db0b60e01b14806105d257506301ffc9a760e01b6001600160e01b03198316146105d2565b611108610cce565b6111255760405163b047186b60e01b815260040160405180910390fd5b565b6111318282610c62565b61089457611149816001600160a01b03166014611e4d565b611154836020611e4d565b604051602001611165929190612a53565b60408051601f198184030181529082905262461bcd60e51b825261065e91600401612ac8565b611193611100565b42600080516020612d90833981519152556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f990600090a1565b600080516020612d10833981519152546001600160a01b0316336001600160a01b0316146111255760405163fef4d83160e01b815260040160405180910390fd5b60006001600160401b038211156112785760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b606482015260840161065e565b5090565b604080516080810182527ff54f01aac0787b485340ed16cefe4fba326c1674376c8dcd7c2a644b4643792f546001600160401b03808216808452600160401b830482166020850152600160801b830490911693830193909352600160c01b900461ffff166060820152908214801561130d575080602001516001600160401b031681604001516001600160401b0316105b15610f2d5760408082015160208084015183516001600160401b03938416815292169082015283917fefc67aab43195093a8d8ed25d52281d96de480748ece2787888c586e8e1e79b4910160405180910390a250505050565b61136e610cce565b1561112557604051630286f07360e31b815260040160405180910390fd5b336113b77f65fa0c17458517c727737e4153dd477fa3e328cf706640b0f68b1a285c5990da82610c62565b1580156113ca57506113c881611fe8565b155b15610613576040516323dada5360e01b815260040160405180910390fd5b60006113f2610a29565b9050808214610894576040516303abe78360e21b8152600481018290526024810183905260440161065e565b60408051606081018252600080516020612cd0833981519152548152600080516020612db0833981519152546001600160401b0380821660208401819052600160401b90920416928201929092529084146114a457602081015160405163490b8d4560e11b81526001600160401b0390911660048201526024810185905260440161065e565b60006114bc600080516020612dd08339815191525490565b90508084146114e857604051632a37dd3d60e11b8152600481018290526024810185905260440161065e565b8151831461151657815160405163642c75c760e11b815260048101919091526024810184905260440161065e565b5050505050565b60408051606081018252600080516020612cd083398151915254808252600080516020612db0833981519152546001600160401b038082166020850152600160401b909104169282019290925260009161158a576040516364dfc18f60e01b815260040160405180910390fd5b6115a081604001516001600160401b031661207e565b60006115b8600080516020612d708339815191525490565b905081602001516001600160401b03168114156115e7576040516252e2c960e41b815260040160405180910390fd5b6020828101516001600160401b0316600080516020612d70833981519152819055835160405190815290917ff73febded7d4502284718948a3e1d75406151c6326bde069424a584a4f6af87a910160405180910390a292915050565b600181606001351461166e57604051630f542bef60e21b81526060820135600482015260240161065e565b604061167d6080830183612afb565b611688929150612b5e565b156116a657604051630260e4e160e41b815260040160405180910390fd5b7f00000000000000000000000028fab2059c713a7f9d8c86db49f9bb0e96af1ef86001600160a01b031663f5e6d50f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ff57600080fd5b505afa158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190612b72565b6001600160a01b0316633e0865dd82604001356040518263ffffffff1660e01b815260040161176891815260200190565b60006040518083038186803b15801561178057600080fd5b505afa158015611794573d6000803e3d6000fd5b50505060408083013591506117ac6080840184612afb565b6117b7929150612b8f565b146117d55760405163f34afee160e01b815260040160405180910390fd5b6117ea6117e56080830183612afb565b6120a2565b60405180608001604052806118028360200135611210565b6001600160401b0316815260200161181d8360400135611210565b6001600160401b031681526020016118388360400135611210565b6001600160401b0316815260016020909101527ff54f01aac0787b485340ed16cefe4fba326c1674376c8dcd7c2a644b4643792f81518154602084015160408086015160609096015161ffff16600160c01b0261ffff60c01b196001600160401b03978816600160801b021669ffffffffffffffffffff60801b19938816600160401b026001600160801b031990951697909516969096179290921716919091179290921790558101356118e95750565b61061381604001356119197f423c0a70d629d0b16eb0cfb674ba25f8352fe47057f0f4af829a850a22c6cc4a5490565b6119239190612ba3565b7f423c0a70d629d0b16eb0cfb674ba25f8352fe47057f0f4af829a850a22c6cc4a55565b6119518282612339565b6000828152600080516020612d30833981519152602052604090206108b590826123af565b61198082826123c4565b6000828152600080516020612d30833981519152602052604090206108b59082612438565b60006119bd600080516020612dd08339815191525490565b9050808214156119e057604051631d7c761b60e21b815260040160405180910390fd5b6119f7600080516020612dd0833981519152839055565b604051819083907ffa5304972d4ec3e3207f0bbf91155a49d0dfa62488f9529403a2a49e4b29a89590600090a35050565b600080611a41600080516020612d108339815191525490565b90506000816001600160a01b03166372f79b136040518163ffffffff1660e01b8152600401604080518083038186803b158015611a7d57600080fd5b505afa158015611a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab59190612bbb565b509392505050565b6000610c5b838361244d565b611ad1611366565b42811015611af2576040516339e2ec5360e11b815260040160405180910390fd5b60006000198214611b0f57611b08826001612ba3565b9050611b14565b506000195b61089481612477565b6001600160a01b038216611b44576040516303988b8160e61b815260040160405180910390fd5b6000611b5c600080516020612d108339815191525490565b9050806001600160a01b0316836001600160a01b03161415611b91576040516321a55ce160e11b815260040160405180910390fd5b600080846001600160a01b031663606c0c946040518163ffffffff1660e01b815260040160606040518083038186803b158015611bcd57600080fd5b505afa158015611be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c059190612bdf565b92509250507f000000000000000000000000000000000000000000000000000000000000000c82141580611c5957507f0000000000000000000000000000000000000000000000000000000065156ac08114155b15611c7757604051635401d0a160e11b815260040160405180910390fd5b6000856001600160a01b0316636095012f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cb257600080fd5b505afa158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea9190612c0d565b905084811015611d1757604051631e779ad160e11b8152600481018290526024810186905260440161065e565b611d2e600080516020612d10833981519152879055565b836001600160a01b0316866001600160a01b03167f25421480fb7f52d18947876279a213696b58d7e0e5416ce5e2c9f9942661c34c60405160405180910390a3505050505050565b60006105d2825490565b6108948282611947565b611d92611366565b80611db05760405163ad58bfc760e01b815260040160405180910390fd5b6000600019821415611dc55750600019611b14565b611dcf8242612ba3565b905061089481612477565b611de4600161250a565b611dee8382611b1d565b611df7826119a5565b611e0e600080516020612d70833981519152829055565b611e1781611210565b600080516020612cd0833981519152600101805467ffffffffffffffff19166001600160401b0392909216919091179055505050565b60606000611e5c836002612c26565b611e67906002612ba3565b6001600160401b03811115611e7e57611e7e6129ca565b6040519080825280601f01601f191660200182016040528015611ea8576020820181803683370190505b509050600360fc1b81600081518110611ec357611ec36129e0565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611ef257611ef26129e0565b60200101906001600160f81b031916908160001a9053506000611f16846002612c26565b611f21906001612ba3565b90505b6001811115611f99576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611f5557611f556129e0565b1a60f81b828281518110611f6b57611f6b6129e0565b60200101906001600160f81b031916908160001a90535060049490941c93611f9281612c45565b9050611f24565b508315610c5b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161065e565b600080612001600080516020612d108339815191525490565b604051631951c03760e01b81526001600160a01b03858116600483015291925090821690631951c0379060240160206040518083038186803b15801561204657600080fd5b505afa15801561205a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5b9190612c5c565b804211156106135760405163537bacdf60e11b81526004810182905260240161065e565b60408051808201909152600080825260208201819052839183830191908190366030425b868810156122cb5760408801976010810193503560801c8681116120fd576040516362851b8960e01b815260040160405180910390fd5b8064ffffffffff604082901c1662ffffff606883901c1680612132576040516370180ea960e01b815260040160405180910390fd5b602881901b82178981146121eb5789156121a25788600080516020612cf083398151915260008c81526020918252604090208251815493909201516001600160401b03166101000268ffffffffffffffff00199215159290921668ffffffffffffffffff19909316929092171790555b6000818152600080516020612cf0833981519152602090815260409182902082518084019093525460ff81161515835261010090046001600160401b0316908201529099509750885b8851801561220f575088602001516001600160401b0316846001600160401b031611155b1561225457602089015160405163d4bb585960e01b815260048101849052602481018590526001600160401b039182166044820152908516606482015260840161065e565b6040518060400160405280600115158152602001856001600160401b03168152509850849a50836001600160401b031683837f96395f55c4997466e5035d777f0e1ba82b8cae217aaad05cf07839eb7c75bcf28b8b8b6040516122b993929190612c7e565b60405180910390a450505050506120c6565b841561232d5783600080516020612cf083398151915260008781526020918252604090208251815493909201516001600160401b03166101000268ffffffffffffffff00199215159290921668ffffffffffffffffff19909316929092171790555b50505050505050505050565b6123438282610c62565b610894576000828152600080516020612d50833981519152602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b6000610c5b836001600160a01b038416612539565b6123ce8282610c62565b15610894576000828152600080516020612d50833981519152602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610c5b836001600160a01b038416612588565b6000826000018281548110612464576124646129e0565b9060005260206000200154905092915050565b61248e600080516020612d90833981519152829055565b6000198114156124d15760405160001981527f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e906020015b60405180910390a150565b7f32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e6124fc4283612ca2565b6040519081526020016124c6565b612512610a29565b156125305760405163184e52a160e21b815260040160405180910390fd5b6106138161267b565b6000818152600183016020526040812054612580575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d2565b5060006105d2565b600081815260018301602052604081205480156126715760006125ac600183612ca2565b85549091506000906125c090600190612ca2565b90508181146126255760008660000182815481106125e0576125e06129e0565b9060005260206000200154905080876000018481548110612603576126036129e0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061263657612636612cb9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d2565b60009150506105d2565b6126a47f4dd0f6662ba1d6b081f08b350f5e9a6a7b15cf586926ba66f753594928fa64a6829055565b6040518181527ffddcded6b4f4730c226821172046b48372d3cd963c159701ae1b7c3bcac541bb906020016124c6565b6000602082840312156126e657600080fd5b81356001600160e01b031981168114610c5b57600080fd5b60008060006060848603121561271357600080fd5b505081359360208301359350604090920135919050565b60006020828403121561273c57600080fd5b5035919050565b6000806040838503121561275657600080fd5b82356001600160401b0381111561276c57600080fd5b830160a0818603121561277e57600080fd5b946020939093013593505050565b6001600160a01b038116811461061357600080fd5b600080604083850312156127b457600080fd5b8235915060208301356127c68161278c565b809150509250929050565b600080604083850312156127e457600080fd5b50508035926020909101359150565b60006020828403121561280557600080fd5b8135610c5b8161278c565b6000806000806080858703121561282657600080fd5b84356128318161278c565b935060208501356128418161278c565b93969395505050506040820135916060013590565b60008060006040848603121561286b57600080fd5b8335925060208401356001600160401b038082111561288957600080fd5b818601915086601f83011261289d57600080fd5b8135818111156128ac57600080fd5b8760208260051b85010111156128c157600080fd5b6020830194508093505050509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561290c578351835292840192918401916001016128f0565b50909695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081528135602082015260208201356040820152604082013560608201526060820135608082015260006080830135601e1984360301811261298357600080fd5b830180356001600160401b0381111561299b57600080fd5b8036038513156129aa57600080fd5b60a0808501526129c160c085018260208501612918565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612a2057612a206129f6565b5060010190565b60005b83811015612a42578181015183820152602001612a2a565b83811115610f2d5750506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612a8b816017850160208801612a27565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612abc816028840160208801612a27565b01602801949350505050565b6020815260008251806020840152612ae7816040850160208701612a27565b601f01601f19169190910160400192915050565b6000808335601e19843603018112612b1257600080fd5b8301803591506001600160401b03821115612b2c57600080fd5b602001915036819003821315612b4157600080fd5b9250929050565b634e487b7160e01b600052601260045260246000fd5b600082612b6d57612b6d612b48565b500690565b600060208284031215612b8457600080fd5b8151610c5b8161278c565b600082612b9e57612b9e612b48565b500490565b60008219821115612bb657612bb66129f6565b500190565b60008060408385031215612bce57600080fd5b505080516020909101519092909150565b600080600060608486031215612bf457600080fd5b8351925060208401519150604084015190509250925092565b600060208284031215612c1f57600080fd5b5051919050565b6000816000190483118215151615612c4057612c406129f6565b500290565b600081612c5457612c546129f6565b506000190190565b600060208284031215612c6e57600080fd5b81518015158114610c5b57600080fd5b604081526000612c92604083018587612918565b9050826020830152949350505050565b600082821015612cb457612cb46129f6565b500390565b634e487b7160e01b600052603160045260246000fdfe9d565e483b8608dc09e04eff85533859683d2eeaa6ebc28af53a92d7dba3eea6bd6f8054a60057d34b01ac26cf9ceebc52adc698c27460513794fb003b6529d6b0e01b719c2c32a677822ce1584cb6a66e576ee3c2c506b9621dbe626355aa658f8c450dae5029cd48cd91dd9db65da48fb742893edfc7941250f6721d93cbbe9a627a5d4aa7c17f87ff26e3fe9a42c2b6c559e8b41a42282d0ecebb17c0e4d3c9bdcd6eb2e956ecf03d8d27bee4c163f9b5c078aa69020d618e76513b5d0a94e8b012900cb200ee5dfc3b895a32791b67d12891b09f117814f167a237783a029d565e483b8608dc09e04eff85533859683d2eeaa6ebc28af53a92d7dba3eea72767d6892477f8d2750fb44e817c9aed93d34d3c6be4101ed58bcac692c99e9ca2646970667358221220ba9315d71daa9272447d2e1f7230a93aee14c04d44e36c5966ac2469f188463e64736f6c63430008090033", +} + +// VeboABI is the input ABI used to generate the binding from. +// Deprecated: Use VeboMetaData.ABI instead. +var VeboABI = VeboMetaData.ABI + +// VeboBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use VeboMetaData.Bin instead. +var VeboBin = VeboMetaData.Bin + +// DeployVebo deploys a new Ethereum contract, binding an instance of Vebo to it. +func DeployVebo(auth *bind.TransactOpts, backend bind.ContractBackend, secondsPerSlot *big.Int, genesisTime *big.Int, lidoLocator common.Address) (common.Address, *types.Transaction, *Vebo, error) { + parsed, err := VeboMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(VeboBin), backend, secondsPerSlot, genesisTime, lidoLocator) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Vebo{VeboCaller: VeboCaller{contract: contract}, VeboTransactor: VeboTransactor{contract: contract}, VeboFilterer: VeboFilterer{contract: contract}}, nil +} + +// Vebo is an auto generated Go binding around an Ethereum contract. +type Vebo struct { + VeboCaller // Read-only binding to the contract + VeboTransactor // Write-only binding to the contract + VeboFilterer // Log filterer for contract events +} + +// VeboCaller is an auto generated read-only Go binding around an Ethereum contract. +type VeboCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// VeboTransactor is an auto generated write-only Go binding around an Ethereum contract. +type VeboTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// VeboFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type VeboFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// VeboSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type VeboSession struct { + Contract *Vebo // 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 +} + +// VeboCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type VeboCallerSession struct { + Contract *VeboCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// VeboTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type VeboTransactorSession struct { + Contract *VeboTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// VeboRaw is an auto generated low-level Go binding around an Ethereum contract. +type VeboRaw struct { + Contract *Vebo // Generic contract binding to access the raw methods on +} + +// VeboCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type VeboCallerRaw struct { + Contract *VeboCaller // Generic read-only contract binding to access the raw methods on +} + +// VeboTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type VeboTransactorRaw struct { + Contract *VeboTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewVebo creates a new instance of Vebo, bound to a specific deployed contract. +func NewVebo(address common.Address, backend bind.ContractBackend) (*Vebo, error) { + contract, err := bindVebo(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Vebo{VeboCaller: VeboCaller{contract: contract}, VeboTransactor: VeboTransactor{contract: contract}, VeboFilterer: VeboFilterer{contract: contract}}, nil +} + +// NewVeboCaller creates a new read-only instance of Vebo, bound to a specific deployed contract. +func NewVeboCaller(address common.Address, caller bind.ContractCaller) (*VeboCaller, error) { + contract, err := bindVebo(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VeboCaller{contract: contract}, nil +} + +// NewVeboTransactor creates a new write-only instance of Vebo, bound to a specific deployed contract. +func NewVeboTransactor(address common.Address, transactor bind.ContractTransactor) (*VeboTransactor, error) { + contract, err := bindVebo(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VeboTransactor{contract: contract}, nil +} + +// NewVeboFilterer creates a new log filterer instance of Vebo, bound to a specific deployed contract. +func NewVeboFilterer(address common.Address, filterer bind.ContractFilterer) (*VeboFilterer, error) { + contract, err := bindVebo(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VeboFilterer{contract: contract}, nil +} + +// bindVebo binds a generic wrapper to an already deployed contract. +func bindVebo(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VeboMetaData.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 (_Vebo *VeboRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Vebo.Contract.VeboCaller.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 (_Vebo *VeboRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Vebo.Contract.VeboTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Vebo *VeboRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Vebo.Contract.VeboTransactor.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 (_Vebo *VeboCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Vebo.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 (_Vebo *VeboTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Vebo.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Vebo *VeboTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Vebo.Contract.contract.Transact(opts, method, params...) +} + +// DATAFORMATLIST is a free data retrieval call binding the contract method 0xe271b774. +// +// Solidity: function DATA_FORMAT_LIST() view returns(uint256) +func (_Vebo *VeboCaller) DATAFORMATLIST(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "DATA_FORMAT_LIST") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// DATAFORMATLIST is a free data retrieval call binding the contract method 0xe271b774. +// +// Solidity: function DATA_FORMAT_LIST() view returns(uint256) +func (_Vebo *VeboSession) DATAFORMATLIST() (*big.Int, error) { + return _Vebo.Contract.DATAFORMATLIST(&_Vebo.CallOpts) +} + +// DATAFORMATLIST is a free data retrieval call binding the contract method 0xe271b774. +// +// Solidity: function DATA_FORMAT_LIST() view returns(uint256) +func (_Vebo *VeboCallerSession) DATAFORMATLIST() (*big.Int, error) { + return _Vebo.Contract.DATAFORMATLIST(&_Vebo.CallOpts) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Vebo *VeboCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Vebo *VeboSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Vebo.Contract.DEFAULTADMINROLE(&_Vebo.CallOpts) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Vebo *VeboCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Vebo.Contract.DEFAULTADMINROLE(&_Vebo.CallOpts) +} + +// GENESISTIME is a free data retrieval call binding the contract method 0xf2882461. +// +// Solidity: function GENESIS_TIME() view returns(uint256) +func (_Vebo *VeboCaller) GENESISTIME(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "GENESIS_TIME") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GENESISTIME is a free data retrieval call binding the contract method 0xf2882461. +// +// Solidity: function GENESIS_TIME() view returns(uint256) +func (_Vebo *VeboSession) GENESISTIME() (*big.Int, error) { + return _Vebo.Contract.GENESISTIME(&_Vebo.CallOpts) +} + +// GENESISTIME is a free data retrieval call binding the contract method 0xf2882461. +// +// Solidity: function GENESIS_TIME() view returns(uint256) +func (_Vebo *VeboCallerSession) GENESISTIME() (*big.Int, error) { + return _Vebo.Contract.GENESISTIME(&_Vebo.CallOpts) +} + +// MANAGECONSENSUSCONTRACTROLE is a free data retrieval call binding the contract method 0xad5cac4e. +// +// Solidity: function MANAGE_CONSENSUS_CONTRACT_ROLE() view returns(bytes32) +func (_Vebo *VeboCaller) MANAGECONSENSUSCONTRACTROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "MANAGE_CONSENSUS_CONTRACT_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// MANAGECONSENSUSCONTRACTROLE is a free data retrieval call binding the contract method 0xad5cac4e. +// +// Solidity: function MANAGE_CONSENSUS_CONTRACT_ROLE() view returns(bytes32) +func (_Vebo *VeboSession) MANAGECONSENSUSCONTRACTROLE() ([32]byte, error) { + return _Vebo.Contract.MANAGECONSENSUSCONTRACTROLE(&_Vebo.CallOpts) +} + +// MANAGECONSENSUSCONTRACTROLE is a free data retrieval call binding the contract method 0xad5cac4e. +// +// Solidity: function MANAGE_CONSENSUS_CONTRACT_ROLE() view returns(bytes32) +func (_Vebo *VeboCallerSession) MANAGECONSENSUSCONTRACTROLE() ([32]byte, error) { + return _Vebo.Contract.MANAGECONSENSUSCONTRACTROLE(&_Vebo.CallOpts) +} + +// MANAGECONSENSUSVERSIONROLE is a free data retrieval call binding the contract method 0x9cc23c79. +// +// Solidity: function MANAGE_CONSENSUS_VERSION_ROLE() view returns(bytes32) +func (_Vebo *VeboCaller) MANAGECONSENSUSVERSIONROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "MANAGE_CONSENSUS_VERSION_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// MANAGECONSENSUSVERSIONROLE is a free data retrieval call binding the contract method 0x9cc23c79. +// +// Solidity: function MANAGE_CONSENSUS_VERSION_ROLE() view returns(bytes32) +func (_Vebo *VeboSession) MANAGECONSENSUSVERSIONROLE() ([32]byte, error) { + return _Vebo.Contract.MANAGECONSENSUSVERSIONROLE(&_Vebo.CallOpts) +} + +// MANAGECONSENSUSVERSIONROLE is a free data retrieval call binding the contract method 0x9cc23c79. +// +// Solidity: function MANAGE_CONSENSUS_VERSION_ROLE() view returns(bytes32) +func (_Vebo *VeboCallerSession) MANAGECONSENSUSVERSIONROLE() ([32]byte, error) { + return _Vebo.Contract.MANAGECONSENSUSVERSIONROLE(&_Vebo.CallOpts) +} + +// PAUSEINFINITELY is a free data retrieval call binding the contract method 0xa302ee38. +// +// Solidity: function PAUSE_INFINITELY() view returns(uint256) +func (_Vebo *VeboCaller) PAUSEINFINITELY(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "PAUSE_INFINITELY") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// PAUSEINFINITELY is a free data retrieval call binding the contract method 0xa302ee38. +// +// Solidity: function PAUSE_INFINITELY() view returns(uint256) +func (_Vebo *VeboSession) PAUSEINFINITELY() (*big.Int, error) { + return _Vebo.Contract.PAUSEINFINITELY(&_Vebo.CallOpts) +} + +// PAUSEINFINITELY is a free data retrieval call binding the contract method 0xa302ee38. +// +// Solidity: function PAUSE_INFINITELY() view returns(uint256) +func (_Vebo *VeboCallerSession) PAUSEINFINITELY() (*big.Int, error) { + return _Vebo.Contract.PAUSEINFINITELY(&_Vebo.CallOpts) +} + +// PAUSEROLE is a free data retrieval call binding the contract method 0x389ed267. +// +// Solidity: function PAUSE_ROLE() view returns(bytes32) +func (_Vebo *VeboCaller) PAUSEROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "PAUSE_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PAUSEROLE is a free data retrieval call binding the contract method 0x389ed267. +// +// Solidity: function PAUSE_ROLE() view returns(bytes32) +func (_Vebo *VeboSession) PAUSEROLE() ([32]byte, error) { + return _Vebo.Contract.PAUSEROLE(&_Vebo.CallOpts) +} + +// PAUSEROLE is a free data retrieval call binding the contract method 0x389ed267. +// +// Solidity: function PAUSE_ROLE() view returns(bytes32) +func (_Vebo *VeboCallerSession) PAUSEROLE() ([32]byte, error) { + return _Vebo.Contract.PAUSEROLE(&_Vebo.CallOpts) +} + +// RESUMEROLE is a free data retrieval call binding the contract method 0x2de03aa1. +// +// Solidity: function RESUME_ROLE() view returns(bytes32) +func (_Vebo *VeboCaller) RESUMEROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "RESUME_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// RESUMEROLE is a free data retrieval call binding the contract method 0x2de03aa1. +// +// Solidity: function RESUME_ROLE() view returns(bytes32) +func (_Vebo *VeboSession) RESUMEROLE() ([32]byte, error) { + return _Vebo.Contract.RESUMEROLE(&_Vebo.CallOpts) +} + +// RESUMEROLE is a free data retrieval call binding the contract method 0x2de03aa1. +// +// Solidity: function RESUME_ROLE() view returns(bytes32) +func (_Vebo *VeboCallerSession) RESUMEROLE() ([32]byte, error) { + return _Vebo.Contract.RESUMEROLE(&_Vebo.CallOpts) +} + +// SECONDSPERSLOT is a free data retrieval call binding the contract method 0x304b9071. +// +// Solidity: function SECONDS_PER_SLOT() view returns(uint256) +func (_Vebo *VeboCaller) SECONDSPERSLOT(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "SECONDS_PER_SLOT") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SECONDSPERSLOT is a free data retrieval call binding the contract method 0x304b9071. +// +// Solidity: function SECONDS_PER_SLOT() view returns(uint256) +func (_Vebo *VeboSession) SECONDSPERSLOT() (*big.Int, error) { + return _Vebo.Contract.SECONDSPERSLOT(&_Vebo.CallOpts) +} + +// SECONDSPERSLOT is a free data retrieval call binding the contract method 0x304b9071. +// +// Solidity: function SECONDS_PER_SLOT() view returns(uint256) +func (_Vebo *VeboCallerSession) SECONDSPERSLOT() (*big.Int, error) { + return _Vebo.Contract.SECONDSPERSLOT(&_Vebo.CallOpts) +} + +// SUBMITDATAROLE is a free data retrieval call binding the contract method 0x46e1f576. +// +// Solidity: function SUBMIT_DATA_ROLE() view returns(bytes32) +func (_Vebo *VeboCaller) SUBMITDATAROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "SUBMIT_DATA_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// SUBMITDATAROLE is a free data retrieval call binding the contract method 0x46e1f576. +// +// Solidity: function SUBMIT_DATA_ROLE() view returns(bytes32) +func (_Vebo *VeboSession) SUBMITDATAROLE() ([32]byte, error) { + return _Vebo.Contract.SUBMITDATAROLE(&_Vebo.CallOpts) +} + +// SUBMITDATAROLE is a free data retrieval call binding the contract method 0x46e1f576. +// +// Solidity: function SUBMIT_DATA_ROLE() view returns(bytes32) +func (_Vebo *VeboCallerSession) SUBMITDATAROLE() ([32]byte, error) { + return _Vebo.Contract.SUBMITDATAROLE(&_Vebo.CallOpts) +} + +// GetConsensusContract is a free data retrieval call binding the contract method 0x8f55b571. +// +// Solidity: function getConsensusContract() view returns(address) +func (_Vebo *VeboCaller) GetConsensusContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getConsensusContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetConsensusContract is a free data retrieval call binding the contract method 0x8f55b571. +// +// Solidity: function getConsensusContract() view returns(address) +func (_Vebo *VeboSession) GetConsensusContract() (common.Address, error) { + return _Vebo.Contract.GetConsensusContract(&_Vebo.CallOpts) +} + +// GetConsensusContract is a free data retrieval call binding the contract method 0x8f55b571. +// +// Solidity: function getConsensusContract() view returns(address) +func (_Vebo *VeboCallerSession) GetConsensusContract() (common.Address, error) { + return _Vebo.Contract.GetConsensusContract(&_Vebo.CallOpts) +} + +// GetConsensusReport is a free data retrieval call binding the contract method 0x60d64d38. +// +// Solidity: function getConsensusReport() view returns(bytes32 hash, uint256 refSlot, uint256 processingDeadlineTime, bool processingStarted) +func (_Vebo *VeboCaller) GetConsensusReport(opts *bind.CallOpts) (struct { + Hash [32]byte + RefSlot *big.Int + ProcessingDeadlineTime *big.Int + ProcessingStarted bool +}, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getConsensusReport") + + outstruct := new(struct { + Hash [32]byte + RefSlot *big.Int + ProcessingDeadlineTime *big.Int + ProcessingStarted bool + }) + if err != nil { + return *outstruct, err + } + + outstruct.Hash = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.RefSlot = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.ProcessingDeadlineTime = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.ProcessingStarted = *abi.ConvertType(out[3], new(bool)).(*bool) + + return *outstruct, err + +} + +// GetConsensusReport is a free data retrieval call binding the contract method 0x60d64d38. +// +// Solidity: function getConsensusReport() view returns(bytes32 hash, uint256 refSlot, uint256 processingDeadlineTime, bool processingStarted) +func (_Vebo *VeboSession) GetConsensusReport() (struct { + Hash [32]byte + RefSlot *big.Int + ProcessingDeadlineTime *big.Int + ProcessingStarted bool +}, error) { + return _Vebo.Contract.GetConsensusReport(&_Vebo.CallOpts) +} + +// GetConsensusReport is a free data retrieval call binding the contract method 0x60d64d38. +// +// Solidity: function getConsensusReport() view returns(bytes32 hash, uint256 refSlot, uint256 processingDeadlineTime, bool processingStarted) +func (_Vebo *VeboCallerSession) GetConsensusReport() (struct { + Hash [32]byte + RefSlot *big.Int + ProcessingDeadlineTime *big.Int + ProcessingStarted bool +}, error) { + return _Vebo.Contract.GetConsensusReport(&_Vebo.CallOpts) +} + +// GetConsensusVersion is a free data retrieval call binding the contract method 0x5be20425. +// +// Solidity: function getConsensusVersion() view returns(uint256) +func (_Vebo *VeboCaller) GetConsensusVersion(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getConsensusVersion") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetConsensusVersion is a free data retrieval call binding the contract method 0x5be20425. +// +// Solidity: function getConsensusVersion() view returns(uint256) +func (_Vebo *VeboSession) GetConsensusVersion() (*big.Int, error) { + return _Vebo.Contract.GetConsensusVersion(&_Vebo.CallOpts) +} + +// GetConsensusVersion is a free data retrieval call binding the contract method 0x5be20425. +// +// Solidity: function getConsensusVersion() view returns(uint256) +func (_Vebo *VeboCallerSession) GetConsensusVersion() (*big.Int, error) { + return _Vebo.Contract.GetConsensusVersion(&_Vebo.CallOpts) +} + +// GetContractVersion is a free data retrieval call binding the contract method 0x8aa10435. +// +// Solidity: function getContractVersion() view returns(uint256) +func (_Vebo *VeboCaller) GetContractVersion(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getContractVersion") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetContractVersion is a free data retrieval call binding the contract method 0x8aa10435. +// +// Solidity: function getContractVersion() view returns(uint256) +func (_Vebo *VeboSession) GetContractVersion() (*big.Int, error) { + return _Vebo.Contract.GetContractVersion(&_Vebo.CallOpts) +} + +// GetContractVersion is a free data retrieval call binding the contract method 0x8aa10435. +// +// Solidity: function getContractVersion() view returns(uint256) +func (_Vebo *VeboCallerSession) GetContractVersion() (*big.Int, error) { + return _Vebo.Contract.GetContractVersion(&_Vebo.CallOpts) +} + +// GetLastProcessingRefSlot is a free data retrieval call binding the contract method 0x3584d59c. +// +// Solidity: function getLastProcessingRefSlot() view returns(uint256) +func (_Vebo *VeboCaller) GetLastProcessingRefSlot(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getLastProcessingRefSlot") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetLastProcessingRefSlot is a free data retrieval call binding the contract method 0x3584d59c. +// +// Solidity: function getLastProcessingRefSlot() view returns(uint256) +func (_Vebo *VeboSession) GetLastProcessingRefSlot() (*big.Int, error) { + return _Vebo.Contract.GetLastProcessingRefSlot(&_Vebo.CallOpts) +} + +// GetLastProcessingRefSlot is a free data retrieval call binding the contract method 0x3584d59c. +// +// Solidity: function getLastProcessingRefSlot() view returns(uint256) +func (_Vebo *VeboCallerSession) GetLastProcessingRefSlot() (*big.Int, error) { + return _Vebo.Contract.GetLastProcessingRefSlot(&_Vebo.CallOpts) +} + +// GetLastRequestedValidatorIndices is a free data retrieval call binding the contract method 0xef9bf37e. +// +// Solidity: function getLastRequestedValidatorIndices(uint256 moduleId, uint256[] nodeOpIds) view returns(int256[]) +func (_Vebo *VeboCaller) GetLastRequestedValidatorIndices(opts *bind.CallOpts, moduleId *big.Int, nodeOpIds []*big.Int) ([]*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getLastRequestedValidatorIndices", moduleId, nodeOpIds) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// GetLastRequestedValidatorIndices is a free data retrieval call binding the contract method 0xef9bf37e. +// +// Solidity: function getLastRequestedValidatorIndices(uint256 moduleId, uint256[] nodeOpIds) view returns(int256[]) +func (_Vebo *VeboSession) GetLastRequestedValidatorIndices(moduleId *big.Int, nodeOpIds []*big.Int) ([]*big.Int, error) { + return _Vebo.Contract.GetLastRequestedValidatorIndices(&_Vebo.CallOpts, moduleId, nodeOpIds) +} + +// GetLastRequestedValidatorIndices is a free data retrieval call binding the contract method 0xef9bf37e. +// +// Solidity: function getLastRequestedValidatorIndices(uint256 moduleId, uint256[] nodeOpIds) view returns(int256[]) +func (_Vebo *VeboCallerSession) GetLastRequestedValidatorIndices(moduleId *big.Int, nodeOpIds []*big.Int) ([]*big.Int, error) { + return _Vebo.Contract.GetLastRequestedValidatorIndices(&_Vebo.CallOpts, moduleId, nodeOpIds) +} + +// GetProcessingState is a free data retrieval call binding the contract method 0x8f7797c2. +// +// Solidity: function getProcessingState() view returns((uint256,uint256,bytes32,bool,uint256,uint256,uint256) result) +func (_Vebo *VeboCaller) GetProcessingState(opts *bind.CallOpts) (ValidatorsExitBusOracleProcessingState, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getProcessingState") + + if err != nil { + return *new(ValidatorsExitBusOracleProcessingState), err + } + + out0 := *abi.ConvertType(out[0], new(ValidatorsExitBusOracleProcessingState)).(*ValidatorsExitBusOracleProcessingState) + + return out0, err + +} + +// GetProcessingState is a free data retrieval call binding the contract method 0x8f7797c2. +// +// Solidity: function getProcessingState() view returns((uint256,uint256,bytes32,bool,uint256,uint256,uint256) result) +func (_Vebo *VeboSession) GetProcessingState() (ValidatorsExitBusOracleProcessingState, error) { + return _Vebo.Contract.GetProcessingState(&_Vebo.CallOpts) +} + +// GetProcessingState is a free data retrieval call binding the contract method 0x8f7797c2. +// +// Solidity: function getProcessingState() view returns((uint256,uint256,bytes32,bool,uint256,uint256,uint256) result) +func (_Vebo *VeboCallerSession) GetProcessingState() (ValidatorsExitBusOracleProcessingState, error) { + return _Vebo.Contract.GetProcessingState(&_Vebo.CallOpts) +} + +// GetResumeSinceTimestamp is a free data retrieval call binding the contract method 0x589ff76c. +// +// Solidity: function getResumeSinceTimestamp() view returns(uint256) +func (_Vebo *VeboCaller) GetResumeSinceTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getResumeSinceTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetResumeSinceTimestamp is a free data retrieval call binding the contract method 0x589ff76c. +// +// Solidity: function getResumeSinceTimestamp() view returns(uint256) +func (_Vebo *VeboSession) GetResumeSinceTimestamp() (*big.Int, error) { + return _Vebo.Contract.GetResumeSinceTimestamp(&_Vebo.CallOpts) +} + +// GetResumeSinceTimestamp is a free data retrieval call binding the contract method 0x589ff76c. +// +// Solidity: function getResumeSinceTimestamp() view returns(uint256) +func (_Vebo *VeboCallerSession) GetResumeSinceTimestamp() (*big.Int, error) { + return _Vebo.Contract.GetResumeSinceTimestamp(&_Vebo.CallOpts) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Vebo *VeboCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Vebo *VeboSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Vebo.Contract.GetRoleAdmin(&_Vebo.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Vebo *VeboCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Vebo.Contract.GetRoleAdmin(&_Vebo.CallOpts, role) +} + +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Vebo *VeboCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getRoleMember", role, index) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Vebo *VeboSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _Vebo.Contract.GetRoleMember(&_Vebo.CallOpts, role, index) +} + +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Vebo *VeboCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _Vebo.Contract.GetRoleMember(&_Vebo.CallOpts, role, index) +} + +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Vebo *VeboCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getRoleMemberCount", role) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Vebo *VeboSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _Vebo.Contract.GetRoleMemberCount(&_Vebo.CallOpts, role) +} + +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Vebo *VeboCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _Vebo.Contract.GetRoleMemberCount(&_Vebo.CallOpts, role) +} + +// GetTotalRequestsProcessed is a free data retrieval call binding the contract method 0xe2793e72. +// +// Solidity: function getTotalRequestsProcessed() view returns(uint256) +func (_Vebo *VeboCaller) GetTotalRequestsProcessed(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "getTotalRequestsProcessed") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetTotalRequestsProcessed is a free data retrieval call binding the contract method 0xe2793e72. +// +// Solidity: function getTotalRequestsProcessed() view returns(uint256) +func (_Vebo *VeboSession) GetTotalRequestsProcessed() (*big.Int, error) { + return _Vebo.Contract.GetTotalRequestsProcessed(&_Vebo.CallOpts) +} + +// GetTotalRequestsProcessed is a free data retrieval call binding the contract method 0xe2793e72. +// +// Solidity: function getTotalRequestsProcessed() view returns(uint256) +func (_Vebo *VeboCallerSession) GetTotalRequestsProcessed() (*big.Int, error) { + return _Vebo.Contract.GetTotalRequestsProcessed(&_Vebo.CallOpts) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Vebo *VeboCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Vebo *VeboSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Vebo.Contract.HasRole(&_Vebo.CallOpts, role, account) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Vebo *VeboCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Vebo.Contract.HasRole(&_Vebo.CallOpts, role, account) +} + +// IsPaused is a free data retrieval call binding the contract method 0xb187bd26. +// +// Solidity: function isPaused() view returns(bool) +func (_Vebo *VeboCaller) IsPaused(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "isPaused") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsPaused is a free data retrieval call binding the contract method 0xb187bd26. +// +// Solidity: function isPaused() view returns(bool) +func (_Vebo *VeboSession) IsPaused() (bool, error) { + return _Vebo.Contract.IsPaused(&_Vebo.CallOpts) +} + +// IsPaused is a free data retrieval call binding the contract method 0xb187bd26. +// +// Solidity: function isPaused() view returns(bool) +func (_Vebo *VeboCallerSession) IsPaused() (bool, error) { + return _Vebo.Contract.IsPaused(&_Vebo.CallOpts) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Vebo *VeboCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Vebo.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Vebo *VeboSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Vebo.Contract.SupportsInterface(&_Vebo.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Vebo *VeboCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Vebo.Contract.SupportsInterface(&_Vebo.CallOpts, interfaceId) +} + +// DiscardConsensusReport is a paid mutator transaction binding the contract method 0xd4381217. +// +// Solidity: function discardConsensusReport(uint256 refSlot) returns() +func (_Vebo *VeboTransactor) DiscardConsensusReport(opts *bind.TransactOpts, refSlot *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "discardConsensusReport", refSlot) +} + +// DiscardConsensusReport is a paid mutator transaction binding the contract method 0xd4381217. +// +// Solidity: function discardConsensusReport(uint256 refSlot) returns() +func (_Vebo *VeboSession) DiscardConsensusReport(refSlot *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.DiscardConsensusReport(&_Vebo.TransactOpts, refSlot) +} + +// DiscardConsensusReport is a paid mutator transaction binding the contract method 0xd4381217. +// +// Solidity: function discardConsensusReport(uint256 refSlot) returns() +func (_Vebo *VeboTransactorSession) DiscardConsensusReport(refSlot *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.DiscardConsensusReport(&_Vebo.TransactOpts, refSlot) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Vebo *VeboTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "grantRole", role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Vebo *VeboSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.Contract.GrantRole(&_Vebo.TransactOpts, role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Vebo *VeboTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.Contract.GrantRole(&_Vebo.TransactOpts, role, account) +} + +// Initialize is a paid mutator transaction binding the contract method 0xeb990c59. +// +// Solidity: function initialize(address admin, address consensusContract, uint256 consensusVersion, uint256 lastProcessingRefSlot) returns() +func (_Vebo *VeboTransactor) Initialize(opts *bind.TransactOpts, admin common.Address, consensusContract common.Address, consensusVersion *big.Int, lastProcessingRefSlot *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "initialize", admin, consensusContract, consensusVersion, lastProcessingRefSlot) +} + +// Initialize is a paid mutator transaction binding the contract method 0xeb990c59. +// +// Solidity: function initialize(address admin, address consensusContract, uint256 consensusVersion, uint256 lastProcessingRefSlot) returns() +func (_Vebo *VeboSession) Initialize(admin common.Address, consensusContract common.Address, consensusVersion *big.Int, lastProcessingRefSlot *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.Initialize(&_Vebo.TransactOpts, admin, consensusContract, consensusVersion, lastProcessingRefSlot) +} + +// Initialize is a paid mutator transaction binding the contract method 0xeb990c59. +// +// Solidity: function initialize(address admin, address consensusContract, uint256 consensusVersion, uint256 lastProcessingRefSlot) returns() +func (_Vebo *VeboTransactorSession) Initialize(admin common.Address, consensusContract common.Address, consensusVersion *big.Int, lastProcessingRefSlot *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.Initialize(&_Vebo.TransactOpts, admin, consensusContract, consensusVersion, lastProcessingRefSlot) +} + +// PauseFor is a paid mutator transaction binding the contract method 0xf3f449c7. +// +// Solidity: function pauseFor(uint256 _duration) returns() +func (_Vebo *VeboTransactor) PauseFor(opts *bind.TransactOpts, _duration *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "pauseFor", _duration) +} + +// PauseFor is a paid mutator transaction binding the contract method 0xf3f449c7. +// +// Solidity: function pauseFor(uint256 _duration) returns() +func (_Vebo *VeboSession) PauseFor(_duration *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.PauseFor(&_Vebo.TransactOpts, _duration) +} + +// PauseFor is a paid mutator transaction binding the contract method 0xf3f449c7. +// +// Solidity: function pauseFor(uint256 _duration) returns() +func (_Vebo *VeboTransactorSession) PauseFor(_duration *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.PauseFor(&_Vebo.TransactOpts, _duration) +} + +// PauseUntil is a paid mutator transaction binding the contract method 0xabe9cfc8. +// +// Solidity: function pauseUntil(uint256 _pauseUntilInclusive) returns() +func (_Vebo *VeboTransactor) PauseUntil(opts *bind.TransactOpts, _pauseUntilInclusive *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "pauseUntil", _pauseUntilInclusive) +} + +// PauseUntil is a paid mutator transaction binding the contract method 0xabe9cfc8. +// +// Solidity: function pauseUntil(uint256 _pauseUntilInclusive) returns() +func (_Vebo *VeboSession) PauseUntil(_pauseUntilInclusive *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.PauseUntil(&_Vebo.TransactOpts, _pauseUntilInclusive) +} + +// PauseUntil is a paid mutator transaction binding the contract method 0xabe9cfc8. +// +// Solidity: function pauseUntil(uint256 _pauseUntilInclusive) returns() +func (_Vebo *VeboTransactorSession) PauseUntil(_pauseUntilInclusive *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.PauseUntil(&_Vebo.TransactOpts, _pauseUntilInclusive) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_Vebo *VeboTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "renounceRole", role, account) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_Vebo *VeboSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.Contract.RenounceRole(&_Vebo.TransactOpts, role, account) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_Vebo *VeboTransactorSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.Contract.RenounceRole(&_Vebo.TransactOpts, role, account) +} + +// Resume is a paid mutator transaction binding the contract method 0x046f7da2. +// +// Solidity: function resume() returns() +func (_Vebo *VeboTransactor) Resume(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "resume") +} + +// Resume is a paid mutator transaction binding the contract method 0x046f7da2. +// +// Solidity: function resume() returns() +func (_Vebo *VeboSession) Resume() (*types.Transaction, error) { + return _Vebo.Contract.Resume(&_Vebo.TransactOpts) +} + +// Resume is a paid mutator transaction binding the contract method 0x046f7da2. +// +// Solidity: function resume() returns() +func (_Vebo *VeboTransactorSession) Resume() (*types.Transaction, error) { + return _Vebo.Contract.Resume(&_Vebo.TransactOpts) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Vebo *VeboTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Vebo *VeboSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.Contract.RevokeRole(&_Vebo.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Vebo *VeboTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Vebo.Contract.RevokeRole(&_Vebo.TransactOpts, role, account) +} + +// SetConsensusContract is a paid mutator transaction binding the contract method 0xc469c307. +// +// Solidity: function setConsensusContract(address addr) returns() +func (_Vebo *VeboTransactor) SetConsensusContract(opts *bind.TransactOpts, addr common.Address) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "setConsensusContract", addr) +} + +// SetConsensusContract is a paid mutator transaction binding the contract method 0xc469c307. +// +// Solidity: function setConsensusContract(address addr) returns() +func (_Vebo *VeboSession) SetConsensusContract(addr common.Address) (*types.Transaction, error) { + return _Vebo.Contract.SetConsensusContract(&_Vebo.TransactOpts, addr) +} + +// SetConsensusContract is a paid mutator transaction binding the contract method 0xc469c307. +// +// Solidity: function setConsensusContract(address addr) returns() +func (_Vebo *VeboTransactorSession) SetConsensusContract(addr common.Address) (*types.Transaction, error) { + return _Vebo.Contract.SetConsensusContract(&_Vebo.TransactOpts, addr) +} + +// SetConsensusVersion is a paid mutator transaction binding the contract method 0x8d591474. +// +// Solidity: function setConsensusVersion(uint256 version) returns() +func (_Vebo *VeboTransactor) SetConsensusVersion(opts *bind.TransactOpts, version *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "setConsensusVersion", version) +} + +// SetConsensusVersion is a paid mutator transaction binding the contract method 0x8d591474. +// +// Solidity: function setConsensusVersion(uint256 version) returns() +func (_Vebo *VeboSession) SetConsensusVersion(version *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.SetConsensusVersion(&_Vebo.TransactOpts, version) +} + +// SetConsensusVersion is a paid mutator transaction binding the contract method 0x8d591474. +// +// Solidity: function setConsensusVersion(uint256 version) returns() +func (_Vebo *VeboTransactorSession) SetConsensusVersion(version *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.SetConsensusVersion(&_Vebo.TransactOpts, version) +} + +// SubmitConsensusReport is a paid mutator transaction binding the contract method 0x063f36ad. +// +// Solidity: function submitConsensusReport(bytes32 reportHash, uint256 refSlot, uint256 deadline) returns() +func (_Vebo *VeboTransactor) SubmitConsensusReport(opts *bind.TransactOpts, reportHash [32]byte, refSlot *big.Int, deadline *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "submitConsensusReport", reportHash, refSlot, deadline) +} + +// SubmitConsensusReport is a paid mutator transaction binding the contract method 0x063f36ad. +// +// Solidity: function submitConsensusReport(bytes32 reportHash, uint256 refSlot, uint256 deadline) returns() +func (_Vebo *VeboSession) SubmitConsensusReport(reportHash [32]byte, refSlot *big.Int, deadline *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.SubmitConsensusReport(&_Vebo.TransactOpts, reportHash, refSlot, deadline) +} + +// SubmitConsensusReport is a paid mutator transaction binding the contract method 0x063f36ad. +// +// Solidity: function submitConsensusReport(bytes32 reportHash, uint256 refSlot, uint256 deadline) returns() +func (_Vebo *VeboTransactorSession) SubmitConsensusReport(reportHash [32]byte, refSlot *big.Int, deadline *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.SubmitConsensusReport(&_Vebo.TransactOpts, reportHash, refSlot, deadline) +} + +// SubmitReportData is a paid mutator transaction binding the contract method 0x294492c8. +// +// Solidity: function submitReportData((uint256,uint256,uint256,uint256,bytes) data, uint256 contractVersion) returns() +func (_Vebo *VeboTransactor) SubmitReportData(opts *bind.TransactOpts, data ValidatorsExitBusOracleReportData, contractVersion *big.Int) (*types.Transaction, error) { + return _Vebo.contract.Transact(opts, "submitReportData", data, contractVersion) +} + +// SubmitReportData is a paid mutator transaction binding the contract method 0x294492c8. +// +// Solidity: function submitReportData((uint256,uint256,uint256,uint256,bytes) data, uint256 contractVersion) returns() +func (_Vebo *VeboSession) SubmitReportData(data ValidatorsExitBusOracleReportData, contractVersion *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.SubmitReportData(&_Vebo.TransactOpts, data, contractVersion) +} + +// SubmitReportData is a paid mutator transaction binding the contract method 0x294492c8. +// +// Solidity: function submitReportData((uint256,uint256,uint256,uint256,bytes) data, uint256 contractVersion) returns() +func (_Vebo *VeboTransactorSession) SubmitReportData(data ValidatorsExitBusOracleReportData, contractVersion *big.Int) (*types.Transaction, error) { + return _Vebo.Contract.SubmitReportData(&_Vebo.TransactOpts, data, contractVersion) +} + +// VeboConsensusHashContractSetIterator is returned from FilterConsensusHashContractSet and is used to iterate over the raw logs and unpacked data for ConsensusHashContractSet events raised by the Vebo contract. +type VeboConsensusHashContractSetIterator struct { + Event *VeboConsensusHashContractSet // 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 *VeboConsensusHashContractSetIterator) 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(VeboConsensusHashContractSet) + 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(VeboConsensusHashContractSet) + 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 *VeboConsensusHashContractSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboConsensusHashContractSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboConsensusHashContractSet represents a ConsensusHashContractSet event raised by the Vebo contract. +type VeboConsensusHashContractSet struct { + Addr common.Address + PrevAddr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterConsensusHashContractSet is a free log retrieval operation binding the contract event 0x25421480fb7f52d18947876279a213696b58d7e0e5416ce5e2c9f9942661c34c. +// +// Solidity: event ConsensusHashContractSet(address indexed addr, address indexed prevAddr) +func (_Vebo *VeboFilterer) FilterConsensusHashContractSet(opts *bind.FilterOpts, addr []common.Address, prevAddr []common.Address) (*VeboConsensusHashContractSetIterator, error) { + + var addrRule []interface{} + for _, addrItem := range addr { + addrRule = append(addrRule, addrItem) + } + var prevAddrRule []interface{} + for _, prevAddrItem := range prevAddr { + prevAddrRule = append(prevAddrRule, prevAddrItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ConsensusHashContractSet", addrRule, prevAddrRule) + if err != nil { + return nil, err + } + return &VeboConsensusHashContractSetIterator{contract: _Vebo.contract, event: "ConsensusHashContractSet", logs: logs, sub: sub}, nil +} + +// WatchConsensusHashContractSet is a free log subscription operation binding the contract event 0x25421480fb7f52d18947876279a213696b58d7e0e5416ce5e2c9f9942661c34c. +// +// Solidity: event ConsensusHashContractSet(address indexed addr, address indexed prevAddr) +func (_Vebo *VeboFilterer) WatchConsensusHashContractSet(opts *bind.WatchOpts, sink chan<- *VeboConsensusHashContractSet, addr []common.Address, prevAddr []common.Address) (event.Subscription, error) { + + var addrRule []interface{} + for _, addrItem := range addr { + addrRule = append(addrRule, addrItem) + } + var prevAddrRule []interface{} + for _, prevAddrItem := range prevAddr { + prevAddrRule = append(prevAddrRule, prevAddrItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ConsensusHashContractSet", addrRule, prevAddrRule) + 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(VeboConsensusHashContractSet) + if err := _Vebo.contract.UnpackLog(event, "ConsensusHashContractSet", 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 +} + +// ParseConsensusHashContractSet is a log parse operation binding the contract event 0x25421480fb7f52d18947876279a213696b58d7e0e5416ce5e2c9f9942661c34c. +// +// Solidity: event ConsensusHashContractSet(address indexed addr, address indexed prevAddr) +func (_Vebo *VeboFilterer) ParseConsensusHashContractSet(log types.Log) (*VeboConsensusHashContractSet, error) { + event := new(VeboConsensusHashContractSet) + if err := _Vebo.contract.UnpackLog(event, "ConsensusHashContractSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboConsensusVersionSetIterator is returned from FilterConsensusVersionSet and is used to iterate over the raw logs and unpacked data for ConsensusVersionSet events raised by the Vebo contract. +type VeboConsensusVersionSetIterator struct { + Event *VeboConsensusVersionSet // 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 *VeboConsensusVersionSetIterator) 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(VeboConsensusVersionSet) + 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(VeboConsensusVersionSet) + 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 *VeboConsensusVersionSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboConsensusVersionSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboConsensusVersionSet represents a ConsensusVersionSet event raised by the Vebo contract. +type VeboConsensusVersionSet struct { + Version *big.Int + PrevVersion *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterConsensusVersionSet is a free log retrieval operation binding the contract event 0xfa5304972d4ec3e3207f0bbf91155a49d0dfa62488f9529403a2a49e4b29a895. +// +// Solidity: event ConsensusVersionSet(uint256 indexed version, uint256 indexed prevVersion) +func (_Vebo *VeboFilterer) FilterConsensusVersionSet(opts *bind.FilterOpts, version []*big.Int, prevVersion []*big.Int) (*VeboConsensusVersionSetIterator, error) { + + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + var prevVersionRule []interface{} + for _, prevVersionItem := range prevVersion { + prevVersionRule = append(prevVersionRule, prevVersionItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ConsensusVersionSet", versionRule, prevVersionRule) + if err != nil { + return nil, err + } + return &VeboConsensusVersionSetIterator{contract: _Vebo.contract, event: "ConsensusVersionSet", logs: logs, sub: sub}, nil +} + +// WatchConsensusVersionSet is a free log subscription operation binding the contract event 0xfa5304972d4ec3e3207f0bbf91155a49d0dfa62488f9529403a2a49e4b29a895. +// +// Solidity: event ConsensusVersionSet(uint256 indexed version, uint256 indexed prevVersion) +func (_Vebo *VeboFilterer) WatchConsensusVersionSet(opts *bind.WatchOpts, sink chan<- *VeboConsensusVersionSet, version []*big.Int, prevVersion []*big.Int) (event.Subscription, error) { + + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + var prevVersionRule []interface{} + for _, prevVersionItem := range prevVersion { + prevVersionRule = append(prevVersionRule, prevVersionItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ConsensusVersionSet", versionRule, prevVersionRule) + 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(VeboConsensusVersionSet) + if err := _Vebo.contract.UnpackLog(event, "ConsensusVersionSet", 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 +} + +// ParseConsensusVersionSet is a log parse operation binding the contract event 0xfa5304972d4ec3e3207f0bbf91155a49d0dfa62488f9529403a2a49e4b29a895. +// +// Solidity: event ConsensusVersionSet(uint256 indexed version, uint256 indexed prevVersion) +func (_Vebo *VeboFilterer) ParseConsensusVersionSet(log types.Log) (*VeboConsensusVersionSet, error) { + event := new(VeboConsensusVersionSet) + if err := _Vebo.contract.UnpackLog(event, "ConsensusVersionSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboContractVersionSetIterator is returned from FilterContractVersionSet and is used to iterate over the raw logs and unpacked data for ContractVersionSet events raised by the Vebo contract. +type VeboContractVersionSetIterator struct { + Event *VeboContractVersionSet // 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 *VeboContractVersionSetIterator) 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(VeboContractVersionSet) + 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(VeboContractVersionSet) + 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 *VeboContractVersionSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboContractVersionSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboContractVersionSet represents a ContractVersionSet event raised by the Vebo contract. +type VeboContractVersionSet struct { + Version *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterContractVersionSet is a free log retrieval operation binding the contract event 0xfddcded6b4f4730c226821172046b48372d3cd963c159701ae1b7c3bcac541bb. +// +// Solidity: event ContractVersionSet(uint256 version) +func (_Vebo *VeboFilterer) FilterContractVersionSet(opts *bind.FilterOpts) (*VeboContractVersionSetIterator, error) { + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ContractVersionSet") + if err != nil { + return nil, err + } + return &VeboContractVersionSetIterator{contract: _Vebo.contract, event: "ContractVersionSet", logs: logs, sub: sub}, nil +} + +// WatchContractVersionSet is a free log subscription operation binding the contract event 0xfddcded6b4f4730c226821172046b48372d3cd963c159701ae1b7c3bcac541bb. +// +// Solidity: event ContractVersionSet(uint256 version) +func (_Vebo *VeboFilterer) WatchContractVersionSet(opts *bind.WatchOpts, sink chan<- *VeboContractVersionSet) (event.Subscription, error) { + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ContractVersionSet") + 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(VeboContractVersionSet) + if err := _Vebo.contract.UnpackLog(event, "ContractVersionSet", 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 +} + +// ParseContractVersionSet is a log parse operation binding the contract event 0xfddcded6b4f4730c226821172046b48372d3cd963c159701ae1b7c3bcac541bb. +// +// Solidity: event ContractVersionSet(uint256 version) +func (_Vebo *VeboFilterer) ParseContractVersionSet(log types.Log) (*VeboContractVersionSet, error) { + event := new(VeboContractVersionSet) + if err := _Vebo.contract.UnpackLog(event, "ContractVersionSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboPausedIterator is returned from FilterPaused and is used to iterate over the raw logs and unpacked data for Paused events raised by the Vebo contract. +type VeboPausedIterator struct { + Event *VeboPaused // 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 *VeboPausedIterator) 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(VeboPaused) + 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(VeboPaused) + 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 *VeboPausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboPausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboPaused represents a Paused event raised by the Vebo contract. +type VeboPaused struct { + Duration *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterPaused is a free log retrieval operation binding the contract event 0x32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e. +// +// Solidity: event Paused(uint256 duration) +func (_Vebo *VeboFilterer) FilterPaused(opts *bind.FilterOpts) (*VeboPausedIterator, error) { + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "Paused") + if err != nil { + return nil, err + } + return &VeboPausedIterator{contract: _Vebo.contract, event: "Paused", logs: logs, sub: sub}, nil +} + +// WatchPaused is a free log subscription operation binding the contract event 0x32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e. +// +// Solidity: event Paused(uint256 duration) +func (_Vebo *VeboFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *VeboPaused) (event.Subscription, error) { + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "Paused") + 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(VeboPaused) + if err := _Vebo.contract.UnpackLog(event, "Paused", 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 +} + +// ParsePaused is a log parse operation binding the contract event 0x32fb7c9891bc4f963c7de9f1186d2a7755c7d6e9f4604dabe1d8bb3027c2f49e. +// +// Solidity: event Paused(uint256 duration) +func (_Vebo *VeboFilterer) ParsePaused(log types.Log) (*VeboPaused, error) { + event := new(VeboPaused) + if err := _Vebo.contract.UnpackLog(event, "Paused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboProcessingStartedIterator is returned from FilterProcessingStarted and is used to iterate over the raw logs and unpacked data for ProcessingStarted events raised by the Vebo contract. +type VeboProcessingStartedIterator struct { + Event *VeboProcessingStarted // 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 *VeboProcessingStartedIterator) 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(VeboProcessingStarted) + 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(VeboProcessingStarted) + 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 *VeboProcessingStartedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboProcessingStartedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboProcessingStarted represents a ProcessingStarted event raised by the Vebo contract. +type VeboProcessingStarted struct { + RefSlot *big.Int + Hash [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterProcessingStarted is a free log retrieval operation binding the contract event 0xf73febded7d4502284718948a3e1d75406151c6326bde069424a584a4f6af87a. +// +// Solidity: event ProcessingStarted(uint256 indexed refSlot, bytes32 hash) +func (_Vebo *VeboFilterer) FilterProcessingStarted(opts *bind.FilterOpts, refSlot []*big.Int) (*VeboProcessingStartedIterator, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ProcessingStarted", refSlotRule) + if err != nil { + return nil, err + } + return &VeboProcessingStartedIterator{contract: _Vebo.contract, event: "ProcessingStarted", logs: logs, sub: sub}, nil +} + +// WatchProcessingStarted is a free log subscription operation binding the contract event 0xf73febded7d4502284718948a3e1d75406151c6326bde069424a584a4f6af87a. +// +// Solidity: event ProcessingStarted(uint256 indexed refSlot, bytes32 hash) +func (_Vebo *VeboFilterer) WatchProcessingStarted(opts *bind.WatchOpts, sink chan<- *VeboProcessingStarted, refSlot []*big.Int) (event.Subscription, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ProcessingStarted", refSlotRule) + 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(VeboProcessingStarted) + if err := _Vebo.contract.UnpackLog(event, "ProcessingStarted", 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 +} + +// ParseProcessingStarted is a log parse operation binding the contract event 0xf73febded7d4502284718948a3e1d75406151c6326bde069424a584a4f6af87a. +// +// Solidity: event ProcessingStarted(uint256 indexed refSlot, bytes32 hash) +func (_Vebo *VeboFilterer) ParseProcessingStarted(log types.Log) (*VeboProcessingStarted, error) { + event := new(VeboProcessingStarted) + if err := _Vebo.contract.UnpackLog(event, "ProcessingStarted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboReportDiscardedIterator is returned from FilterReportDiscarded and is used to iterate over the raw logs and unpacked data for ReportDiscarded events raised by the Vebo contract. +type VeboReportDiscardedIterator struct { + Event *VeboReportDiscarded // 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 *VeboReportDiscardedIterator) 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(VeboReportDiscarded) + 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(VeboReportDiscarded) + 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 *VeboReportDiscardedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboReportDiscardedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboReportDiscarded represents a ReportDiscarded event raised by the Vebo contract. +type VeboReportDiscarded struct { + RefSlot *big.Int + Hash [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterReportDiscarded is a free log retrieval operation binding the contract event 0xe21266bc27ee721ac10034efaf7fd724656ef471c75b8402cd8f07850af6b676. +// +// Solidity: event ReportDiscarded(uint256 indexed refSlot, bytes32 hash) +func (_Vebo *VeboFilterer) FilterReportDiscarded(opts *bind.FilterOpts, refSlot []*big.Int) (*VeboReportDiscardedIterator, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ReportDiscarded", refSlotRule) + if err != nil { + return nil, err + } + return &VeboReportDiscardedIterator{contract: _Vebo.contract, event: "ReportDiscarded", logs: logs, sub: sub}, nil +} + +// WatchReportDiscarded is a free log subscription operation binding the contract event 0xe21266bc27ee721ac10034efaf7fd724656ef471c75b8402cd8f07850af6b676. +// +// Solidity: event ReportDiscarded(uint256 indexed refSlot, bytes32 hash) +func (_Vebo *VeboFilterer) WatchReportDiscarded(opts *bind.WatchOpts, sink chan<- *VeboReportDiscarded, refSlot []*big.Int) (event.Subscription, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ReportDiscarded", refSlotRule) + 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(VeboReportDiscarded) + if err := _Vebo.contract.UnpackLog(event, "ReportDiscarded", 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 +} + +// ParseReportDiscarded is a log parse operation binding the contract event 0xe21266bc27ee721ac10034efaf7fd724656ef471c75b8402cd8f07850af6b676. +// +// Solidity: event ReportDiscarded(uint256 indexed refSlot, bytes32 hash) +func (_Vebo *VeboFilterer) ParseReportDiscarded(log types.Log) (*VeboReportDiscarded, error) { + event := new(VeboReportDiscarded) + if err := _Vebo.contract.UnpackLog(event, "ReportDiscarded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboReportSubmittedIterator is returned from FilterReportSubmitted and is used to iterate over the raw logs and unpacked data for ReportSubmitted events raised by the Vebo contract. +type VeboReportSubmittedIterator struct { + Event *VeboReportSubmitted // 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 *VeboReportSubmittedIterator) 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(VeboReportSubmitted) + 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(VeboReportSubmitted) + 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 *VeboReportSubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboReportSubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboReportSubmitted represents a ReportSubmitted event raised by the Vebo contract. +type VeboReportSubmitted struct { + RefSlot *big.Int + Hash [32]byte + ProcessingDeadlineTime *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterReportSubmitted is a free log retrieval operation binding the contract event 0xaed7d1a7a1831158dcda1e4214f5862f450bd3eb5721a5f322bf8c9fe1790b0a. +// +// Solidity: event ReportSubmitted(uint256 indexed refSlot, bytes32 hash, uint256 processingDeadlineTime) +func (_Vebo *VeboFilterer) FilterReportSubmitted(opts *bind.FilterOpts, refSlot []*big.Int) (*VeboReportSubmittedIterator, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ReportSubmitted", refSlotRule) + if err != nil { + return nil, err + } + return &VeboReportSubmittedIterator{contract: _Vebo.contract, event: "ReportSubmitted", logs: logs, sub: sub}, nil +} + +// WatchReportSubmitted is a free log subscription operation binding the contract event 0xaed7d1a7a1831158dcda1e4214f5862f450bd3eb5721a5f322bf8c9fe1790b0a. +// +// Solidity: event ReportSubmitted(uint256 indexed refSlot, bytes32 hash, uint256 processingDeadlineTime) +func (_Vebo *VeboFilterer) WatchReportSubmitted(opts *bind.WatchOpts, sink chan<- *VeboReportSubmitted, refSlot []*big.Int) (event.Subscription, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ReportSubmitted", refSlotRule) + 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(VeboReportSubmitted) + if err := _Vebo.contract.UnpackLog(event, "ReportSubmitted", 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 +} + +// ParseReportSubmitted is a log parse operation binding the contract event 0xaed7d1a7a1831158dcda1e4214f5862f450bd3eb5721a5f322bf8c9fe1790b0a. +// +// Solidity: event ReportSubmitted(uint256 indexed refSlot, bytes32 hash, uint256 processingDeadlineTime) +func (_Vebo *VeboFilterer) ParseReportSubmitted(log types.Log) (*VeboReportSubmitted, error) { + event := new(VeboReportSubmitted) + if err := _Vebo.contract.UnpackLog(event, "ReportSubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboResumedIterator is returned from FilterResumed and is used to iterate over the raw logs and unpacked data for Resumed events raised by the Vebo contract. +type VeboResumedIterator struct { + Event *VeboResumed // 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 *VeboResumedIterator) 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(VeboResumed) + 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(VeboResumed) + 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 *VeboResumedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboResumedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboResumed represents a Resumed event raised by the Vebo contract. +type VeboResumed struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterResumed is a free log retrieval operation binding the contract event 0x62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f9. +// +// Solidity: event Resumed() +func (_Vebo *VeboFilterer) FilterResumed(opts *bind.FilterOpts) (*VeboResumedIterator, error) { + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "Resumed") + if err != nil { + return nil, err + } + return &VeboResumedIterator{contract: _Vebo.contract, event: "Resumed", logs: logs, sub: sub}, nil +} + +// WatchResumed is a free log subscription operation binding the contract event 0x62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f9. +// +// Solidity: event Resumed() +func (_Vebo *VeboFilterer) WatchResumed(opts *bind.WatchOpts, sink chan<- *VeboResumed) (event.Subscription, error) { + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "Resumed") + 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(VeboResumed) + if err := _Vebo.contract.UnpackLog(event, "Resumed", 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 +} + +// ParseResumed is a log parse operation binding the contract event 0x62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f9. +// +// Solidity: event Resumed() +func (_Vebo *VeboFilterer) ParseResumed(log types.Log) (*VeboResumed, error) { + event := new(VeboResumed) + if err := _Vebo.contract.UnpackLog(event, "Resumed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Vebo contract. +type VeboRoleAdminChangedIterator struct { + Event *VeboRoleAdminChanged // 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 *VeboRoleAdminChangedIterator) 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(VeboRoleAdminChanged) + 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(VeboRoleAdminChanged) + 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 *VeboRoleAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboRoleAdminChanged represents a RoleAdminChanged event raised by the Vebo contract. +type VeboRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Vebo *VeboFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*VeboRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &VeboRoleAdminChangedIterator{contract: _Vebo.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil +} + +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Vebo *VeboFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *VeboRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + 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(VeboRoleAdminChanged) + if err := _Vebo.contract.UnpackLog(event, "RoleAdminChanged", 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 +} + +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Vebo *VeboFilterer) ParseRoleAdminChanged(log types.Log) (*VeboRoleAdminChanged, error) { + event := new(VeboRoleAdminChanged) + if err := _Vebo.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Vebo contract. +type VeboRoleGrantedIterator struct { + Event *VeboRoleGranted // 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 *VeboRoleGrantedIterator) 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(VeboRoleGranted) + 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(VeboRoleGranted) + 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 *VeboRoleGrantedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboRoleGranted represents a RoleGranted event raised by the Vebo contract. +type VeboRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Vebo *VeboFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*VeboRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &VeboRoleGrantedIterator{contract: _Vebo.contract, event: "RoleGranted", logs: logs, sub: sub}, nil +} + +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Vebo *VeboFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *VeboRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + 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(VeboRoleGranted) + if err := _Vebo.contract.UnpackLog(event, "RoleGranted", 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 +} + +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Vebo *VeboFilterer) ParseRoleGranted(log types.Log) (*VeboRoleGranted, error) { + event := new(VeboRoleGranted) + if err := _Vebo.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Vebo contract. +type VeboRoleRevokedIterator struct { + Event *VeboRoleRevoked // 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 *VeboRoleRevokedIterator) 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(VeboRoleRevoked) + 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(VeboRoleRevoked) + 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 *VeboRoleRevokedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboRoleRevoked represents a RoleRevoked event raised by the Vebo contract. +type VeboRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Vebo *VeboFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*VeboRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &VeboRoleRevokedIterator{contract: _Vebo.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Vebo *VeboFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *VeboRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + 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(VeboRoleRevoked) + if err := _Vebo.contract.UnpackLog(event, "RoleRevoked", 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 +} + +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Vebo *VeboFilterer) ParseRoleRevoked(log types.Log) (*VeboRoleRevoked, error) { + event := new(VeboRoleRevoked) + if err := _Vebo.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboValidatorExitRequestIterator is returned from FilterValidatorExitRequest and is used to iterate over the raw logs and unpacked data for ValidatorExitRequest events raised by the Vebo contract. +type VeboValidatorExitRequestIterator struct { + Event *VeboValidatorExitRequest // 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 *VeboValidatorExitRequestIterator) 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(VeboValidatorExitRequest) + 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(VeboValidatorExitRequest) + 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 *VeboValidatorExitRequestIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboValidatorExitRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboValidatorExitRequest represents a ValidatorExitRequest event raised by the Vebo contract. +type VeboValidatorExitRequest struct { + StakingModuleId *big.Int + NodeOperatorId *big.Int + ValidatorIndex *big.Int + ValidatorPubkey []byte + Timestamp *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorExitRequest is a free log retrieval operation binding the contract event 0x96395f55c4997466e5035d777f0e1ba82b8cae217aaad05cf07839eb7c75bcf2. +// +// Solidity: event ValidatorExitRequest(uint256 indexed stakingModuleId, uint256 indexed nodeOperatorId, uint256 indexed validatorIndex, bytes validatorPubkey, uint256 timestamp) +func (_Vebo *VeboFilterer) FilterValidatorExitRequest(opts *bind.FilterOpts, stakingModuleId []*big.Int, nodeOperatorId []*big.Int, validatorIndex []*big.Int) (*VeboValidatorExitRequestIterator, error) { + + var stakingModuleIdRule []interface{} + for _, stakingModuleIdItem := range stakingModuleId { + stakingModuleIdRule = append(stakingModuleIdRule, stakingModuleIdItem) + } + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var validatorIndexRule []interface{} + for _, validatorIndexItem := range validatorIndex { + validatorIndexRule = append(validatorIndexRule, validatorIndexItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "ValidatorExitRequest", stakingModuleIdRule, nodeOperatorIdRule, validatorIndexRule) + if err != nil { + return nil, err + } + return &VeboValidatorExitRequestIterator{contract: _Vebo.contract, event: "ValidatorExitRequest", logs: logs, sub: sub}, nil +} + +// WatchValidatorExitRequest is a free log subscription operation binding the contract event 0x96395f55c4997466e5035d777f0e1ba82b8cae217aaad05cf07839eb7c75bcf2. +// +// Solidity: event ValidatorExitRequest(uint256 indexed stakingModuleId, uint256 indexed nodeOperatorId, uint256 indexed validatorIndex, bytes validatorPubkey, uint256 timestamp) +func (_Vebo *VeboFilterer) WatchValidatorExitRequest(opts *bind.WatchOpts, sink chan<- *VeboValidatorExitRequest, stakingModuleId []*big.Int, nodeOperatorId []*big.Int, validatorIndex []*big.Int) (event.Subscription, error) { + + var stakingModuleIdRule []interface{} + for _, stakingModuleIdItem := range stakingModuleId { + stakingModuleIdRule = append(stakingModuleIdRule, stakingModuleIdItem) + } + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var validatorIndexRule []interface{} + for _, validatorIndexItem := range validatorIndex { + validatorIndexRule = append(validatorIndexRule, validatorIndexItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "ValidatorExitRequest", stakingModuleIdRule, nodeOperatorIdRule, validatorIndexRule) + 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(VeboValidatorExitRequest) + if err := _Vebo.contract.UnpackLog(event, "ValidatorExitRequest", 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 +} + +// ParseValidatorExitRequest is a log parse operation binding the contract event 0x96395f55c4997466e5035d777f0e1ba82b8cae217aaad05cf07839eb7c75bcf2. +// +// Solidity: event ValidatorExitRequest(uint256 indexed stakingModuleId, uint256 indexed nodeOperatorId, uint256 indexed validatorIndex, bytes validatorPubkey, uint256 timestamp) +func (_Vebo *VeboFilterer) ParseValidatorExitRequest(log types.Log) (*VeboValidatorExitRequest, error) { + event := new(VeboValidatorExitRequest) + if err := _Vebo.contract.UnpackLog(event, "ValidatorExitRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboWarnDataIncompleteProcessingIterator is returned from FilterWarnDataIncompleteProcessing and is used to iterate over the raw logs and unpacked data for WarnDataIncompleteProcessing events raised by the Vebo contract. +type VeboWarnDataIncompleteProcessingIterator struct { + Event *VeboWarnDataIncompleteProcessing // 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 *VeboWarnDataIncompleteProcessingIterator) 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(VeboWarnDataIncompleteProcessing) + 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(VeboWarnDataIncompleteProcessing) + 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 *VeboWarnDataIncompleteProcessingIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboWarnDataIncompleteProcessingIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboWarnDataIncompleteProcessing represents a WarnDataIncompleteProcessing event raised by the Vebo contract. +type VeboWarnDataIncompleteProcessing struct { + RefSlot *big.Int + RequestsProcessed *big.Int + RequestsCount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWarnDataIncompleteProcessing is a free log retrieval operation binding the contract event 0xefc67aab43195093a8d8ed25d52281d96de480748ece2787888c586e8e1e79b4. +// +// Solidity: event WarnDataIncompleteProcessing(uint256 indexed refSlot, uint256 requestsProcessed, uint256 requestsCount) +func (_Vebo *VeboFilterer) FilterWarnDataIncompleteProcessing(opts *bind.FilterOpts, refSlot []*big.Int) (*VeboWarnDataIncompleteProcessingIterator, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "WarnDataIncompleteProcessing", refSlotRule) + if err != nil { + return nil, err + } + return &VeboWarnDataIncompleteProcessingIterator{contract: _Vebo.contract, event: "WarnDataIncompleteProcessing", logs: logs, sub: sub}, nil +} + +// WatchWarnDataIncompleteProcessing is a free log subscription operation binding the contract event 0xefc67aab43195093a8d8ed25d52281d96de480748ece2787888c586e8e1e79b4. +// +// Solidity: event WarnDataIncompleteProcessing(uint256 indexed refSlot, uint256 requestsProcessed, uint256 requestsCount) +func (_Vebo *VeboFilterer) WatchWarnDataIncompleteProcessing(opts *bind.WatchOpts, sink chan<- *VeboWarnDataIncompleteProcessing, refSlot []*big.Int) (event.Subscription, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "WarnDataIncompleteProcessing", refSlotRule) + 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(VeboWarnDataIncompleteProcessing) + if err := _Vebo.contract.UnpackLog(event, "WarnDataIncompleteProcessing", 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 +} + +// ParseWarnDataIncompleteProcessing is a log parse operation binding the contract event 0xefc67aab43195093a8d8ed25d52281d96de480748ece2787888c586e8e1e79b4. +// +// Solidity: event WarnDataIncompleteProcessing(uint256 indexed refSlot, uint256 requestsProcessed, uint256 requestsCount) +func (_Vebo *VeboFilterer) ParseWarnDataIncompleteProcessing(log types.Log) (*VeboWarnDataIncompleteProcessing, error) { + event := new(VeboWarnDataIncompleteProcessing) + if err := _Vebo.contract.UnpackLog(event, "WarnDataIncompleteProcessing", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// VeboWarnProcessingMissedIterator is returned from FilterWarnProcessingMissed and is used to iterate over the raw logs and unpacked data for WarnProcessingMissed events raised by the Vebo contract. +type VeboWarnProcessingMissedIterator struct { + Event *VeboWarnProcessingMissed // 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 *VeboWarnProcessingMissedIterator) 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(VeboWarnProcessingMissed) + 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(VeboWarnProcessingMissed) + 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 *VeboWarnProcessingMissedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *VeboWarnProcessingMissedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// VeboWarnProcessingMissed represents a WarnProcessingMissed event raised by the Vebo contract. +type VeboWarnProcessingMissed struct { + RefSlot *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWarnProcessingMissed is a free log retrieval operation binding the contract event 0x800b849c8bf80718cf786c99d1091c079fe2c5e420a3ba7ba9b0ef8179ef2c38. +// +// Solidity: event WarnProcessingMissed(uint256 indexed refSlot) +func (_Vebo *VeboFilterer) FilterWarnProcessingMissed(opts *bind.FilterOpts, refSlot []*big.Int) (*VeboWarnProcessingMissedIterator, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.FilterLogs(opts, "WarnProcessingMissed", refSlotRule) + if err != nil { + return nil, err + } + return &VeboWarnProcessingMissedIterator{contract: _Vebo.contract, event: "WarnProcessingMissed", logs: logs, sub: sub}, nil +} + +// WatchWarnProcessingMissed is a free log subscription operation binding the contract event 0x800b849c8bf80718cf786c99d1091c079fe2c5e420a3ba7ba9b0ef8179ef2c38. +// +// Solidity: event WarnProcessingMissed(uint256 indexed refSlot) +func (_Vebo *VeboFilterer) WatchWarnProcessingMissed(opts *bind.WatchOpts, sink chan<- *VeboWarnProcessingMissed, refSlot []*big.Int) (event.Subscription, error) { + + var refSlotRule []interface{} + for _, refSlotItem := range refSlot { + refSlotRule = append(refSlotRule, refSlotItem) + } + + logs, sub, err := _Vebo.contract.WatchLogs(opts, "WarnProcessingMissed", refSlotRule) + 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(VeboWarnProcessingMissed) + if err := _Vebo.contract.UnpackLog(event, "WarnProcessingMissed", 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 +} + +// ParseWarnProcessingMissed is a log parse operation binding the contract event 0x800b849c8bf80718cf786c99d1091c079fe2c5e420a3ba7ba9b0ef8179ef2c38. +// +// Solidity: event WarnProcessingMissed(uint256 indexed refSlot) +func (_Vebo *VeboFilterer) ParseWarnProcessingMissed(log types.Log) (*VeboWarnProcessingMissed, error) { + event := new(VeboWarnProcessingMissed) + if err := _Vebo.contract.UnpackLog(event, "WarnProcessingMissed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} From c933c5486a3f9d1065f7a0a47bc95e4ad18e5faa Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Thu, 12 Sep 2024 16:31:03 +0000 Subject: [PATCH 02/34] feat: Support Staking Module ID usage --- internal/lido/contracts/contractsAddress.go | 4 ++ internal/lido/contracts/stakingModuleIDs.go | 35 ++++++++++++++ .../lido/contracts/stakingModuleIDs_test.go | 48 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 internal/lido/contracts/stakingModuleIDs.go create mode 100644 internal/lido/contracts/stakingModuleIDs_test.go diff --git a/internal/lido/contracts/contractsAddress.go b/internal/lido/contracts/contractsAddress.go index 3f4dcdde..9f82fe12 100644 --- a/internal/lido/contracts/contractsAddress.go +++ b/internal/lido/contracts/contractsAddress.go @@ -29,6 +29,7 @@ const ( CSAccounting = "sepolia" CSFeeDistributor = "gnosis" MEVBoostRelayAllowedList = "mevboostrelayallowedlist" + Vebo = "vebo" ) var deployedAddresses = map[string]address{ @@ -45,6 +46,9 @@ var deployedAddresses = map[string]address{ configs.NetworkMainnet: "0xF95f069F9AD107938F6ba802a3da87892298610E", configs.NetworkHolesky: "0x2d86C5855581194a386941806E38cA119E50aEA3", }, + Vebo: { + configs.NetworkHolesky: "0xffDDF7025410412deaa05E3E1cE68FE53208afcb", + }, } func DeployedAddresses(contractName string) address { diff --git a/internal/lido/contracts/stakingModuleIDs.go b/internal/lido/contracts/stakingModuleIDs.go new file mode 100644 index 00000000..e190d53b --- /dev/null +++ b/internal/lido/contracts/stakingModuleIDs.go @@ -0,0 +1,35 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package contracts + +import ( + "fmt" + "math/big" + + "github.com/NethermindEth/sedge/configs" +) + +var stakingModuleIDs = map[string]*big.Int{ + configs.NetworkHolesky: big.NewInt(4), +} + +func StakingModuleID(network string) (*big.Int, error) { + stakingModuleID, found := stakingModuleIDs[network] + if !found { + return nil, fmt.Errorf("no staking module ID found for network %s", network) + } + return stakingModuleID, nil +} diff --git a/internal/lido/contracts/stakingModuleIDs_test.go b/internal/lido/contracts/stakingModuleIDs_test.go new file mode 100644 index 00000000..ac19a88b --- /dev/null +++ b/internal/lido/contracts/stakingModuleIDs_test.go @@ -0,0 +1,48 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package contracts + +import ( + "math/big" + "testing" + + "github.com/NethermindEth/sedge/configs" +) + +func TestStakingModuleID(t *testing.T) { + tcs := []struct { + network string + want *big.Int + wantErr bool + }{ + {configs.NetworkHolesky, big.NewInt(4), false}, + {"unknown", nil, true}, + {configs.NetworkMainnet, nil, true}, + } + + for _, tc := range tcs { + got, err := StakingModuleID(tc.network) + if tc.wantErr && err == nil { + t.Errorf("StakingModuleID(%s) returned no error, want error", tc.network) + } + if !tc.wantErr && err != nil { + t.Errorf("StakingModuleID(%s) returned error: %v", tc.network, err) + } + if got.Cmp(tc.want) != 0 { + t.Errorf("StakingModuleID(%s) = %v, want %v", tc.network, got, tc.want) + } + } +} From b3568fd53527f711d37e56c8803c12b0188504d7 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Thu, 12 Sep 2024 16:31:28 +0000 Subject: [PATCH 03/34] feat: Add ChainID to network configs --- configs/init.go | 11 ++++++++--- configs/types.go | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/configs/init.go b/configs/init.go index 77e953d1..d42363a4 100644 --- a/configs/init.go +++ b/configs/init.go @@ -32,7 +32,8 @@ var networksConfigs map[string]NetworkConfig = map[string]NetworkConfig{ "https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net", "https://0xa1559ace749633b997cb3fdacffb890aeebdb0f5a3b6aaa7eeeaf1a38af0a8fe88b9e4b1f61f236d2e64d95733327a62@relay.ultrasound.money", }, - Weight: 1, + ChainID: 1, + Weight: 1, }, NetworkSepolia: { Name: NetworkSepolia, @@ -43,13 +44,15 @@ var networksConfigs map[string]NetworkConfig = map[string]NetworkConfig{ RelayURLs: []string{ "https://0x845bd072b7cd566f02faeb0a4033ce9399e42839ced64e8b2adcfc859ed1e8e1a5a293336a49feac6d9a5edb779be53a@builder-relay-sepolia.flashbots.net", }, - Weight: 3, + ChainID: 11155111, + Weight: 3, }, NetworkChiado: { Name: NetworkChiado, NetworkService: "merge", GenesisForkVersion: "0x0000006f", CheckpointSyncURL: "https://checkpoint.chiadochain.net", + ChainID: 10200, Weight: 5, }, NetworkGnosis: { @@ -57,6 +60,7 @@ var networksConfigs map[string]NetworkConfig = map[string]NetworkConfig{ NetworkService: "merge", GenesisForkVersion: "0x00000064", CheckpointSyncURL: "https://checkpoint.gnosischain.com", + ChainID: 100, Weight: 4, }, NetworkHolesky: { @@ -71,7 +75,8 @@ var networksConfigs map[string]NetworkConfig = map[string]NetworkConfig{ "https://0xab78bf8c781c58078c3beb5710c57940874dd96aef2835e7742c866b4c7c0406754376c2c8285a36c630346aa5c5f833@holesky.aestus.live", "https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@holesky.titanrelay.xyz", }, - Weight: 2, + ChainID: 17000, + Weight: 2, }, NetworkCustom: { Name: NetworkCustom, diff --git a/configs/types.go b/configs/types.go index 599b3288..6fe1cf60 100644 --- a/configs/types.go +++ b/configs/types.go @@ -34,5 +34,6 @@ type NetworkConfig struct { SupportsMEVBoost bool CheckpointSyncURL string RelayURLs []string + ChainID uint64 Weight int // Weight of the network for sorting purposes } From 9fe399ca336f24039f38a28f44e3ce1c5fd7e734 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Thu, 12 Sep 2024 16:33:31 +0000 Subject: [PATCH 04/34] refac: Update RPC client creation Updates: - Strengthen client validation - Allow providing a list of RPC endpoints --- .../{contract_setup.go => client.go} | 36 +++++-- internal/lido/contracts/client_test.go | 102 ++++++++++++++++++ 2 files changed, 132 insertions(+), 6 deletions(-) rename internal/lido/contracts/{contract_setup.go => client.go} (51%) create mode 100644 internal/lido/contracts/client_test.go diff --git a/internal/lido/contracts/contract_setup.go b/internal/lido/contracts/client.go similarity index 51% rename from internal/lido/contracts/contract_setup.go rename to internal/lido/contracts/client.go index 051956e4..de0f61cf 100644 --- a/internal/lido/contracts/contract_setup.go +++ b/internal/lido/contracts/client.go @@ -16,7 +16,9 @@ limitations under the License. package contracts import ( + "context" "fmt" + "math/big" "github.com/NethermindEth/sedge/configs" "github.com/ethereum/go-ethereum/ethclient" @@ -36,17 +38,39 @@ func connectToRPCETH(RPCs []string) (*ethclient.Client, error) { return nil, fmt.Errorf("failed to connect to any RPC URL") } -func ConnectClient(network string) (*ethclient.Client, error) { - rpcs, err := configs.GetPublicRPCs(network) - if err != nil { - return nil, fmt.Errorf("failed to get public RPC: %w", err) +func ConnectClient(network string, RPCs ...string) (*ethclient.Client, error) { + var rpcs []string + var err error + + if len(RPCs) == 0 { + rpcs, err = configs.GetPublicRPCs(network) + if err != nil { + return nil, fmt.Errorf("failed to get public RPC: %w", err) + } + } else { + rpcs = RPCs } - // Connect to the RPC endpoint client, err := connectToRPCETH(rpcs) if err != nil { return nil, fmt.Errorf("failed to connect to RPC: %w", err) } - return client, nil + // Verify that the client is indeed an Ethereum RPC client + if client != nil { + // Try to get the chain ID, which is a basic operation that should work for any Ethereum client + chainID, err := client.ChainID(context.Background()) + if err == nil { + expectedChainID := configs.NetworksConfigs()[network].ChainID + if chainID.Cmp(new(big.Int).SetUint64(expectedChainID)) == 0 { + // If we successfully got the chain ID and it matches the expected one, + // we can be reasonably sure this is the correct Ethereum client + return client, nil + } + } + // If there was an error or chain ID mismatch, close the client and continue to the next URL + client.Close() + } + + return nil, fmt.Errorf("failed to connect to RPC: %w", err) } diff --git a/internal/lido/contracts/client_test.go b/internal/lido/contracts/client_test.go new file mode 100644 index 00000000..ced442c2 --- /dev/null +++ b/internal/lido/contracts/client_test.go @@ -0,0 +1,102 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package contracts + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestConnectClient(t *testing.T) { + tcs := []struct { + name string + network string + wantErr bool + }{ + { + name: "ConnectClient, Holesky", + network: "holesky", + wantErr: false, + }, + { + name: "ConnectClient, invalid Network", + network: "invalid", + wantErr: true, + }, + { + name: "ConnectClient, Mainnet", + network: "mainnet", + wantErr: false, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + client, err := ConnectClient(tc.network) + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, client) + } + }) + } +} + +func TestConnectClientWithRPCs(t *testing.T) { + tcs := []struct { + name string + network string + RPCs []string + wantErr bool + }{ + { + name: "ConnectClientWithRPCs, Holesky", + network: "holesky", + RPCs: []string{"https://endpoints.omniatech.io/v1/eth/holesky/public", "https://ethereum-holesky.blockpi.network/v1/rpc/public"}, + wantErr: false, + }, + { + name: "ConnectClientWithRPCs, Holesky, invalid RPC", + network: "holesky", + RPCs: []string{"https://www.google.com"}, + wantErr: true, + }, + { + name: "ConnectClientWithRPCs, invalid Network RPCs", + network: "holesky", + RPCs: []string{"https://eth.llamarpc.com"}, // Mainnet RPC + wantErr: true, + }, + { + name: "ConnectClient, Mainnet", + network: "mainnet", + RPCs: []string{"https://eth.llamarpc.com"}, + wantErr: false, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + client, err := ConnectClient(tc.network, tc.RPCs...) + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, client) + } + }) + } +} From 8039ac02448f9bd1e9a58b08ce311ff75fb00f8b Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Thu, 12 Sep 2024 16:33:58 +0000 Subject: [PATCH 05/34] feat: Add Lido Exporter app --- cmd/lido-exporter/cli/lido_exporter.go | 153 +++++++++++++++++++++ cmd/lido-exporter/main.go | 31 +++++ cmd/lido-exporter/metrics/bonds.go | 70 ++++++++++ cmd/lido-exporter/metrics/exit_requests.go | 67 +++++++++ cmd/lido-exporter/metrics/keys.go | 96 +++++++++++++ cmd/lido-exporter/metrics/metrics.go | 89 ++++++++++++ cmd/lido-exporter/metrics/node_operator.go | 63 +++++++++ cmd/lido-exporter/metrics/penalties.go | 81 +++++++++++ cmd/lido-exporter/metrics/rewards.go | 49 +++++++ go.mod | 29 +++- 10 files changed, 724 insertions(+), 4 deletions(-) create mode 100644 cmd/lido-exporter/cli/lido_exporter.go create mode 100644 cmd/lido-exporter/main.go create mode 100644 cmd/lido-exporter/metrics/bonds.go create mode 100644 cmd/lido-exporter/metrics/exit_requests.go create mode 100644 cmd/lido-exporter/metrics/keys.go create mode 100644 cmd/lido-exporter/metrics/metrics.go create mode 100644 cmd/lido-exporter/metrics/node_operator.go create mode 100644 cmd/lido-exporter/metrics/penalties.go create mode 100644 cmd/lido-exporter/metrics/rewards.go diff --git a/cmd/lido-exporter/cli/lido_exporter.go b/cmd/lido-exporter/cli/lido_exporter.go new file mode 100644 index 00000000..3dc285bc --- /dev/null +++ b/cmd/lido-exporter/cli/lido_exporter.go @@ -0,0 +1,153 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cli + +import ( + "context" + "fmt" + "math/big" + "net/http" + "os" + "os/signal" + "strconv" + "strings" + "syscall" + "time" + + "github.com/NethermindEth/sedge/cmd/lido-exporter/metrics" + "github.com/NethermindEth/sedge/configs" + "github.com/NethermindEth/sedge/internal/lido/contracts" + "github.com/NethermindEth/sedge/internal/lido/contracts/csmodule" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + nested "github.com/antonfisher/nested-logrus-formatter" + log "github.com/sirupsen/logrus" +) + +var logLevel string + +func RootCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "lido-exporter", + Short: "Lido Exporter exports Lido CSM metrics to Prometheus", + Long: `Lido Exporter exports Lido CSM metrics to Prometheus`, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + initLogging() + }, + Run: run, + } + + viper.BindPFlag("node-operator-id", cmd.PersistentFlags().Lookup("node-operator-id")) + viper.BindPFlag("reward-address", cmd.PersistentFlags().Lookup("reward-address")) + viper.BindPFlag("network", cmd.PersistentFlags().Lookup("network")) + viper.BindPFlag("rpc-endpoints", cmd.PersistentFlags().Lookup("rpc-endpoints")) + viper.BindPFlag("port", cmd.PersistentFlags().Lookup("port")) + viper.BindPFlag("scrape-time", cmd.PersistentFlags().Lookup("scrape-time")) + viper.BindPFlag("log-level", cmd.PersistentFlags().Lookup("log-level")) + viper.SetEnvPrefix("LIDO_EXPORTER") + viper.AutomaticEnv() + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "")) + + // Disable completion default cmd + cmd.CompletionOptions.DisableDefaultCmd = true + + // Persistent flags + cmd.PersistentFlags().String("node-operator-id", "", "Node Operator ID") + cmd.PersistentFlags().String("reward-address", "", "Reward address of Node Operator") + cmd.PersistentFlags().String("network", "holesky", "Network name") + cmd.PersistentFlags().StringSlice("rpc-endpoints", nil, "List of Ethereum RPC endpoints") + cmd.PersistentFlags().String("port", "8080", "Port where the metrics will be exported") + cmd.PersistentFlags().Duration("scrape-time", 10*time.Second, "Time interval for scraping metrics") + cmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace") + + return cmd +} + +func run(cmd *cobra.Command, args []string) { + nodeOperatorID := viper.GetString("node-operator-id") + rewardAddress := viper.GetString("reward-address") + if nodeOperatorID == "" && rewardAddress == "" { + log.Fatal("Node Operator ID or Reward Address is required") + } + + // Validate port + port := viper.GetString("port") + _, err := strconv.Atoi(port) + if err != nil { + log.Fatalf("Invalid port: %s", port) + } + + network := viper.GetString("network") + var nodeOperatorIDBigInt *big.Int + if nodeOperatorID != "" { + var ok bool + nodeOperatorIDBigInt, ok = new(big.Int).SetString(nodeOperatorID, 10) + if !ok { + log.Fatalf("Failed to convert Node Operator ID to big.Int: %s", nodeOperatorID) + } + } else { + var err error + nodeOperatorIDBigInt, err = csmodule.NodeID(network, rewardAddress) + if err != nil { + log.Fatalf("Failed to get Node Operator ID: %v", err) + } + } + + rpcEndpoints := viper.GetStringSlice("rpc-endpoints") + + client, err := contracts.ConnectClient(network, rpcEndpoints...) + if err != nil { + log.Fatalf("Failed to connect to Ethereum RPC: %v", err) + } + + // Initialize metrics + metrics.InitMetrics(nodeOperatorID, network) + + // Start the metrics server + go func() { + http.Handle("/metrics", promhttp.Handler()) + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", viper.GetString("port")), nil)) + }() + + // Start collecting metrics + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go metrics.CollectMetrics(ctx, client, nodeOperatorIDBigInt, network, viper.GetDuration("scrape-time")) + + // Wait for interrupt signal to gracefully shutdown the exporter + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + <-sigCh + fmt.Println("Shutting down Lido Exporter...") +} + +func initLogging() { + log.SetFormatter(&nested.Formatter{ + HideKeys: true, + FieldsOrder: []string{configs.Component}, + TimestampFormat: "2006-01-02 15:04:05 --", + }) + + level, err := log.ParseLevel(strings.ToLower(logLevel)) + if err != nil { + log.WithField(configs.Component, "Logger Init").Error(err) + return + } + log.SetLevel(level) + log.WithField(configs.Component, "Logger Init").Infof("Log level: %+v", logLevel) +} diff --git a/cmd/lido-exporter/main.go b/cmd/lido-exporter/main.go new file mode 100644 index 00000000..36e3994b --- /dev/null +++ b/cmd/lido-exporter/main.go @@ -0,0 +1,31 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package main + +import ( + "github.com/NethermindEth/sedge/cmd/lido-exporter/cli" + log "github.com/sirupsen/logrus" +) + +func main() { + rootCmd := cli.RootCmd() + rootCmd.SilenceErrors = true + rootCmd.SilenceUsage = true + + if err := rootCmd.Execute(); err != nil { + log.Fatal(err) + } +} diff --git a/cmd/lido-exporter/metrics/bonds.go b/cmd/lido-exporter/metrics/bonds.go new file mode 100644 index 00000000..d0895735 --- /dev/null +++ b/cmd/lido-exporter/metrics/bonds.go @@ -0,0 +1,70 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + "time" + + bonds "github.com/NethermindEth/sedge/internal/lido/contracts/csaccounting" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + log "github.com/sirupsen/logrus" +) + +var ( + bondCurrentGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_bond_current", + Help: "The current amount of bonded ETH", + }, []string{"node_operator_id", "network"}) + + bondRequiredGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_bond_required", + Help: "The required amount of ETH to maintain", + }, []string{"node_operator_id", "network"}) + + bondExcessGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_bond_excess", + Help: "The amount of excess bond over the required amount", + }, []string{"node_operator_id", "network"}) + + bondMissedGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_bond_missed", + Help: "The amount of bond that is missing", + }, []string{"node_operator_id", "network"}) +) + +func collectBondInfo(ctx context.Context, network string, nodeOperatorID *big.Int, scrapeTime time.Duration) { + for { + select { + case <-ctx.Done(): + return + case <-time.After(scrapeTime): + bondInfo, err := bonds.BondSummary(network, nodeOperatorID) + if err != nil { + log.Errorf("Failed to get bond summary: %v", err) + return + } + + bondCurrentGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Current.Int64())) + bondRequiredGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Required.Int64())) + bondExcessGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Excess.Int64())) + bondMissedGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Missed.Int64())) + } + } +} diff --git a/cmd/lido-exporter/metrics/exit_requests.go b/cmd/lido-exporter/metrics/exit_requests.go new file mode 100644 index 00000000..8fabc103 --- /dev/null +++ b/cmd/lido-exporter/metrics/exit_requests.go @@ -0,0 +1,67 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + + "github.com/NethermindEth/sedge/internal/lido/contracts" + "github.com/NethermindEth/sedge/internal/lido/contracts/vebo" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + log "github.com/sirupsen/logrus" +) + +var exitRequestsTotal = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "csm_onchain_exit_requests_total", + Help: "Number of validator exit requests", +}, []string{"node_operator_id", "network", "tx_hash"}) + +// collectExitRequests listens for ValidatorExitRequest events on the Vebo contract and updates the exit requests counter. +// `filterOpts` is used to specify the start block for the event logs. +func collectExitRequests(ctx context.Context, network string, nodeOperatorID *big.Int, client *ethclient.Client, filterOpts *bind.WatchOpts) { + validatorExitRequestCh := make(chan *vebo.VeboValidatorExitRequest) + + // Get staking module ID + stakingModuleID, err := contracts.StakingModuleID(network) + if err != nil { + log.Errorf("Failed to get staking module ID: %v", err) + return + } + + veboFilterer, err := vebo.NewVeboFilterer(common.HexToAddress(contracts.DeployedAddresses(contracts.Vebo)[network]), client) + + // Should ValidatorIndex be added? + // Subscribe to ValidatorExitRequest events + _, err = veboFilterer.WatchValidatorExitRequest(filterOpts, validatorExitRequestCh, []*big.Int{stakingModuleID}, []*big.Int{nodeOperatorID}, nil) + if err != nil { + log.Printf("Failed to watch ValidatorExitRequest events: %v", err) + } + + for { + select { + case event := <-validatorExitRequestCh: + exitRequestsTotal.WithLabelValues(nodeOperatorID.String(), network, event.Raw.TxHash.Hex()).Inc() + case <-ctx.Done(): + return + } + } +} diff --git a/cmd/lido-exporter/metrics/keys.go b/cmd/lido-exporter/metrics/keys.go new file mode 100644 index 00000000..2cda8d75 --- /dev/null +++ b/cmd/lido-exporter/metrics/keys.go @@ -0,0 +1,96 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + "time" + + "github.com/NethermindEth/sedge/internal/lido/contracts/csmodule" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + log "github.com/sirupsen/logrus" +) + +var ( + keysStuckValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_keys_stuck_validators_count", + Help: "Number of keys stuck in the system", + }, []string{"node_operator_id", "network"}) + + keysRefundedValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_keys_refunded_validators_count", + Help: "Number of keys refunded", + }, []string{"node_operator_id", "network"}) + + keysExitedValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_keys_exited_validators_count", + Help: "Number of keys exited", + }, []string{"node_operator_id", "network"}) + + keysDepositedValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_keys_deposited_validators_count", + Help: "Number of keys that already received deposits including withdrawn keys", + }, []string{"node_operator_id", "network"}) + + keysDepositableValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_keys_depositable_validators_count", + Help: "Number of keys eligible for deposits", + }, []string{"node_operator_id", "network"}) + + addedKeysCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_added_keys_count", + Help: "Number of keys added", + }, []string{"node_operator_id", "network"}) + + withdrawnKeysCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_withdrawn_keys_count", + Help: "Number of keys withdrawn", + }, []string{"node_operator_id", "network"}) + + vettedKeysCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_vetted_keys_count", + Help: "Number of keys vetted", + }, []string{"node_operator_id", "network"}) + + enqueuedKeysCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_enqueued_keys_count", + Help: "Number of keys in the deposit queue", + }, []string{"node_operator_id", "network"}) +) + +func collectKeysInfo(ctx context.Context, network string, nodeOperatorID *big.Int, scrapeTime time.Duration) { + for { + select { + case <-ctx.Done(): + return + case <-time.After(scrapeTime): + keysStatus, err := csmodule.KeysStatus(network, nodeOperatorID) + if err != nil { + log.Errorf("Failed to get keys status: %v", err) + return + } + + keysStuckValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.StuckValidatorsCount.Int64())) + keysRefundedValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.RefundedValidatorsCount.Int64())) + keysExitedValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.ExitedValidators.Int64())) + keysDepositedValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.DepositedValidators.Int64())) + keysDepositableValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.DepositableValidatorsCount.Int64())) + } + } +} diff --git a/cmd/lido-exporter/metrics/metrics.go b/cmd/lido-exporter/metrics/metrics.go new file mode 100644 index 00000000..431f65be --- /dev/null +++ b/cmd/lido-exporter/metrics/metrics.go @@ -0,0 +1,89 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/ethclient" + log "github.com/sirupsen/logrus" +) + +func InitMetrics(nodeOperatorID, network string) { + // Node operator metrics + nodeOperatorIDGauge.WithLabelValues(nodeOperatorID, network) + nodeOperatorManagerAddressGauge.WithLabelValues(nodeOperatorID, network) + nodeOperatorRewardAddressGauge.WithLabelValues(nodeOperatorID, network) + + // Keys metrics + keysStuckValidatorsCountGauge.WithLabelValues(nodeOperatorID, network) + keysRefundedValidatorsCountGauge.WithLabelValues(nodeOperatorID, network) + keysExitedValidatorsCountGauge.WithLabelValues(nodeOperatorID, network) + keysDepositedValidatorsCountGauge.WithLabelValues(nodeOperatorID, network) + keysDepositableValidatorsCountGauge.WithLabelValues(nodeOperatorID, network) + addedKeysCountGauge.WithLabelValues(nodeOperatorID, network) + withdrawnKeysCountGauge.WithLabelValues(nodeOperatorID, network) + vettedKeysCountGauge.WithLabelValues(nodeOperatorID, network) + enqueuedKeysCountGauge.WithLabelValues(nodeOperatorID, network) + + // Penalties metrics + penaltiesTotal.WithLabelValues(nodeOperatorID, "", "") + + // Exit requests metrics + exitRequestsTotal.WithLabelValues(nodeOperatorID, network, "") + + // Bond metrics + bondCurrentGauge.WithLabelValues(nodeOperatorID, network) + bondRequiredGauge.WithLabelValues(nodeOperatorID, network) + bondExcessGauge.WithLabelValues(nodeOperatorID, network) + bondMissedGauge.WithLabelValues(nodeOperatorID, network) + + // Rewards metrics + nonClaimedRewardsGauge.WithLabelValues(nodeOperatorID, network) +} + +func CollectMetrics(ctx context.Context, client *ethclient.Client, nodeOperatorID *big.Int, network string, scrapeTime time.Duration) { + var filterOpts *bind.WatchOpts + + // Get start block + // Try to use current block - 1000, if not then use 0 + currentBlock, err := client.BlockNumber(ctx) + if err != nil { + log.Errorf("Failed to get current block: %v", err) + zero := uint64(0) + filterOpts = &bind.WatchOpts{ + Start: &zero, + } + } else { + startBlock := currentBlock - 1000 + if startBlock < 0 { + startBlock = 0 + } + filterOpts = &bind.WatchOpts{ + Start: &startBlock, + } + } + + go collectPenalties(ctx, network, nodeOperatorID, client, filterOpts) + go collectExitRequests(ctx, network, nodeOperatorID, client, filterOpts) + go collectNodeOperatorInfo(ctx, network, nodeOperatorID, scrapeTime) + go collectKeysInfo(ctx, network, nodeOperatorID, scrapeTime) + go collectBondInfo(ctx, network, nodeOperatorID, scrapeTime) + go collectRewardsInfo(ctx, network, nodeOperatorID, scrapeTime) +} diff --git a/cmd/lido-exporter/metrics/node_operator.go b/cmd/lido-exporter/metrics/node_operator.go new file mode 100644 index 00000000..4944e3ac --- /dev/null +++ b/cmd/lido-exporter/metrics/node_operator.go @@ -0,0 +1,63 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + "time" + + "github.com/NethermindEth/sedge/internal/lido/contracts/csmodule" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + log "github.com/sirupsen/logrus" +) + +var ( + nodeOperatorIDGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_node_operator_id", + Help: "Unique identifier for the node operator", + }, []string{"node_operator_id", "network"}) + + nodeOperatorManagerAddressGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_node_operator_manager_address", + Help: "Address used to perform routine management operations regarding the CSM Node Operator", + }, []string{"node_operator_id", "network"}) + + nodeOperatorRewardAddressGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_node_operator_reward_address", + Help: "Address that is the ultimate recipient of the rewards", + }, []string{"node_operator_id", "network"}) +) + +func collectNodeOperatorInfo(ctx context.Context, network string, nodeOperatorID *big.Int, scrapeTime time.Duration) { + for { + select { + case <-ctx.Done(): + return + case <-time.After(scrapeTime): + nodeOperator, err := csmodule.NodeOperatorInfo(network, nodeOperatorID) + if err != nil { + log.Errorf("Failed to get node operator info: %v", err) + return + } + + nodeOperatorIDGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(nodeOperatorID.Int64())) + nodeOperatorManagerAddressGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(nodeOperator.ManagerAddress.Big().Int64())) + nodeOperatorRewardAddressGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(nodeOperator.RewardAddress.Big().Int64())) + } + } +} diff --git a/cmd/lido-exporter/metrics/penalties.go b/cmd/lido-exporter/metrics/penalties.go new file mode 100644 index 00000000..22d08418 --- /dev/null +++ b/cmd/lido-exporter/metrics/penalties.go @@ -0,0 +1,81 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + + "github.com/NethermindEth/sedge/internal/lido/contracts" + "github.com/NethermindEth/sedge/internal/lido/contracts/csmodule" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + log "github.com/sirupsen/logrus" +) + +var penaltiesTotal = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "csm_onchain_penalties_total", + Help: "Number of penalties", +}, []string{"node_operator_id", "penalty_type", "tx_hash"}) + +// collectPenalties listens for Penalty events on the CSModule contract and updates the penalties counter. +// `filterOpts` is used to specify the start block for the event logs. +func collectPenalties(ctx context.Context, network string, nodeOperatorID *big.Int, client *ethclient.Client, filterOpts *bind.WatchOpts) { + elRewardsStealingPenaltyReportedCh := make(chan *csmodule.CsmoduleELRewardsStealingPenaltyReported) + initialSlashingSubmittedCh := make(chan *csmodule.CsmoduleInitialSlashingSubmitted) + withdrawalSubmittedCh := make(chan *csmodule.CsmoduleWithdrawalSubmitted) + + csmoduleFilterer, err := csmodule.NewCsmoduleFilterer(common.HexToAddress(contracts.DeployedAddresses(contracts.CSModule)[network]), client) + if err != nil { + log.Errorf("Failed to create CSModule filterer: %v", err) + return + } + + // Subscribe to penalty events + _, err = csmoduleFilterer.WatchELRewardsStealingPenaltyReported(filterOpts, elRewardsStealingPenaltyReportedCh, []*big.Int{nodeOperatorID}) + if err != nil { + log.Errorf("Failed to watch ELRewardsStealingPenaltyReported events: %v", err) + } + + _, err = csmoduleFilterer.WatchInitialSlashingSubmitted(filterOpts, initialSlashingSubmittedCh, []*big.Int{nodeOperatorID}) + if err != nil { + log.Errorf("Failed to watch InitialSlashingSubmitted events: %v", err) + } + + _, err = csmoduleFilterer.WatchWithdrawalSubmitted(filterOpts, withdrawalSubmittedCh, []*big.Int{nodeOperatorID}) + if err != nil { + log.Errorf("Failed to watch WithdrawalSubmitted events: %v", err) + } + + for { + select { + case event := <-elRewardsStealingPenaltyReportedCh: + penaltiesTotal.WithLabelValues(nodeOperatorID.String(), "el_rewards_stealing", event.Raw.TxHash.Hex()).Inc() + case event := <-initialSlashingSubmittedCh: + penaltiesTotal.WithLabelValues(nodeOperatorID.String(), "initial_slashing", event.Raw.TxHash.Hex()).Inc() + case event := <-withdrawalSubmittedCh: + // Amount is in Wei, but we want to count only less than 32 ETH + if event.Amount.Cmp(new(big.Int).Mul(big.NewInt(32), big.NewInt(1e18))) < 0 { + penaltiesTotal.WithLabelValues(nodeOperatorID.String(), "withdrawal", event.Raw.TxHash.Hex()).Inc() + } + case <-ctx.Done(): + return + } + } +} diff --git a/cmd/lido-exporter/metrics/rewards.go b/cmd/lido-exporter/metrics/rewards.go new file mode 100644 index 00000000..4b9505f0 --- /dev/null +++ b/cmd/lido-exporter/metrics/rewards.go @@ -0,0 +1,49 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package metrics + +import ( + "context" + "math/big" + "time" + + rewards "github.com/NethermindEth/sedge/internal/lido/contracts/csfeedistributor" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + log "github.com/sirupsen/logrus" +) + +var nonClaimedRewardsGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "csm_non_claimed_rewards", + Help: "The amount of rewards available for claiming", +}, []string{"node_operator_id", "network"}) + +func collectRewardsInfo(ctx context.Context, network string, nodeOperatorID *big.Int, scrapeTime time.Duration) { + for { + select { + case <-ctx.Done(): + return + case <-time.After(scrapeTime): + rewards, err := rewards.Rewards(network, nodeOperatorID) + if err != nil { + log.Errorf("Failed to get rewards: %v", err) + return + } + + nonClaimedRewardsGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(rewards.Int64())) + } + } +} diff --git a/go.mod b/go.mod index 6998395d..5b0acc77 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/joho/godotenv v1.5.1 github.com/opencontainers/image-spec v1.1.0 github.com/otiai10/copy v1.9.0 + github.com/prometheus/client_golang v1.12.1 github.com/protolambda/go-keystorev4 v0.0.0-20211007151826-f20444f6d564 github.com/protolambda/zrnt v0.32.2 github.com/protolambda/ztyp v0.2.2 @@ -57,8 +58,10 @@ require ( github.com/alecthomas/chroma/v2 v2.14.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/lipgloss v0.12.1 // indirect github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/consensys/bavard v0.1.13 // indirect @@ -66,7 +69,8 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/creack/pty v1.1.18 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/distribution/distribution/v3 v3.0.0-20230223072852-e5d5810851d1 // indirect @@ -76,17 +80,18 @@ require ( github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ferranbt/fastssz v0.1.3 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uilive v0.0.4 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -95,10 +100,12 @@ require ( github.com/klauspost/compress v1.17.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -114,15 +121,25 @@ require ( github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/protolambda/bls12-381-util v0.1.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect @@ -132,6 +149,8 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect @@ -145,5 +164,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) From 24ad9b90fc7acb8c5606a5b95847edacbfa9a88a Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 13:07:57 +0000 Subject: [PATCH 06/34] feat: Add support for RPC WebSocket connection --- cmd/lido-exporter/cli/lido_exporter.go | 39 ++++--- cmd/lido-exporter/metrics/metrics.go | 8 +- configs/networks.go | 24 ++-- configs/public_rpcs.go | 15 +++ internal/lido/contracts/client.go | 74 +++++++----- internal/lido/contracts/client_test.go | 110 +++++++++++++++++- internal/lido/contracts/csaccounting/bonds.go | 2 +- .../contracts/csfeedistributor/rewards.go | 2 +- .../lido/contracts/csmodule/nodeOperator.go | 2 +- .../contracts/mevboostrelaylist/get_relays.go | 2 +- 10 files changed, 218 insertions(+), 60 deletions(-) diff --git a/cmd/lido-exporter/cli/lido_exporter.go b/cmd/lido-exporter/cli/lido_exporter.go index 3dc285bc..be16c696 100644 --- a/cmd/lido-exporter/cli/lido_exporter.go +++ b/cmd/lido-exporter/cli/lido_exporter.go @@ -22,6 +22,7 @@ import ( "net/http" "os" "os/signal" + "slices" "strconv" "strings" "syscall" @@ -31,6 +32,7 @@ import ( "github.com/NethermindEth/sedge/configs" "github.com/NethermindEth/sedge/internal/lido/contracts" "github.com/NethermindEth/sedge/internal/lido/contracts/csmodule" + "github.com/NethermindEth/sedge/internal/utils" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -52,28 +54,30 @@ func RootCmd() *cobra.Command { Run: run, } + // Disable completion default cmd + cmd.CompletionOptions.DisableDefaultCmd = true + + // Persistent flags + cmd.PersistentFlags().String("node-operator-id", "", "Node Operator ID") + cmd.PersistentFlags().String("reward-address", "", "Reward address of Node Operator. It is used to calculate Node Operator ID if not set") + cmd.PersistentFlags().String("network", "holesky", "Network name") + cmd.PersistentFlags().StringSlice("rpc-endpoints", nil, "List of Ethereum HTTP RPC endpoints") + cmd.PersistentFlags().StringSlice("ws-endpoints", nil, "List of Ethereum WebSocket RPC endpoints") + cmd.PersistentFlags().String("port", "8080", "Port where the metrics will be exported.") + cmd.PersistentFlags().Duration("scrape-time", 10*time.Second, "Time interval for scraping metrics. Values should be in the format of 10s, 1m, 1h, etc.") + cmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace") + viper.BindPFlag("node-operator-id", cmd.PersistentFlags().Lookup("node-operator-id")) viper.BindPFlag("reward-address", cmd.PersistentFlags().Lookup("reward-address")) viper.BindPFlag("network", cmd.PersistentFlags().Lookup("network")) viper.BindPFlag("rpc-endpoints", cmd.PersistentFlags().Lookup("rpc-endpoints")) + viper.BindPFlag("ws-endpoints", cmd.PersistentFlags().Lookup("ws-endpoints")) viper.BindPFlag("port", cmd.PersistentFlags().Lookup("port")) viper.BindPFlag("scrape-time", cmd.PersistentFlags().Lookup("scrape-time")) viper.BindPFlag("log-level", cmd.PersistentFlags().Lookup("log-level")) viper.SetEnvPrefix("LIDO_EXPORTER") viper.AutomaticEnv() - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "")) - - // Disable completion default cmd - cmd.CompletionOptions.DisableDefaultCmd = true - - // Persistent flags - cmd.PersistentFlags().String("node-operator-id", "", "Node Operator ID") - cmd.PersistentFlags().String("reward-address", "", "Reward address of Node Operator") - cmd.PersistentFlags().String("network", "holesky", "Network name") - cmd.PersistentFlags().StringSlice("rpc-endpoints", nil, "List of Ethereum RPC endpoints") - cmd.PersistentFlags().String("port", "8080", "Port where the metrics will be exported") - cmd.PersistentFlags().Duration("scrape-time", 10*time.Second, "Time interval for scraping metrics") - cmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace") + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) return cmd } @@ -109,11 +113,16 @@ func run(cmd *cobra.Command, args []string) { } rpcEndpoints := viper.GetStringSlice("rpc-endpoints") + wsEndpoints := viper.GetStringSlice("ws-endpoints") - client, err := contracts.ConnectClient(network, rpcEndpoints...) + client, err := contracts.ConnectClient(network, false, rpcEndpoints...) if err != nil { log.Fatalf("Failed to connect to Ethereum RPC: %v", err) } + wsClient, err := contracts.ConnectClient(network, true, wsEndpoints...) + if err != nil { + log.Fatalf("Failed to connect to Ethereum WebSocket: %v", err) + } // Initialize metrics metrics.InitMetrics(nodeOperatorID, network) @@ -127,7 +136,7 @@ func run(cmd *cobra.Command, args []string) { // Start collecting metrics ctx, cancel := context.WithCancel(context.Background()) defer cancel() - go metrics.CollectMetrics(ctx, client, nodeOperatorIDBigInt, network, viper.GetDuration("scrape-time")) + go metrics.CollectMetrics(ctx, client, wsClient, nodeOperatorIDBigInt, network, viper.GetDuration("scrape-time")) // Wait for interrupt signal to gracefully shutdown the exporter sigCh := make(chan os.Signal, 1) diff --git a/cmd/lido-exporter/metrics/metrics.go b/cmd/lido-exporter/metrics/metrics.go index 431f65be..0aa90e89 100644 --- a/cmd/lido-exporter/metrics/metrics.go +++ b/cmd/lido-exporter/metrics/metrics.go @@ -58,11 +58,11 @@ func InitMetrics(nodeOperatorID, network string) { nonClaimedRewardsGauge.WithLabelValues(nodeOperatorID, network) } -func CollectMetrics(ctx context.Context, client *ethclient.Client, nodeOperatorID *big.Int, network string, scrapeTime time.Duration) { +func CollectMetrics(ctx context.Context, client *ethclient.Client, wsClient *ethclient.Client, nodeOperatorID *big.Int, network string, scrapeTime time.Duration) { var filterOpts *bind.WatchOpts // Get start block - // Try to use current block - 1000, if not then use 0 + // Try to use current block - 50000, if not then use 0 currentBlock, err := client.BlockNumber(ctx) if err != nil { log.Errorf("Failed to get current block: %v", err) @@ -71,7 +71,7 @@ func CollectMetrics(ctx context.Context, client *ethclient.Client, nodeOperatorI Start: &zero, } } else { - startBlock := currentBlock - 1000 + startBlock := currentBlock - 50000 if startBlock < 0 { startBlock = 0 } @@ -82,6 +82,8 @@ func CollectMetrics(ctx context.Context, client *ethclient.Client, nodeOperatorI go collectPenalties(ctx, network, nodeOperatorID, client, filterOpts) go collectExitRequests(ctx, network, nodeOperatorID, client, filterOpts) + go collectPenalties(ctx, network, nodeOperatorID, wsClient, filterOpts) + go collectExitRequests(ctx, network, nodeOperatorID, wsClient, filterOpts) go collectNodeOperatorInfo(ctx, network, nodeOperatorID, scrapeTime) go collectKeysInfo(ctx, network, nodeOperatorID, scrapeTime) go collectBondInfo(ctx, network, nodeOperatorID, scrapeTime) diff --git a/configs/networks.go b/configs/networks.go index bda3744c..bd339a74 100644 --- a/configs/networks.go +++ b/configs/networks.go @@ -77,14 +77,22 @@ func GetPublicRPCs(network string) ([]string, error) { if !exists { return nil, fmt.Errorf("invalid network") } - // Create a copy of the slice to avoid modifying the original - shuffledRPCs := make([]string, len(rpcs.PublicRPCs)) - copy(shuffledRPCs, rpcs.PublicRPCs) - // Randomize the slice order - sort.Slice(shuffledRPCs, func(i, j int) bool { - return rand.Float32() < 0.5 - }) + return shuffleRPCs(rpcs.PublicRPCs), nil +} + +func GetPublicWSs(network string) ([]string, error) { + ws, exists := networkWSs[network] + if !exists { + return nil, fmt.Errorf("invalid network") + } + return shuffleRPCs(ws.PublicRPCs), nil +} - return shuffledRPCs, nil +func shuffleRPCs(rpcs []string) []string { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + r.Shuffle(len(rpcs), func(i, j int) { + rpcs[i], rpcs[j] = rpcs[j], rpcs[i] + }) + return rpcs } diff --git a/configs/public_rpcs.go b/configs/public_rpcs.go index 91fe6202..c9d22f18 100644 --- a/configs/public_rpcs.go +++ b/configs/public_rpcs.go @@ -41,3 +41,18 @@ var networkRPCs = map[string]RPC{ }, }, } + +var networkWSs = map[string]RPC{ + NetworkMainnet: { + NetworkName: NetworkMainnet, + PublicRPCs: []string{ + "wss://ethereum-rpc.publicnode.com", + }, + }, + NetworkHolesky: { + NetworkName: NetworkHolesky, + PublicRPCs: []string{ + "wss://ethereum-holesky-rpc.publicnode.com", + }, + }, +} diff --git a/internal/lido/contracts/client.go b/internal/lido/contracts/client.go index de0f61cf..326afda7 100644 --- a/internal/lido/contracts/client.go +++ b/internal/lido/contracts/client.go @@ -19,58 +19,78 @@ import ( "context" "fmt" "math/big" + "strings" "github.com/NethermindEth/sedge/configs" "github.com/ethereum/go-ethereum/ethclient" + + log "github.com/sirupsen/logrus" ) -func connectToRPCETH(RPCs []string) (*ethclient.Client, error) { +func connectToRPCETH(RPCs []string, network string) (*ethclient.Client, error) { var client *ethclient.Client var err error for _, url := range RPCs { client, err = ethclient.Dial(url) if err == nil { - return client, nil + // Try to get the chain ID, which is a basic operation that should work for any Ethereum client + chainID, err := client.ChainID(context.Background()) + if err == nil { + expectedChainID := configs.NetworksConfigs()[network].ChainID + if chainID.Cmp(new(big.Int).SetUint64(expectedChainID)) == 0 { + // If we successfully got the chain ID and it matches the expected one, + // we can be reasonably sure this is the correct Ethereum client + log.Debugf("connected to %s", url) + return client, nil + } else { + log.Errorf("chain ID mismatch: expected %d, got %d", expectedChainID, chainID.Uint64()) + } + } + // If there was an error or chain ID mismatch, close the client and continue to the next URL + client.Close() } } - return nil, fmt.Errorf("failed to connect to any RPC URL") + return nil, fmt.Errorf("failed to connect to any RPC URL, either the RPCs are wrong or the network is not supported") } -func ConnectClient(network string, RPCs ...string) (*ethclient.Client, error) { +// ConnectClient returns a new Ethereum client connected to the given network. +// If websocket is true, it will try to connect to the first available WS RPC. +// If websocket is false, it will try to connect to the first available HTTP RPC. +// If no RPCs are provided, it will use the public RPCs or WSs for the given network. +// The RPCs are shuffled to avoid the same RPC being used by multiple clients. +func ConnectClient(network string, websocket bool, RPCs ...string) (*ethclient.Client, error) { var rpcs []string var err error - if len(RPCs) == 0 { - rpcs, err = configs.GetPublicRPCs(network) + for _, rpc := range RPCs { + if websocket { + if strings.HasPrefix(rpc, "wss://") { + rpcs = append(rpcs, rpc) + } + } else { + if strings.HasPrefix(rpc, "https://") || strings.HasPrefix(rpc, "http://") { + rpcs = append(rpcs, rpc) + } + } + } + + if len(rpcs) == 0 { + if websocket { + rpcs, err = configs.GetPublicWSs(network) + } else { + rpcs, err = configs.GetPublicRPCs(network) + } if err != nil { return nil, fmt.Errorf("failed to get public RPC: %w", err) } - } else { - rpcs = RPCs } - client, err := connectToRPCETH(rpcs) + client, err := connectToRPCETH(rpcs, network) if err != nil { - return nil, fmt.Errorf("failed to connect to RPC: %w", err) - } - - // Verify that the client is indeed an Ethereum RPC client - if client != nil { - // Try to get the chain ID, which is a basic operation that should work for any Ethereum client - chainID, err := client.ChainID(context.Background()) - if err == nil { - expectedChainID := configs.NetworksConfigs()[network].ChainID - if chainID.Cmp(new(big.Int).SetUint64(expectedChainID)) == 0 { - // If we successfully got the chain ID and it matches the expected one, - // we can be reasonably sure this is the correct Ethereum client - return client, nil - } - } - // If there was an error or chain ID mismatch, close the client and continue to the next URL - client.Close() + return nil, err } - return nil, fmt.Errorf("failed to connect to RPC: %w", err) + return client, nil } diff --git a/internal/lido/contracts/client_test.go b/internal/lido/contracts/client_test.go index ced442c2..2708e75a 100644 --- a/internal/lido/contracts/client_test.go +++ b/internal/lido/contracts/client_test.go @@ -45,7 +45,7 @@ func TestConnectClient(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - client, err := ConnectClient(tc.network) + client, err := ConnectClient(tc.network, false) if tc.wantErr { require.Error(t, err) } else { @@ -66,7 +66,7 @@ func TestConnectClientWithRPCs(t *testing.T) { { name: "ConnectClientWithRPCs, Holesky", network: "holesky", - RPCs: []string{"https://endpoints.omniatech.io/v1/eth/holesky/public", "https://ethereum-holesky.blockpi.network/v1/rpc/public"}, + RPCs: []string{"https://endpoints.omniatech.io/v1/eth/holesky/public", "http://ethereum-holesky.blockpi.network/v1/rpc/public"}, wantErr: false, }, { @@ -81,6 +81,18 @@ func TestConnectClientWithRPCs(t *testing.T) { RPCs: []string{"https://eth.llamarpc.com"}, // Mainnet RPC wantErr: true, }, + { + name: "ConnectClientWithRPCs, invalid Network RPCs, no HTTPS", + network: "holesky", + RPCs: []string{"wss://ethereum-holesky-rpc.publicnode.com"}, // Mainnet RPC + wantErr: false, + }, + { + name: "ConnectClientWithRPCs, mix Network RPCs", + network: "holesky", + RPCs: []string{"https://ethereum-holesky-rpc.publicnode.com", "wss://ethereum-rpc.publicnode.com"}, + wantErr: false, + }, { name: "ConnectClient, Mainnet", network: "mainnet", @@ -90,7 +102,99 @@ func TestConnectClientWithRPCs(t *testing.T) { } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - client, err := ConnectClient(tc.network, tc.RPCs...) + client, err := ConnectClient(tc.network, false, tc.RPCs...) + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, client) + } + }) + } +} + +func TestConnectClientWS(t *testing.T) { + tcs := []struct { + name string + network string + wantErr bool + }{ + { + name: "ConnectClient, Holesky", + network: "holesky", + wantErr: false, + }, + { + name: "ConnectClient, invalid Network", + network: "invalid", + wantErr: true, + }, + { + name: "ConnectClient, Mainnet", + network: "mainnet", + wantErr: false, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + client, err := ConnectClient(tc.network, true) + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, client) + } + }) + } +} + +func TestConnectClientWSWithRPCs(t *testing.T) { + tcs := []struct { + name string + network string + RPCs []string + wantErr bool + }{ + { + name: "ConnectClientWithRPCs, Holesky", + network: "holesky", + RPCs: []string{"wss://ethereum-holesky-rpc.publicnode.com", "wss://holesky.drpc.org"}, + wantErr: false, + }, + { + name: "ConnectClientWithRPCs, Holesky, invalid RPC", + network: "holesky", + RPCs: []string{"https://www.google.com"}, + wantErr: false, + }, + { + name: "ConnectClientWithRPCs, invalid Network RPCs", + network: "holesky", + RPCs: []string{"wss://ethereum-rpc.publicnode.com"}, // Mainnet RPC + wantErr: true, + }, + { + name: "ConnectClientWithRPCs, invalid Network RPCs, no WS", + network: "holesky", + RPCs: []string{"https://ethereum-holesky-rpc.publicnode.com"}, // Mainnet RPC + wantErr: false, + }, + { + name: "ConnectClientWithRPCs, mix Network RPCs", + network: "mainnet", + RPCs: []string{"https://ethereum-holesky-rpc.publicnode.com", "wss://ethereum-rpc.publicnode.com"}, + wantErr: false, + }, + { + name: "ConnectClient, Mainnet", + network: "mainnet", + RPCs: []string{"wss://ethereum-rpc.publicnode.com"}, + wantErr: false, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + client, err := ConnectClient(tc.network, true, tc.RPCs...) if tc.wantErr { require.Error(t, err) } else { diff --git a/internal/lido/contracts/csaccounting/bonds.go b/internal/lido/contracts/csaccounting/bonds.go index 44d2db2b..9b879b12 100644 --- a/internal/lido/contracts/csaccounting/bonds.go +++ b/internal/lido/contracts/csaccounting/bonds.go @@ -82,7 +82,7 @@ func BondSummary(network string, nodeID *big.Int) (BondInfo, error) { } func csAccountingContract(network string) (*Csaccounting, *ethclient.Client, error) { - client, err := contracts.ConnectClient(network) + client, err := contracts.ConnectClient(network, false) if err != nil { return nil, nil, fmt.Errorf("failed to connect to client: %w", err) } diff --git a/internal/lido/contracts/csfeedistributor/rewards.go b/internal/lido/contracts/csfeedistributor/rewards.go index e09a8b2b..1abac93f 100644 --- a/internal/lido/contracts/csfeedistributor/rewards.go +++ b/internal/lido/contracts/csfeedistributor/rewards.go @@ -151,7 +151,7 @@ func convertTreeValuesToBigInt(value interface{}) (*big.Int, error) { } func csFeeDistributorContract(network string) (*Csfeedistributor, *ethclient.Client, error) { - client, err := contracts.ConnectClient(network) + client, err := contracts.ConnectClient(network, false) if err != nil { return nil, nil, fmt.Errorf("failed to connect to client: %w", err) } diff --git a/internal/lido/contracts/csmodule/nodeOperator.go b/internal/lido/contracts/csmodule/nodeOperator.go index 0b7010fd..6e90fd14 100644 --- a/internal/lido/contracts/csmodule/nodeOperator.go +++ b/internal/lido/contracts/csmodule/nodeOperator.go @@ -132,7 +132,7 @@ func nodeOpsCount(network string) (*big.Int, error) { } func csModuleContract(network string) (*Csmodule, *ethclient.Client, error) { - client, err := contracts.ConnectClient(network) + client, err := contracts.ConnectClient(network, false) if err != nil { return nil, nil, fmt.Errorf("failed to connect to client: %w", err) } diff --git a/internal/lido/contracts/mevboostrelaylist/get_relays.go b/internal/lido/contracts/mevboostrelaylist/get_relays.go index fa6081b3..5cea898b 100644 --- a/internal/lido/contracts/mevboostrelaylist/get_relays.go +++ b/internal/lido/contracts/mevboostrelaylist/get_relays.go @@ -120,7 +120,7 @@ func NetworkSupportedByLidoMevBoost(network string) ([]string, bool) { } func mevBoostRelayListContract(network string) (*Mevboostrelaylist, *ethclient.Client, error) { - client, err := contracts.ConnectClient(network) + client, err := contracts.ConnectClient(network, false) if err != nil { return nil, nil, fmt.Errorf("failed to connect to client: %w", err) } From 894a330a55bbce263893f27bb9ea01002d262ddf Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 13:08:29 +0000 Subject: [PATCH 07/34] chore: Update logging --- cmd/lido-exporter/cli/lido_exporter.go | 22 ++++++++++++++++++---- cmd/lido-exporter/metrics/bonds.go | 1 + cmd/lido-exporter/metrics/exit_requests.go | 4 +++- cmd/lido-exporter/metrics/keys.go | 4 +++- cmd/lido-exporter/metrics/metrics.go | 3 +-- cmd/lido-exporter/metrics/node_operator.go | 2 ++ cmd/lido-exporter/metrics/penalties.go | 3 +++ cmd/lido-exporter/metrics/rewards.go | 1 + 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/cmd/lido-exporter/cli/lido_exporter.go b/cmd/lido-exporter/cli/lido_exporter.go index be16c696..36c4ac61 100644 --- a/cmd/lido-exporter/cli/lido_exporter.go +++ b/cmd/lido-exporter/cli/lido_exporter.go @@ -49,7 +49,13 @@ func RootCmd() *cobra.Command { Short: "Lido Exporter exports Lido CSM metrics to Prometheus", Long: `Lido Exporter exports Lido CSM metrics to Prometheus`, PersistentPreRun: func(cmd *cobra.Command, args []string) { - initLogging() + logLevel = viper.GetString("log-level") + level, err := log.ParseLevel(strings.ToLower(logLevel)) + if err != nil { + log.WithField(configs.Component, "Logger Init").Error(err) + return + } + log.SetLevel(level) }, Run: run, } @@ -97,6 +103,10 @@ func run(cmd *cobra.Command, args []string) { } network := viper.GetString("network") + if !slices.Contains(configs.NetworkSupported(), network) { + log.Fatalf("Invalid network: %s", network) + } + var nodeOperatorIDBigInt *big.Int if nodeOperatorID != "" { var ok bool @@ -105,6 +115,10 @@ func run(cmd *cobra.Command, args []string) { log.Fatalf("Failed to convert Node Operator ID to big.Int: %s", nodeOperatorID) } } else { + if !utils.IsAddress(rewardAddress) { + log.Fatalf("Invalid reward address: %s", rewardAddress) + } + var err error nodeOperatorIDBigInt, err = csmodule.NodeID(network, rewardAddress) if err != nil { @@ -142,17 +156,17 @@ func run(cmd *cobra.Command, args []string) { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) <-sigCh - fmt.Println("Shutting down Lido Exporter...") + log.Info("Shutting down Lido Exporter...") } -func initLogging() { +func init() { log.SetFormatter(&nested.Formatter{ HideKeys: true, FieldsOrder: []string{configs.Component}, TimestampFormat: "2006-01-02 15:04:05 --", }) - level, err := log.ParseLevel(strings.ToLower(logLevel)) + level, err := log.ParseLevel(strings.ToLower("error")) if err != nil { log.WithField(configs.Component, "Logger Init").Error(err) return diff --git a/cmd/lido-exporter/metrics/bonds.go b/cmd/lido-exporter/metrics/bonds.go index d0895735..56dbff02 100644 --- a/cmd/lido-exporter/metrics/bonds.go +++ b/cmd/lido-exporter/metrics/bonds.go @@ -65,6 +65,7 @@ func collectBondInfo(ctx context.Context, network string, nodeOperatorID *big.In bondRequiredGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Required.Int64())) bondExcessGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Excess.Int64())) bondMissedGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(bondInfo.Missed.Int64())) + log.Infof("Processed bond data") } } } diff --git a/cmd/lido-exporter/metrics/exit_requests.go b/cmd/lido-exporter/metrics/exit_requests.go index 8fabc103..0f2c4f7e 100644 --- a/cmd/lido-exporter/metrics/exit_requests.go +++ b/cmd/lido-exporter/metrics/exit_requests.go @@ -42,6 +42,7 @@ func collectExitRequests(ctx context.Context, network string, nodeOperatorID *bi // Get staking module ID stakingModuleID, err := contracts.StakingModuleID(network) + log.Debugf("Staking module ID: %d", stakingModuleID) if err != nil { log.Errorf("Failed to get staking module ID: %v", err) return @@ -53,13 +54,14 @@ func collectExitRequests(ctx context.Context, network string, nodeOperatorID *bi // Subscribe to ValidatorExitRequest events _, err = veboFilterer.WatchValidatorExitRequest(filterOpts, validatorExitRequestCh, []*big.Int{stakingModuleID}, []*big.Int{nodeOperatorID}, nil) if err != nil { - log.Printf("Failed to watch ValidatorExitRequest events: %v", err) + log.Errorf("Failed to watch ValidatorExitRequest events: %v", err) } for { select { case event := <-validatorExitRequestCh: exitRequestsTotal.WithLabelValues(nodeOperatorID.String(), network, event.Raw.TxHash.Hex()).Inc() + log.Infof("Processed exit request event") case <-ctx.Done(): return } diff --git a/cmd/lido-exporter/metrics/keys.go b/cmd/lido-exporter/metrics/keys.go index 2cda8d75..7b56e394 100644 --- a/cmd/lido-exporter/metrics/keys.go +++ b/cmd/lido-exporter/metrics/keys.go @@ -30,7 +30,7 @@ import ( var ( keysStuckValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "csm_keys_stuck_validators_count", - Help: "Number of keys stuck in the system", + Help: "Number of keys stuck in the system. A validator is considered to be stuck if it has not been exited timely following an exit signal from the protocol", }, []string{"node_operator_id", "network"}) keysRefundedValidatorsCountGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ @@ -91,6 +91,8 @@ func collectKeysInfo(ctx context.Context, network string, nodeOperatorID *big.In keysExitedValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.ExitedValidators.Int64())) keysDepositedValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.DepositedValidators.Int64())) keysDepositableValidatorsCountGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(keysStatus.DepositableValidatorsCount.Int64())) + + log.Info("Processed keys data") } } } diff --git a/cmd/lido-exporter/metrics/metrics.go b/cmd/lido-exporter/metrics/metrics.go index 0aa90e89..e0518a06 100644 --- a/cmd/lido-exporter/metrics/metrics.go +++ b/cmd/lido-exporter/metrics/metrics.go @@ -80,8 +80,7 @@ func CollectMetrics(ctx context.Context, client *ethclient.Client, wsClient *eth } } - go collectPenalties(ctx, network, nodeOperatorID, client, filterOpts) - go collectExitRequests(ctx, network, nodeOperatorID, client, filterOpts) + log.Infof("Collecting metrics for network %s with start block %d", network, filterOpts.Start) go collectPenalties(ctx, network, nodeOperatorID, wsClient, filterOpts) go collectExitRequests(ctx, network, nodeOperatorID, wsClient, filterOpts) go collectNodeOperatorInfo(ctx, network, nodeOperatorID, scrapeTime) diff --git a/cmd/lido-exporter/metrics/node_operator.go b/cmd/lido-exporter/metrics/node_operator.go index 4944e3ac..35e8bd3f 100644 --- a/cmd/lido-exporter/metrics/node_operator.go +++ b/cmd/lido-exporter/metrics/node_operator.go @@ -58,6 +58,8 @@ func collectNodeOperatorInfo(ctx context.Context, network string, nodeOperatorID nodeOperatorIDGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(nodeOperatorID.Int64())) nodeOperatorManagerAddressGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(nodeOperator.ManagerAddress.Big().Int64())) nodeOperatorRewardAddressGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(nodeOperator.RewardAddress.Big().Int64())) + + log.Infof("Processed node operator data") } } } diff --git a/cmd/lido-exporter/metrics/penalties.go b/cmd/lido-exporter/metrics/penalties.go index 22d08418..add7d1e3 100644 --- a/cmd/lido-exporter/metrics/penalties.go +++ b/cmd/lido-exporter/metrics/penalties.go @@ -67,13 +67,16 @@ func collectPenalties(ctx context.Context, network string, nodeOperatorID *big.I select { case event := <-elRewardsStealingPenaltyReportedCh: penaltiesTotal.WithLabelValues(nodeOperatorID.String(), "el_rewards_stealing", event.Raw.TxHash.Hex()).Inc() + log.Infof("Processed EL rewards stealing penalty event") case event := <-initialSlashingSubmittedCh: penaltiesTotal.WithLabelValues(nodeOperatorID.String(), "initial_slashing", event.Raw.TxHash.Hex()).Inc() + log.Infof("Processed initial slashing penalty event") case event := <-withdrawalSubmittedCh: // Amount is in Wei, but we want to count only less than 32 ETH if event.Amount.Cmp(new(big.Int).Mul(big.NewInt(32), big.NewInt(1e18))) < 0 { penaltiesTotal.WithLabelValues(nodeOperatorID.String(), "withdrawal", event.Raw.TxHash.Hex()).Inc() } + log.Infof("Processed withdrawal penalty event") case <-ctx.Done(): return } diff --git a/cmd/lido-exporter/metrics/rewards.go b/cmd/lido-exporter/metrics/rewards.go index 4b9505f0..5e43a6d1 100644 --- a/cmd/lido-exporter/metrics/rewards.go +++ b/cmd/lido-exporter/metrics/rewards.go @@ -44,6 +44,7 @@ func collectRewardsInfo(ctx context.Context, network string, nodeOperatorID *big } nonClaimedRewardsGauge.WithLabelValues(nodeOperatorID.String(), network).Set(float64(rewards.Int64())) + log.Infof("Processed rewards data") } } } From 2fa82d030067b27c987ac61c2080ac34834f0187 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 13:09:39 +0000 Subject: [PATCH 08/34] refac!: Separate sedge and lido-exporter e2e test suites --- e2e/e2e.go | 134 +++++++-------------------- e2e/lido-exporter/cleanup_unix.go | 33 +++++++ e2e/lido-exporter/cleanup_windows.go | 32 +++++++ e2e/lido-exporter/e2e.go | 93 +++++++++++++++++++ e2e/sedge/e2e.go | 112 ++++++++++++++++++++++ e2e/{ => sedge}/generate_test.go | 37 ++++++-- e2e/{ => sedge}/keys_test.go | 37 ++++++-- e2e/{ => sedge}/lidoStatus_test.go | 41 +++++--- e2e/utils.go | 129 ++++++++++++++++++++++++-- go.mod | 2 +- 10 files changed, 511 insertions(+), 139 deletions(-) create mode 100644 e2e/lido-exporter/cleanup_unix.go create mode 100644 e2e/lido-exporter/cleanup_windows.go create mode 100644 e2e/lido-exporter/e2e.go create mode 100644 e2e/sedge/e2e.go rename e2e/{ => sedge}/generate_test.go (76%) rename e2e/{ => sedge}/keys_test.go (90%) rename e2e/{ => sedge}/lidoStatus_test.go (61%) diff --git a/e2e/e2e.go b/e2e/e2e.go index 9aa2af11..ed566603 100644 --- a/e2e/e2e.go +++ b/e2e/e2e.go @@ -1,127 +1,65 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( - "os" "os/exec" "path/filepath" "runtime" "testing" ) -type ( - e2eArranger func(t *testing.T, sedgePath string) error - e2eAct func(t *testing.T, sedgePath, dataDirPath string) - e2eAssert func(t *testing.T, dataDirPath string) -) - -type e2eTestCase struct { - t *testing.T - testDir string - repoPath string - arranger e2eArranger - act e2eAct - assert e2eAssert -} - -func newE2ETestCase(t *testing.T, arranger e2eArranger, act e2eAct, assert e2eAssert) *e2eTestCase { - t.Helper() - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - tc := &e2eTestCase{ - t: t, - testDir: t.TempDir(), - repoPath: filepath.Dir(wd), - arranger: arranger, - act: act, - assert: assert, - } - t.Logf("Creating new E2E test case (%p). TestDir: %s", tc, tc.testDir) - checkGoInstalled(t) - tc.installGoModules() - tc.build() - return tc -} - -func (e *e2eTestCase) run() { - // Cleanup environment before and after test - e.Cleanup() - defer e.Cleanup() - if e.arranger != nil { - err := e.arranger(e.t, e.BinaryPath()) - if err != nil { - e.t.Fatalf("error in Arrange step: %v", err) - } - } - if e.act != nil { - e.act(e.t, e.BinaryPath(), e.dataDirPath()) - } - if e.assert != nil { - e.assert(e.t, e.dataDirPath()) - } +type E2ETestCase struct { + T *testing.T + TestDir string + RepoPath string + BinaryName string } -func (e *e2eTestCase) BinaryPath() string { - binaryName := "sedge" +func (e *E2ETestCase) BinaryPath() string { if runtime.GOOS == "windows" { - binaryName += ".exe" - } - return filepath.Join(e.testDir, binaryName) -} - -func (e *e2eTestCase) Cleanup() { - dataDir := e.dataDirPath() - // Check if data directory exists - if _, err := os.Stat(dataDir); os.IsNotExist(err) { - return - } - // Remove docker compose stack - err := exec.Command("docker", "compose", "-f", filepath.Join(dataDir, "docker-compose.yml"), "down", "--volumes").Run() - if err != nil { - e.t.Logf("error removing docker compose stack: %v", err) - } - - // Remove sedge-data directory - err = os.RemoveAll(dataDir) - if err != nil { - e.t.Logf("error removing data directory: %v", err) + e.BinaryName += ".exe" } + return filepath.Join(e.TestDir, e.BinaryName) } -func (e *e2eTestCase) installGoModules() { - e.t.Helper() +func (e *E2ETestCase) InstallGoModules() { + e.T.Helper() cmd := exec.Command("go", "mod", "download") - cmd.Dir = e.repoPath - e.t.Logf("Installing Go modules in %s", e.repoPath) + cmd.Dir = e.RepoPath + e.T.Logf("Installing Go modules in %s", e.RepoPath) if err := cmd.Run(); err != nil { - e.t.Fatalf("error installing Go modules: %v", err) + e.T.Fatalf("error installing Go modules: %v", err) } else { - e.t.Logf("Go modules installed") + e.T.Logf("Go modules installed") } } -func (e *e2eTestCase) build() { - e.t.Helper() - binaryName := "sedge" - if runtime.GOOS == "windows" { - binaryName += ".exe" - } - outPath := filepath.Join(e.testDir, binaryName) - e.t.Logf("Building binary to %s", outPath) - err := exec.Command("go", "build", "-o", outPath, filepath.Join(e.repoPath, "cmd", "sedge", "main.go")).Run() +func (e *E2ETestCase) Build() { + e.T.Helper() + e.T.Logf("Building binary to %s", e.BinaryPath()) + err := exec.Command("go", "build", "-o", e.BinaryPath(), filepath.Join(e.RepoPath, "cmd", e.BinaryName, "main.go")).Run() if err != nil { - e.t.Fatalf("error building binary: %v", err) + e.T.Fatalf("error building binary: %v", err) } else { - e.t.Logf("binary built") + e.T.Logf("binary built") } } -func (e *e2eTestCase) dataDirPath() string { - return filepath.Join(e.testDir, "sedge-data") -} - -func checkGoInstalled(t *testing.T) { +func CheckGoInstalled(t *testing.T) { t.Helper() err := exec.Command("go", "version").Run() if err != nil { diff --git a/e2e/lido-exporter/cleanup_unix.go b/e2e/lido-exporter/cleanup_unix.go new file mode 100644 index 00000000..f6c088c5 --- /dev/null +++ b/e2e/lido-exporter/cleanup_unix.go @@ -0,0 +1,33 @@ +//go:build !windows +// +build !windows + +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "os" + "syscall" +) + +func (e *e2eLidoExporterTestCase) Cleanup() { + if e.pid != 0 { + process, err := os.FindProcess(e.pid) + if err == nil { + process.Signal(syscall.SIGTERM) + } + } +} diff --git a/e2e/lido-exporter/cleanup_windows.go b/e2e/lido-exporter/cleanup_windows.go new file mode 100644 index 00000000..35b0e7bd --- /dev/null +++ b/e2e/lido-exporter/cleanup_windows.go @@ -0,0 +1,32 @@ +//go:build windows +// +build windows + +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "golang.org/x/sys/windows" +) + +func (e *e2eLidoExporterTestCase) Cleanup() { + if e.pid != 0 { + err := windows.GenerateConsoleCtrlEvent(windows.CTRL_C_EVENT, uint32(e.pid)) + if err != nil { + e.T.Fatalf("error sending CTRL_C_EVENT to process %d: %v", e.pid, err) + } + } +} diff --git a/e2e/lido-exporter/e2e.go b/e2e/lido-exporter/e2e.go new file mode 100644 index 00000000..4b3f9f4c --- /dev/null +++ b/e2e/lido-exporter/e2e.go @@ -0,0 +1,93 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" + + base "github.com/NethermindEth/sedge/e2e" +) + +type ( + e2eArranger func(t *testing.T, appPath string) error + e2eAct func(t *testing.T, appPath string) *exec.Cmd + e2eAssert func(t *testing.T) +) + +type e2eLidoExporterTestCase struct { + base.E2ETestCase + arranger e2eArranger + act e2eAct + assert e2eAssert + pid int + ctx context.Context +} + +func newE2ELidoExporterTestCase(t *testing.T, arranger e2eArranger, act e2eAct, assert e2eAssert) *e2eLidoExporterTestCase { + t.Helper() + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + tc := &e2eLidoExporterTestCase{ + E2ETestCase: base.E2ETestCase{ + T: t, + TestDir: t.TempDir(), + RepoPath: filepath.Dir(filepath.Dir(wd)), + BinaryName: "lido-exporter", + }, + arranger: arranger, + act: act, + assert: assert, + } + t.Logf("Creating new E2E test case (%p). TestDir: %s", tc, tc.TestDir) + base.CheckGoInstalled(t) + tc.E2ETestCase.InstallGoModules() + tc.E2ETestCase.Build() + return tc +} + +func (e *e2eLidoExporterTestCase) run() { + // Cleanup environment before and after test + e.Cleanup() + defer e.Cleanup() + if e.arranger != nil { + err := e.arranger(e.T, e.BinaryPath()) + if err != nil { + e.T.Fatalf("error in Arrange step: %v", err) + } + } + if e.act != nil { + cmd := e.act(e.T, e.BinaryPath()) + e.pid = cmd.Process.Pid + } + if e.assert != nil { + e.assert(e.T) + } +} + +func (e *e2eLidoExporterTestCase) BinaryPath() string { + binaryName := "lido-exporter" + if runtime.GOOS == "windows" { + binaryName += ".exe" + } + return filepath.Join(e.TestDir, binaryName) +} diff --git a/e2e/sedge/e2e.go b/e2e/sedge/e2e.go new file mode 100644 index 00000000..e2ce2182 --- /dev/null +++ b/e2e/sedge/e2e.go @@ -0,0 +1,112 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" + + base "github.com/NethermindEth/sedge/e2e" +) + +type ( + e2eArranger func(t *testing.T, sedgePath string) error + e2eAct func(t *testing.T, sedgePath, dataDirPath string) + e2eAssert func(t *testing.T, dataDirPath string) +) + +type e2eSedgeTestCase struct { + base.E2ETestCase + arranger e2eArranger + act e2eAct + assert e2eAssert +} + +func newE2ESedgeTestCase(t *testing.T, arranger e2eArranger, act e2eAct, assert e2eAssert) *e2eSedgeTestCase { + t.Helper() + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + tc := &e2eSedgeTestCase{ + E2ETestCase: base.E2ETestCase{ + T: t, + TestDir: t.TempDir(), + RepoPath: filepath.Dir(filepath.Dir(wd)), + BinaryName: "sedge", + }, + arranger: arranger, + act: act, + assert: assert, + } + t.Logf("Creating new E2E test case (%p). TestDir: %s", tc, tc.TestDir) + base.CheckGoInstalled(t) + tc.E2ETestCase.InstallGoModules() + tc.E2ETestCase.Build() + return tc +} + +func (e *e2eSedgeTestCase) run() { + // Cleanup environment before and after test + e.Cleanup() + defer e.Cleanup() + if e.arranger != nil { + err := e.arranger(e.T, e.BinaryPath()) + if err != nil { + e.T.Fatalf("error in Arrange step: %v", err) + } + } + if e.act != nil { + e.act(e.T, e.BinaryPath(), e.dataDirPath()) + } + if e.assert != nil { + e.assert(e.T, e.dataDirPath()) + } +} + +func (e *e2eSedgeTestCase) BinaryPath() string { + binaryName := "sedge" + if runtime.GOOS == "windows" { + binaryName += ".exe" + } + return filepath.Join(e.TestDir, binaryName) +} + +func (e *e2eSedgeTestCase) Cleanup() { + dataDir := e.dataDirPath() + // Check if data directory exists + if _, err := os.Stat(dataDir); os.IsNotExist(err) { + return + } + // Remove docker compose stack + err := exec.Command("docker", "compose", "-f", filepath.Join(dataDir, "docker-compose.yml"), "down", "--volumes").Run() + if err != nil { + e.T.Logf("error removing docker compose stack: %v", err) + } + + // Remove sedge-data directory + err = os.RemoveAll(dataDir) + if err != nil { + e.T.Logf("error removing data directory: %v", err) + } +} + +func (e *e2eSedgeTestCase) dataDirPath() string { + return filepath.Join(e.TestDir, "sedge-data") +} diff --git a/e2e/generate_test.go b/e2e/sedge/generate_test.go similarity index 76% rename from e2e/generate_test.go rename to e2e/sedge/generate_test.go index 792d5875..908e29e7 100644 --- a/e2e/generate_test.go +++ b/e2e/sedge/generate_test.go @@ -1,3 +1,18 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( @@ -9,6 +24,8 @@ import ( "github.com/NethermindEth/sedge/internal/lido/contracts/mevboostrelaylist" "github.com/joho/godotenv" "github.com/stretchr/testify/assert" + + base "github.com/NethermindEth/sedge/e2e" ) func TestE2E_Generate_FullNode_GoerliNotSupported(t *testing.T) { @@ -17,13 +34,13 @@ func TestE2E_Generate_FullNode_GoerliNotSupported(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath, dataDirPath string) { - runErr = runSedge(t, binaryPath, "generate", "full-node", "--network", "goerli") + runErr = base.RunSedge(t, binaryPath, "generate", "full-node", "--network", "goerli") }, // Assert func(t *testing.T, dataDirPath string) { @@ -40,13 +57,13 @@ func TestE2E_Generate_FullNode_Lido_GnosisNotSupported(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "gnosis") + runErr = base.RunSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "gnosis") }, // Assert func(t *testing.T, dataDirPath string) { @@ -63,13 +80,13 @@ func TestE2E_Generate_FullNode_Lido_SepoliaNotSupported(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "sepolia") + runErr = base.RunSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "sepolia") }, // Assert func(t *testing.T, dataDirPath string) { @@ -87,13 +104,13 @@ func TestE2E_Generate_FullNode_Lido_Sepolia_NoMEV(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "sepolia", "--no-mev-boost") + runErr = base.RunSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "sepolia", "--no-mev-boost") }, // Assert func(t *testing.T, dataDirPath string) { @@ -127,13 +144,13 @@ func TestE2E_Generate_FullNode_Lido_Mainnet(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "mainnet") + runErr = base.RunSedge(t, binaryPath, "generate", "--lido", "full-node", "--network", "mainnet") }, // Assert func(t *testing.T, dataDirPath string) { diff --git a/e2e/keys_test.go b/e2e/sedge/keys_test.go similarity index 90% rename from e2e/keys_test.go rename to e2e/sedge/keys_test.go index 7503bf1f..58d3e24b 100644 --- a/e2e/keys_test.go +++ b/e2e/sedge/keys_test.go @@ -1,3 +1,18 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( @@ -11,6 +26,8 @@ import ( "github.com/NethermindEth/sedge/internal/lido/contracts" "github.com/NethermindEth/sedge/internal/pkg/keystores" "github.com/stretchr/testify/assert" + + base "github.com/NethermindEth/sedge/e2e" ) type depositDataKey struct { @@ -33,7 +50,7 @@ func TestE2E_Keys_Eth_Withdrawal_Keys_Mainnet(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, binaryPath string) error { @@ -50,7 +67,7 @@ func TestE2E_Keys_Eth_Withdrawal_Keys_Mainnet(t *testing.T) { // Act func(t *testing.T, binaryPath, dataDirPath string) { mnemonicPathFile := filepath.Join(filepath.Dir(binaryPath), "mnemonic.txt") - runErr = runSedge(t, binaryPath, "keys", + runErr = base.RunSedge(t, binaryPath, "keys", "--eth-withdrawal-address", "0xb794f5ea0ba39494ce839613fffba74279579268", "--network", "mainnet", "--num-validators", "10", @@ -91,7 +108,7 @@ func TestE2E_Keys_Lido_Mainnet(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, binaryPath string) error { @@ -108,7 +125,7 @@ func TestE2E_Keys_Lido_Mainnet(t *testing.T) { // Act func(t *testing.T, binaryPath, dataDirPath string) { mnemonicPathFile := filepath.Join(filepath.Dir(binaryPath), "mnemonic.txt") - runErr = runSedge(t, binaryPath, "keys", + runErr = base.RunSedge(t, binaryPath, "keys", "--lido", "--network", "mainnet", "--num-validators", "10", @@ -153,7 +170,7 @@ func TestE2E_Keys_Lido_Holesky(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, binaryPath string) error { @@ -170,7 +187,7 @@ func TestE2E_Keys_Lido_Holesky(t *testing.T) { // Act func(t *testing.T, binaryPath, dataDirPath string) { mnemonicPathFile := filepath.Join(filepath.Dir(binaryPath), "mnemonic.txt") - runErr = runSedge(t, binaryPath, "keys", + runErr = base.RunSedge(t, binaryPath, "keys", "--lido", "--network", "holesky", "--num-validators", "10", @@ -216,7 +233,7 @@ func TestE2E_Keys_Lido_EthWithdrawal_HoleskyInvalid(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, binaryPath string) error { @@ -233,7 +250,7 @@ func TestE2E_Keys_Lido_EthWithdrawal_HoleskyInvalid(t *testing.T) { // Act func(t *testing.T, binaryPath, dataDirPath string) { mnemonicPathFile := filepath.Join(filepath.Dir(binaryPath), "mnemonic.txt") - runErr = runSedge(t, binaryPath, "keys", + runErr = base.RunSedge(t, binaryPath, "keys", "--lido", "--eth-withdrawal-address", "0xb794f5ea0ba39494ce839613fffba74279579268", "--network", "holesky", @@ -259,7 +276,7 @@ func TestE2E_Keys_Lido_GnosisUnsupported(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, binaryPath string) error { @@ -276,7 +293,7 @@ func TestE2E_Keys_Lido_GnosisUnsupported(t *testing.T) { // Act func(t *testing.T, binaryPath, dataDirPath string) { mnemonicPathFile := filepath.Join(filepath.Dir(binaryPath), "mnemonic.txt") - runErr = runSedge(t, binaryPath, "keys", + runErr = base.RunSedge(t, binaryPath, "keys", "--lido", "--eth-withdrawal-address", "0xb794f5ea0ba39494ce839613fffba74279579268", "--network", "gnosis", diff --git a/e2e/lidoStatus_test.go b/e2e/sedge/lidoStatus_test.go similarity index 61% rename from e2e/lidoStatus_test.go rename to e2e/sedge/lidoStatus_test.go index b2610c0a..4899ad6d 100644 --- a/e2e/lidoStatus_test.go +++ b/e2e/sedge/lidoStatus_test.go @@ -1,9 +1,26 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( "testing" "github.com/stretchr/testify/assert" + + base "github.com/NethermindEth/sedge/e2e" ) func TestE2E_LidoStatus_ValidFlags(t *testing.T) { @@ -12,13 +29,13 @@ func TestE2E_LidoStatus_ValidFlags(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "lido-status", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--l", "--network", "holesky") + runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--l", "--network", "holesky") }, // Assert func(t *testing.T, dataDirPath string) { @@ -35,13 +52,13 @@ func TestE2E_LidoStatus_ValidNodeID(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "lido-status", "--nodeID", "10", "--l", "--network", "holesky") + runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "--nodeID", "10", "--l", "--network", "holesky") }, // Assert func(t *testing.T, dataDirPath string) { @@ -58,13 +75,13 @@ func TestE2E_LidoStatus_InvalidNodeID(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "lido-status", "--nodeID", "-2", "--l", "--network", "holesky") + runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "--nodeID", "-2", "--l", "--network", "holesky") }, // Assert func(t *testing.T, dataDirPath string) { @@ -82,13 +99,13 @@ func TestE2E_LidoStatus_InvalidRewardAddress(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "lido-status", "0xccb", "--network", "holesky") + runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "0xccb", "--network", "holesky") }, // Assert func(t *testing.T, dataDirPath string) { @@ -105,13 +122,13 @@ func TestE2E_LidoStatus_RewardAddressNotFound(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "lido-status", "0xC870Fd7316956C1582A2c8Fd2c42552cCEC70C89", "--network", "holesky") + runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "0xC870Fd7316956C1582A2c8Fd2c42552cCEC70C89", "--network", "holesky") }, // Assert func(t *testing.T, dataDirPath string) { @@ -128,13 +145,13 @@ func TestE2E_LidoStatus_InvalidZeroRewardAddress(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "lido-status", "0x0000000000000000000000000000000000000000", "--network", "holesky") + runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "0x0000000000000000000000000000000000000000", "--network", "holesky") }, // Assert func(t *testing.T, dataDirPath string) { diff --git a/e2e/utils.go b/e2e/utils.go index a2f4a7c5..8e8418e8 100644 --- a/e2e/utils.go +++ b/e2e/utils.go @@ -1,3 +1,18 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( @@ -16,23 +31,121 @@ import ( "github.com/docker/docker/client" ) -func runSedge(t *testing.T, binaryPath string, args ...string) error { +func RunSedge(t *testing.T, binaryPath string, args ...string) error { dataDir := filepath.Join(filepath.Dir(binaryPath), "sedge-data") - return runCommand(t, binaryPath, append([]string{"--path", dataDir}, args...)...) + return RunCommand(t, binaryPath, "sedge", append([]string{"--path", dataDir}, args...)...) } -func runCommand(t *testing.T, path string, args ...string) error { - _, err := runCommandOutput(t, path, args...) +func RunCommand(t *testing.T, path string, binaryName string, args ...string) error { + _, _, err := runCommandOutput(t, path, binaryName, args...) return err } -func runCommandOutput(t *testing.T, path string, args ...string) ([]byte, error) { +func RunCommandCMD(t *testing.T, path string, binaryName string, args ...string) *exec.Cmd { + t.Helper() + t.Logf("Running command: %s %s", binaryName, strings.Join(args, " ")) + cmd := exec.Command(path, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Start(); err != nil { + t.Fatalf("Failed to start command: %s %s", binaryName, strings.Join(args, " ")) + } + return cmd +} + +func runCommandOutput(t *testing.T, path string, binaryName string, args ...string) ([]byte, *exec.Cmd, error) { t.Helper() t.Logf("Binary path: %s", path) - t.Logf("Running command: sedge %s", strings.Join(args, " ")) - out, err := exec.Command(path, args...).CombinedOutput() + t.Logf("Running command: %s %s", binaryName, strings.Join(args, " ")) + cmd := exec.Command(path, args...) + out, err := cmd.CombinedOutput() t.Logf("===== OUTPUT =====\n%s\n==================", out) - return out, err + return out, cmd, err +} + +func LogAndPipeError(t *testing.T, prefix string, err error) error { + t.Helper() + if err != nil { + t.Log(prefix, err) + } + return err +} + +func dataDirPath() (string, error) { + userDataHome := os.Getenv("XDG_DATA_HOME") + if userDataHome == "" { + userHome, err := os.UserHomeDir() + if err != nil { + return "", err + } + userDataHome = filepath.Join(userHome, ".local", "share") + } + return filepath.Join(userDataHome, ".sedge"), nil +} + +type Target struct { + Labels Labels `json:"labels"` + Health string `json:"health"` +} + +type Labels map[string]string + +type Data struct { + ActiveTargets []Target `json:"activeTargets"` +} + +type PrometheusTargetsResponse struct { + Status string `json:"status"` + Data Data `json:"data"` +} + +func prometheusTargets(t *testing.T) (*PrometheusTargetsResponse, error) { + response, err := utils.GetRequest("http://localhost:9090/api/v1/targets", time.Second) + if err != nil { + return nil, err + } + if response.StatusCode != 200 { + return nil, fmt.Errorf("prometheus targets status code should be 200") + } + var r PrometheusTargetsResponse + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + err = json.Unmarshal(body, &r) + if err != nil { + return nil, err + } + return &r, nil +} + +func logAndPipeError(t *testing.T, prefix string, err error) error { + t.Helper() + if err != nil { + t.Log(prefix, err) + } + return err +} + +func getContainerIDByName(containerName string) (string, error) { + cli, err := client.NewClientWithOpts( + client.FromEnv, + client.WithAPIVersionNegotiation(), + ) + if err != nil { + return "", err + } + defer cli.Close() + + dockerServiceManager := services.NewDockerServiceManager(cli) + + containerID, err := dockerServiceManager.ContainerID(containerName) + if err != nil { + return "", err + } + + return containerID, nil } func dataDirPath() (string, error) { diff --git a/go.mod b/go.mod index 5b0acc77..ffaaab69 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/wealdtech/go-eth2-util v1.8.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.7.0 + golang.org/x/sys v0.22.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.4.0 @@ -158,7 +159,6 @@ require ( go.opentelemetry.io/otel/trace v1.28.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.23.0 // indirect golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect From 685d3af2f573b16173ff34c4e71aa52ec8000b83 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 13:10:12 +0000 Subject: [PATCH 09/34] test: lido-exporter e2e --- e2e/lido-exporter/args_test.go | 453 +++++++++++++++++++++++++++++++++ e2e/lido-exporter/checks.go | 67 +++++ e2e/lido-exporter/metrics.go | 186 ++++++++++++++ 3 files changed, 706 insertions(+) create mode 100644 e2e/lido-exporter/args_test.go create mode 100644 e2e/lido-exporter/checks.go create mode 100644 e2e/lido-exporter/metrics.go diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go new file mode 100644 index 00000000..d57d4be4 --- /dev/null +++ b/e2e/lido-exporter/args_test.go @@ -0,0 +1,453 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "os" + "os/exec" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + base "github.com/NethermindEth/sedge/e2e" +) + +func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "250", "--network", "holesky", "--port", "9980") + time.Sleep(2 * time.Second) + return cmd + }, + // Assert + func(t *testing.T) { + checkPrometheusServerUp(t, 9980) + checkMetrics(t, 9980) + + cmd.Process.Kill() + err := cmd.Wait() + assert.ErrorContains(t, err, "killed") + assert.Equal(t, -1, cmd.ProcessState.ExitCode(), "lido-exporter command should not return a non-zero exit code") + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + func(t *testing.T, binaryPath string) (err error) { + os.Setenv("LIDO_EXPORTER_NODE_OPERATOR_ID", "250") + return + }, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") + time.Sleep(2 * time.Second) + return cmd + }, + // Assert + func(t *testing.T) { + checkPrometheusServerUp(t, 8080) + checkMetrics(t, 8080) + + cmd.Process.Kill() + err := cmd.Wait() + assert.ErrorContains(t, err, "killed") + assert.Equal(t, -1, cmd.ProcessState.ExitCode(), "lido-exporter command should not return a non-zero exit code") + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_ValidArgs_RewardAddress(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter", "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--network", "holesky", "--port", "9981") + time.Sleep(2 * time.Second) + + return cmd + }, + // Assert + func(t *testing.T) { + // With --reward-address, the test take too long to start the prometheus server due to the time it takes to get the NO ID from the reward address + // checkPrometheusServerUp(t, 9981) + // checkMetrics(t, 9981) + + cmd.Process.Kill() + err := cmd.Wait() + assert.ErrorContains(t, err, "killed") + assert.Equal(t, -1, cmd.ProcessState.ExitCode(), "lido-exporter command should not return a non-zero exit code") + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_MissingRequiredArgs(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + func(t *testing.T, binaryPath string) (err error) { + os.Setenv("LIDO_EXPORTER_PORT", "9982") + return + }, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with missing required arguments") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with missing required arguments") + checkPrometheusServerDown(t, 9982) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "lol_what_a_node_operator_id", "--network", "holesky", "--port", "9983") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid node operator ID") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid node operator ID") + checkPrometheusServerDown(t, 9983) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--reward-address", "lol_what_a_reward_address", "--network", "holesky", "--port", "9984") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid reward address") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid reward address") + checkPrometheusServerDown(t, 9984) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_Network(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--network", "lol_what_a_network", "--port", "9985") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid network") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid network") + checkPrometheusServerDown(t, 9985) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--scrape-time", "666", "--network", "holesky", "--port", "9986") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid scrape time") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid scrape time") + checkPrometheusServerDown(t, 9986) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_Port(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--port", "lol_what_a_port", "--network", "holesky") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid port") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid port") + checkPrometheusServerDown(t, 8080) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--rpc-endpoints", "lol_what_a_rpc_endpoint", "--network", "holesky", "--port", "9987") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid RPC endpoints") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid RPC endpoints") + checkPrometheusServerDown(t, 9987) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--ws-endpoints", "lol_what_a_ws_endpoint", "--network", "holesky", "--port", "9988") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.Error(t, err, "lido-exporter command should fail with invalid WebSocket endpoints") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid WebSocket endpoints") + checkPrometheusServerDown(t, 9988) + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_ValidFlags_All(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", + "--rpc-endpoints", "https://ethereum-holesky-rpc.publicnode.com", "https://endpoints.omniatech.io/v1/eth/holesky/public", "https://ethereum-holesky.blockpi.network/v1/rpc/public", + "--ws-endpoints", "https://ethereum-holesky-rpc.publicnode.com,wss://ethereum-holesky-rpc.publicnode.com", // https endpoint should be ignored + "--port", "9989", + "--scrape-time", "1s", + "--network", "holesky", + "--node-operator-id", "250", // should be prioritized over reward address + "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", + ) + time.Sleep(2 * time.Second) + return cmd + }, + // Assert + func(t *testing.T) { + checkPrometheusServerUp(t, 9989) + checkMetrics(t, 9989) + + cmd.Process.Kill() + err := cmd.Wait() + assert.ErrorContains(t, err, "killed") + assert.Equal(t, -1, cmd.ProcessState.ExitCode(), "lido-exporter command should not return a non-zero exit code") + }, + ) + // Run test case + e2eTest.run() +} + +func TestE2E_ValidEnv_All(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + func(t *testing.T, binaryPath string) (err error) { + os.Setenv("LIDO_EXPORTER_RPC_ENDPOINTS", "'https://ethereum-holesky-rpc.publicnode.com','https://endpoints.omniatech.io/v1/eth/holesky/public','https://ethereum-holesky.blockpi.network/v1/rpc/public'") + os.Setenv("LIDO_EXPORTER_WS_ENDPOINTS", "'wss://ethereum-holesky-rpc.publicnode.com'") + os.Setenv("LIDO_EXPORTER_PORT", "9990") + os.Setenv("LIDO_EXPORTER_SCRAPE_TIME", "2s") + os.Setenv("LIDO_EXPORTER_NETWORK", "holesky") + os.Setenv("LIDO_EXPORTER_NODE_OPERATOR_ID", "250") + os.Setenv("LIDO_EXPORTER_REWARD_ADDRESS", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c") + return + }, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") + time.Sleep(2 * time.Second) + return cmd + }, + // Assert + func(t *testing.T) { + checkPrometheusServerUp(t, 9990) + checkMetrics(t, 9990) + + cmd.Process.Kill() + err := cmd.Wait() + assert.ErrorContains(t, err, "killed") + assert.Equal(t, -1, cmd.ProcessState.ExitCode(), "lido-exporter command should not return a non-zero exit code") + }, + ) + // Run test case + e2eTest.run() +} diff --git a/e2e/lido-exporter/checks.go b/e2e/lido-exporter/checks.go new file mode 100644 index 00000000..f5dd42a4 --- /dev/null +++ b/e2e/lido-exporter/checks.go @@ -0,0 +1,67 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "fmt" + "io" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/NethermindEth/sedge/internal/utils" +) + +// checkPrometheusServerUp checks that the prometheus server is up +func checkPrometheusServerUp(t *testing.T, port int) { + t.Helper() + response, err := utils.GetRequest(fmt.Sprintf("http://localhost:%d/metrics", port), 1*time.Second) + require.NoError(t, err, "prometheus server should be up, it is not") + require.Equal(t, http.StatusOK, response.StatusCode, "prometheus server should be up, but it is not") +} + +// checkPrometheusServerDown checks that the prometheus server is down +func checkPrometheusServerDown(t *testing.T, port int) { + t.Helper() + response, err := utils.GetRequest(fmt.Sprintf("http://localhost:%d/metrics", port), 1*time.Second) + require.Error(t, err, "prometheus server should be down, it is not") + require.Nil(t, response, "prometheus server should be down, but it is not") +} + +// checkMetrics checks that the metrics from the prometheus server are valid +// Should be called after checkPrometheusServerUp. +func checkMetrics(t *testing.T, port int) { + t.Helper() + // Get metrics from prometheus + response, err := utils.GetRequest(fmt.Sprintf("http://localhost:%d/metrics", port), 1*time.Second) + require.NoError(t, err, "request to prometheus server should succeed") + require.Equal(t, http.StatusOK, response.StatusCode, "prometheus server should be up, but it is not") + + // Read response body into a string + body, err := io.ReadAll(response.Body) + require.NoError(t, err, "should read response body") + defer response.Body.Close() + + reader := strings.NewReader(string(body)) + metrics, err := parseMetrics(reader) + require.NoError(t, err, "metrics should be parsed successfully") + + // Validate metrics + validateMetrics(t, metrics, expectedMetrics) +} diff --git a/e2e/lido-exporter/metrics.go b/e2e/lido-exporter/metrics.go new file mode 100644 index 00000000..f20bcff4 --- /dev/null +++ b/e2e/lido-exporter/metrics.go @@ -0,0 +1,186 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "io" + "strings" + "testing" + + dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/expfmt" + "gotest.tools/v3/assert" +) + +type ExpectedMetric struct { + Name string + Type string + Help string + Labels []string +} + +var expectedMetrics = map[string]ExpectedMetric{ + "csm_onchain_penalties_total": { + Name: "csm_onchain_penalties_total", + Type: "counter", + Help: "Number of penalties", + Labels: []string{"node_operator_id", "penalty_type", "tx_hash"}, + }, + "csm_onchain_exit_requests_total": { + Name: "csm_onchain_exit_requests_total", + Type: "counter", + Help: "Number of validator exit requests", + Labels: []string{"node_operator_id", "network", "tx_hash"}, + }, + "csm_node_operator_id": { + Name: "csm_node_operator_id", + Type: "gauge", + Help: "Unique identifier for the node operator", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_node_operator_manager_address": { + Name: "csm_node_operator_manager_address", + Type: "gauge", + Help: "Address used to perform routine management operations regarding the CSM Node Operator", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_node_operator_reward_address": { + Name: "csm_node_operator_reward_address", + Type: "gauge", + Help: "Address that is the ultimate recipient of the rewards", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_keys_stuck_validators_count": { + Name: "csm_keys_stuck_validators_count", + Type: "gauge", + Help: "Number of keys stuck in the system. A validator is considered to be stuck if it has not been exited timely following an exit signal from the protocol", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_keys_refunded_validators_count": { + Name: "csm_keys_refunded_validators_count", + Type: "gauge", + Help: "Number of keys refunded", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_keys_exited_validators_count": { + Name: "csm_keys_exited_validators_count", + Type: "gauge", + Help: "Number of keys exited", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_keys_deposited_validators_count": { + Name: "csm_keys_deposited_validators_count", + Type: "gauge", + Help: "Number of keys that already received deposits including withdrawn keys", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_keys_depositable_validators_count": { + Name: "csm_keys_depositable_validators_count", + Type: "gauge", + Help: "Number of keys eligible for deposits", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_added_keys_count": { + Name: "csm_added_keys_count", + Type: "gauge", + Help: "Number of keys added", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_withdrawn_keys_count": { + Name: "csm_withdrawn_keys_count", + Type: "gauge", + Help: "Number of keys withdrawn", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_vetted_keys_count": { + Name: "csm_vetted_keys_count", + Type: "gauge", + Help: "Number of keys vetted", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_enqueued_keys_count": { + Name: "csm_enqueued_keys_count", + Type: "gauge", + Help: "Number of keys in the deposit queue", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_bond_current": { + Name: "csm_bond_current", + Type: "gauge", + Help: "The current amount of bonded ETH", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_bond_required": { + Name: "csm_bond_required", + Type: "gauge", + Help: "The required amount of ETH to maintain", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_bond_excess": { + Name: "csm_bond_excess", + Type: "gauge", + Help: "The amount of excess bond over the required amount", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_bond_missed": { + Name: "csm_bond_missed", + Type: "gauge", + Help: "The amount of bond that is missing", + Labels: []string{"node_operator_id", "network"}, + }, + "csm_non_claimed_rewards": { + Name: "csm_non_claimed_rewards", + Type: "gauge", + Help: "The amount of rewards available for claiming", + Labels: []string{"node_operator_id", "network"}, + }, +} + +func parseMetrics(reader io.Reader) (map[string]*dto.MetricFamily, error) { + parser := expfmt.TextParser{} + return parser.TextToMetricFamilies(reader) +} + +func validateMetrics(t *testing.T, parsedMetrics map[string]*dto.MetricFamily, expectedMetrics map[string]ExpectedMetric) { + t.Helper() + t.Logf("Validating metrics") + foundMetrics := make(map[string]bool) + for name, expected := range expectedMetrics { + metricFamily, found := parsedMetrics[name] + if !found { + t.Logf("Metric %s not found in the response\n", name) + continue + } + foundMetrics[name] = true + + // Check the metric type + assert.Equal(t, metricFamily.GetType().String(), strings.ToUpper(expected.Type), "Metric %s has incorrect type. Expected: %s, Got: %s\n", name, strings.ToUpper(expected.Type), metricFamily.GetType()) + + // Check the help string + assert.Equal(t, metricFamily.GetHelp(), expected.Help, "Metric %s has incorrect help string. Expected: %s, Got: %s\n", name, expected.Help, metricFamily.GetHelp()) + + // Check labels + for _, metric := range metricFamily.Metric { + labelNames := make(map[string]bool) + for _, label := range metric.Label { + labelNames[label.GetName()] = true + } + for _, expectedLabel := range expected.Labels { + assert.Equal(t, labelNames[expectedLabel], true, "Metric %s is missing expected label: %s\n", name, expectedLabel) + } + } + } +} From 4db3f5816a867d4287e99e38462c7d7bf471c9dc Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 13:10:30 +0000 Subject: [PATCH 10/34] doc: Add README for lido-exporter --- cmd/lido-exporter/README.md | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 cmd/lido-exporter/README.md diff --git a/cmd/lido-exporter/README.md b/cmd/lido-exporter/README.md new file mode 100644 index 00000000..51570a79 --- /dev/null +++ b/cmd/lido-exporter/README.md @@ -0,0 +1,53 @@ +# Lido Exporter + +Lido Exporter is a service that exports data from the Lido CSM smart contracts as Prometheus metrics. + +## Features + +- Collects metrics for penalties, exit requests, node operator info, keys info, bond info, and rewards info +- Supports Holesky network (Mainnet support can be easily added) +- Exports metrics in Prometheus format + +## Usage + +### Running with Docker + +1. Build the Docker image: + ``` + docker build -t lido-exporter . + ``` + +2. Run the Docker container: + ``` + docker run -d -p 8080:8080 -e LIDO_EXPORTER_NODE_OPERATOR_ID= -e LIDO_EXPORTER_NETWORK= lido-exporter + ``` + +### Running as a CLI Application + +1. Build the application: + ``` + go build -o lido-exporter cmd/lido-exporter/main.go + ``` + +2. Run the application: + ``` + ./lido-exporter --node-operator-id --network + ``` + +## Configuration + +The service can be configured using the following methods (in order of precedence): + +1. Environment variables +2. Command-line flags + +Available settings: + +- `LIDO_EXPORTER_NODE_OPERATOR_ID` (required): Node Operator ID +- `LIDO_EXPORTER_REWARD_ADDRESS` (optional): Reward address of Node Operator. It is used to calculate Node Operator ID if not set +- `LIDO_EXPORTER_NETWORK`: Network name (default: "holesky") +- `LIDO_EXPORTER_RPC_ENDPOINTS`: Comma-separated list of Ethereum RPC endpoints +- `LIDO_EXPORTER_WS_ENDPOINTS`: Comma-separated list of Ethereum WebSocket endpoints +- `LIDO_EXPORTER_PORT`: Port to listen on (default: "8080") +- `LIDO_EXPORTER_SCRAPE_TIME`: Scrape interval (default: 10s) +- `LIDO_EXPORTER_LOG_LEVEL`: Log level (default: "info") \ No newline at end of file From f2076dfa537edd582188fe9f9464759376d5eea7 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 13:10:49 +0000 Subject: [PATCH 11/34] feat: Add Dockerfile for lido-exporter --- cmd/lido-exporter/Dockerfile | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 cmd/lido-exporter/Dockerfile diff --git a/cmd/lido-exporter/Dockerfile b/cmd/lido-exporter/Dockerfile new file mode 100644 index 00000000..d85297a0 --- /dev/null +++ b/cmd/lido-exporter/Dockerfile @@ -0,0 +1,33 @@ +# Use the official Golang image to build the application +FROM golang:1.22 as builder + +# Set the Current Working Directory inside the container +WORKDIR /app + +# Copy go mod and sum files +COPY go.mod go.sum ./ + +# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed +RUN go mod download + +# Copy the source from the current directory to the Working Directory inside the container +COPY . . + +# Build the Go app +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o lido-exporter ./cmd/lido-exporter + +# Start a new stage from scratch +FROM alpine:latest + +RUN apk --no-cache add ca-certificates + +WORKDIR /root/ + +# Copy the Pre-built binary file from the previous stage +COPY --from=builder /app/lido-exporter . + +# Expose port 8080 to the outside world +EXPOSE 8080 + +# Command to run the executable +ENTRYPOINT ["./lido-exporter"] \ No newline at end of file From d9e6aa2c8e29956df6b4b8d5c94e58cfb745a1ac Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 15:24:42 +0200 Subject: [PATCH 12/34] fix: Rewards test case --- internal/lido/contracts/csfeedistributor/rewards_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/lido/contracts/csfeedistributor/rewards_test.go b/internal/lido/contracts/csfeedistributor/rewards_test.go index 46c359d9..390d270e 100644 --- a/internal/lido/contracts/csfeedistributor/rewards_test.go +++ b/internal/lido/contracts/csfeedistributor/rewards_test.go @@ -39,9 +39,9 @@ func TestRewards(t *testing.T) { wantErr: false, }, { - name: "Rewards for nodeID 182, Holesky", + name: "Rewards for nodeID 250, Holesky", network: "holesky", - nodeID: big.NewInt(182), + nodeID: big.NewInt(250), wantErr: false, }, { From 62546a3db213e7accb189017a38c4de79bd1db4e Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 15:25:46 +0200 Subject: [PATCH 13/34] fix: Unused import --- configs/networks.go | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/networks.go b/configs/networks.go index bd339a74..0892e9b2 100644 --- a/configs/networks.go +++ b/configs/networks.go @@ -19,7 +19,6 @@ import ( "errors" "fmt" "math/rand" - "sort" "time" ) From d58600e9a393c5bbae03d0634da639e2c5d83357 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 17:36:59 +0200 Subject: [PATCH 14/34] chore: Update go.mod --- go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index ffaaab69..25f7b228 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,8 @@ require ( github.com/opencontainers/image-spec v1.1.0 github.com/otiai10/copy v1.9.0 github.com/prometheus/client_golang v1.12.1 + github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a + github.com/prometheus/common v0.32.1 github.com/protolambda/go-keystorev4 v0.0.0-20211007151826-f20444f6d564 github.com/protolambda/zrnt v0.32.2 github.com/protolambda/ztyp v0.2.2 @@ -125,8 +127,6 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect - github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect From b8b417047c05eca97825213353e4597d363bb0c9 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 16:04:57 +0000 Subject: [PATCH 15/34] chore: Update Makefile --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c6d2b157..1101813f 100644 --- a/Makefile +++ b/Makefile @@ -9,11 +9,13 @@ LDFLAGS=-X github.com/NethermindEth/sedge/internal/utils.Version="${SEDGE_VERSIO compile: ## compile: @mkdir -p build @go build -ldflags "${LDFLAGS}" -o build/sedge cmd/sedge/main.go + @go build -ldflags "${LDFLAGS}" -o build/lido-exporter cmd/lido-exporter/main.go compile-linux: ## compile: @mkdir -p build @env GOOS=linux go build -ldflags="${LDFLAGS[*]}" -o build/sedge cmd/sedge/main.go - + @env GOOS=linux go build -ldflags="${LDFLAGS[*]}" -o build/lido-exporter cmd/lido-exporter/main.go + install: compile ## compile the binary and copy it to PATH @sudo cp build/sedge /usr/local/bin @@ -28,11 +30,12 @@ generate: ## generate go files @abigen --abi ./internal/lido/contracts/csfeedistributor/CSFeeDistributor.abi --bin ./internal/lido/contracts/csfeedistributor/CSFeeDistributor.bin --pkg csfeedistributor --out ./internal/lido/contracts/csfeedistributor/CSFeeDistributor.go @abigen --abi ./internal/lido/contracts/csaccounting/CSAccounting.abi --bin ./internal/lido/contracts/csaccounting/CSAccounting.bin --pkg csaccounting --out ./internal/lido/contracts/csaccounting/CSAccounting.go @abigen --abi ./internal/lido/contracts/mevboostrelaylist/MEVBoostRelayAllowedList.abi --bin ./internal/lido/contracts/mevboostrelaylist/MEVBoostRelayAllowedList.bin --pkg mevboostrelaylist --out ./internal/lido/contracts/mevboostrelaylist/MEVBoostRelayAllowedList.go + @abigen --abi ./internal/lido/contracts/vebo/VEBO.abi --bin ./internal/lido/contracts/vebo/VEBO.bin --pkg vebo --out ./internal/lido/contracts/vebo/VEBO.go @go generate ./... test: generate ## run tests @mkdir -p coverage - @go test -coverprofile=coverage/coverage.out -covermode=count ./... + @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests @go test -timeout 20m -count=1 ./e2e/... From 2f0953af004115e15878c9ad11932bb2f9aa1076 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 16:19:54 +0000 Subject: [PATCH 16/34] refac: Remove courtney dependency --- Makefile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 1101813f..0530e47a 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ test-no-e2e: generate ## run tests excluding e2e codecov-test: generate ## unit tests with coverage using the courtney tool @mkdir -p coverage - @courtney/courtney -v -o coverage/coverage.out -t="-skip=TestE2E" ./... + @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m -t="-skip=TestE2E" ./... @go tool cover -html=coverage/coverage.out -o coverage/coverage.html install-gofumpt: ## install gofumpt @@ -58,15 +58,10 @@ install-gofumpt: ## install gofumpt install-mockgen: ## install mockgen go install github.com/golang/mock/mockgen@v1.6.0 -install-courtney: ## Install courtney for code coverage - @git clone https://github.com/dave/courtney - @(cd courtney && go get ./... && go build courtney.go) - @go get ./... - install-abigen: ## install abigen go install github.com/ethereum/go-ethereum/cmd/abigen@latest -install-deps: | install-gofumpt install-courtney install-mockgen install-abigen ## Install some project dependencies +install-deps: | install-gofumpt install-mockgen install-abigen ## Install some project dependencies coverage: ## show tests coverage @go tool cover -html=coverage/coverage.out -o coverage/coverage.html From 60c7a3dd8c08c692cefec4861e272c831d865012 Mon Sep 17 00:00:00 2001 From: AntiD2ta Date: Sun, 15 Sep 2024 16:21:59 +0000 Subject: [PATCH 17/34] chore: Turn some prints into debug logs --- internal/lido/contracts/csfeedistributor/rewards.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/lido/contracts/csfeedistributor/rewards.go b/internal/lido/contracts/csfeedistributor/rewards.go index 1abac93f..4845b6fe 100644 --- a/internal/lido/contracts/csfeedistributor/rewards.go +++ b/internal/lido/contracts/csfeedistributor/rewards.go @@ -19,7 +19,6 @@ import ( "encoding/json" "fmt" "io" - "log" "math/big" "time" @@ -28,6 +27,8 @@ import ( "github.com/NethermindEth/sedge/internal/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" + + log "github.com/sirupsen/logrus" ) // Tree : struct that reperesents Merkle Tree data @@ -92,15 +93,15 @@ func cumulativeFeeShares(treeCID string, nodeID *big.Int) (*big.Int, error) { nodeOperatorId, err1 := convertTreeValuesToBigInt(item.Value[0]) shares, err2 := convertTreeValuesToBigInt(item.Value[1]) if err1 != nil || err2 != nil { - log.Println("Error converting values:", err1, err2) + log.Debugf("Error converting values:", err1, err2) continue } if nodeOperatorId.Cmp(nodeID) == 0 { - log.Printf("shares: %v", shares) + log.Debugf("shares: %v", shares) return shares, nil } } else { - log.Println("Unexpected value format, expected 2 elements") + log.Debugf("Unexpected value format, expected 2 elements") } } return nil, fmt.Errorf("invalid nodeId") From 07390d340b10adb87132005803f23a5254ffd8f7 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Mon, 16 Sep 2024 12:01:30 +0300 Subject: [PATCH 18/34] fix: e2e binary name for Windows --- e2e/e2e.go | 5 +++-- internal/lido/contracts/csfeedistributor/rewards.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/e2e/e2e.go b/e2e/e2e.go index ed566603..ebe676b6 100644 --- a/e2e/e2e.go +++ b/e2e/e2e.go @@ -30,10 +30,11 @@ type E2ETestCase struct { } func (e *E2ETestCase) BinaryPath() string { + binaryName := e.BinaryName if runtime.GOOS == "windows" { - e.BinaryName += ".exe" + binaryName += ".exe" } - return filepath.Join(e.TestDir, e.BinaryName) + return filepath.Join(e.TestDir, binaryName) } func (e *E2ETestCase) InstallGoModules() { diff --git a/internal/lido/contracts/csfeedistributor/rewards.go b/internal/lido/contracts/csfeedistributor/rewards.go index 4845b6fe..f4db79a8 100644 --- a/internal/lido/contracts/csfeedistributor/rewards.go +++ b/internal/lido/contracts/csfeedistributor/rewards.go @@ -93,7 +93,7 @@ func cumulativeFeeShares(treeCID string, nodeID *big.Int) (*big.Int, error) { nodeOperatorId, err1 := convertTreeValuesToBigInt(item.Value[0]) shares, err2 := convertTreeValuesToBigInt(item.Value[1]) if err1 != nil || err2 != nil { - log.Debugf("Error converting values:", err1, err2) + log.Debugf("Error converting values: %v, %v", err1, err2) continue } if nodeOperatorId.Cmp(nodeID) == 0 { From b53a947cd3ad895b8fc255b7389fdfd2c8b410dc Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 13:05:40 +0300 Subject: [PATCH 19/34] refac: Include e2e monitoring stack tests --- Makefile | 4 +- e2e/{ => sedge}/checks.go | 34 +++-- e2e/{ => sedge}/monitoring_stack_test.go | 40 ++++-- e2e/sedge/monitoring_utils.go | 98 ++++++++++++++ e2e/utils.go | 160 ----------------------- go.mod | 23 ++-- go.sum | 53 ++++++-- 7 files changed, 205 insertions(+), 207 deletions(-) rename e2e/{ => sedge}/checks.go (78%) rename e2e/{ => sedge}/monitoring_stack_test.go (76%) create mode 100644 e2e/sedge/monitoring_utils.go diff --git a/Makefile b/Makefile index 0530e47a..fcaeafd0 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 20m -count=1 ./e2e/... + @go test -timeout 25m -count=1 ./e2e/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 20m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 25m -count=1 -skip TestE2E_MonitoringStack ./e2e/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage diff --git a/e2e/checks.go b/e2e/sedge/checks.go similarity index 78% rename from e2e/checks.go rename to e2e/sedge/checks.go index 6b8cb6be..a38a1730 100644 --- a/e2e/checks.go +++ b/e2e/sedge/checks.go @@ -1,3 +1,18 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( @@ -9,6 +24,7 @@ import ( "testing" "time" + base "github.com/NethermindEth/sedge/e2e" "github.com/NethermindEth/sedge/internal/pkg/services" "github.com/cenkalti/backoff" "github.com/docker/docker/client" @@ -90,13 +106,13 @@ func checkPrometheusTargetsUp(t *testing.T, targets ...string) { logPrefix := fmt.Sprintf("checkPrometheusTargetsUp (%d)", tries) promTargets, err = prometheusTargets(t) if err != nil { - return logAndPipeError(t, logPrefix, err) + return base.LogAndPipeError(t, logPrefix, err) } if promTargets.Status != "success" { - return logAndPipeError(t, logPrefix, fmt.Errorf("expected status success, got %s", promTargets.Status)) + return base.LogAndPipeError(t, logPrefix, fmt.Errorf("expected status success, got %s", promTargets.Status)) } if len(promTargets.Data.ActiveTargets) != len(targets) { - return logAndPipeError(t, logPrefix, fmt.Errorf("expected %d targets, got %d", len(targets), len(promTargets.Data.ActiveTargets))) + return base.LogAndPipeError(t, logPrefix, fmt.Errorf("expected %d targets, got %d", len(targets), len(promTargets.Data.ActiveTargets))) } for i, target := range promTargets.Data.ActiveTargets { var labels []string @@ -104,14 +120,14 @@ func checkPrometheusTargetsUp(t *testing.T, targets ...string) { labels = append(labels, label) } if !slices.Contains(labels, "instance") { - return logAndPipeError(t, logPrefix, fmt.Errorf("target %d does not have instance label", i)) + return base.LogAndPipeError(t, logPrefix, fmt.Errorf("target %d does not have instance label", i)) } instanceLabel := target.Labels["instance"] if !slices.Contains(targets, instanceLabel) { - return logAndPipeError(t, logPrefix, fmt.Errorf("target %d instance label is not expected", i)) + return base.LogAndPipeError(t, logPrefix, fmt.Errorf("target %d instance label is not expected", i)) } if target.Health == "unknown" { - return logAndPipeError(t, logPrefix, fmt.Errorf("target %d health is unknown", i)) + return base.LogAndPipeError(t, logPrefix, fmt.Errorf("target %d health is unknown", i)) } } return nil @@ -134,14 +150,14 @@ func checkGrafanaHealth(t *testing.T) { BasicAuth: url.UserPassword("admin", "admin"), }) if err != nil { - return logAndPipeError(t, logPrefix, err) + return base.LogAndPipeError(t, logPrefix, err) } healthResponse, err := gClient.Health() if err != nil { - return logAndPipeError(t, logPrefix, err) + return base.LogAndPipeError(t, logPrefix, err) } if healthResponse.Database != "ok" { - return logAndPipeError(t, logPrefix, fmt.Errorf("expected database ok, got %s", healthResponse.Database)) + return base.LogAndPipeError(t, logPrefix, fmt.Errorf("expected database ok, got %s", healthResponse.Database)) } return nil }, b) diff --git a/e2e/monitoring_stack_test.go b/e2e/sedge/monitoring_stack_test.go similarity index 76% rename from e2e/monitoring_stack_test.go rename to e2e/sedge/monitoring_stack_test.go index 0c54b7dc..9d458f58 100644 --- a/e2e/monitoring_stack_test.go +++ b/e2e/sedge/monitoring_stack_test.go @@ -1,8 +1,24 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package e2e import ( "testing" + base "github.com/NethermindEth/sedge/e2e" "github.com/stretchr/testify/assert" ) @@ -13,13 +29,13 @@ func TestE2E_MonitoringStack_NotInitialized(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "--help") + runErr = base.RunCommand(t, binaryPath, "--help") }, // Assert func(t *testing.T, dataDirPath string) { @@ -40,13 +56,13 @@ func TestE2E_MonitoringStack_Init(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "monitoring", "init") + runErr = base.RunCommand(t, binaryPath, "monitoring", "init") }, // Assert func(t *testing.T, dataDirPath string) { @@ -70,11 +86,11 @@ func TestE2E_MonitoringStack_NotReinstalled(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, sedgePath string) error { - err := runCommand(t, sedgePath, "monitoring", "init") + err := base.RunCommand(t, sedgePath, "monitoring", "init") if err != nil { return err } @@ -91,7 +107,7 @@ func TestE2E_MonitoringStack_NotReinstalled(t *testing.T) { }, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "monitoring", "init") + runErr = base.RunCommand(t, binaryPath, "monitoring", "init") }, // Assert func(t *testing.T, dataDirPath string) { @@ -121,15 +137,15 @@ func TestE2E_MonitoringStack_Clean(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange func(t *testing.T, sedgePath string) error { - return runCommand(t, sedgePath, "monitoring", "init") + return base.RunCommand(t, sedgePath, "monitoring", "init") }, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "monitoring", "clean") + runErr = base.RunCommand(t, binaryPath, "monitoring", "clean") }, // Assert func(t *testing.T, dataDirPath string) { @@ -152,13 +168,13 @@ func TestE2E_MonitoringStack_CleanNonExistent(t *testing.T) { runErr error ) // Build test case - e2eTest := newE2ETestCase( + e2eTest := newE2ESedgeTestCase( t, // Arrange nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = runCommand(t, binaryPath, "monitoring", "clean") + runErr = base.RunCommand(t, binaryPath, "monitoring", "clean") }, // Assert func(t *testing.T, dataDirPath string) { diff --git a/e2e/sedge/monitoring_utils.go b/e2e/sedge/monitoring_utils.go new file mode 100644 index 00000000..06efc5bd --- /dev/null +++ b/e2e/sedge/monitoring_utils.go @@ -0,0 +1,98 @@ +/* +Copyright 2022 Nethermind + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package e2e + +import ( + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "testing" + "time" + + "github.com/NethermindEth/sedge/internal/pkg/services" + "github.com/NethermindEth/sedge/internal/utils" + "github.com/docker/docker/client" +) + +func dataDirPath() (string, error) { + userDataHome := os.Getenv("XDG_DATA_HOME") + if userDataHome == "" { + userHome, err := os.UserHomeDir() + if err != nil { + return "", err + } + userDataHome = filepath.Join(userHome, ".local", "share") + } + return filepath.Join(userDataHome, ".sedge"), nil +} + +type Target struct { + Labels Labels `json:"labels"` + Health string `json:"health"` +} + +type Labels map[string]string + +type Data struct { + ActiveTargets []Target `json:"activeTargets"` +} + +type PrometheusTargetsResponse struct { + Status string `json:"status"` + Data Data `json:"data"` +} + +func prometheusTargets(t *testing.T) (*PrometheusTargetsResponse, error) { + response, err := utils.GetRequest("http://localhost:9090/api/v1/targets", time.Second) + if err != nil { + return nil, err + } + if response.StatusCode != 200 { + return nil, fmt.Errorf("prometheus targets status code should be 200") + } + var r PrometheusTargetsResponse + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + err = json.Unmarshal(body, &r) + if err != nil { + return nil, err + } + return &r, nil +} + +func getContainerIDByName(containerName string) (string, error) { + cli, err := client.NewClientWithOpts( + client.FromEnv, + client.WithAPIVersionNegotiation(), + ) + if err != nil { + return "", err + } + defer cli.Close() + + dockerServiceManager := services.NewDockerServiceManager(cli) + + containerID, err := dockerServiceManager.ContainerID(containerName) + if err != nil { + return "", err + } + + return containerID, nil +} diff --git a/e2e/utils.go b/e2e/utils.go index 8e8418e8..6023ea21 100644 --- a/e2e/utils.go +++ b/e2e/utils.go @@ -16,19 +16,11 @@ limitations under the License. package e2e import ( - "encoding/json" - "fmt" - "io" "os" "os/exec" "path/filepath" "strings" "testing" - "time" - - "github.com/NethermindEth/sedge/internal/pkg/services" - "github.com/NethermindEth/sedge/internal/utils" - "github.com/docker/docker/client" ) func RunSedge(t *testing.T, binaryPath string, args ...string) error { @@ -71,155 +63,3 @@ func LogAndPipeError(t *testing.T, prefix string, err error) error { } return err } - -func dataDirPath() (string, error) { - userDataHome := os.Getenv("XDG_DATA_HOME") - if userDataHome == "" { - userHome, err := os.UserHomeDir() - if err != nil { - return "", err - } - userDataHome = filepath.Join(userHome, ".local", "share") - } - return filepath.Join(userDataHome, ".sedge"), nil -} - -type Target struct { - Labels Labels `json:"labels"` - Health string `json:"health"` -} - -type Labels map[string]string - -type Data struct { - ActiveTargets []Target `json:"activeTargets"` -} - -type PrometheusTargetsResponse struct { - Status string `json:"status"` - Data Data `json:"data"` -} - -func prometheusTargets(t *testing.T) (*PrometheusTargetsResponse, error) { - response, err := utils.GetRequest("http://localhost:9090/api/v1/targets", time.Second) - if err != nil { - return nil, err - } - if response.StatusCode != 200 { - return nil, fmt.Errorf("prometheus targets status code should be 200") - } - var r PrometheusTargetsResponse - body, err := io.ReadAll(response.Body) - if err != nil { - return nil, err - } - err = json.Unmarshal(body, &r) - if err != nil { - return nil, err - } - return &r, nil -} - -func logAndPipeError(t *testing.T, prefix string, err error) error { - t.Helper() - if err != nil { - t.Log(prefix, err) - } - return err -} - -func getContainerIDByName(containerName string) (string, error) { - cli, err := client.NewClientWithOpts( - client.FromEnv, - client.WithAPIVersionNegotiation(), - ) - if err != nil { - return "", err - } - defer cli.Close() - - dockerServiceManager := services.NewDockerServiceManager(cli) - - containerID, err := dockerServiceManager.ContainerID(containerName) - if err != nil { - return "", err - } - - return containerID, nil -} - -func dataDirPath() (string, error) { - userDataHome := os.Getenv("XDG_DATA_HOME") - if userDataHome == "" { - userHome, err := os.UserHomeDir() - if err != nil { - return "", err - } - userDataHome = filepath.Join(userHome, ".local", "share") - } - return filepath.Join(userDataHome, ".sedge"), nil -} - -type Target struct { - Labels Labels `json:"labels"` - Health string `json:"health"` -} - -type Labels map[string]string - -type Data struct { - ActiveTargets []Target `json:"activeTargets"` -} - -type PrometheusTargetsResponse struct { - Status string `json:"status"` - Data Data `json:"data"` -} - -func prometheusTargets(t *testing.T) (*PrometheusTargetsResponse, error) { - response, err := utils.GetRequest("http://localhost:9090/api/v1/targets", time.Second) - if err != nil { - return nil, err - } - if response.StatusCode != 200 { - return nil, fmt.Errorf("prometheus targets status code should be 200") - } - var r PrometheusTargetsResponse - body, err := io.ReadAll(response.Body) - if err != nil { - return nil, err - } - err = json.Unmarshal(body, &r) - if err != nil { - return nil, err - } - return &r, nil -} - -func logAndPipeError(t *testing.T, prefix string, err error) error { - t.Helper() - if err != nil { - t.Log(prefix, err) - } - return err -} - -func getContainerIDByName(containerName string) (string, error) { - cli, err := client.NewClientWithOpts( - client.FromEnv, - client.WithAPIVersionNegotiation(), - ) - if err != nil { - return "", err - } - defer cli.Close() - - dockerServiceManager := services.NewDockerServiceManager(cli) - - containerID, err := dockerServiceManager.ContainerID(containerName) - if err != nil { - return "", err - } - - return containerID, nil -} diff --git a/go.mod b/go.mod index 25f7b228..347e1f23 100644 --- a/go.mod +++ b/go.mod @@ -24,9 +24,9 @@ require ( github.com/joho/godotenv v1.5.1 github.com/opencontainers/image-spec v1.1.0 github.com/otiai10/copy v1.9.0 - github.com/prometheus/client_golang v1.12.1 - github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a - github.com/prometheus/common v0.32.1 + github.com/prometheus/client_golang v1.19.1 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.48.0 github.com/protolambda/go-keystorev4 v0.0.0-20211007151826-f20444f6d564 github.com/protolambda/zrnt v0.32.2 github.com/protolambda/ztyp v0.2.2 @@ -35,6 +35,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.7.0 + github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 github.com/thoas/go-funk v0.9.3 github.com/tyler-smith/go-bip39 v1.1.0 @@ -72,7 +73,6 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect - github.com/creack/pty v1.1.18 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -88,19 +88,19 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uilive v0.0.4 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -108,7 +108,6 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -127,9 +126,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/protolambda/bls12-381-util v0.1.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect @@ -137,7 +134,6 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect @@ -150,13 +146,13 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.9.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/term v0.22.0 // indirect @@ -164,7 +160,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect - google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index d3b3ef89..aa6c0252 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,9 @@ github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= @@ -115,8 +116,10 @@ github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16M github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE= github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= @@ -171,6 +174,8 @@ github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpx github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/herumi/bls-eth-go-binary v1.29.1 h1:XcNSHYTyNjEUVfWDCE2gtG5r95biTwd7MJUJF09LtSE= github.com/herumi/bls-eth-go-binary v1.29.1/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= @@ -202,8 +207,8 @@ github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4 github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= @@ -217,6 +222,8 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -275,10 +282,13 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6 github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4= github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -306,6 +316,10 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= @@ -314,21 +328,35 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -385,6 +413,10 @@ go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+ go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -431,13 +463,12 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= @@ -461,7 +492,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= @@ -473,6 +504,8 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 4e261410237d318ecbc497fedf409bfdcffe88db Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 13:20:46 +0300 Subject: [PATCH 20/34] fix: Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fcaeafd0..cd14e617 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ test-no-e2e: generate ## run tests excluding e2e codecov-test: generate ## unit tests with coverage using the courtney tool @mkdir -p coverage - @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m -t="-skip=TestE2E" ./... + @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... -skip TestE2E @go tool cover -html=coverage/coverage.out -o coverage/coverage.html install-gofumpt: ## install gofumpt From afac1f2ca98ea29efd006bd0c19ddaf2dcf46259 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 13:54:32 +0300 Subject: [PATCH 21/34] tests: Update e2e monitoring stack --- e2e/sedge/monitoring_stack_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/sedge/monitoring_stack_test.go b/e2e/sedge/monitoring_stack_test.go index 9d458f58..aeea81a4 100644 --- a/e2e/sedge/monitoring_stack_test.go +++ b/e2e/sedge/monitoring_stack_test.go @@ -35,7 +35,7 @@ func TestE2E_MonitoringStack_NotInitialized(t *testing.T) { nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = base.RunCommand(t, binaryPath, "--help") + runErr = base.RunCommand(t, binaryPath, "sedge", "--help") }, // Assert func(t *testing.T, dataDirPath string) { @@ -62,7 +62,7 @@ func TestE2E_MonitoringStack_Init(t *testing.T) { nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = base.RunCommand(t, binaryPath, "monitoring", "init") + runErr = base.RunCommand(t, binaryPath, "sedge", "monitoring", "init") }, // Assert func(t *testing.T, dataDirPath string) { @@ -90,7 +90,7 @@ func TestE2E_MonitoringStack_NotReinstalled(t *testing.T) { t, // Arrange func(t *testing.T, sedgePath string) error { - err := base.RunCommand(t, sedgePath, "monitoring", "init") + err := base.RunCommand(t, sedgePath, "sedge", "monitoring", "init") if err != nil { return err } @@ -107,7 +107,7 @@ func TestE2E_MonitoringStack_NotReinstalled(t *testing.T) { }, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = base.RunCommand(t, binaryPath, "monitoring", "init") + runErr = base.RunCommand(t, binaryPath, "sedge", "monitoring", "init") }, // Assert func(t *testing.T, dataDirPath string) { @@ -141,11 +141,11 @@ func TestE2E_MonitoringStack_Clean(t *testing.T) { t, // Arrange func(t *testing.T, sedgePath string) error { - return base.RunCommand(t, sedgePath, "monitoring", "init") + return base.RunCommand(t, sedgePath, "sedge", "monitoring", "init") }, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = base.RunCommand(t, binaryPath, "monitoring", "clean") + runErr = base.RunCommand(t, binaryPath, "sedge", "monitoring", "clean") }, // Assert func(t *testing.T, dataDirPath string) { @@ -174,7 +174,7 @@ func TestE2E_MonitoringStack_CleanNonExistent(t *testing.T) { nil, // Act func(t *testing.T, binaryPath string, dataDirPath string) { - runErr = base.RunCommand(t, binaryPath, "monitoring", "clean") + runErr = base.RunCommand(t, binaryPath, "sedge", "monitoring", "clean") }, // Assert func(t *testing.T, dataDirPath string) { From de0e846e93c165392015deedd8398a94cc2cbe76 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 15:07:15 +0300 Subject: [PATCH 22/34] feat: Validate Node Operator ID --- cmd/lido-exporter/cli/lido_exporter.go | 3 +++ e2e/lido-exporter/args_test.go | 30 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/cmd/lido-exporter/cli/lido_exporter.go b/cmd/lido-exporter/cli/lido_exporter.go index 36c4ac61..6e4975bb 100644 --- a/cmd/lido-exporter/cli/lido_exporter.go +++ b/cmd/lido-exporter/cli/lido_exporter.go @@ -114,6 +114,9 @@ func run(cmd *cobra.Command, args []string) { if !ok { log.Fatalf("Failed to convert Node Operator ID to big.Int: %s", nodeOperatorID) } + if nodeOperatorIDBigInt.Sign() < 0 { // Check if the value is negative + log.Fatalf("Node Operator ID cannot be negative: %s", nodeOperatorID) + } } else { if !utils.IsAddress(rewardAddress) { log.Fatalf("Invalid reward address: %s", rewardAddress) diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index d57d4be4..410288bd 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -451,3 +451,33 @@ func TestE2E_ValidEnv_All(t *testing.T) { // Run test case e2eTest.run() } + +func TestE2E_InvalidArgs_NegativeNodeID(t *testing.T) { + t.Parallel() + // Test context + var ( + cmd *exec.Cmd + ) + // Build test case + e2eTest := newE2ELidoExporterTestCase( + t, + // Arrange + nil, + // Act + func(t *testing.T, binaryPath string) *exec.Cmd { + cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "-2", "--network", "holesky", "--port", "9983") + return cmd + }, + // Assert + func(t *testing.T) { + err := cmd.Wait() + assert.NotContains(t, err.Error(), "killed") + assert.Error(t, err, "lido-exporter command should fail with invalid node operator ID") + // cmd should return status code 1 + assert.Equal(t, 1, cmd.ProcessState.ExitCode(), "lido-exporter command should fail with invalid node operator ID") + checkPrometheusServerDown(t, 9983) + }, + ) + // Run test case + e2eTest.run() +} From cb7e5580c96bd9f64f2d7c74e7c1eb96c470a6d1 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 15:41:02 +0300 Subject: [PATCH 23/34] tests: Increase timeout --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cd14e617..e7aa0355 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 25m -count=1 ./e2e/... + @go test -timeout 30m -count=1 ./e2e/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 25m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 30m -count=1 -skip TestE2E_MonitoringStack ./e2e/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage From e37fb5ba464a704e0b328232beced714cc79db01 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 16:37:30 +0300 Subject: [PATCH 24/34] test: Increase timeout for e2e tests --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e7aa0355..6ae74020 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 30m -count=1 ./e2e/... + @go test -timeout 50m -count=1 ./e2e/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 30m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 50m -count=1 -skip TestE2E_MonitoringStack ./e2e/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage From 12ee06a1de977b3297632a939adbac48ec6e3fa0 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Tue, 17 Sep 2024 17:41:15 +0300 Subject: [PATCH 25/34] test: Adjust clean up for Windows --- cmd/lido-exporter/cli/lido_exporter.go | 2 +- e2e/lido-exporter/cleanup_windows.go | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/cmd/lido-exporter/cli/lido_exporter.go b/cmd/lido-exporter/cli/lido_exporter.go index 6e4975bb..8cd3cff8 100644 --- a/cmd/lido-exporter/cli/lido_exporter.go +++ b/cmd/lido-exporter/cli/lido_exporter.go @@ -70,7 +70,7 @@ func RootCmd() *cobra.Command { cmd.PersistentFlags().StringSlice("rpc-endpoints", nil, "List of Ethereum HTTP RPC endpoints") cmd.PersistentFlags().StringSlice("ws-endpoints", nil, "List of Ethereum WebSocket RPC endpoints") cmd.PersistentFlags().String("port", "8080", "Port where the metrics will be exported.") - cmd.PersistentFlags().Duration("scrape-time", 10*time.Second, "Time interval for scraping metrics. Values should be in the format of 10s, 1m, 1h, etc.") + cmd.PersistentFlags().Duration("scrape-time", 30*time.Second, "Time interval for scraping metrics. Values should be in the format of 10s, 1m, 1h, etc.") cmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set Log Level, e.g panic, fatal, error, warn, warning, info, debug, trace") viper.BindPFlag("node-operator-id", cmd.PersistentFlags().Lookup("node-operator-id")) diff --git a/e2e/lido-exporter/cleanup_windows.go b/e2e/lido-exporter/cleanup_windows.go index 35b0e7bd..b0ace0b8 100644 --- a/e2e/lido-exporter/cleanup_windows.go +++ b/e2e/lido-exporter/cleanup_windows.go @@ -24,9 +24,20 @@ import ( func (e *e2eLidoExporterTestCase) Cleanup() { if e.pid != 0 { - err := windows.GenerateConsoleCtrlEvent(windows.CTRL_C_EVENT, uint32(e.pid)) - if err != nil { - e.T.Fatalf("error sending CTRL_C_EVENT to process %d: %v", e.pid, err) + // Check if the process is still running + handle, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(e.pid)) + if err == nil { + defer func() { + if closeErr := windows.CloseHandle(handle); closeErr != nil { + e.T.Fatalf("error closing handle: %v", closeErr) + } + }() + + // Terminate Process + err = windows.TerminateProcess(handle, 0) // Exit code 0 + if err != nil { + e.T.Fatalf("error terminating process %d: %v", e.pid, err) + } } } } From eef4f9bd3f149f46b427a8a7b173bd147fd0dd3e Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 01:16:28 +0300 Subject: [PATCH 26/34] test: Increase test sleep duration --- Makefile | 4 ++-- e2e/lido-exporter/args_test.go | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 6ae74020..6aa115b6 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 50m -count=1 ./e2e/... + @go test -timeout 120m -count=1 ./e2e/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 50m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 120m -count=1 -skip TestE2E_MonitoringStack ./e2e/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index 410288bd..be755a08 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -40,7 +40,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "250", "--network", "holesky", "--port", "9980") - time.Sleep(2 * time.Second) + time.Sleep(5* time.Second) return cmd }, // Assert @@ -75,7 +75,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(2 * time.Second) + time.Sleep(5* time.Second) return cmd }, // Assert @@ -107,7 +107,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter", "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--network", "holesky", "--port", "9981") - time.Sleep(2 * time.Second) + time.Sleep(5* time.Second) return cmd }, @@ -393,7 +393,7 @@ func TestE2E_ValidFlags_All(t *testing.T) { "--node-operator-id", "250", // should be prioritized over reward address "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", ) - time.Sleep(2 * time.Second) + time.Sleep(5* time.Second) return cmd }, // Assert @@ -434,7 +434,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(2 * time.Second) + time.Sleep(5* time.Second) return cmd }, // Assert From 9f32bfc5469e7a12ba31cb00ae0e6caa3ed71f7b Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 01:19:04 +0300 Subject: [PATCH 27/34] style: Adjust formatting --- e2e/lido-exporter/args_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index be755a08..9480657f 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -40,7 +40,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "250", "--network", "holesky", "--port", "9980") - time.Sleep(5* time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -75,7 +75,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(5* time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -107,7 +107,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter", "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--network", "holesky", "--port", "9981") - time.Sleep(5* time.Second) + time.Sleep(5 * time.Second) return cmd }, @@ -393,7 +393,7 @@ func TestE2E_ValidFlags_All(t *testing.T) { "--node-operator-id", "250", // should be prioritized over reward address "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", ) - time.Sleep(5* time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -434,7 +434,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(5* time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert From 14416d0841063fa45782ed4992b43a16549ffeb5 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 12:35:11 +0300 Subject: [PATCH 28/34] test: Adjust timeout --- e2e/lido-exporter/args_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index 9480657f..e418fb05 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -40,7 +40,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "250", "--network", "holesky", "--port", "9980") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -75,7 +75,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -107,7 +107,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter", "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--network", "holesky", "--port", "9981") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, @@ -388,12 +388,12 @@ func TestE2E_ValidFlags_All(t *testing.T) { "--rpc-endpoints", "https://ethereum-holesky-rpc.publicnode.com", "https://endpoints.omniatech.io/v1/eth/holesky/public", "https://ethereum-holesky.blockpi.network/v1/rpc/public", "--ws-endpoints", "https://ethereum-holesky-rpc.publicnode.com,wss://ethereum-holesky-rpc.publicnode.com", // https endpoint should be ignored "--port", "9989", - "--scrape-time", "1s", + "--scrape-time", "40s", "--network", "holesky", "--node-operator-id", "250", // should be prioritized over reward address "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", ) - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -434,7 +434,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert From 3dc2bb2a909d64124b5569da1a38139484c04371 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 14:37:58 +0300 Subject: [PATCH 29/34] test: Run tests sequentially --- Makefile | 4 ++-- e2e/lido-exporter/args_test.go | 38 +++++++++++++++++----------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 6aa115b6..c19ccf68 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 120m -count=1 ./e2e/... + @go test -timeout 60m -count=1 ./e2e/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 120m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 60m -count=1 -skip TestE2E_MonitoringStack ./e2e/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index e418fb05..f3589b93 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -27,7 +27,7 @@ import ( ) func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -40,7 +40,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "250", "--network", "holesky", "--port", "9980") - time.Sleep(2 * time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -59,7 +59,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { } func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -75,7 +75,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(2 * time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -94,7 +94,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { } func TestE2E_ValidArgs_RewardAddress(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -107,7 +107,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter", "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--network", "holesky", "--port", "9981") - time.Sleep(2 * time.Second) + time.Sleep(5 * time.Second) return cmd }, @@ -128,7 +128,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { } func TestE2E_MissingRequiredArgs(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -163,7 +163,7 @@ func TestE2E_MissingRequiredArgs(t *testing.T) { } func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -193,7 +193,7 @@ func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { } func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -223,7 +223,7 @@ func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { } func TestE2E_InvalidArgs_Network(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -253,7 +253,7 @@ func TestE2E_InvalidArgs_Network(t *testing.T) { } func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -283,7 +283,7 @@ func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { } func TestE2E_InvalidArgs_Port(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -313,7 +313,7 @@ func TestE2E_InvalidArgs_Port(t *testing.T) { } func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -343,7 +343,7 @@ func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { } func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -372,7 +372,7 @@ func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { } func TestE2E_ValidFlags_All(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -393,7 +393,7 @@ func TestE2E_ValidFlags_All(t *testing.T) { "--node-operator-id", "250", // should be prioritized over reward address "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", ) - time.Sleep(2 * time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -412,7 +412,7 @@ func TestE2E_ValidFlags_All(t *testing.T) { } func TestE2E_ValidEnv_All(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd @@ -434,7 +434,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(2 * time.Second) + time.Sleep(5 * time.Second) return cmd }, // Assert @@ -453,7 +453,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { } func TestE2E_InvalidArgs_NegativeNodeID(t *testing.T) { - t.Parallel() + //t.Parallel() // Test context var ( cmd *exec.Cmd From 32b170442c9872ac66829934d9fed081e4a7ae81 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 14:46:01 +0300 Subject: [PATCH 30/34] style: Adjust formatting --- e2e/lido-exporter/args_test.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index f3589b93..9e159635 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -27,7 +27,7 @@ import ( ) func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -59,7 +59,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { } func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -94,7 +94,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { } func TestE2E_ValidArgs_RewardAddress(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -128,7 +128,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { } func TestE2E_MissingRequiredArgs(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -163,7 +163,7 @@ func TestE2E_MissingRequiredArgs(t *testing.T) { } func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -193,7 +193,7 @@ func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { } func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -223,7 +223,7 @@ func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { } func TestE2E_InvalidArgs_Network(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -253,7 +253,7 @@ func TestE2E_InvalidArgs_Network(t *testing.T) { } func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -283,7 +283,7 @@ func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { } func TestE2E_InvalidArgs_Port(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -313,7 +313,7 @@ func TestE2E_InvalidArgs_Port(t *testing.T) { } func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -343,7 +343,7 @@ func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { } func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -372,7 +372,7 @@ func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { } func TestE2E_ValidFlags_All(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -412,7 +412,7 @@ func TestE2E_ValidFlags_All(t *testing.T) { } func TestE2E_ValidEnv_All(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd @@ -453,7 +453,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { } func TestE2E_InvalidArgs_NegativeNodeID(t *testing.T) { - //t.Parallel() + // t.Parallel() // Test context var ( cmd *exec.Cmd From 71202943d7a6fd75b03976b41178cf14568630bb Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 15:58:23 +0300 Subject: [PATCH 31/34] test: Increase timeout --- cmd/lido-exporter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lido-exporter/README.md b/cmd/lido-exporter/README.md index 51570a79..b23767f1 100644 --- a/cmd/lido-exporter/README.md +++ b/cmd/lido-exporter/README.md @@ -49,5 +49,5 @@ Available settings: - `LIDO_EXPORTER_RPC_ENDPOINTS`: Comma-separated list of Ethereum RPC endpoints - `LIDO_EXPORTER_WS_ENDPOINTS`: Comma-separated list of Ethereum WebSocket endpoints - `LIDO_EXPORTER_PORT`: Port to listen on (default: "8080") -- `LIDO_EXPORTER_SCRAPE_TIME`: Scrape interval (default: 10s) +- `LIDO_EXPORTER_SCRAPE_TIME`: Scrape interval (default: 30s) - `LIDO_EXPORTER_LOG_LEVEL`: Log level (default: "info") \ No newline at end of file From 13969a562b9f9afd84900c3c8983a5f411b875ea Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 20:29:50 +0300 Subject: [PATCH 32/34] test: Increase timeout --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c19ccf68..6aa115b6 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 60m -count=1 ./e2e/... + @go test -timeout 120m -count=1 ./e2e/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 60m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 120m -count=1 -skip TestE2E_MonitoringStack ./e2e/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage From 4eadbd8d861a26d6c5d6bb4bd9120c3ffa3c1b77 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Wed, 18 Sep 2024 21:53:36 +0300 Subject: [PATCH 33/34] test: Skip lido-exporter e2e tests --- Makefile | 20 +++++++++++++++-- e2e/lido-exporter/args_test.go | 40 +++++++++++++++++----------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 6aa115b6..5caadccb 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,22 @@ compile-linux: ## compile: @env GOOS=linux go build -ldflags="${LDFLAGS[*]}" -o build/sedge cmd/sedge/main.go @env GOOS=linux go build -ldflags="${LDFLAGS[*]}" -o build/lido-exporter cmd/lido-exporter/main.go +compile-sedge: + @mkdir -p build + @go build -ldflags "${LDFLAGS}" -o build/sedge cmd/sedge/main.go + +compile-lido-exporter: + @mkdir -p build + @go build -ldflags "${LDFLAGS}" -o build/lido-exporter cmd/lido-exporter/main.go + +compile-sedge-linux: + @mkdir -p build + @env GOOS=linux go build -ldflags="${LDFLAGS[*]}" -o build/sedge cmd/sedge/main.go + +compile-lido-exporter-linux: + @mkdir -p build + @env GOOS=linux go build -ldflags="${LDFLAGS[*]}" -o build/lido-exporter cmd/lido-exporter/main.go + install: compile ## compile the binary and copy it to PATH @sudo cp build/sedge /usr/local/bin @@ -38,10 +54,10 @@ test: generate ## run tests @go test -coverprofile=coverage/coverage.out -covermode=count -timeout 25m ./... e2e-test: generate ## Run e2e tests - @go test -timeout 120m -count=1 ./e2e/... + @go test -timeout 25m -count=1 ./e2e/sedge/... e2e-test-windows: generate ## Run e2e tests on Windows - @go test -timeout 120m -count=1 -skip TestE2E_MonitoringStack ./e2e/... + @go test -timeout 25m -count=1 -skip TestE2E_MonitoringStack ./e2e/sedge/... test-no-e2e: generate ## run tests excluding e2e @mkdir -p coverage diff --git a/e2e/lido-exporter/args_test.go b/e2e/lido-exporter/args_test.go index 9e159635..410288bd 100644 --- a/e2e/lido-exporter/args_test.go +++ b/e2e/lido-exporter/args_test.go @@ -27,7 +27,7 @@ import ( ) func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -40,7 +40,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "250", "--network", "holesky", "--port", "9980") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -59,7 +59,7 @@ func TestE2E_ValidArgs_NodeOperatorID(t *testing.T) { } func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -75,7 +75,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -94,7 +94,7 @@ func TestE2E_ValidArgs_EnvNodeOperatorID(t *testing.T) { } func TestE2E_ValidArgs_RewardAddress(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -107,7 +107,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "", "lido-exporter", "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", "--network", "holesky", "--port", "9981") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, @@ -128,7 +128,7 @@ func TestE2E_ValidArgs_RewardAddress(t *testing.T) { } func TestE2E_MissingRequiredArgs(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -163,7 +163,7 @@ func TestE2E_MissingRequiredArgs(t *testing.T) { } func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -193,7 +193,7 @@ func TestE2E_InvalidArgs_NodeOperatorID(t *testing.T) { } func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -223,7 +223,7 @@ func TestE2E_InvalidArgs_RewardAddress(t *testing.T) { } func TestE2E_InvalidArgs_Network(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -253,7 +253,7 @@ func TestE2E_InvalidArgs_Network(t *testing.T) { } func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -283,7 +283,7 @@ func TestE2E_InvalidArgs_ScrapeTime(t *testing.T) { } func TestE2E_InvalidArgs_Port(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -313,7 +313,7 @@ func TestE2E_InvalidArgs_Port(t *testing.T) { } func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -343,7 +343,7 @@ func TestE2E_InvalidArgs_RPCEndpoints(t *testing.T) { } func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -372,7 +372,7 @@ func TestE2E_InvalidArgs_WSEndpoints(t *testing.T) { } func TestE2E_ValidFlags_All(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -388,12 +388,12 @@ func TestE2E_ValidFlags_All(t *testing.T) { "--rpc-endpoints", "https://ethereum-holesky-rpc.publicnode.com", "https://endpoints.omniatech.io/v1/eth/holesky/public", "https://ethereum-holesky.blockpi.network/v1/rpc/public", "--ws-endpoints", "https://ethereum-holesky-rpc.publicnode.com,wss://ethereum-holesky-rpc.publicnode.com", // https endpoint should be ignored "--port", "9989", - "--scrape-time", "40s", + "--scrape-time", "1s", "--network", "holesky", "--node-operator-id", "250", // should be prioritized over reward address "--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", ) - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -412,7 +412,7 @@ func TestE2E_ValidFlags_All(t *testing.T) { } func TestE2E_ValidEnv_All(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd @@ -434,7 +434,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { // Act func(t *testing.T, binaryPath string) *exec.Cmd { cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter") - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) return cmd }, // Assert @@ -453,7 +453,7 @@ func TestE2E_ValidEnv_All(t *testing.T) { } func TestE2E_InvalidArgs_NegativeNodeID(t *testing.T) { - // t.Parallel() + t.Parallel() // Test context var ( cmd *exec.Cmd From 2ecb0644c4a73fe9828e91923554594d07f471e6 Mon Sep 17 00:00:00 2001 From: Haneen Khalifa Date: Thu, 19 Sep 2024 16:22:35 +0300 Subject: [PATCH 34/34] refac: PublicRPCs --- configs/networks.go | 4 ++-- configs/public_rpcs.go | 18 +++++------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/configs/networks.go b/configs/networks.go index 0892e9b2..32583878 100644 --- a/configs/networks.go +++ b/configs/networks.go @@ -81,11 +81,11 @@ func GetPublicRPCs(network string) ([]string, error) { } func GetPublicWSs(network string) ([]string, error) { - ws, exists := networkWSs[network] + ws, exists := networkRPCs[network] if !exists { return nil, fmt.Errorf("invalid network") } - return shuffleRPCs(ws.PublicRPCs), nil + return shuffleRPCs(ws.PublicWSs), nil } func shuffleRPCs(rpcs []string) []string { diff --git a/configs/public_rpcs.go b/configs/public_rpcs.go index c9d22f18..bf5884c2 100644 --- a/configs/public_rpcs.go +++ b/configs/public_rpcs.go @@ -18,6 +18,7 @@ package configs type RPC struct { NetworkName string PublicRPCs []string + PublicWSs []string } var networkRPCs = map[string]RPC{ @@ -31,6 +32,9 @@ var networkRPCs = map[string]RPC{ "https://rpc.flashbots.net", "https://eth.drpc.org", }, + PublicWSs: []string{ + "wss://ethereum-rpc.publicnode.com", + }, }, NetworkHolesky: { NetworkName: NetworkHolesky, @@ -39,19 +43,7 @@ var networkRPCs = map[string]RPC{ "https://endpoints.omniatech.io/v1/eth/holesky/public", "https://ethereum-holesky.blockpi.network/v1/rpc/public", }, - }, -} - -var networkWSs = map[string]RPC{ - NetworkMainnet: { - NetworkName: NetworkMainnet, - PublicRPCs: []string{ - "wss://ethereum-rpc.publicnode.com", - }, - }, - NetworkHolesky: { - NetworkName: NetworkHolesky, - PublicRPCs: []string{ + PublicWSs: []string{ "wss://ethereum-holesky-rpc.publicnode.com", }, },