From d889aba396fff1bff9c44bc01078de91db4869a2 Mon Sep 17 00:00:00 2001 From: Edgars Date: Mon, 9 Feb 2026 16:04:05 +0000 Subject: [PATCH 1/4] feat: update consensus ABI to v0.5 IConsensusMain interface - Replace consensus_main_abi.json with v0.5 IConsensusMain ABI - Add valid_until parameter to addTransaction encoder/decoder - Update actions.py to pass valid_until (default 0 = no expiry) --- .../consensus/abi/consensus_main_abi.json | 949 +++++++----------- .../consensus/consensus_main/decoder.py | 1 + .../consensus/consensus_main/encoder.py | 2 + genlayer_py/contracts/actions.py | 2 + 4 files changed, 344 insertions(+), 610 deletions(-) diff --git a/genlayer_py/consensus/abi/consensus_main_abi.json b/genlayer_py/consensus/abi/consensus_main_abi.json index e0aa589..d6f97c3 100644 --- a/genlayer_py/consensus/abi/consensus_main_abi.json +++ b/genlayer_py/consensus/abi/consensus_main_abi.json @@ -1,127 +1,41 @@ [ { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "account", - "type": "address" - }, - { + "indexed": true, "internalType": "bytes32", - "name": "neededRole", + "name": "txId", "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "CallerNotMessages", - "type": "error" - }, - { - "inputs": [], - "name": "CanNotAppeal", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyTransaction", - "type": "error" - }, - { - "inputs": [], - "name": "FinalizationNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidGhostContract", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidVote", - "type": "error" - }, - { - "inputs": [], - "name": "MaxNumOfIterationsInPendingQueueReached", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numOfMessages", - "type": "uint256" }, { - "internalType": "uint256", - "name": "maxAllocatedMessages", - "type": "uint256" - } - ], - "name": "MaxNumOfMessagesExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "NonGenVMContract", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ + "indexed": true, + "internalType": "address", + "name": "oldActivator", + "type": "address" + }, { + "indexed": true, "internalType": "address", - "name": "owner", + "name": "newActivator", "type": "address" } ], - "name": "OwnableInvalidOwner", - "type": "error" + "name": "ActivatorReplaced", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "account", + "name": "addressManager", "type": "address" } ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuardReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "TransactionNotAtPendingQueueHead", - "type": "error" + "name": "AddressManagerSet", + "type": "event" }, { "anonymous": false, @@ -132,26 +46,14 @@ "name": "txId", "type": "bytes32" }, - { - "indexed": true, - "internalType": "address", - "name": "appealer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "appealBond", - "type": "uint256" - }, { "indexed": false, - "internalType": "address[]", - "name": "appealValidators", - "type": "address[]" + "internalType": "enum ITransactions.TransactionStatus", + "name": "newStatus", + "type": "uint8" } ], - "name": "AppealStarted", + "name": "AllVotesCommitted", "type": "event" }, { @@ -166,17 +68,23 @@ { "indexed": true, "internalType": "address", - "name": "recipient", + "name": "appellant", "type": "address" }, { "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "bond", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "validators", + "type": "address[]" } ], - "name": "ErrorMessage", + "name": "AppealStarted", "type": "event" }, { @@ -184,67 +92,24 @@ "inputs": [ { "indexed": false, - "internalType": "address", - "name": "ghostFactory", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "genManager", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "genTransactions", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "genQueue", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "genStaking", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "genMessages", - "type": "address" + "internalType": "uint256", + "name": "attempted", + "type": "uint256" }, { "indexed": false, - "internalType": "address", - "name": "idleness", - "type": "address" + "internalType": "uint256", + "name": "succeeded", + "type": "uint256" }, { "indexed": false, - "internalType": "address", - "name": "tribunalAppeal", - "type": "address" - } - ], - "name": "ExternalContractsSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" + "internalType": "uint256", + "name": "failed", + "type": "uint256" } ], - "name": "Initialized", + "name": "BatchFinalizationCompleted", "type": "event" }, { @@ -257,19 +122,13 @@ "type": "bytes32" }, { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "activator", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "txSlot", + "type": "uint256" } ], - "name": "InternalMessageProcessed", + "name": "CreatedTransaction", "type": "event" }, { @@ -294,70 +153,7 @@ "type": "address" } ], - "name": "NewTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "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", + "name": "InternalMessageProcessed", "type": "event" }, { @@ -366,23 +162,23 @@ { "indexed": true, "internalType": "bytes32", - "name": "role", + "name": "txId", "type": "bytes32" }, { "indexed": true, "internalType": "address", - "name": "account", + "name": "oldLeader", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "sender", + "name": "newLeader", "type": "address" } ], - "name": "RoleGranted", + "name": "LeaderIdlenessProcessed", "type": "event" }, { @@ -391,23 +187,23 @@ { "indexed": true, "internalType": "bytes32", - "name": "role", + "name": "txId", "type": "bytes32" }, { "indexed": true, "internalType": "address", - "name": "account", + "name": "recipient", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "sender", + "name": "activator", "type": "address" } ], - "name": "RoleRevoked", + "name": "NewTransaction", "type": "event" }, { @@ -418,15 +214,9 @@ "internalType": "bytes32", "name": "txId", "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" } ], - "name": "SlashAppealSubmitted", + "name": "ProcessIdlenessAccepted", "type": "event" }, { @@ -435,7 +225,7 @@ { "indexed": true, "internalType": "bytes32", - "name": "tx_id", + "name": "txId", "type": "bytes32" } ], @@ -473,7 +263,7 @@ { "indexed": true, "internalType": "address", - "name": "sender", + "name": "cancelledBy", "type": "address" } ], @@ -486,11 +276,11 @@ { "indexed": true, "internalType": "bytes32", - "name": "tx_id", + "name": "txId", "type": "bytes32" } ], - "name": "TransactionFinalized", + "name": "TransactionFinalizationFailed", "type": "event" }, { @@ -501,21 +291,9 @@ "internalType": "bytes32", "name": "txId", "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oldValidator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newValidator", - "type": "address" } ], - "name": "TransactionIdleValidatorReplaced", + "name": "TransactionFinalized", "type": "event" }, { @@ -526,15 +304,9 @@ "internalType": "bytes32", "name": "txId", "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "validatorIndex", - "type": "uint256" } ], - "name": "TransactionIdleValidatorReplacementFailed", + "name": "TransactionLeaderRevealed", "type": "event" }, { @@ -562,7 +334,7 @@ { "indexed": true, "internalType": "bytes32", - "name": "tx_id", + "name": "txId", "type": "bytes32" } ], @@ -575,7 +347,7 @@ { "indexed": false, "internalType": "bytes32[]", - "name": "tx_ids", + "name": "txIds", "type": "bytes32[]" } ], @@ -588,7 +360,7 @@ { "indexed": true, "internalType": "bytes32", - "name": "tx_id", + "name": "txId", "type": "bytes32" }, { @@ -607,7 +379,7 @@ { "indexed": true, "internalType": "bytes32", - "name": "tx_id", + "name": "txId", "type": "bytes32" } ], @@ -623,17 +395,17 @@ "name": "txId", "type": "bytes32" }, + { + "indexed": false, + "internalType": "uint256", + "name": "tribunalIndex", + "type": "uint256" + }, { "indexed": true, "internalType": "address", "name": "validator", "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isLastVote", - "type": "bool" } ], "name": "TribunalAppealVoteCommitted", @@ -648,6 +420,12 @@ "name": "txId", "type": "bytes32" }, + { + "indexed": false, + "internalType": "uint256", + "name": "tribunalIndex", + "type": "uint256" + }, { "indexed": true, "internalType": "address", @@ -656,14 +434,70 @@ }, { "indexed": false, - "internalType": "bool", - "name": "isLastVote", - "type": "bool" + "internalType": "enum ITransactions.VoteType", + "name": "voteType", + "type": "uint8" } ], "name": "TribunalAppealVoteRevealed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldValidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newValidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + } + ], + "name": "ValidatorReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "ValueWithdrawalFailed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -726,26 +560,6 @@ "name": "VoteRevealed", "type": "event" }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -753,6 +567,11 @@ "name": "_txId", "type": "bytes32" }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, { "internalType": "bytes", "name": "_vrfProof", @@ -788,13 +607,18 @@ }, { "internalType": "bytes", - "name": "_txData", + "name": "_calldata", "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_validUntil", + "type": "uint256" } ], "name": "addTransaction", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { @@ -817,6 +641,11 @@ "name": "_txId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_tribunalIndex", + "type": "uint256" + }, { "internalType": "bytes32", "name": "_commitHash", @@ -839,6 +668,11 @@ "internalType": "bytes32", "name": "_commitHash", "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" } ], "name": "commitVote", @@ -847,51 +681,41 @@ "type": "function" }, { - "inputs": [], - "name": "contracts", - "outputs": [ - { - "internalType": "contract IGenManager", - "name": "genManager", - "type": "address" - }, - { - "internalType": "contract ITransactions", - "name": "genTransactions", - "type": "address" - }, + "inputs": [ { - "internalType": "contract IQueues", - "name": "genQueue", + "internalType": "address", + "name": "_sender", "type": "address" }, { - "internalType": "contract IGhostFactory", - "name": "ghostFactory", - "type": "address" + "internalType": "uint256", + "name": "_numOfInitialValidators", + "type": "uint256" }, { - "internalType": "contract IGenStaking", - "name": "genStaking", - "type": "address" + "internalType": "uint256", + "name": "_maxRotations", + "type": "uint256" }, { - "internalType": "contract IMessages", - "name": "genMessages", - "type": "address" + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" }, { - "internalType": "contract IIdleness", - "name": "idleness", - "type": "address" + "internalType": "uint256", + "name": "_saltNonce", + "type": "uint256" }, { - "internalType": "contract ITribunalAppeal", - "name": "tribunalAppeal", - "type": "address" + "internalType": "uint256", + "name": "_validUntil", + "type": "uint256" } ], - "stateMutability": "view", + "name": "deploySalted", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { @@ -923,6 +747,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_txIds", + "type": "bytes32[]" + } + ], + "name": "finalizeIdlenessTxs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -936,56 +773,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" + } + ], + "name": "flushExternalMessages", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], - "name": "getContracts", + "name": "getAddressManager", "outputs": [ { - "components": [ - { - "internalType": "contract IGenManager", - "name": "genManager", - "type": "address" - }, - { - "internalType": "contract ITransactions", - "name": "genTransactions", - "type": "address" - }, - { - "internalType": "contract IQueues", - "name": "genQueue", - "type": "address" - }, - { - "internalType": "contract IGhostFactory", - "name": "ghostFactory", - "type": "address" - }, - { - "internalType": "contract IGenStaking", - "name": "genStaking", - "type": "address" - }, - { - "internalType": "contract IMessages", - "name": "genMessages", - "type": "address" - }, - { - "internalType": "contract IIdleness", - "name": "idleness", - "type": "address" - }, - { - "internalType": "contract ITribunalAppeal", - "name": "tribunalAppeal", - "type": "address" - } - ], - "internalType": "struct IConsensusMain.ExternalContracts", + "internalType": "contract IAddressManager", "name": "", - "type": "tuple" + "type": "address" } ], "stateMutability": "view", @@ -995,16 +803,16 @@ "inputs": [ { "internalType": "bytes32", - "name": "role", + "name": "txId", "type": "bytes32" } ], - "name": "getRoleAdmin", + "name": "getPendingTransactionValue", "outputs": [ { - "internalType": "bytes32", + "internalType": "uint256", "name": "", - "type": "bytes32" + "type": "uint256" } ], "stateMutability": "view", @@ -1018,11 +826,11 @@ "type": "address" } ], - "name": "ghostContracts", + "name": "isGhostContract", "outputs": [ { "internalType": "bool", - "name": "isGhost", + "name": "", "type": "bool" } ], @@ -1033,16 +841,11 @@ "inputs": [ { "internalType": "bytes32", - "name": "role", + "name": "_txId", "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" } ], - "name": "grantRole", + "name": "leaderIdleness", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1050,69 +853,94 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" + "components": [ + { + "internalType": "bytes32", + "name": "txId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "saltAsAValidator", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txExecutionHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagesAndOtherFieldsHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "otherExecutionFieldsHash", + "type": "bytes32" + }, + { + "internalType": "enum ITransactions.VoteType", + "name": "resultValue", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum IMessages.MessageType", + "name": "messageType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "onAcceptance", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + } + ], + "internalType": "struct IMessages.SubmittedMessage[]", + "name": "messages", + "type": "tuple[]" + } + ], + "internalType": "struct IConsensusMain.LeaderRevealVoteParams", + "name": "leaderRevealVoteParams", + "type": "tuple" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", + "name": "leaderRevealVote", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { - "internalType": "address", - "name": "recipient", - "type": "address" + "internalType": "bytes32", + "name": "_txId", + "type": "bytes32" } ], - "name": "proceedPendingQueueProcessing", + "name": "processIdleness", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1125,9 +953,9 @@ "type": "bytes32" }, { - "internalType": "bytes", - "name": "_txReceipt", - "type": "bytes" + "internalType": "bytes32", + "name": "_txExecutionHash", + "type": "bytes32" }, { "internalType": "uint256", @@ -1135,36 +963,14 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "enum IMessages.MessageType", - "name": "messageType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "onAcceptance", - "type": "bool" - } - ], - "internalType": "struct IMessages.SubmittedMessage[]", - "name": "_messages", - "type": "tuple[]" + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_eqBlocksOutputs", + "type": "bytes" }, { "internalType": "bytes", @@ -1178,26 +984,27 @@ "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_txIds", + "type": "bytes32[]" + } + ], + "name": "redButtonFinalize", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, { "internalType": "address", - "name": "callerConfirmation", + "name": "ghost", "type": "address" } ], - "name": "renounceRole", + "name": "registerGhostContract", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1209,16 +1016,26 @@ "name": "_txId", "type": "bytes32" }, + { + "internalType": "uint256", + "name": "_tribunalIndex", + "type": "uint256" + }, { "internalType": "bytes32", "name": "_voteHash", "type": "bytes32" }, { - "internalType": "enum ITribunalAppeal.TribunalVoteType", + "internalType": "enum ITransactions.VoteType", "name": "_voteType", "type": "uint8" }, + { + "internalType": "bytes32", + "name": "_otherExecutionFieldsHash", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_nonce", @@ -1247,31 +1064,23 @@ "name": "_voteType", "type": "uint8" }, + { + "internalType": "bytes32", + "name": "_otherExecutionFieldsHash", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_nonce", "type": "uint256" - } - ], - "name": "revealVote", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" }, { - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "_validatorIndex", + "type": "uint256" } ], - "name": "revokeRole", + "name": "revealVote", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1280,46 +1089,11 @@ "inputs": [ { "internalType": "address", - "name": "_ghostFactory", - "type": "address" - }, - { - "internalType": "address", - "name": "_genManager", - "type": "address" - }, - { - "internalType": "address", - "name": "_genTransactions", - "type": "address" - }, - { - "internalType": "address", - "name": "_genQueue", - "type": "address" - }, - { - "internalType": "address", - "name": "_genStaking", - "type": "address" - }, - { - "internalType": "address", - "name": "_genMessages", - "type": "address" - }, - { - "internalType": "address", - "name": "_idleness", - "type": "address" - }, - { - "internalType": "address", - "name": "_tribunalAppeal", + "name": "_addressManager", "type": "address" } ], - "name": "setExternalContracts", + "name": "setAddressManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1336,50 +1110,5 @@ "outputs": [], "stateMutability": "payable", "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_txId", - "type": "bytes32" - } - ], - "name": "submitSlashAppeal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" } -] \ No newline at end of file +] diff --git a/genlayer_py/consensus/consensus_main/decoder.py b/genlayer_py/consensus/consensus_main/decoder.py index f02b14a..e87db38 100644 --- a/genlayer_py/consensus/consensus_main/decoder.py +++ b/genlayer_py/consensus/consensus_main/decoder.py @@ -26,6 +26,7 @@ def decode_add_transaction_data(encoded_data): "encoded": encoded_tx_data, "decoded": decoded_tx_data, }, + "valid_until": abi_decoded[5], } diff --git a/genlayer_py/consensus/consensus_main/encoder.py b/genlayer_py/consensus/consensus_main/encoder.py index 1fe2836..bc24412 100644 --- a/genlayer_py/consensus/consensus_main/encoder.py +++ b/genlayer_py/consensus/consensus_main/encoder.py @@ -16,6 +16,7 @@ def encode_add_transaction_data( num_of_initial_validators: int, max_rotations: int, tx_data: HexStr, + valid_until: int = 0, ): w3 = Web3() consensus_main_contract = w3.eth.contract(abi=CONSENSUS_MAIN_ABI) @@ -29,6 +30,7 @@ def encode_add_transaction_data( num_of_initial_validators, max_rotations, w3.to_bytes(hexstr=tx_data), + valid_until, ], ) function_selector = eth_utils.keccak(text=contract_fn.signature)[:4].hex() diff --git a/genlayer_py/contracts/actions.py b/genlayer_py/contracts/actions.py index 08e69b1..78d1a3e 100644 --- a/genlayer_py/contracts/actions.py +++ b/genlayer_py/contracts/actions.py @@ -245,6 +245,7 @@ def _encode_add_transaction_data( recipient, consensus_max_rotations, data, + valid_until: int = 0, ): consensus_main_contract = self.w3.eth.contract( abi=self.chain.consensus_main_contract["abi"] @@ -258,6 +259,7 @@ def _encode_add_transaction_data( self.chain.default_number_of_initial_validators, consensus_max_rotations, self.w3.to_bytes(hexstr=data), + valid_until, ], ) function_selector = eth_utils.keccak(text=contract_fn.signature)[:4].hex() From 2d4154cacc8265cd0ac25a894de3ec3fe2577114 Mon Sep 17 00:00:00 2001 From: Edgars Date: Tue, 10 Feb 2026 11:45:52 +0000 Subject: [PATCH 2/4] feat: fix WS URL and add consensus contract smoke tests --- genlayer_py/chains/testnet_asimov.py | 2 +- tests/unit/smoke/test_testnet_smoke.py | 118 +++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/genlayer_py/chains/testnet_asimov.py b/genlayer_py/chains/testnet_asimov.py index 1b7aafc..528eb5d 100644 --- a/genlayer_py/chains/testnet_asimov.py +++ b/genlayer_py/chains/testnet_asimov.py @@ -3,7 +3,7 @@ TESTNET_JSON_RPC_URL = "https://zksync-os-testnet-genlayer.zksync.dev" -TESTNET_WS_URL = "wss://zksync-os-testnet-alpha.zksync.dev/ws" +TESTNET_WS_URL = "wss://zksync-os-testnet-genlayer.zksync.dev/ws" EXPLORER_URL = "https://explorer-asimov.genlayer.com/" CONSENSUS_MAIN_CONTRACT = { diff --git a/tests/unit/smoke/test_testnet_smoke.py b/tests/unit/smoke/test_testnet_smoke.py index 6be5dc7..8ed50fe 100644 --- a/tests/unit/smoke/test_testnet_smoke.py +++ b/tests/unit/smoke/test_testnet_smoke.py @@ -50,3 +50,121 @@ def test_chain_id_matches(self): def test_block_number_positive(self): w3 = Web3(Web3.HTTPProvider(TESTNET_JSON_RPC_URL)) assert w3.eth.block_number > 0 + + +@pytest.mark.testnet +class TestConsensusContractReadOnly: + """Verify the consensus main contract ABI matches the deployed contract.""" + + @pytest.fixture(autouse=True) + def setup(self): + from genlayer_py.consensus.abi import CONSENSUS_MAIN_ABI + + self.w3 = Web3(Web3.HTTPProvider(TESTNET_JSON_RPC_URL)) + self.contract = self.w3.eth.contract( + address=Web3.to_checksum_address(CONSENSUS_MAIN_CONTRACT["address"]), + abi=CONSENSUS_MAIN_ABI, + ) + + def test_get_address_manager(self): + """Call getAddressManager() — zero-arg view function.""" + result = self.contract.functions.getAddressManager().call() + # Should return a valid non-zero address + assert Web3.is_address(result) + assert result != "0x0000000000000000000000000000000000000000" + + def test_is_ghost_contract_zero_address(self): + """Call isGhostContract with the zero address.""" + result = self.contract.functions.isGhostContract( + "0x0000000000000000000000000000000000000000" + ).call() + assert isinstance(result, bool) + + def test_get_pending_transaction_value_zero(self): + """Call getPendingTransactionValue with a zero txId.""" + result = self.contract.functions.getPendingTransactionValue(b"\x00" * 32).call() + assert isinstance(result, int) + assert result == 0 + + +@pytest.mark.testnet +class TestEncoderDecoderRoundTrip: + """Verify encode/decode round-trip for addTransaction data.""" + + def test_round_trip_call(self): + from genlayer_py.consensus.consensus_main.encoder import ( + encode_add_transaction_data, + encode_tx_data_call, + ) + from genlayer_py.consensus.consensus_main.decoder import ( + decode_add_transaction_data, + ) + + sender = "0xABcdEFABcdEFabcdEfAbCdefAbCdEFaBcDEFabCD" + recipient = "0x1111111111111111111111111111111111111111" + num_validators = 7 + max_rotations = 2 + + tx_data = encode_tx_data_call( + function_name="my_method", + leader_only=True, + args=["hello"], + kwargs={"key": "value"}, + ) + + encoded = encode_add_transaction_data( + sender_address=sender, + recipient_address=recipient, + num_of_initial_validators=num_validators, + max_rotations=max_rotations, + tx_data=tx_data.hex() if isinstance(tx_data, bytes) else tx_data, + ) + + decoded = decode_add_transaction_data(encoded) + assert decoded["sender_address"].lower() == sender.lower() + assert decoded["recipient_address"].lower() == recipient.lower() + assert decoded["num_of_initial_validators"] == num_validators + assert decoded["max_rotations"] == max_rotations + assert decoded["tx_data"]["decoded"]["call_data"]["method"] == "my_method" + assert decoded["tx_data"]["decoded"]["leader_only"] is True + assert decoded["tx_data"]["decoded"]["type"] == "call" + + def test_round_trip_deploy(self): + from genlayer_py.consensus.consensus_main.encoder import ( + encode_add_transaction_data, + encode_tx_data_deploy, + ) + from genlayer_py.consensus.consensus_main.decoder import ( + decode_add_transaction_data, + ) + + sender = "0xABcdEFABcdEFabcdEfAbCdefAbCdEFaBcDEFabCD" + recipient = "0x0000000000000000000000000000000000000000" + code = "print('hello world')" + + tx_data = encode_tx_data_deploy( + code=code, + leader_only=False, + args=[], + kwargs={}, + ) + + encoded = encode_add_transaction_data( + sender_address=sender, + recipient_address=recipient, + num_of_initial_validators=5, + max_rotations=3, + tx_data=tx_data, + ) + + decoded = decode_add_transaction_data(encoded) + assert decoded["sender_address"].lower() == sender.lower() + assert decoded["recipient_address"].lower() == recipient.lower() + assert decoded["num_of_initial_validators"] == 5 + assert decoded["max_rotations"] == 3 + assert ( + Web3.to_bytes(hexstr=decoded["tx_data"]["decoded"]["code"]).decode("utf-8") + == code + ) + assert decoded["tx_data"]["decoded"]["leader_only"] is False + assert decoded["tx_data"]["decoded"]["type"] == "deploy" From 5d029d4992cc57be9b01d5a9aea90c2920fbf595 Mon Sep 17 00:00:00 2001 From: Edgars Date: Tue, 10 Feb 2026 12:16:27 +0000 Subject: [PATCH 3/4] ci: add daily smoke test workflow, exclude testnet tests from PR CI --- .github/workflows/smoke.yml | 31 +++++++++++++++++++++++++++++++ .github/workflows/tests.yml | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/smoke.yml diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml new file mode 100644 index 0000000..9702a43 --- /dev/null +++ b/.github/workflows/smoke.yml @@ -0,0 +1,31 @@ +name: Smoke Tests + +on: + schedule: + - cron: '0 8 * * *' + workflow_dispatch: + +jobs: + smoke: + name: Testnet Smoke Tests + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + matrix: + python-version: ['3.12'] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install . + pip install -r requirements.test.txt + + - name: Run smoke tests + run: pytest tests/unit/smoke -v -m testnet diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6c6ea4c..88f1dda 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,4 +29,4 @@ jobs: pip install -r requirements.test.txt - name: Action | Run Unit Tests - run: pytest tests/unit --disable-warnings -v + run: pytest tests/unit --disable-warnings -v -m "not testnet" From 51ad32b8b7d86b9a9d0d9c464e0f4c53f752e080 Mon Sep 17 00:00:00 2001 From: Edgars Date: Tue, 10 Feb 2026 12:23:34 +0000 Subject: [PATCH 4/4] ci: add PR trigger to smoke tests (non-blocking) --- .github/workflows/smoke.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 9702a43..2310035 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -1,6 +1,7 @@ name: Smoke Tests on: + pull_request: schedule: - cron: '0 8 * * *' workflow_dispatch: @@ -10,6 +11,7 @@ jobs: name: Testnet Smoke Tests runs-on: ubuntu-latest timeout-minutes: 5 + continue-on-error: true strategy: matrix: python-version: ['3.12']