diff --git a/.gas-snapshot b/.gas-snapshot new file mode 100644 index 0000000..7dfdd05 --- /dev/null +++ b/.gas-snapshot @@ -0,0 +1,257 @@ +AuthenticatorTest:test_buildLocalAccounts_BuildsCorrectly() (gas: 36093) +AuthenticatorTest:test_decodeTxID_RevertsIf_LengthIsLong() (gas: 9778) +AuthenticatorTest:test_decodeTxID_RevertsIf_LengthIsShort() (gas: 9388) +AuthenticatorTest:test_decodeTxID_RevertsIf_LengthIsZero() (gas: 9599) +AuthenticatorTest:test_decodeTxID_SucceedsWith32Bytes() (gas: 6825) +AuthenticatorTest:test_extSignTx_RevertsIf_TxIDLengthInvalid() (gas: 30496) +AuthenticatorTest:test_extSignTx_RevertsIf_VerificationFails() (gas: 49006) +AuthenticatorTest:test_extSignTx_SucceedsAsCompletedAndEmitsEvent() (gas: 84175) +AuthenticatorTest:test_extSignTx_SucceedsAsPending() (gas: 44306) +AuthenticatorTest:test_signTx_RevertsIf_SignerNotEqualSender() (gas: 30692) +AuthenticatorTest:test_signTx_RevertsIf_SignersLengthMultiple() (gas: 60751) +AuthenticatorTest:test_signTx_RevertsIf_SignersLengthZero() (gas: 22045) +AuthenticatorTest:test_signTx_RevertsIf_TxIDLengthInvalid() (gas: 26856) +AuthenticatorTest:test_signTx_SucceedsAsCompletedAndEmitsEvent() (gas: 84718) +AuthenticatorTest:test_signTx_SucceedsAsPending() (gas: 42021) +AuthenticatorTest:test_txAuthState_ReturnsState() (gas: 99523) +AuthenticatorTest:test_txAuthState_RevertsIf_TxIDLengthInvalid() (gas: 12432) +ContractModuleBaseTest:test_onContractCommitImmediately_CallsAuthorizeAndImplementation() (gas: 24818) +ContractModuleBaseTest:test_onContractCommitImmediately_RevertsWhen_AuthorizeFails() (gas: 23975) +ContractModuleBaseTest:test_onContractPrepare_CallsAuthorizeAndImplementation() (gas: 24689) +ContractModuleBaseTest:test_onContractPrepare_RevertsWhen_AuthorizeFails() (gas: 23676) +CoordinatorTest:test_coordinatorState_ReturnsCorrectState() (gas: 99124) +CoordinatorTest:test_coordinatorState_RevertIf_StateNotFound() (gas: 18786) +CoordinatorTest:test_coordinatorState_RevertIf_TxIDLengthInvalid_Empty() (gas: 13396) +CoordinatorTest:test_coordinatorState_RevertIf_TxIDLengthInvalid_TooLong() (gas: 13814) +CoordinatorTest:test_coordinatorState_RevertIf_TxIDLengthInvalid_TooShort() (gas: 13332) +CoordinatorTest:test_executeTx_RevertIf_AuthNotCompleted() (gas: 62177) +CoordinatorTest:test_executeTx_RevertIf_TimeoutHeight() (gas: 43871) +CoordinatorTest:test_executeTx_RevertIf_TimeoutTimestamp() (gas: 44366) +CoordinatorTest:test_executeTx_RevertIf_TxNotRecorded() (gas: 62119) +CoordinatorTest:test_executeTx_Succeeds() (gas: 109649) +CrossModuleTest:test_constructor_GrantsIbcRoleToHandler() (gas: 11699) +CrossModuleTest:test_onAcknowledgementPacket_CallsHandlerWhenCallerHasRole() (gas: 82449) +CrossModuleTest:test_onAcknowledgementPacket_RevertWhen_CallerLacksIbcRole() (gas: 30689) +CrossModuleTest:test_onChanCloseConfirm_RevertWhen_CallerLacksIbcRole() (gas: 11987) +CrossModuleTest:test_onChanCloseConfirm_SucceedsWhenCallerHasRole() (gas: 14160) +CrossModuleTest:test_onChanCloseInit_RevertWhen_CallerLacksIbcRole() (gas: 11833) +CrossModuleTest:test_onChanCloseInit_SucceedsWhenCallerHasRole() (gas: 13962) +CrossModuleTest:test_onChanOpenAck_RevertWhen_CallerLacksIbcRole() (gas: 12068) +CrossModuleTest:test_onChanOpenAck_SucceedsWhenCallerHasRole() (gas: 13977) +CrossModuleTest:test_onChanOpenConfirm_RevertWhen_CallerLacksIbcRole() (gas: 12449) +CrossModuleTest:test_onChanOpenConfirm_SucceedsWhenCallerHasRole() (gas: 14490) +CrossModuleTest:test_onChanOpenInit_ReturnsSelfAndVersionWhenCallerHasRole() (gas: 18346) +CrossModuleTest:test_onChanOpenInit_RevertWhen_CallerLacksIbcRole() (gas: 14847) +CrossModuleTest:test_onChanOpenTry_ReturnsSelfAndCounterpartyVersionWhenCallerHasRole() (gas: 18874) +CrossModuleTest:test_onChanOpenTry_RevertWhen_CallerLacksIbcRole() (gas: 15701) +CrossModuleTest:test_onRecvPacket_CallsHandlerAndReturnsAckWhenCallerHasRole() (gas: 57121) +CrossModuleTest:test_onRecvPacket_RevertWhen_CallerLacksIbcRole() (gas: 31310) +CrossModuleTest:test_onTimeoutPacket_CallsHandlerWhenCallerHasRole() (gas: 55726) +CrossModuleTest:test_onTimeoutPacket_RevertWhen_CallerLacksIbcRole() (gas: 29694) +CrossModuleTest:test_supportsInterface_ReturnsTrueForIIBCAndIAccessControlAndFalseForUnsupported() (gas: 8391) +CrossSimpleModuleTest:test_constructor_DoesNotGrantIbcRoleWhenDebugModeFalse() (gas: 3240600) +CrossSimpleModuleTest:test_constructor_GrantsIbcRoleWhenDebugModeTrue() (gas: 3262879) +CrossStoreTest:test_SaveAndLoad_CoordinatorState() (gas: 119980) +CrossStoreTest:test_SaveLoad_DataLossChannel0() (gas: 102862) +CrossStoreTest:test_SaveLoad_DataLossExtraChannels() (gas: 98710) +CrossStoreTest:test_SaveLoad_DataLossUnsupportedIndices() (gas: 72010) +CrossStoreTest:test_getAuthStorage_IsIsolated() (gas: 20854) +CrossStoreTest:test_getCoordStorage_IsIsolated() (gas: 21082) +CrossStoreTest:test_getTxStorage_IsIsolated() (gas: 21162) +CrossStoreTest:test_maskToUint32Array_Both() (gas: 8190) +CrossStoreTest:test_maskToUint32Array_CoordinatorOnly() (gas: 7819) +CrossStoreTest:test_maskToUint32Array_Empty() (gas: 7041) +CrossStoreTest:test_maskToUint32Array_ParticipantOnly() (gas: 7735) +CrossStoreTest:test_uint32ArrayToMask_Both() (gas: 7706) +CrossStoreTest:test_uint32ArrayToMask_BothReversedOrder() (gas: 8133) +CrossStoreTest:test_uint32ArrayToMask_CoordinatorOnly() (gas: 7197) +CrossStoreTest:test_uint32ArrayToMask_Empty() (gas: 6724) +CrossStoreTest:test_uint32ArrayToMask_ParticipantOnly() (gas: 7580) +DelegatedLogicHandlerTest:test_createTx_DelegatesToTxManager() (gas: 85756) +DelegatedLogicHandlerTest:test_delegateWithData_RevertIf_DelegateCallFails() (gas: 56876) +DelegatedLogicHandlerTest:test_delegateWithData_RevertWhen_TargetReverts() (gas: 115803) +DelegatedLogicHandlerTest:test_delegateWithData_SucceedsAndReturnsData() (gas: 81375) +DelegatedLogicHandlerTest:test_getAuthState_DelegatesToAuthManager() (gas: 38572) +DelegatedLogicHandlerTest:test_getAuthState_RevertIf_CalledExternally() (gas: 14357) +DelegatedLogicHandlerTest:test_getCoordinatorState_DelegatesToTxManager() (gas: 89819) +DelegatedLogicHandlerTest:test_getCoordinatorState_RevertIf_CalledExternally() (gas: 15708) +DelegatedLogicHandlerTest:test_handleAcknowledgement_DelegatesToTxManager() (gas: 54817) +DelegatedLogicHandlerTest:test_handlePacket_DelegatesToTxManager() (gas: 60530) +DelegatedLogicHandlerTest:test_handleTimeout_DelegatesToTxManager() (gas: 53748) +DelegatedLogicHandlerTest:test_initAuthState_DelegatesToAuthManager() (gas: 74424) +DelegatedLogicHandlerTest:test_isCompletedAuth_DelegatesToAuthManager() (gas: 19325) +DelegatedLogicHandlerTest:test_isCompletedAuth_RevertIf_CalledExternally() (gas: 11939) +DelegatedLogicHandlerTest:test_isTxRecorded_DelegatesToTxManager() (gas: 19036) +DelegatedLogicHandlerTest:test_isTxRecorded_RevertIf_CalledExternally() (gas: 11697) +DelegatedLogicHandlerTest:test_runTxIfCompleted_DelegatesToTxManager() (gas: 106839) +DelegatedLogicHandlerTest:test_sign_DelegatesToAuthManager() (gas: 51649) +DelegatedLogicHandlerTest:test_staticCallSelf_RevertsIf_CallFailsEmpty() (gas: 12600) +DelegatedLogicHandlerTest:test_staticCallSelf_RevertsIf_OnStateChange() (gas: 1040431853) +DelegatedLogicHandlerTest:test_staticCallSelf_RevertsIf_TargetReverts() (gas: 14237) +DelegatedLogicHandlerTest:test_staticCallSelf_Succeeds() (gas: 9181) +DelegatedLogicHandlerTest:test_verifySignatures_DelegatesToAuthManager() (gas: 49084) +ERC20TransferModuleTest:test_decodeCallInfo_RevertWhen_InvalidLength() (gas: 11651) +ERC20TransferModuleTest:test_decodeCallInfo_Success() (gas: 11807) +ERC20TransferModuleTest:test_initialize_RevertWhen_AlreadyInitialized() (gas: 13202) +ERC20TransferModuleTest:test_initialize_RevertWhen_CallerIsNotOwner() (gas: 684068) +ERC20TransferModuleTest:test_initialize_RevertWhen_InvalidAddress() (gas: 703383) +ERC20TransferModuleTest:test_initialize_Success() (gas: 732264) +ERC20TransferModuleTest:test_onAbort_DoNothingWhenTxNotFound() (gas: 33969) +ERC20TransferModuleTest:test_onAbort_RevertWhen_CalledByOthers() (gas: 23445) +ERC20TransferModuleTest:test_onAbort_RevertWhen_NotInitialized() (gas: 666934) +ERC20TransferModuleTest:test_onAbort_Success() (gas: 133223) +ERC20TransferModuleTest:test_onCommit_DoNothingWhenTxNotFound() (gas: 34060) +ERC20TransferModuleTest:test_onCommit_RevertWhen_CalledByOthers() (gas: 23511) +ERC20TransferModuleTest:test_onCommit_RevertWhen_NotInitialized() (gas: 667330) +ERC20TransferModuleTest:test_onCommit_Success() (gas: 148737) +ERC20TransferModuleTest:test_onContractCommitImmediately_RevertWhen_CalledByOthers() (gas: 28420) +ERC20TransferModuleTest:test_onContractCommitImmediately_RevertWhen_InsufficientAllowance() (gas: 35323) +ERC20TransferModuleTest:test_onContractCommitImmediately_RevertWhen_NotInitialized() (gas: 672088) +ERC20TransferModuleTest:test_onContractCommitImmediately_Success() (gas: 76133) +ERC20TransferModuleTest:test_onContractPrepare_RevertWhen_CalledByOthers() (gas: 28578) +ERC20TransferModuleTest:test_onContractPrepare_RevertWhen_InsufficientAllowance() (gas: 102532) +ERC20TransferModuleTest:test_onContractPrepare_RevertWhen_InsufficientBalance() (gas: 130288) +ERC20TransferModuleTest:test_onContractPrepare_RevertWhen_NotInitialized() (gas: 672224) +ERC20TransferModuleTest:test_onContractPrepare_RevertWhen_TxAlreadyPending() (gas: 162795) +ERC20TransferModuleTest:test_onContractPrepare_Success() (gas: 139360) +IBCKeeperTest:test_exposed_initIBCKeeper_AllowsZeroAddress() (gas: 192201) +IBCKeeperTest:test_exposed_initIBCKeeper_RevertOn_SecondInitialization() (gas: 12904) +IBCKeeperTest:test_getIBCHandler_ReturnsSameAddress() (gas: 9955) +InitiatorTest:test_constructor_SetsChainIDHash() (gas: 8310) +InitiatorTest:test_getRequiredAccounts_AggregatesSigners() (gas: 266833) +InitiatorTest:test_getRequiredAccounts_ReturnsEmptyArrayWhenNoSigners() (gas: 69831) +InitiatorTest:test_getRequiredAccounts_ReturnsEmptyArrayWhenNoTxs() (gas: 40964) +InitiatorTest:test_initiateTx_RevertWhen_ChainIDMismatch() (gas: 61018) +InitiatorTest:test_initiateTx_RevertWhen_TimeoutHeightExpired() (gas: 58522) +InitiatorTest:test_initiateTx_RevertWhen_TimeoutTimestampExpired() (gas: 59317) +InitiatorTest:test_initiateTx_RevertWhen_txIDAlreadyExists() (gas: 155517) +InitiatorTest:test_initiateTx_SucceedsAsPendingWhenSignersNotMet() (gas: 272288) +InitiatorTest:test_initiateTx_SucceedsAsVerifiedWhenSignersMet() (gas: 309278) +InitiatorTest:test_selfXCC_ReturnsCorrectChannelInfo() (gas: 17058) +MockCrossContractTest:test_onAbort_Succeeds() (gas: 9583) +MockCrossContractTest:test_onCommit_Succeeds() (gas: 9429) +MockCrossContractTest:test_onContractCommitImmediately_ReturnsExpectedBytes() (gas: 15797) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_AuthModeIsNotChannel() (gas: 15714) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_CallInfoIsNot0x01() (gas: 16771) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_CallInfoLenIsTwo() (gas: 17114) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_CallInfoLenIsZero() (gas: 16912) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_SignersLenIsTwo() (gas: 17726) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_SignersLenIsZero() (gas: 12570) +MockCrossContractTest:test_onContractCommitImmediately_RevertWhen_UnexpectedAccountId() (gas: 16344) +MockCrossContractTest:test_onContractPrepare_ReturnsExpectedBytes() (gas: 14386) +SampleExtensionVerifierTest:test_verify_ReturnsFalseWhenAuthModeIsNotExtension() (gas: 32717) +SampleExtensionVerifierTest:test_verify_ReturnsFalseWhenSignedMsgMismatch() (gas: 46365) +SampleExtensionVerifierTest:test_verify_ReturnsFalseWhenSignerIdIsInvalidLength() (gas: 33868) +SampleExtensionVerifierTest:test_verify_ReturnsFalseWhenSignerIdMismatch() (gas: 37781) +SampleExtensionVerifierTest:test_verify_RevertsWhen_OptionDataIsMalformed() (gas: 35500) +SampleExtensionVerifierTest:test_verify_RevertsWhen_SignatureIsIncorrect() (gas: 44779) +SampleExtensionVerifierTest:test_verify_RevertsWhen_SignatureIsInvalidLength() (gas: 39974) +SampleExtensionVerifierTest:test_verify_SucceedsWhenSignatureIsValid() (gas: 35372) +SimpleContractRegistryTest:testFuzz_register_ThenGetReturnsSameAddress(address) (runs: 256, μ: 76328, ~: 76328) +SimpleContractRegistryTest:test_get_RevertWhen_NotInitialized() (gas: 31429) +SimpleContractRegistryTest:test_register_RevertOn_SecondInitialization() (gas: 57822) +SimpleContractRegistryTest:test_register_ThenGetReturnsSameAddress() (gas: 75584) +TxAtomicSimpleTest:test_handleAck_Failure() (gas: 342066) +TxAtomicSimpleTest:test_handleAck_RevertWhen_AckIsNotSuccess() (gas: 180832) +TxAtomicSimpleTest:test_handleAck_RevertWhen_AckPayloadDecodeFailed() (gas: 191269) +TxAtomicSimpleTest:test_handleAck_RevertWhen_AckTypeURLUnexpected() (gas: 208707) +TxAtomicSimpleTest:test_handleAck_RevertWhen_AllTransactionsConfirmed() (gas: 283749) +TxAtomicSimpleTest:test_handleAck_RevertWhen_ChannelMismatch() (gas: 272493) +TxAtomicSimpleTest:test_handleAck_RevertWhen_ChannelNotFound() (gas: 272680) +TxAtomicSimpleTest:test_handleAck_RevertWhen_CoordinatorPhaseNotPrepare() (gas: 258829) +TxAtomicSimpleTest:test_handleAck_RevertWhen_CoordinatorStateInconsistent() (gas: 304288) +TxAtomicSimpleTest:test_handleAck_RevertWhen_CoordinatorStateNotFound() (gas: 282380) +TxAtomicSimpleTest:test_handleAck_RevertWhen_CoordinatorTxStatusNotPrepare() (gas: 291116) +TxAtomicSimpleTest:test_handleAck_RevertWhen_InvalidTxIDLength() (gas: 275922) +TxAtomicSimpleTest:test_handleAck_RevertWhen_ModuleNotInitialized() (gas: 285140) +TxAtomicSimpleTest:test_handleAck_RevertWhen_OnAbortReverts() (gas: 339906) +TxAtomicSimpleTest:test_handleAck_RevertWhen_OnCommitReverts() (gas: 339467) +TxAtomicSimpleTest:test_handleAck_RevertWhen_PacketPayloadDecodeFailed() (gas: 227249) +TxAtomicSimpleTest:test_handleAck_RevertWhen_PacketTypeURLUnexpected() (gas: 264838) +TxAtomicSimpleTest:test_handleAck_RevertWhen_StateNotFound() (gas: 135005) +TxAtomicSimpleTest:test_handleAck_RevertWhen_UnexpectedCommitStatus() (gas: 271840) +TxAtomicSimpleTest:test_handleAck_Success() (gas: 341680) +TxAtomicSimpleTest:test_handlePacket_ReturnsFailedAndEmitsEventWhenModuleReverts() (gas: 193262) +TxAtomicSimpleTest:test_handlePacket_ReturnsFailedWhenPayloadEmpty() (gas: 61844) +TxAtomicSimpleTest:test_handlePacket_ReturnsFailedWhenTypeURLUnexpected() (gas: 76320) +TxAtomicSimpleTest:test_handlePacket_ReturnsOkAndEmitsEventWhenModuleSucceeds() (gas: 174389) +TxAtomicSimpleTest:test_handleTimeout_RevertOn_NotImplemented() (gas: 11363) +TxAtomicSimpleTest:test_runTx_PrepareFailed() (gas: 206131) +TxAtomicSimpleTest:test_runTx_RevertWhen_ChannelNotFound() (gas: 95122) +TxAtomicSimpleTest:test_runTx_RevertWhen_LinksNotSupported() (gas: 38334) +TxAtomicSimpleTest:test_runTx_RevertWhen_ModuleNotInitialized() (gas: 47110) +TxAtomicSimpleTest:test_runTx_RevertWhen_SignerLenMismatch() (gas: 28031) +TxAtomicSimpleTest:test_runTx_RevertWhen_TPCNotImplemented() (gas: 24118) +TxAtomicSimpleTest:test_runTx_RevertWhen_TimeoutHeight() (gas: 25576) +TxAtomicSimpleTest:test_runTx_RevertWhen_TimeoutTimestamp() (gas: 26190) +TxAtomicSimpleTest:test_runTx_RevertWhen_Tx0NotLocal() (gas: 52212) +TxAtomicSimpleTest:test_runTx_RevertWhen_TxIDAlreadyExists() (gas: 161679) +TxAtomicSimpleTest:test_runTx_RevertWhen_UnexpectedReturnValue() (gas: 81874) +TxAtomicSimpleTest:test_runTx_RevertWhen_UnknownCommitProtocol() (gas: 23503) +TxAtomicSimpleTest:test_runTx_SucceedsAndSendsPacket() (gas: 289827) +TxAuthManagerTest:test_accountKey_ExtensionModeIgnoresOptionValue() (gas: 15975) +TxAuthManagerTest:test_accountKey_GeneratesUniqueKeys() (gas: 57014) +TxAuthManagerTest:test_getAuthState_ReturnsCorrectRemainingSigners() (gas: 360320) +TxAuthManagerTest:test_getAuthState_RevertWhen_NotInitialized() (gas: 16241) +TxAuthManagerTest:test_getRemainingSigners_TracksSigningProgress() (gas: 353717) +TxAuthManagerTest:test_initAuthState_HandlesDuplicateSigners() (gas: 277966) +TxAuthManagerTest:test_initAuthState_RevertWhen_AlreadyInitialized() (gas: 171833) +TxAuthManagerTest:test_initAuthState_Succeeds() (gas: 270899) +TxAuthManagerTest:test_initialize_RevertWhen_AlreadyInitialized() (gas: 1483796) +TxAuthManagerTest:test_initialize_RevertWhen_ArrayLengthMismatch() (gas: 1519901) +TxAuthManagerTest:test_initialize_RevertWhen_EmptyTypeUrl() (gas: 1457667) +TxAuthManagerTest:test_initialize_RevertWhen_ZeroAddressVerifier() (gas: 1395572) +TxAuthManagerTest:test_initialize_SucceedsAndEmitsEvents() (gas: 1565772) +TxAuthManagerTest:test_initialize_SucceedsWithEmptyArrays() (gas: 1392106) +TxAuthManagerTest:test_isCompletedAuth_ReturnsFalseWhenInitializedEmpty() (gas: 34759) +TxAuthManagerTest:test_isCompletedAuth_ReturnsFalseWhenNotCompleted() (gas: 244840) +TxAuthManagerTest:test_isCompletedAuth_ReturnsTrueWhenCompleted() (gas: 133928) +TxAuthManagerTest:test_isCompletedAuth_RevertWhen_NotInitialized() (gas: 14387) +TxAuthManagerTest:test_setStateFromRemainingList_HandlesDuplicatesAndReturnsRemains() (gas: 261903) +TxAuthManagerTest:test_sign_FinalSignReturnsTrue() (gas: 214053) +TxAuthManagerTest:test_sign_IgnoresDuplicateSignatures() (gas: 283706) +TxAuthManagerTest:test_sign_IgnoresUnknownSigners() (gas: 211355) +TxAuthManagerTest:test_sign_PartialSignReturnsFalse() (gas: 242956) +TxAuthManagerTest:test_sign_RevertWhen_AuthAlreadyCompleted() (gas: 140603) +TxAuthManagerTest:test_sign_RevertWhen_NotInitialized() (gas: 27957) +TxAuthManagerTest:test_verifySignatures_RevertWhen_AuthModeMismatch() (gas: 23650) +TxAuthManagerTest:test_verifySignatures_RevertWhen_StaticCallFails() (gas: 31433) +TxAuthManagerTest:test_verifySignatures_RevertWhen_TooManySigners() (gas: 146596) +TxAuthManagerTest:test_verifySignatures_RevertWhen_VerifierNotFound() (gas: 27421) +TxAuthManagerTest:test_verifySignatures_RevertWhen_VerifierReturnsFalse() (gas: 32413) +TxAuthManagerTest:test_verifySignatures_SucceedsMultipleSigners() (gas: 42534) +TxAuthManagerTest:test_verifySignatures_SucceedsSingleSigner() (gas: 28188) +TxIDUtilsTest:test_computeTxId_ReturnsConsistentId() (gas: 63200) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentCallInfo() (gas: 63666) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentChainId() (gas: 63768) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentChannelAnyValue() (gas: 63713) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentCommitProtocol() (gas: 63347) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentLinks() (gas: 67024) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentLocalSigners() (gas: 82236) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentNonce() (gas: 63432) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentReturnValue() (gas: 64333) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentRootSigners() (gas: 79211) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentSignerAuthMode() (gas: 96022) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentSignerAuthOptionTypeUrl() (gas: 97465) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentSignerAuthOptionValue() (gas: 96702) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentTimeoutHeight_RevisionHeight() (gas: 64119) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentTimeoutHeight_RevisionNumber() (gas: 63964) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentTimeoutTimestamp() (gas: 63969) +TxIDUtilsTest:test_computeTxId_ReturnsDifferentIdForDifferentTxArrayLength() (gas: 79680) +TxIDUtilsTest:test_computeTxId_SucceedsWithMinimalMsg() (gas: 14266) +TxIDUtilsTest:test_computeTxId_SucceedsWithTypicalMsg() (gas: 34235) +TxManagerTest:test_createTx_RevertWhen_TxAlreadyExists() (gas: 51344) +TxManagerTest:test_createTx_SucceedsWithNonEmptyData() (gas: 127143) +TxManagerTest:test_getCoordinatorState_ReturnsCorrectState() (gas: 54095) +TxManagerTest:test_getCoordinatorState_RevertsIfNotFound() (gas: 28356) +TxManagerTest:test_getPacketAcknowledgementCall_EncodesCorrectly() (gas: 91027) +TxManagerTest:test_handleAcknowledgement_CallsLogic() (gas: 83066) +TxManagerTest:test_handlePacket_CallsLogic() (gas: 87503) +TxManagerTest:test_handleTimeout_CallsLogic() (gas: 82728) +TxManagerTest:test_initialize_RevertWhen_DoubleInit() (gas: 61611) +TxManagerTest:test_initialize_Succeeds() (gas: 58187) +TxManagerTest:test_isTxRecorded_ReturnsFalseForUnknownTx() (gas: 10225) +TxManagerTest:test_isTxRecorded_ReturnsTrueForKnownTx() (gas: 46174) +TxManagerTest:test_runTxIfCompleted_DoesNothingForUnknownTx() (gas: 31191) +TxManagerTest:test_runTxIfCompleted_DoesNothingIfAlreadyVerified() (gas: 104010) +TxManagerTest:test_runTxIfCompleted_RunsTxAndSetsVerifiedStatus() (gas: 100601) \ No newline at end of file diff --git a/.github/workflows/coverage-report.yml b/.github/workflows/coverage-report.yml index 974ed87..f082c11 100644 --- a/.github/workflows/coverage-report.yml +++ b/.github/workflows/coverage-report.yml @@ -34,13 +34,16 @@ jobs: 'src/proto/**' \ 'src/core/PacketHandler.sol' \ 'src/core/ContractRegistry.sol' \ + 'src/core/TxAuthManagerBase.sol' \ + 'src/core/TxManagerBase.sol' \ + 'src/core/TxRunnerBase.sol' \ -o lcov.filtered.info - name: Report code coverage uses: zgosalvez/github-actions-report-lcov@v5 with: coverage-files: lcov.filtered.info - minimum-coverage: 100 + minimum-coverage: 96 artifact-name: code-coverage-report github-token: ${{ secrets.GITHUB_TOKEN }} update-comment: true diff --git a/.github/workflows/gas-snapshot-diff.yml b/.github/workflows/gas-snapshot-diff.yml new file mode 100644 index 0000000..eb0218a --- /dev/null +++ b/.github/workflows/gas-snapshot-diff.yml @@ -0,0 +1,109 @@ +name: Gas Snapshot Diff Report + +on: + pull_request: + paths: + - 'src/**' + - 'test/**' + - 'foundry.toml' + +permissions: + contents: read + pull-requests: write + +jobs: + gas-diff: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '25' + + - name: Install dependencies + run: npm ci + + - name: Fetch .gas-snapshot from Base Branch + run: | + BASE_BRANCH="origin/${{ github.base_ref }}" + echo "Fetching snapshot from $BASE_BRANCH..." + + if git show "$BASE_BRANCH:.gas-snapshot" > .gas-snapshot 2>/dev/null; then + echo "Successfully fetched .gas-snapshot from base branch." + else + echo "⚠️ .gas-snapshot not found in base branch." + exit 0 + fi + + - name: Run Snapshot Diff + id: run_diff + shell: bash + run: | + npm run snapshot:diff | \ + sed 's/\x1b\[[0-9;]*m//g' | \ + grep -v "^>" | \ + grep -vE "^\[PASS\]|^Ran |^Suite result" | \ + grep -v "gas: 0 (0.000%)" | \ + grep -v "compilation skipped" | \ + sed '/^$/d' | \ + sed -E 's/\(gas: ([0-9])/(gas: +\1/g' > gas_diff.txt + + cat gas_diff.txt + + - name: Comment Gas Diff on PR + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const diffOutput = fs.readFileSync('gas_diff.txt', 'utf8'); + + if (diffOutput.trim() === '') { + console.log("No gas changes detected."); + return; + } + + const body = `### ⛽ Gas Usage Changes + + Comparison against \`${{ github.base_ref }}\` branch: + +
+ Click to view gas diff + + \`\`\`diff + ${diffOutput} + \`\`\` + +
+ + *Calculated by Foundry Gas Snapshot Action*`; + + const { owner, repo, number } = context.issue; + const comments = await github.rest.issues.listComments({ + owner, + repo, + issue_number: number, + }); + + const botComment = comments.data.find(c => c.body.includes('### ⛽ Gas Usage Changes')); + + if (botComment) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: botComment.id, + body: body + }); + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number: number, + body: body + }); + } diff --git a/.github/workflows/gas-snapshot-update.yml b/.github/workflows/gas-snapshot-update.yml new file mode 100644 index 0000000..a87a1f9 --- /dev/null +++ b/.github/workflows/gas-snapshot-update.yml @@ -0,0 +1,40 @@ +name: Update Gas Snapshot on Merge + +on: + push: + branches: + - develop # ToDo: change develop to main when main branch is ready + paths: + - 'src/**' + - 'test/**' + - 'foundry.toml' + +permissions: + contents: write + +jobs: + update-snapshot: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '25' + + - name: Install dependencies + run: npm ci + + - name: Generate Snapshot + run: npm run snapshot + + - name: Commit and Push changes + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "chore(gas): update .gas-snapshot [skip ci]" + file_pattern: .gas-snapshot + branch: ${{ github.ref }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5901d19..24b1a56 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: steps: - name: Set up Go 1.24 - uses: actions/setup-go@v1 + uses: actions/setup-go@v6 with: go-version: 1.24 id: go @@ -22,7 +22,7 @@ jobs: - name: Resolve dependencies run: npm install - - name: Setup ganache-cli + - name: Setup chain & Deploy contracts run: NO_GEN_CODE=1 ./script/setup.sh development - name: Test diff --git a/.husky/pre-commit b/.husky/pre-commit index 7f800e3..039841a 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -3,6 +3,4 @@ set -e -npm run fmt:sol - -git add -A +npx lint-staged diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000..07f03fc --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,3 @@ +{ + "*.sol": ["npm run fmt:sol"] +} diff --git a/README.md b/README.md index 73b119d..ca7d1bf 100644 --- a/README.md +++ b/README.md @@ -7,28 +7,47 @@ This is a solidity implementation of [Cross Framework](https://github.com/datach Currently, it provides the following features: - the registry feature that allows developers to register their contracts -- the participant feature of the simple commit protocol +- the coordinator feature of the simple commit protocol +- the participant features for the simple-commit and two-phase commit protocols - it's implemented on top of [yui-ibc-solidity](https://github.com/hyperledger-labs/yui-ibc-solidity) -A coordinator feature of the simple commit and two-phase commit will be provided in the future. +The coordinator feature of the two-phase commit will be provided in the future. -## Contract module development +## Demo -A developer who develops contract using Cross Framework need to implement IContractModule, which is defined in [IContractModule.sol](./src/core/IContractModule.sol). +For an ERC20 atomic swap demo, please refer to [ethereum-cross-demo](https://github.com/datachainlab/ethereum-cross-demo) + +## Contract module development -``` // IContractModule defines the expected interface of a contract module on Cross Framework +```solidity interface IContractModule { - // onContractCall is a callback function that is called at the commit(simple-commit) phase - function onContractCall(CrossContext calldata context, bytes calldata callInfo) external returns (bytes memory); + // onContractCommitImmediately is a callback function that is called on the participant chain to execute the transaction logic immediately + // This function is intended to be used only in the simple-commit protocol + function onContractCommitImmediately(CrossContext calldata context, bytes calldata callInfo) + external + returns (bytes memory); + + // onContractPrepare is a callback function that is called at the prepare(2pc) phase + function onContractPrepare(CrossContext calldata context, bytes calldata callInfo) external returns (bytes memory); + + // onCommit is a callback function that is called at the commit(2pc) phase + // It is expected that it commits the changes in the contract module + // IMPORTANT: This function MUST NOT revert. + function onCommit(CrossContext calldata context) external; + + // onAbort is a callback function that is called at the commit(2pc) phase + // It is expected that it aborts the changes in the contract module + // IMPORTANT: This function MUST NOT revert. + function onAbort(CrossContext calldata context) external; } ``` -- Currently, only one function `onContractCall` is defined, which implements the process of a transaction called via the cross-chain transaction. +- For the current simple-commit coordinator flow, the coordinator-side participant uses `onContractPrepare` to execute and lock state changes, and later finalizes them with `onCommit` or `onAbort` based on the acknowledgement from the counterparty. -- The return value of `onContractCall` is emitted as an Event `OnContractCall` with the transaction info. +- The counterparty participant executes the incoming call and finalizes immediately via `onContractCommitImmediately`. -- If it gets an unexpected call, the developer need to perform `revert` in the contract. This will request the coordinator to abort the transaction. +- IMPORTANT: `onCommit` and `onAbort` MUST NOT revert. ## How to deploy a contract module diff --git a/chains/docker-compose.yml b/chains/docker-compose.yml index 21a7086..5429610 100644 --- a/chains/docker-compose.yml +++ b/chains/docker-compose.yml @@ -20,8 +20,3 @@ services: interval: 2s timeout: 1s retries: 30 - geth: - build: ./geth - ports: - - 8545:8545 - - 8546:8546 diff --git a/chains/geth/Dockerfile b/chains/geth/Dockerfile deleted file mode 100644 index 04470bd..0000000 --- a/chains/geth/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM ethereum/client-go:v1.9.25 - -ADD geth.password /root/geth.password -ADD genesis.json /root/genesis.json -ADD privatekey /root/privatekey -ADD run.sh /run.sh - -RUN /usr/local/bin/geth --nousb --datadir /root/.ethereum init /root/genesis.json - -RUN /usr/local/bin/geth --nousb account import /root/privatekey --password /root/geth.password - -EXPOSE 8545 - -ENTRYPOINT ["/run.sh"] -CMD ["--verbosity", "5", "--vmdebug", "--shh"] diff --git a/chains/geth/genesis.json b/chains/geth/genesis.json deleted file mode 100644 index b87c204..0000000 --- a/chains/geth/genesis.json +++ /dev/null @@ -1,827 +0,0 @@ -{ - "config": { - "chainId": 2018, - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "clique": { - "period": 1, - "epoch": 30000 - } - }, - "nonce": "0x0", - "timestamp": "0x5bc065b3", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000a89f47c6b463f74d87572b058427da0a13ec54250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x80000000", - "difficulty": "0x1", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "0000000000000000000000000000000000000000": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000001": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000002": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000003": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000004": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000005": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000006": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000007": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000008": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000009": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000000f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000010": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000011": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000012": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000013": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000014": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000015": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000016": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000017": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000018": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000019": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000001f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000020": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000021": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000022": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000023": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000024": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000025": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000026": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000027": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000028": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000029": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000002f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000030": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000031": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000032": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000033": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000034": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000035": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000036": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000037": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000038": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000039": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000003f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000040": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000041": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000042": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000043": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000044": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000045": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000046": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000047": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000048": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000049": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000004f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000050": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000051": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000052": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000053": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000054": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000055": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000056": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000057": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000058": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000059": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000005f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000060": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000061": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000062": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000063": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000064": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000065": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000066": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000067": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000068": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000069": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000006f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000070": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000071": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000072": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000073": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000074": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000075": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000076": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000077": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000078": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000079": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000007f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000080": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000081": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000082": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000083": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000084": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000085": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000086": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000087": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000088": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000089": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000008f": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000090": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000091": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000092": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000093": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000094": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000095": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000096": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000097": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000098": { - "balance": "0x1" - }, - "0000000000000000000000000000000000000099": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009a": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009b": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009c": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009d": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009e": { - "balance": "0x1" - }, - "000000000000000000000000000000000000009f": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000a9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000aa": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ab": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ac": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ad": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ae": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000af": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000b9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ba": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000be": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000bf": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000c9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ca": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ce": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000cf": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000d9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000da": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000db": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000dc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000dd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000de": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000df": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000e9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ea": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000eb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ec": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ed": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ee": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ef": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f0": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f1": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f2": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f3": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f4": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f5": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f6": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f7": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f8": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000f9": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fa": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fb": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fc": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fd": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000fe": { - "balance": "0x1" - }, - "00000000000000000000000000000000000000ff": { - "balance": "0x1" - }, - "a89f47c6b463f74d87572b058427da0a13ec5425": { - "balance": "1000000000000000000000000" - }, - "cBED645B1C1a6254f1149Df51d3591c6B3803007": { - "balance": "100000000000000000000" - }, - "00731540cd6060991D6B9C57CE295998d9bC2faB": { - "balance": "100000000000000000000" - }, - "F885ef252e94def5C54746218704e0122c53Bdf5": { - "balance": "100000000000000000000" - }, - "55797d2257292f97736A2610f2f182A9b61432D6": { - "balance": "100000000000000000000" - }, - "47468060B00a27F9138F007eba28127593D79523": { - "balance": "100000000000000000000" - }, - "A3dBD48429fb6f2309c36BFee865B74b74bd7F4E": { - "balance": "100000000000000000000" - }, - "CEa4C7063b8d9D40C8274a4A68fffad2F8d5eebD": { - "balance": "100000000000000000000" - }, - "0Ac126739bb9c448B2fF5B554abB41EC92F36dec": { - "balance": "100000000000000000000" - }, - "37f63b6f490C6752d1bE18604967AD102bB98883": { - "balance": "100000000000000000000" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/chains/geth/geth.password b/chains/geth/geth.password deleted file mode 100644 index f3097ab..0000000 --- a/chains/geth/geth.password +++ /dev/null @@ -1 +0,0 @@ -password diff --git a/chains/geth/privatekey b/chains/geth/privatekey deleted file mode 100644 index 51a8fb5..0000000 --- a/chains/geth/privatekey +++ /dev/null @@ -1 +0,0 @@ -e517af47112e4f501afb26e4f34eadc8b0ad8eadaf4962169fc04bc8ddbfe091 \ No newline at end of file diff --git a/chains/geth/run.sh b/chains/geth/run.sh deleted file mode 100755 index 6b3f315..0000000 --- a/chains/geth/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -/usr/local/bin/geth --password /root/geth.password \ - --unlock "0" --syncmode full \ - --rpc --rpcvhosts "*" --rpcaddr "0.0.0.0" --rpcport "8545" --rpcapi web3,eth,net,personal,miner,txpool --rpccorsdomain '*' \ - --ws --wsapi eth,net,web3,personal,txpool --wsaddr "0.0.0.0" --wsport "8546" --wsorigins '*' \ - --datadir /root/.ethereum --networkid "2018" --nodiscover \ - --mine --minerthreads 1 --gasprice "0" \ - --allow-insecure-unlock --nousb \ - $@ diff --git a/deployments.toml b/deployments.toml index d7c06c7..a724a4e 100644 --- a/deployments.toml +++ b/deployments.toml @@ -15,6 +15,7 @@ debug_mode = true [31337.address] ibc_handler = "0xaa43d337145E8930d01cb4E60Abf6595C692921E" mock_cross_contract = "0xff77D90D6aA12db33d3Ba50A34fB25401f6e4c4F" -cross_simple_module = "0x2F5703804E29F4252FA9405B8D357220d11b3bd9" -mock_client = "0xaE1C9125BbcF63bf51294C4D15CBD472782E330D" +cross_simple_module = "0x87d7778dbc81251D5A0D78DFD8a0C359887E98C9" +mock_client = "0x37978908bac82F0191b674235A0fEEE31e7524a4" deployer = "0xa89F47C6b463f74d87572b058427dA0A13ec5425" +tx_manager = "0xa7f733a4fEA1071f58114b203F57444969b86524" diff --git a/foundry.toml b/foundry.toml index 5de3e38..e1ab652 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,12 +1,13 @@ [profile.default] -solc_version = "0.8.20" +solc_version = "0.8.30" libs = ["lib", "node_modules"] optimizer = true -optimizer_runs = 1000 +optimizer_runs = 200 evm_version = "london" fs_permissions = [ { access = "read-write", path = "./deployments.toml" } ] +via_ir = true [rpc_endpoints] anvil = "http://127.0.0.1:8545" diff --git a/package.json b/package.json index 6ca2334..ead0150 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "postinstall": "husky && forge build", "clean": "rm -rf build", "test": "forge test -vvv", - "lint:sol": "solhint -f table 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'", + "lint:sol": "solhint -f table --max-warnings 0 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'", "fmt:sol": "forge fmt", - "coverage:sol": "forge coverage --report lcov" + "coverage:sol": "forge coverage --report lcov --ir-minimum", + "snapshot": "forge snapshot", + "snapshot:diff": "forge snapshot --diff" }, "dependencies": { "@hyperledger-labs/yui-ibc-solidity": "git+https://github.com/hyperledger-labs/yui-ibc-solidity.git#v0.3.40", diff --git a/pkg/consts/contract.go b/pkg/consts/contract.go index cccb0ff..cc43722 100644 --- a/pkg/consts/contract.go +++ b/pkg/consts/contract.go @@ -6,7 +6,8 @@ import ( const ( IBCHandlerAddress = "0xaa43d337145E8930d01cb4E60Abf6595C692921E" - CrossSimpleModuleAddress = "0x2F5703804E29F4252FA9405B8D357220d11b3bd9" + CrossSimpleModuleAddress = "0x87d7778dbc81251D5A0D78DFD8a0C359887E98C9" + TxManagerAddress = "0xa7f733a4fEA1071f58114b203F57444969b86524" ) type contractConfig struct{} @@ -20,3 +21,7 @@ func (contractConfig) GetIBCHandlerAddress() common.Address { func (contractConfig) GetCrossSimpleModuleAddress() common.Address { return common.HexToAddress(CrossSimpleModuleAddress) } + +func (contractConfig) GetTxManagerAddress() common.Address { + return common.HexToAddress(TxManagerAddress) +} diff --git a/pkg/contract/crosssimplemodule/crosssimplemodule.go b/pkg/contract/crosssimplemodule/crosssimplemodule.go index 7d947c8..b4b63d0 100644 --- a/pkg/contract/crosssimplemodule/crosssimplemodule.go +++ b/pkg/contract/crosssimplemodule/crosssimplemodule.go @@ -29,12 +29,55 @@ var ( _ = abi.ConvertType ) +// AccountData is an auto generated low-level Go binding around an user-defined struct. +type AccountData struct { + Id []byte + AuthType AuthTypeData +} + +// AuthTypeData is an auto generated low-level Go binding around an user-defined struct. +type AuthTypeData struct { + Mode uint8 + Option GoogleProtobufAnyData +} + // ChannelCounterpartyData is an auto generated low-level Go binding around an user-defined struct. type ChannelCounterpartyData struct { PortId string ChannelId string } +// ChannelInfoData is an auto generated low-level Go binding around an user-defined struct. +type ChannelInfoData struct { + Port string + Channel string +} + +// ContractTransactionData is an auto generated low-level Go binding around an user-defined struct. +type ContractTransactionData struct { + CrossChainChannel GoogleProtobufAnyData + Signers []AccountData + CallInfo []byte + ReturnValue ReturnValueData + Links []LinkData +} + +// CoordinatorStateData is an auto generated low-level Go binding around an user-defined struct. +type CoordinatorStateData struct { + CommitProtocol uint8 + Channels []ChannelInfoData + Phase uint8 + Decision uint8 + ConfirmedTxs []uint32 + Acks []uint32 +} + +// GoogleProtobufAnyData is an auto generated low-level Go binding around an user-defined struct. +type GoogleProtobufAnyData struct { + TypeUrl string + Value []byte +} + // HeightData is an auto generated low-level Go binding around an user-defined struct. type HeightData struct { RevisionNumber uint64 @@ -86,6 +129,59 @@ type IIBCModuleMsgOnChanOpenConfirm struct { ChannelId string } +// IbcCoreClientV1HeightData is an auto generated low-level Go binding around an user-defined struct. +type IbcCoreClientV1HeightData struct { + RevisionNumber uint64 + RevisionHeight uint64 +} + +// LinkData is an auto generated low-level Go binding around an user-defined struct. +type LinkData struct { + SrcIndex uint32 +} + +// MsgExtSignTxData is an auto generated low-level Go binding around an user-defined struct. +type MsgExtSignTxData struct { + TxID []byte + Signers []AccountData +} + +// MsgExtSignTxResponseData is an auto generated low-level Go binding around an user-defined struct. +type MsgExtSignTxResponseData struct { + X bool +} + +// MsgInitiateTxData is an auto generated low-level Go binding around an user-defined struct. +type MsgInitiateTxData struct { + ChainId string + Nonce uint64 + CommitProtocol uint8 + ContractTransactions []ContractTransactionData + Signers []AccountData + TimeoutHeight IbcCoreClientV1HeightData + TimeoutTimestamp uint64 +} + +// MsgInitiateTxResponseData is an auto generated low-level Go binding around an user-defined struct. +type MsgInitiateTxResponseData struct { + TxID []byte + Status uint8 +} + +// MsgSignTxData is an auto generated low-level Go binding around an user-defined struct. +type MsgSignTxData struct { + TxID []byte + Signers [][]byte + TimeoutHeight IbcCoreClientV1HeightData + TimeoutTimestamp uint64 +} + +// MsgSignTxResponseData is an auto generated low-level Go binding around an user-defined struct. +type MsgSignTxResponseData struct { + TxAuthCompleted bool + Log string +} + // Packet is an auto generated low-level Go binding around an user-defined struct. type Packet struct { Sequence uint64 @@ -98,9 +194,44 @@ type Packet struct { TimeoutTimestamp uint64 } +// QueryCoordinatorStateRequestData is an auto generated low-level Go binding around an user-defined struct. +type QueryCoordinatorStateRequestData struct { + TxId []byte +} + +// QueryCoordinatorStateResponseData is an auto generated low-level Go binding around an user-defined struct. +type QueryCoordinatorStateResponseData struct { + CoodinatorState CoordinatorStateData +} + +// QuerySelfXCCResponseData is an auto generated low-level Go binding around an user-defined struct. +type QuerySelfXCCResponseData struct { + Xcc GoogleProtobufAnyData +} + +// QueryTxAuthStateRequestData is an auto generated low-level Go binding around an user-defined struct. +type QueryTxAuthStateRequestData struct { + TxID []byte +} + +// QueryTxAuthStateResponseData is an auto generated low-level Go binding around an user-defined struct. +type QueryTxAuthStateResponseData struct { + TxAuthState TxAuthStateData +} + +// ReturnValueData is an auto generated low-level Go binding around an user-defined struct. +type ReturnValueData struct { + Value []byte +} + +// TxAuthStateData is an auto generated low-level Go binding around an user-defined struct. +type TxAuthStateData struct { + RemainingSigners []AccountData +} + // CrosssimplemoduleMetaData contains all meta data concerning the Crosssimplemodule contract. var CrosssimplemoduleMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"ibcHandler_\",\"type\":\"address\",\"internalType\":\"contractIIBCHandler\"},{\"name\":\"module\",\"type\":\"address\",\"internalType\":\"contractIContractModule\"},{\"name\":\"debugMode\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"IBC_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPacketAcknowledgementCall\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumPacketAcknowledgementCall.CommitStatus\"}],\"outputs\":[{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"onAcknowledgementPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanCloseConfirm\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanCloseConfirm\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanCloseInit\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanCloseInit\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenAck\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanOpenAck\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterpartyVersion\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenConfirm\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanOpenConfirm\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenInit\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModuleInitializer.MsgOnChanOpenInit\",\"components\":[{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"},{\"name\":\"connectionHops\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterparty\",\"type\":\"tuple\",\"internalType\":\"structChannelCounterparty.Data\",\"components\":[{\"name\":\"port_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel_id\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[{\"name\":\"moduleAddr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenTry\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModuleInitializer.MsgOnChanOpenTry\",\"components\":[{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"},{\"name\":\"connectionHops\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterparty\",\"type\":\"tuple\",\"internalType\":\"structChannelCounterparty.Data\",\"components\":[{\"name\":\"port_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel_id\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"counterpartyVersion\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[{\"name\":\"moduleAddr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onRecvPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onTimeoutPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"OnContractCall\",\"inputs\":[{\"name\":\"txId\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":true,\"internalType\":\"bool\"},{\"name\":\"ret\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ModuleAlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ModuleNotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PayloadDecodeFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedTypeURL\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"ibcHandler_\",\"type\":\"address\",\"internalType\":\"contractIIBCHandler\"},{\"name\":\"txAuthManager_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"txManager_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"module_\",\"type\":\"address\",\"internalType\":\"contractIContractModule\"},{\"name\":\"authTypeUrls_\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"authVerifiers_\",\"type\":\"address[]\",\"internalType\":\"contractIAuthExtensionVerifier[]\"},{\"name\":\"debugMode\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"CHAIN_ID_HASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"IBC_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"TX_AUTH_MANAGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"TX_MANAGER\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"__getAuthState\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTxAuthState.Data\",\"components\":[{\"name\":\"remaining_signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"__getCoordinatorState\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structCoordinatorState.Data\",\"components\":[{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"channels\",\"type\":\"tuple[]\",\"internalType\":\"structChannelInfo.Data[]\",\"components\":[{\"name\":\"port\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"phase\",\"type\":\"uint8\",\"internalType\":\"enumCoordinatorState.CoordinatorPhase\"},{\"name\":\"decision\",\"type\":\"uint8\",\"internalType\":\"enumCoordinatorState.CoordinatorDecision\"},{\"name\":\"confirmed_txs\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"acks\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"__isCompletedAuth\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"__isTxRecorded\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"coordinatorState\",\"inputs\":[{\"name\":\"req\",\"type\":\"tuple\",\"internalType\":\"structQueryCoordinatorStateRequest.Data\",\"components\":[{\"name\":\"tx_id\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structQueryCoordinatorStateResponse.Data\",\"components\":[{\"name\":\"coodinator_state\",\"type\":\"tuple\",\"internalType\":\"structCoordinatorState.Data\",\"components\":[{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"channels\",\"type\":\"tuple[]\",\"internalType\":\"structChannelInfo.Data[]\",\"components\":[{\"name\":\"port\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"phase\",\"type\":\"uint8\",\"internalType\":\"enumCoordinatorState.CoordinatorPhase\"},{\"name\":\"decision\",\"type\":\"uint8\",\"internalType\":\"enumCoordinatorState.CoordinatorDecision\"},{\"name\":\"confirmed_txs\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"acks\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeTx\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structMsgInitiateTx.Data\",\"components\":[{\"name\":\"chain_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"contract_transactions\",\"type\":\"tuple[]\",\"internalType\":\"structContractTransaction.Data[]\",\"components\":[{\"name\":\"cross_chain_channel\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"call_info\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"return_value\",\"type\":\"tuple\",\"internalType\":\"structReturnValue.Data\",\"components\":[{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"links\",\"type\":\"tuple[]\",\"internalType\":\"structLink.Data[]\",\"components\":[{\"name\":\"src_index\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"extSignTx\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structMsgExtSignTx.Data\",\"components\":[{\"name\":\"txID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structMsgExtSignTxResponse.Data\",\"components\":[{\"name\":\"x\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initiateTx\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structMsgInitiateTx.Data\",\"components\":[{\"name\":\"chain_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"contract_transactions\",\"type\":\"tuple[]\",\"internalType\":\"structContractTransaction.Data[]\",\"components\":[{\"name\":\"cross_chain_channel\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"call_info\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"return_value\",\"type\":\"tuple\",\"internalType\":\"structReturnValue.Data\",\"components\":[{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"links\",\"type\":\"tuple[]\",\"internalType\":\"structLink.Data[]\",\"components\":[{\"name\":\"src_index\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[{\"name\":\"resp\",\"type\":\"tuple\",\"internalType\":\"structMsgInitiateTxResponse.Data\",\"components\":[{\"name\":\"txID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumMsgInitiateTxResponse.InitiateTxStatus\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onAcknowledgementPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanCloseConfirm\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanCloseConfirm\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanCloseInit\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanCloseInit\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenAck\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanOpenAck\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterpartyVersion\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenConfirm\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIIBCModule.MsgOnChanOpenConfirm\",\"components\":[{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenInit\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModuleInitializer.MsgOnChanOpenInit\",\"components\":[{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"},{\"name\":\"connectionHops\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterparty\",\"type\":\"tuple\",\"internalType\":\"structChannelCounterparty.Data\",\"components\":[{\"name\":\"port_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel_id\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[{\"name\":\"moduleAddr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onChanOpenTry\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structIIBCModuleInitializer.MsgOnChanOpenTry\",\"components\":[{\"name\":\"order\",\"type\":\"uint8\",\"internalType\":\"enumChannel.Order\"},{\"name\":\"connectionHops\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"portId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channelId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"counterparty\",\"type\":\"tuple\",\"internalType\":\"structChannelCounterparty.Data\",\"components\":[{\"name\":\"port_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel_id\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"counterpartyVersion\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"outputs\":[{\"name\":\"moduleAddr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"version\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onRecvPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"onTimeoutPacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"selfXCC\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structQuerySelfXCCResponse.Data\",\"components\":[{\"name\":\"xcc\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"signTx\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structMsgSignTx.Data\",\"components\":[{\"name\":\"txID\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"signers\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structMsgSignTxResponse.Data\",\"components\":[{\"name\":\"tx_auth_completed\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"log\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"txAuthState\",\"inputs\":[{\"name\":\"req_\",\"type\":\"tuple\",\"internalType\":\"structQueryTxAuthStateRequest.Data\",\"components\":[{\"name\":\"txID\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"resp\",\"type\":\"tuple\",\"internalType\":\"structQueryTxAuthStateResponse.Data\",\"components\":[{\"name\":\"tx_auth_state\",\"type\":\"tuple\",\"internalType\":\"structTxAuthState.Data\",\"components\":[{\"name\":\"remaining_signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}]}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"OnAbort\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OnCommit\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OnContractCommitImmediately\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":true,\"internalType\":\"bool\"},{\"name\":\"ret\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TxExecuted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"proposer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TxInitiated\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"proposer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"msgData\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMsgInitiateTx.Data\",\"components\":[{\"name\":\"chain_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"contract_transactions\",\"type\":\"tuple[]\",\"internalType\":\"structContractTransaction.Data[]\",\"components\":[{\"name\":\"cross_chain_channel\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"call_info\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"return_value\",\"type\":\"tuple\",\"internalType\":\"structReturnValue.Data\",\"components\":[{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"links\",\"type\":\"tuple[]\",\"internalType\":\"structLink.Data[]\",\"components\":[{\"name\":\"src_index\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TxSigned\",\"inputs\":[{\"name\":\"signer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"txID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"method\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumAuthType.AuthMode\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AckIsNotSuccess\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AllTransactionsConfirmed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ArrayLengthMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AuthAlreadyCompleted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AuthModeMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AuthNotCompleted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AuthStateAlreadyInitialized\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ChannelNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorPhaseNotPrepare\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorStateInconsistent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorStateNotFound\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"CoordinatorTxStatusNotPrepare\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DelegateCallFailed\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"EmptyTypeUrl\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IDNotFound\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidSignersLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTxIDLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"LinksNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageTimeoutHeight\",\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timeoutVersionHeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MessageTimeoutTimestamp\",\"inputs\":[{\"name\":\"blockTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ModuleAlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ModuleNotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PayloadDecodeFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SignatureVerificationFailed\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"SignerCountMismatch\",\"inputs\":[{\"name\":\"signerCount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"signatureCount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"SignerMustEqualSender\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaticCallFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TPCNotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TooManySigners\",\"inputs\":[{\"name\":\"got\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxAllowed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"Tx0MustBeForSelfChain\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TxAlreadyExists\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxAlreadyVerified\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxIDAlreadyExists\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxIDNotFound\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnexpectedChainID\",\"inputs\":[{\"name\":\"expectedHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"gotHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnexpectedCommitStatus\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedReturnValue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedSourceChannel\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedTypeURL\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnknownCommitProtocol\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VerifierNotFound\",\"inputs\":[{\"name\":\"typeUrl\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"VerifierReturnedFalse\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"typeUrl\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressVerifier\",\"inputs\":[]}]", } // CrosssimplemoduleABI is the input ABI used to generate the binding from. @@ -249,6 +380,37 @@ func (_Crosssimplemodule *CrosssimplemoduleTransactorRaw) Transact(opts *bind.Tr return _Crosssimplemodule.Contract.contract.Transact(opts, method, params...) } +// CHAINIDHASH is a free data retrieval call binding the contract method 0x2aed401b. +// +// Solidity: function CHAIN_ID_HASH() view returns(bytes32) +func (_Crosssimplemodule *CrosssimplemoduleCaller) CHAINIDHASH(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Crosssimplemodule.contract.Call(opts, &out, "CHAIN_ID_HASH") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// CHAINIDHASH is a free data retrieval call binding the contract method 0x2aed401b. +// +// Solidity: function CHAIN_ID_HASH() view returns(bytes32) +func (_Crosssimplemodule *CrosssimplemoduleSession) CHAINIDHASH() ([32]byte, error) { + return _Crosssimplemodule.Contract.CHAINIDHASH(&_Crosssimplemodule.CallOpts) +} + +// CHAINIDHASH is a free data retrieval call binding the contract method 0x2aed401b. +// +// Solidity: function CHAIN_ID_HASH() view returns(bytes32) +func (_Crosssimplemodule *CrosssimplemoduleCallerSession) CHAINIDHASH() ([32]byte, error) { + return _Crosssimplemodule.Contract.CHAINIDHASH(&_Crosssimplemodule.CallOpts) +} + // DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // // Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) @@ -311,35 +473,97 @@ func (_Crosssimplemodule *CrosssimplemoduleCallerSession) IBCROLE() ([32]byte, e return _Crosssimplemodule.Contract.IBCROLE(&_Crosssimplemodule.CallOpts) } -// GetPacketAcknowledgementCall is a free data retrieval call binding the contract method 0x34a30a65. +// TXAUTHMANAGER is a free data retrieval call binding the contract method 0xd9a4dcbe. +// +// Solidity: function TX_AUTH_MANAGER() view returns(address) +func (_Crosssimplemodule *CrosssimplemoduleCaller) TXAUTHMANAGER(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Crosssimplemodule.contract.Call(opts, &out, "TX_AUTH_MANAGER") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// TXAUTHMANAGER is a free data retrieval call binding the contract method 0xd9a4dcbe. +// +// Solidity: function TX_AUTH_MANAGER() view returns(address) +func (_Crosssimplemodule *CrosssimplemoduleSession) TXAUTHMANAGER() (common.Address, error) { + return _Crosssimplemodule.Contract.TXAUTHMANAGER(&_Crosssimplemodule.CallOpts) +} + +// TXAUTHMANAGER is a free data retrieval call binding the contract method 0xd9a4dcbe. +// +// Solidity: function TX_AUTH_MANAGER() view returns(address) +func (_Crosssimplemodule *CrosssimplemoduleCallerSession) TXAUTHMANAGER() (common.Address, error) { + return _Crosssimplemodule.Contract.TXAUTHMANAGER(&_Crosssimplemodule.CallOpts) +} + +// TXMANAGER is a free data retrieval call binding the contract method 0x49bfd237. +// +// Solidity: function TX_MANAGER() view returns(address) +func (_Crosssimplemodule *CrosssimplemoduleCaller) TXMANAGER(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Crosssimplemodule.contract.Call(opts, &out, "TX_MANAGER") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// TXMANAGER is a free data retrieval call binding the contract method 0x49bfd237. +// +// Solidity: function TX_MANAGER() view returns(address) +func (_Crosssimplemodule *CrosssimplemoduleSession) TXMANAGER() (common.Address, error) { + return _Crosssimplemodule.Contract.TXMANAGER(&_Crosssimplemodule.CallOpts) +} + +// TXMANAGER is a free data retrieval call binding the contract method 0x49bfd237. +// +// Solidity: function TX_MANAGER() view returns(address) +func (_Crosssimplemodule *CrosssimplemoduleCallerSession) TXMANAGER() (common.Address, error) { + return _Crosssimplemodule.Contract.TXMANAGER(&_Crosssimplemodule.CallOpts) +} + +// CoordinatorState is a free data retrieval call binding the contract method 0x9c1c9c9d. // -// Solidity: function getPacketAcknowledgementCall(uint8 status) pure returns(bytes acknowledgement) -func (_Crosssimplemodule *CrosssimplemoduleCaller) GetPacketAcknowledgementCall(opts *bind.CallOpts, status uint8) ([]byte, error) { +// Solidity: function coordinatorState((bytes) req) view returns(((uint8,(string,string)[],uint8,uint8,uint32[],uint32[]))) +func (_Crosssimplemodule *CrosssimplemoduleCaller) CoordinatorState(opts *bind.CallOpts, req QueryCoordinatorStateRequestData) (QueryCoordinatorStateResponseData, error) { var out []interface{} - err := _Crosssimplemodule.contract.Call(opts, &out, "getPacketAcknowledgementCall", status) + err := _Crosssimplemodule.contract.Call(opts, &out, "coordinatorState", req) if err != nil { - return *new([]byte), err + return *new(QueryCoordinatorStateResponseData), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new(QueryCoordinatorStateResponseData)).(*QueryCoordinatorStateResponseData) return out0, err } -// GetPacketAcknowledgementCall is a free data retrieval call binding the contract method 0x34a30a65. +// CoordinatorState is a free data retrieval call binding the contract method 0x9c1c9c9d. // -// Solidity: function getPacketAcknowledgementCall(uint8 status) pure returns(bytes acknowledgement) -func (_Crosssimplemodule *CrosssimplemoduleSession) GetPacketAcknowledgementCall(status uint8) ([]byte, error) { - return _Crosssimplemodule.Contract.GetPacketAcknowledgementCall(&_Crosssimplemodule.CallOpts, status) +// Solidity: function coordinatorState((bytes) req) view returns(((uint8,(string,string)[],uint8,uint8,uint32[],uint32[]))) +func (_Crosssimplemodule *CrosssimplemoduleSession) CoordinatorState(req QueryCoordinatorStateRequestData) (QueryCoordinatorStateResponseData, error) { + return _Crosssimplemodule.Contract.CoordinatorState(&_Crosssimplemodule.CallOpts, req) } -// GetPacketAcknowledgementCall is a free data retrieval call binding the contract method 0x34a30a65. +// CoordinatorState is a free data retrieval call binding the contract method 0x9c1c9c9d. // -// Solidity: function getPacketAcknowledgementCall(uint8 status) pure returns(bytes acknowledgement) -func (_Crosssimplemodule *CrosssimplemoduleCallerSession) GetPacketAcknowledgementCall(status uint8) ([]byte, error) { - return _Crosssimplemodule.Contract.GetPacketAcknowledgementCall(&_Crosssimplemodule.CallOpts, status) +// Solidity: function coordinatorState((bytes) req) view returns(((uint8,(string,string)[],uint8,uint8,uint32[],uint32[]))) +func (_Crosssimplemodule *CrosssimplemoduleCallerSession) CoordinatorState(req QueryCoordinatorStateRequestData) (QueryCoordinatorStateResponseData, error) { + return _Crosssimplemodule.Contract.CoordinatorState(&_Crosssimplemodule.CallOpts, req) } // GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. @@ -404,12 +628,43 @@ func (_Crosssimplemodule *CrosssimplemoduleCallerSession) HasRole(role [32]byte, return _Crosssimplemodule.Contract.HasRole(&_Crosssimplemodule.CallOpts, role, account) } +// SelfXCC is a free data retrieval call binding the contract method 0xeb245d6c. +// +// Solidity: function selfXCC() view returns(((string,bytes))) +func (_Crosssimplemodule *CrosssimplemoduleCaller) SelfXCC(opts *bind.CallOpts) (QuerySelfXCCResponseData, error) { + var out []interface{} + err := _Crosssimplemodule.contract.Call(opts, &out, "selfXCC") + + if err != nil { + return *new(QuerySelfXCCResponseData), err + } + + out0 := *abi.ConvertType(out[0], new(QuerySelfXCCResponseData)).(*QuerySelfXCCResponseData) + + return out0, err + +} + +// SelfXCC is a free data retrieval call binding the contract method 0xeb245d6c. +// +// Solidity: function selfXCC() view returns(((string,bytes))) +func (_Crosssimplemodule *CrosssimplemoduleSession) SelfXCC() (QuerySelfXCCResponseData, error) { + return _Crosssimplemodule.Contract.SelfXCC(&_Crosssimplemodule.CallOpts) +} + +// SelfXCC is a free data retrieval call binding the contract method 0xeb245d6c. +// +// Solidity: function selfXCC() view returns(((string,bytes))) +func (_Crosssimplemodule *CrosssimplemoduleCallerSession) SelfXCC() (QuerySelfXCCResponseData, error) { + return _Crosssimplemodule.Contract.SelfXCC(&_Crosssimplemodule.CallOpts) +} + // SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Crosssimplemodule *CrosssimplemoduleCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { +// Solidity: function supportsInterface(bytes4 interfaceID) view returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleCaller) SupportsInterface(opts *bind.CallOpts, interfaceID [4]byte) (bool, error) { var out []interface{} - err := _Crosssimplemodule.contract.Call(opts, &out, "supportsInterface", interfaceId) + err := _Crosssimplemodule.contract.Call(opts, &out, "supportsInterface", interfaceID) if err != nil { return *new(bool), err @@ -423,16 +678,142 @@ func (_Crosssimplemodule *CrosssimplemoduleCaller) SupportsInterface(opts *bind. // SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Crosssimplemodule *CrosssimplemoduleSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Crosssimplemodule.Contract.SupportsInterface(&_Crosssimplemodule.CallOpts, interfaceId) +// Solidity: function supportsInterface(bytes4 interfaceID) view returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleSession) SupportsInterface(interfaceID [4]byte) (bool, error) { + return _Crosssimplemodule.Contract.SupportsInterface(&_Crosssimplemodule.CallOpts, interfaceID) } // SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Crosssimplemodule *CrosssimplemoduleCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Crosssimplemodule.Contract.SupportsInterface(&_Crosssimplemodule.CallOpts, interfaceId) +// Solidity: function supportsInterface(bytes4 interfaceID) view returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleCallerSession) SupportsInterface(interfaceID [4]byte) (bool, error) { + return _Crosssimplemodule.Contract.SupportsInterface(&_Crosssimplemodule.CallOpts, interfaceID) +} + +// GetAuthState is a paid mutator transaction binding the contract method 0x5b3af7a0. +// +// Solidity: function __getAuthState(bytes32 txID) returns(((bytes,(uint8,(string,bytes)))[])) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) GetAuthState(opts *bind.TransactOpts, txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "__getAuthState", txID) +} + +// GetAuthState is a paid mutator transaction binding the contract method 0x5b3af7a0. +// +// Solidity: function __getAuthState(bytes32 txID) returns(((bytes,(uint8,(string,bytes)))[])) +func (_Crosssimplemodule *CrosssimplemoduleSession) GetAuthState(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.GetAuthState(&_Crosssimplemodule.TransactOpts, txID) +} + +// GetAuthState is a paid mutator transaction binding the contract method 0x5b3af7a0. +// +// Solidity: function __getAuthState(bytes32 txID) returns(((bytes,(uint8,(string,bytes)))[])) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) GetAuthState(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.GetAuthState(&_Crosssimplemodule.TransactOpts, txID) +} + +// GetCoordinatorState is a paid mutator transaction binding the contract method 0x3a57f0d2. +// +// Solidity: function __getCoordinatorState(bytes32 txID) returns((uint8,(string,string)[],uint8,uint8,uint32[],uint32[])) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) GetCoordinatorState(opts *bind.TransactOpts, txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "__getCoordinatorState", txID) +} + +// GetCoordinatorState is a paid mutator transaction binding the contract method 0x3a57f0d2. +// +// Solidity: function __getCoordinatorState(bytes32 txID) returns((uint8,(string,string)[],uint8,uint8,uint32[],uint32[])) +func (_Crosssimplemodule *CrosssimplemoduleSession) GetCoordinatorState(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.GetCoordinatorState(&_Crosssimplemodule.TransactOpts, txID) +} + +// GetCoordinatorState is a paid mutator transaction binding the contract method 0x3a57f0d2. +// +// Solidity: function __getCoordinatorState(bytes32 txID) returns((uint8,(string,string)[],uint8,uint8,uint32[],uint32[])) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) GetCoordinatorState(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.GetCoordinatorState(&_Crosssimplemodule.TransactOpts, txID) +} + +// IsCompletedAuth is a paid mutator transaction binding the contract method 0x8081e423. +// +// Solidity: function __isCompletedAuth(bytes32 txID) returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) IsCompletedAuth(opts *bind.TransactOpts, txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "__isCompletedAuth", txID) +} + +// IsCompletedAuth is a paid mutator transaction binding the contract method 0x8081e423. +// +// Solidity: function __isCompletedAuth(bytes32 txID) returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleSession) IsCompletedAuth(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.IsCompletedAuth(&_Crosssimplemodule.TransactOpts, txID) +} + +// IsCompletedAuth is a paid mutator transaction binding the contract method 0x8081e423. +// +// Solidity: function __isCompletedAuth(bytes32 txID) returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) IsCompletedAuth(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.IsCompletedAuth(&_Crosssimplemodule.TransactOpts, txID) +} + +// IsTxRecorded is a paid mutator transaction binding the contract method 0x7d9c639c. +// +// Solidity: function __isTxRecorded(bytes32 txID) returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) IsTxRecorded(opts *bind.TransactOpts, txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "__isTxRecorded", txID) +} + +// IsTxRecorded is a paid mutator transaction binding the contract method 0x7d9c639c. +// +// Solidity: function __isTxRecorded(bytes32 txID) returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleSession) IsTxRecorded(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.IsTxRecorded(&_Crosssimplemodule.TransactOpts, txID) +} + +// IsTxRecorded is a paid mutator transaction binding the contract method 0x7d9c639c. +// +// Solidity: function __isTxRecorded(bytes32 txID) returns(bool) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) IsTxRecorded(txID [32]byte) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.IsTxRecorded(&_Crosssimplemodule.TransactOpts, txID) +} + +// ExecuteTx is a paid mutator transaction binding the contract method 0x7bc6a510. +// +// Solidity: function executeTx((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns() +func (_Crosssimplemodule *CrosssimplemoduleTransactor) ExecuteTx(opts *bind.TransactOpts, msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "executeTx", msg_) +} + +// ExecuteTx is a paid mutator transaction binding the contract method 0x7bc6a510. +// +// Solidity: function executeTx((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns() +func (_Crosssimplemodule *CrosssimplemoduleSession) ExecuteTx(msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.ExecuteTx(&_Crosssimplemodule.TransactOpts, msg_) +} + +// ExecuteTx is a paid mutator transaction binding the contract method 0x7bc6a510. +// +// Solidity: function executeTx((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns() +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) ExecuteTx(msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.ExecuteTx(&_Crosssimplemodule.TransactOpts, msg_) +} + +// ExtSignTx is a paid mutator transaction binding the contract method 0x2df86abc. +// +// Solidity: function extSignTx((bytes,(bytes,(uint8,(string,bytes)))[]) msg_) returns((bool)) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) ExtSignTx(opts *bind.TransactOpts, msg_ MsgExtSignTxData) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "extSignTx", msg_) +} + +// ExtSignTx is a paid mutator transaction binding the contract method 0x2df86abc. +// +// Solidity: function extSignTx((bytes,(bytes,(uint8,(string,bytes)))[]) msg_) returns((bool)) +func (_Crosssimplemodule *CrosssimplemoduleSession) ExtSignTx(msg_ MsgExtSignTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.ExtSignTx(&_Crosssimplemodule.TransactOpts, msg_) +} + +// ExtSignTx is a paid mutator transaction binding the contract method 0x2df86abc. +// +// Solidity: function extSignTx((bytes,(bytes,(uint8,(string,bytes)))[]) msg_) returns((bool)) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) ExtSignTx(msg_ MsgExtSignTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.ExtSignTx(&_Crosssimplemodule.TransactOpts, msg_) } // GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. @@ -456,6 +837,27 @@ func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) GrantRole(role [32 return _Crosssimplemodule.Contract.GrantRole(&_Crosssimplemodule.TransactOpts, role, account) } +// InitiateTx is a paid mutator transaction binding the contract method 0x909445fc. +// +// Solidity: function initiateTx((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns((bytes,uint8) resp) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) InitiateTx(opts *bind.TransactOpts, msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "initiateTx", msg_) +} + +// InitiateTx is a paid mutator transaction binding the contract method 0x909445fc. +// +// Solidity: function initiateTx((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns((bytes,uint8) resp) +func (_Crosssimplemodule *CrosssimplemoduleSession) InitiateTx(msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.InitiateTx(&_Crosssimplemodule.TransactOpts, msg_) +} + +// InitiateTx is a paid mutator transaction binding the contract method 0x909445fc. +// +// Solidity: function initiateTx((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns((bytes,uint8) resp) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) InitiateTx(msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.InitiateTx(&_Crosssimplemodule.TransactOpts, msg_) +} + // OnAcknowledgementPacket is a paid mutator transaction binding the contract method 0xfb8b532e. // // Solidity: function onAcknowledgementPacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement, address ) returns() @@ -687,9 +1089,51 @@ func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) RevokeRole(role [3 return _Crosssimplemodule.Contract.RevokeRole(&_Crosssimplemodule.TransactOpts, role, account) } -// CrosssimplemoduleOnContractCallIterator is returned from FilterOnContractCall and is used to iterate over the raw logs and unpacked data for OnContractCall events raised by the Crosssimplemodule contract. -type CrosssimplemoduleOnContractCallIterator struct { - Event *CrosssimplemoduleOnContractCall // Event containing the contract specifics and raw log +// SignTx is a paid mutator transaction binding the contract method 0x4391870b. +// +// Solidity: function signTx((bytes,bytes[],(uint64,uint64),uint64) msg_) returns((bool,string)) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) SignTx(opts *bind.TransactOpts, msg_ MsgSignTxData) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "signTx", msg_) +} + +// SignTx is a paid mutator transaction binding the contract method 0x4391870b. +// +// Solidity: function signTx((bytes,bytes[],(uint64,uint64),uint64) msg_) returns((bool,string)) +func (_Crosssimplemodule *CrosssimplemoduleSession) SignTx(msg_ MsgSignTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.SignTx(&_Crosssimplemodule.TransactOpts, msg_) +} + +// SignTx is a paid mutator transaction binding the contract method 0x4391870b. +// +// Solidity: function signTx((bytes,bytes[],(uint64,uint64),uint64) msg_) returns((bool,string)) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) SignTx(msg_ MsgSignTxData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.SignTx(&_Crosssimplemodule.TransactOpts, msg_) +} + +// TxAuthState is a paid mutator transaction binding the contract method 0xa7edcfd6. +// +// Solidity: function txAuthState((bytes) req_) returns((((bytes,(uint8,(string,bytes)))[])) resp) +func (_Crosssimplemodule *CrosssimplemoduleTransactor) TxAuthState(opts *bind.TransactOpts, req_ QueryTxAuthStateRequestData) (*types.Transaction, error) { + return _Crosssimplemodule.contract.Transact(opts, "txAuthState", req_) +} + +// TxAuthState is a paid mutator transaction binding the contract method 0xa7edcfd6. +// +// Solidity: function txAuthState((bytes) req_) returns((((bytes,(uint8,(string,bytes)))[])) resp) +func (_Crosssimplemodule *CrosssimplemoduleSession) TxAuthState(req_ QueryTxAuthStateRequestData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.TxAuthState(&_Crosssimplemodule.TransactOpts, req_) +} + +// TxAuthState is a paid mutator transaction binding the contract method 0xa7edcfd6. +// +// Solidity: function txAuthState((bytes) req_) returns((((bytes,(uint8,(string,bytes)))[])) resp) +func (_Crosssimplemodule *CrosssimplemoduleTransactorSession) TxAuthState(req_ QueryTxAuthStateRequestData) (*types.Transaction, error) { + return _Crosssimplemodule.Contract.TxAuthState(&_Crosssimplemodule.TransactOpts, req_) +} + +// CrosssimplemoduleOnAbortIterator is returned from FilterOnAbort and is used to iterate over the raw logs and unpacked data for OnAbort events raised by the Crosssimplemodule contract. +type CrosssimplemoduleOnAbortIterator struct { + Event *CrosssimplemoduleOnAbort // 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 @@ -703,7 +1147,7 @@ type CrosssimplemoduleOnContractCallIterator struct { // 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 *CrosssimplemoduleOnContractCallIterator) Next() bool { +func (it *CrosssimplemoduleOnAbortIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -712,7 +1156,7 @@ func (it *CrosssimplemoduleOnContractCallIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleOnContractCall) + it.Event = new(CrosssimplemoduleOnAbort) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -727,7 +1171,7 @@ func (it *CrosssimplemoduleOnContractCallIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleOnContractCall) + it.Event = new(CrosssimplemoduleOnAbort) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -743,70 +1187,60 @@ func (it *CrosssimplemoduleOnContractCallIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *CrosssimplemoduleOnContractCallIterator) Error() error { +func (it *CrosssimplemoduleOnAbortIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *CrosssimplemoduleOnContractCallIterator) Close() error { +func (it *CrosssimplemoduleOnAbortIterator) Close() error { it.sub.Unsubscribe() return nil } -// CrosssimplemoduleOnContractCall represents a OnContractCall event raised by the Crosssimplemodule contract. -type CrosssimplemoduleOnContractCall struct { - TxId common.Hash +// CrosssimplemoduleOnAbort represents a OnAbort event raised by the Crosssimplemodule contract. +type CrosssimplemoduleOnAbort struct { + TxID common.Hash TxIndex uint8 - Success bool - Ret []byte Raw types.Log // Blockchain specific contextual infos } -// FilterOnContractCall is a free log retrieval operation binding the contract event 0x3cf6800c9da1119c1bcca8a173f94e0cd281ab3fae5f1e09ebbb95a64092584f. +// FilterOnAbort is a free log retrieval operation binding the contract event 0x250bcd3f1f48512b15dbba0fb804f06878f25675cc2381898c392169d814a6f1. // -// Solidity: event OnContractCall(bytes indexed txId, uint8 indexed txIndex, bool indexed success, bytes ret) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterOnContractCall(opts *bind.FilterOpts, txId [][]byte, txIndex []uint8, success []bool) (*CrosssimplemoduleOnContractCallIterator, error) { +// Solidity: event OnAbort(bytes indexed txID, uint8 indexed txIndex) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterOnAbort(opts *bind.FilterOpts, txID [][]byte, txIndex []uint8) (*CrosssimplemoduleOnAbortIterator, error) { - var txIdRule []interface{} - for _, txIdItem := range txId { - txIdRule = append(txIdRule, txIdItem) + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) } var txIndexRule []interface{} for _, txIndexItem := range txIndex { txIndexRule = append(txIndexRule, txIndexItem) } - var successRule []interface{} - for _, successItem := range success { - successRule = append(successRule, successItem) - } - logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "OnContractCall", txIdRule, txIndexRule, successRule) + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "OnAbort", txIDRule, txIndexRule) if err != nil { return nil, err } - return &CrosssimplemoduleOnContractCallIterator{contract: _Crosssimplemodule.contract, event: "OnContractCall", logs: logs, sub: sub}, nil + return &CrosssimplemoduleOnAbortIterator{contract: _Crosssimplemodule.contract, event: "OnAbort", logs: logs, sub: sub}, nil } -// WatchOnContractCall is a free log subscription operation binding the contract event 0x3cf6800c9da1119c1bcca8a173f94e0cd281ab3fae5f1e09ebbb95a64092584f. +// WatchOnAbort is a free log subscription operation binding the contract event 0x250bcd3f1f48512b15dbba0fb804f06878f25675cc2381898c392169d814a6f1. // -// Solidity: event OnContractCall(bytes indexed txId, uint8 indexed txIndex, bool indexed success, bytes ret) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchOnContractCall(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleOnContractCall, txId [][]byte, txIndex []uint8, success []bool) (event.Subscription, error) { +// Solidity: event OnAbort(bytes indexed txID, uint8 indexed txIndex) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchOnAbort(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleOnAbort, txID [][]byte, txIndex []uint8) (event.Subscription, error) { - var txIdRule []interface{} - for _, txIdItem := range txId { - txIdRule = append(txIdRule, txIdItem) + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) } var txIndexRule []interface{} for _, txIndexItem := range txIndex { txIndexRule = append(txIndexRule, txIndexItem) } - var successRule []interface{} - for _, successItem := range success { - successRule = append(successRule, successItem) - } - logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "OnContractCall", txIdRule, txIndexRule, successRule) + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "OnAbort", txIDRule, txIndexRule) if err != nil { return nil, err } @@ -816,8 +1250,8 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchOnContractCall(opts *b select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(CrosssimplemoduleOnContractCall) - if err := _Crosssimplemodule.contract.UnpackLog(event, "OnContractCall", log); err != nil { + event := new(CrosssimplemoduleOnAbort) + if err := _Crosssimplemodule.contract.UnpackLog(event, "OnAbort", log); err != nil { return err } event.Raw = log @@ -838,21 +1272,21 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchOnContractCall(opts *b }), nil } -// ParseOnContractCall is a log parse operation binding the contract event 0x3cf6800c9da1119c1bcca8a173f94e0cd281ab3fae5f1e09ebbb95a64092584f. +// ParseOnAbort is a log parse operation binding the contract event 0x250bcd3f1f48512b15dbba0fb804f06878f25675cc2381898c392169d814a6f1. // -// Solidity: event OnContractCall(bytes indexed txId, uint8 indexed txIndex, bool indexed success, bytes ret) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseOnContractCall(log types.Log) (*CrosssimplemoduleOnContractCall, error) { - event := new(CrosssimplemoduleOnContractCall) - if err := _Crosssimplemodule.contract.UnpackLog(event, "OnContractCall", log); err != nil { +// Solidity: event OnAbort(bytes indexed txID, uint8 indexed txIndex) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseOnAbort(log types.Log) (*CrosssimplemoduleOnAbort, error) { + event := new(CrosssimplemoduleOnAbort) + if err := _Crosssimplemodule.contract.UnpackLog(event, "OnAbort", log); err != nil { return nil, err } event.Raw = log return event, nil } -// CrosssimplemoduleRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Crosssimplemodule contract. -type CrosssimplemoduleRoleAdminChangedIterator struct { - Event *CrosssimplemoduleRoleAdminChanged // Event containing the contract specifics and raw log +// CrosssimplemoduleOnCommitIterator is returned from FilterOnCommit and is used to iterate over the raw logs and unpacked data for OnCommit events raised by the Crosssimplemodule contract. +type CrosssimplemoduleOnCommitIterator struct { + Event *CrosssimplemoduleOnCommit // 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 @@ -866,7 +1300,7 @@ type CrosssimplemoduleRoleAdminChangedIterator struct { // 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 *CrosssimplemoduleRoleAdminChangedIterator) Next() bool { +func (it *CrosssimplemoduleOnCommitIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -875,7 +1309,7 @@ func (it *CrosssimplemoduleRoleAdminChangedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleRoleAdminChanged) + it.Event = new(CrosssimplemoduleOnCommit) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -890,7 +1324,7 @@ func (it *CrosssimplemoduleRoleAdminChangedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleRoleAdminChanged) + it.Event = new(CrosssimplemoduleOnCommit) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -906,69 +1340,60 @@ func (it *CrosssimplemoduleRoleAdminChangedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *CrosssimplemoduleRoleAdminChangedIterator) Error() error { +func (it *CrosssimplemoduleOnCommitIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *CrosssimplemoduleRoleAdminChangedIterator) Close() error { +func (it *CrosssimplemoduleOnCommitIterator) Close() error { it.sub.Unsubscribe() return nil } -// CrosssimplemoduleRoleAdminChanged represents a RoleAdminChanged event raised by the Crosssimplemodule contract. -type CrosssimplemoduleRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos +// CrosssimplemoduleOnCommit represents a OnCommit event raised by the Crosssimplemodule contract. +type CrosssimplemoduleOnCommit struct { + TxID common.Hash + TxIndex uint8 + Raw types.Log // Blockchain specific contextual infos } -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// FilterOnCommit is a free log retrieval operation binding the contract event 0x7aaf0b63467fb40eac34c045248842f31e4e1edff7f0dd939f7ddeeddd83adc0. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*CrosssimplemoduleRoleAdminChangedIterator, error) { +// Solidity: event OnCommit(bytes indexed txID, uint8 indexed txIndex) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterOnCommit(opts *bind.FilterOpts, txID [][]byte, txIndex []uint8) (*CrosssimplemoduleOnCommitIterator, error) { - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) } - logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "OnCommit", txIDRule, txIndexRule) if err != nil { return nil, err } - return &CrosssimplemoduleRoleAdminChangedIterator{contract: _Crosssimplemodule.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil + return &CrosssimplemoduleOnCommitIterator{contract: _Crosssimplemodule.contract, event: "OnCommit", logs: logs, sub: sub}, nil } -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// WatchOnCommit is a free log subscription operation binding the contract event 0x7aaf0b63467fb40eac34c045248842f31e4e1edff7f0dd939f7ddeeddd83adc0. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { +// Solidity: event OnCommit(bytes indexed txID, uint8 indexed txIndex) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchOnCommit(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleOnCommit, txID [][]byte, txIndex []uint8) (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 txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) } - logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "OnCommit", txIDRule, txIndexRule) if err != nil { return nil, err } @@ -978,8 +1403,8 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleAdminChanged(opts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(CrosssimplemoduleRoleAdminChanged) - if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + event := new(CrosssimplemoduleOnCommit) + if err := _Crosssimplemodule.contract.UnpackLog(event, "OnCommit", log); err != nil { return err } event.Raw = log @@ -1000,21 +1425,21 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleAdminChanged(opts }), nil } -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// ParseOnCommit is a log parse operation binding the contract event 0x7aaf0b63467fb40eac34c045248842f31e4e1edff7f0dd939f7ddeeddd83adc0. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseRoleAdminChanged(log types.Log) (*CrosssimplemoduleRoleAdminChanged, error) { - event := new(CrosssimplemoduleRoleAdminChanged) - if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { +// Solidity: event OnCommit(bytes indexed txID, uint8 indexed txIndex) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseOnCommit(log types.Log) (*CrosssimplemoduleOnCommit, error) { + event := new(CrosssimplemoduleOnCommit) + if err := _Crosssimplemodule.contract.UnpackLog(event, "OnCommit", log); err != nil { return nil, err } event.Raw = log return event, nil } -// CrosssimplemoduleRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Crosssimplemodule contract. -type CrosssimplemoduleRoleGrantedIterator struct { - Event *CrosssimplemoduleRoleGranted // Event containing the contract specifics and raw log +// CrosssimplemoduleOnContractCommitImmediatelyIterator is returned from FilterOnContractCommitImmediately and is used to iterate over the raw logs and unpacked data for OnContractCommitImmediately events raised by the Crosssimplemodule contract. +type CrosssimplemoduleOnContractCommitImmediatelyIterator struct { + Event *CrosssimplemoduleOnContractCommitImmediately // 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 @@ -1028,7 +1453,7 @@ type CrosssimplemoduleRoleGrantedIterator struct { // 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 *CrosssimplemoduleRoleGrantedIterator) Next() bool { +func (it *CrosssimplemoduleOnContractCommitImmediatelyIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1037,7 +1462,7 @@ func (it *CrosssimplemoduleRoleGrantedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleRoleGranted) + it.Event = new(CrosssimplemoduleOnContractCommitImmediately) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1052,7 +1477,7 @@ func (it *CrosssimplemoduleRoleGrantedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleRoleGranted) + it.Event = new(CrosssimplemoduleOnContractCommitImmediately) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1068,69 +1493,70 @@ func (it *CrosssimplemoduleRoleGrantedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *CrosssimplemoduleRoleGrantedIterator) Error() error { +func (it *CrosssimplemoduleOnContractCommitImmediatelyIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *CrosssimplemoduleRoleGrantedIterator) Close() error { +func (it *CrosssimplemoduleOnContractCommitImmediatelyIterator) Close() error { it.sub.Unsubscribe() return nil } -// CrosssimplemoduleRoleGranted represents a RoleGranted event raised by the Crosssimplemodule contract. -type CrosssimplemoduleRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address +// CrosssimplemoduleOnContractCommitImmediately represents a OnContractCommitImmediately event raised by the Crosssimplemodule contract. +type CrosssimplemoduleOnContractCommitImmediately struct { + TxID common.Hash + TxIndex uint8 + Success bool + Ret []byte Raw types.Log // Blockchain specific contextual infos } -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// FilterOnContractCommitImmediately is a free log retrieval operation binding the contract event 0x7da7723d423258c97d02fba73c0951597dc48566af572d5cb8e2698c22102e61. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*CrosssimplemoduleRoleGrantedIterator, error) { +// Solidity: event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterOnContractCommitImmediately(opts *bind.FilterOpts, txID [][]byte, txIndex []uint8, success []bool) (*CrosssimplemoduleOnContractCommitImmediatelyIterator, error) { - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) + var successRule []interface{} + for _, successItem := range success { + successRule = append(successRule, successItem) } - logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "OnContractCommitImmediately", txIDRule, txIndexRule, successRule) if err != nil { return nil, err } - return &CrosssimplemoduleRoleGrantedIterator{contract: _Crosssimplemodule.contract, event: "RoleGranted", logs: logs, sub: sub}, nil + return &CrosssimplemoduleOnContractCommitImmediatelyIterator{contract: _Crosssimplemodule.contract, event: "OnContractCommitImmediately", logs: logs, sub: sub}, nil } -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// WatchOnContractCommitImmediately is a free log subscription operation binding the contract event 0x7da7723d423258c97d02fba73c0951597dc48566af572d5cb8e2698c22102e61. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { +// Solidity: event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchOnContractCommitImmediately(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleOnContractCommitImmediately, txID [][]byte, txIndex []uint8, success []bool) (event.Subscription, error) { - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) + var successRule []interface{} + for _, successItem := range success { + successRule = append(successRule, successItem) } - logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "OnContractCommitImmediately", txIDRule, txIndexRule, successRule) if err != nil { return nil, err } @@ -1140,8 +1566,8 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleGranted(opts *bind select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(CrosssimplemoduleRoleGranted) - if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleGranted", log); err != nil { + event := new(CrosssimplemoduleOnContractCommitImmediately) + if err := _Crosssimplemodule.contract.UnpackLog(event, "OnContractCommitImmediately", log); err != nil { return err } event.Raw = log @@ -1162,21 +1588,21 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleGranted(opts *bind }), nil } -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// ParseOnContractCommitImmediately is a log parse operation binding the contract event 0x7da7723d423258c97d02fba73c0951597dc48566af572d5cb8e2698c22102e61. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseRoleGranted(log types.Log) (*CrosssimplemoduleRoleGranted, error) { - event := new(CrosssimplemoduleRoleGranted) - if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleGranted", log); err != nil { +// Solidity: event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseOnContractCommitImmediately(log types.Log) (*CrosssimplemoduleOnContractCommitImmediately, error) { + event := new(CrosssimplemoduleOnContractCommitImmediately) + if err := _Crosssimplemodule.contract.UnpackLog(event, "OnContractCommitImmediately", log); err != nil { return nil, err } event.Raw = log return event, nil } -// CrosssimplemoduleRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Crosssimplemodule contract. -type CrosssimplemoduleRoleRevokedIterator struct { - Event *CrosssimplemoduleRoleRevoked // Event containing the contract specifics and raw log +// CrosssimplemoduleRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Crosssimplemodule contract. +type CrosssimplemoduleRoleAdminChangedIterator struct { + Event *CrosssimplemoduleRoleAdminChanged // 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 @@ -1190,7 +1616,7 @@ type CrosssimplemoduleRoleRevokedIterator struct { // 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 *CrosssimplemoduleRoleRevokedIterator) Next() bool { +func (it *CrosssimplemoduleRoleAdminChangedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1199,7 +1625,7 @@ func (it *CrosssimplemoduleRoleRevokedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleRoleRevoked) + it.Event = new(CrosssimplemoduleRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1214,7 +1640,7 @@ func (it *CrosssimplemoduleRoleRevokedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(CrosssimplemoduleRoleRevoked) + it.Event = new(CrosssimplemoduleRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1230,69 +1656,69 @@ func (it *CrosssimplemoduleRoleRevokedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *CrosssimplemoduleRoleRevokedIterator) Error() error { +func (it *CrosssimplemoduleRoleAdminChangedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *CrosssimplemoduleRoleRevokedIterator) Close() error { +func (it *CrosssimplemoduleRoleAdminChangedIterator) Close() error { it.sub.Unsubscribe() return nil } -// CrosssimplemoduleRoleRevoked represents a RoleRevoked event raised by the Crosssimplemodule contract. -type CrosssimplemoduleRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// CrosssimplemoduleRoleAdminChanged represents a RoleAdminChanged event raised by the Crosssimplemodule contract. +type CrosssimplemoduleRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*CrosssimplemoduleRoleRevokedIterator, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*CrosssimplemoduleRoleAdminChangedIterator, error) { var roleRule []interface{} for _, roleItem := range role { roleRule = append(roleRule, roleItem) } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return &CrosssimplemoduleRoleRevokedIterator{contract: _Crosssimplemodule.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil + return &CrosssimplemoduleRoleAdminChangedIterator{contract: _Crosssimplemodule.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (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 previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } @@ -1302,8 +1728,8 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleRevoked(opts *bind select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(CrosssimplemoduleRoleRevoked) - if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + event := new(CrosssimplemoduleRoleAdminChanged) + if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return err } event.Raw = log @@ -1324,12 +1750,781 @@ func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleRevoked(opts *bind }), nil } -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseRoleRevoked(log types.Log) (*CrosssimplemoduleRoleRevoked, error) { - event := new(CrosssimplemoduleRoleRevoked) - if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleRevoked", log); err != nil { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseRoleAdminChanged(log types.Log) (*CrosssimplemoduleRoleAdminChanged, error) { + event := new(CrosssimplemoduleRoleAdminChanged) + if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CrosssimplemoduleRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Crosssimplemodule contract. +type CrosssimplemoduleRoleGrantedIterator struct { + Event *CrosssimplemoduleRoleGranted // 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 *CrosssimplemoduleRoleGrantedIterator) 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(CrosssimplemoduleRoleGranted) + 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(CrosssimplemoduleRoleGranted) + 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 *CrosssimplemoduleRoleGrantedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CrosssimplemoduleRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CrosssimplemoduleRoleGranted represents a RoleGranted event raised by the Crosssimplemodule contract. +type CrosssimplemoduleRoleGranted 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 (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*CrosssimplemoduleRoleGrantedIterator, 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 := _Crosssimplemodule.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &CrosssimplemoduleRoleGrantedIterator{contract: _Crosssimplemodule.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 (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleRoleGranted, 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 := _Crosssimplemodule.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(CrosssimplemoduleRoleGranted) + if err := _Crosssimplemodule.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 (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseRoleGranted(log types.Log) (*CrosssimplemoduleRoleGranted, error) { + event := new(CrosssimplemoduleRoleGranted) + if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CrosssimplemoduleRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Crosssimplemodule contract. +type CrosssimplemoduleRoleRevokedIterator struct { + Event *CrosssimplemoduleRoleRevoked // 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 *CrosssimplemoduleRoleRevokedIterator) 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(CrosssimplemoduleRoleRevoked) + 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(CrosssimplemoduleRoleRevoked) + 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 *CrosssimplemoduleRoleRevokedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CrosssimplemoduleRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CrosssimplemoduleRoleRevoked represents a RoleRevoked event raised by the Crosssimplemodule contract. +type CrosssimplemoduleRoleRevoked 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 (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*CrosssimplemoduleRoleRevokedIterator, 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 := _Crosssimplemodule.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &CrosssimplemoduleRoleRevokedIterator{contract: _Crosssimplemodule.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 (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleRoleRevoked, 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 := _Crosssimplemodule.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(CrosssimplemoduleRoleRevoked) + if err := _Crosssimplemodule.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 (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseRoleRevoked(log types.Log) (*CrosssimplemoduleRoleRevoked, error) { + event := new(CrosssimplemoduleRoleRevoked) + if err := _Crosssimplemodule.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CrosssimplemoduleTxExecutedIterator is returned from FilterTxExecuted and is used to iterate over the raw logs and unpacked data for TxExecuted events raised by the Crosssimplemodule contract. +type CrosssimplemoduleTxExecutedIterator struct { + Event *CrosssimplemoduleTxExecuted // 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 *CrosssimplemoduleTxExecutedIterator) 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(CrosssimplemoduleTxExecuted) + 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(CrosssimplemoduleTxExecuted) + 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 *CrosssimplemoduleTxExecutedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CrosssimplemoduleTxExecutedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CrosssimplemoduleTxExecuted represents a TxExecuted event raised by the Crosssimplemodule contract. +type CrosssimplemoduleTxExecuted struct { + TxID []byte + Proposer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxExecuted is a free log retrieval operation binding the contract event 0xdf7ae1f6bc0bafd42f6b0ffe61265f1f2b82ec85389dbacc0664f47af522db18. +// +// Solidity: event TxExecuted(bytes txID, address indexed proposer) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterTxExecuted(opts *bind.FilterOpts, proposer []common.Address) (*CrosssimplemoduleTxExecutedIterator, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "TxExecuted", proposerRule) + if err != nil { + return nil, err + } + return &CrosssimplemoduleTxExecutedIterator{contract: _Crosssimplemodule.contract, event: "TxExecuted", logs: logs, sub: sub}, nil +} + +// WatchTxExecuted is a free log subscription operation binding the contract event 0xdf7ae1f6bc0bafd42f6b0ffe61265f1f2b82ec85389dbacc0664f47af522db18. +// +// Solidity: event TxExecuted(bytes txID, address indexed proposer) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchTxExecuted(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleTxExecuted, proposer []common.Address) (event.Subscription, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "TxExecuted", proposerRule) + 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(CrosssimplemoduleTxExecuted) + if err := _Crosssimplemodule.contract.UnpackLog(event, "TxExecuted", 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 +} + +// ParseTxExecuted is a log parse operation binding the contract event 0xdf7ae1f6bc0bafd42f6b0ffe61265f1f2b82ec85389dbacc0664f47af522db18. +// +// Solidity: event TxExecuted(bytes txID, address indexed proposer) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseTxExecuted(log types.Log) (*CrosssimplemoduleTxExecuted, error) { + event := new(CrosssimplemoduleTxExecuted) + if err := _Crosssimplemodule.contract.UnpackLog(event, "TxExecuted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CrosssimplemoduleTxInitiatedIterator is returned from FilterTxInitiated and is used to iterate over the raw logs and unpacked data for TxInitiated events raised by the Crosssimplemodule contract. +type CrosssimplemoduleTxInitiatedIterator struct { + Event *CrosssimplemoduleTxInitiated // 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 *CrosssimplemoduleTxInitiatedIterator) 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(CrosssimplemoduleTxInitiated) + 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(CrosssimplemoduleTxInitiated) + 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 *CrosssimplemoduleTxInitiatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CrosssimplemoduleTxInitiatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CrosssimplemoduleTxInitiated represents a TxInitiated event raised by the Crosssimplemodule contract. +type CrosssimplemoduleTxInitiated struct { + TxID []byte + Proposer common.Address + MsgData MsgInitiateTxData + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxInitiated is a free log retrieval operation binding the contract event 0x82b61ce957ceac1596e6ab9a00110d416225ef3b28693a337d32eede878df6cf. +// +// Solidity: event TxInitiated(bytes txID, address indexed proposer, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msgData) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterTxInitiated(opts *bind.FilterOpts, proposer []common.Address) (*CrosssimplemoduleTxInitiatedIterator, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "TxInitiated", proposerRule) + if err != nil { + return nil, err + } + return &CrosssimplemoduleTxInitiatedIterator{contract: _Crosssimplemodule.contract, event: "TxInitiated", logs: logs, sub: sub}, nil +} + +// WatchTxInitiated is a free log subscription operation binding the contract event 0x82b61ce957ceac1596e6ab9a00110d416225ef3b28693a337d32eede878df6cf. +// +// Solidity: event TxInitiated(bytes txID, address indexed proposer, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msgData) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchTxInitiated(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleTxInitiated, proposer []common.Address) (event.Subscription, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "TxInitiated", proposerRule) + 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(CrosssimplemoduleTxInitiated) + if err := _Crosssimplemodule.contract.UnpackLog(event, "TxInitiated", 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 +} + +// ParseTxInitiated is a log parse operation binding the contract event 0x82b61ce957ceac1596e6ab9a00110d416225ef3b28693a337d32eede878df6cf. +// +// Solidity: event TxInitiated(bytes txID, address indexed proposer, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msgData) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseTxInitiated(log types.Log) (*CrosssimplemoduleTxInitiated, error) { + event := new(CrosssimplemoduleTxInitiated) + if err := _Crosssimplemodule.contract.UnpackLog(event, "TxInitiated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CrosssimplemoduleTxSignedIterator is returned from FilterTxSigned and is used to iterate over the raw logs and unpacked data for TxSigned events raised by the Crosssimplemodule contract. +type CrosssimplemoduleTxSignedIterator struct { + Event *CrosssimplemoduleTxSigned // 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 *CrosssimplemoduleTxSignedIterator) 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(CrosssimplemoduleTxSigned) + 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(CrosssimplemoduleTxSigned) + 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 *CrosssimplemoduleTxSignedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CrosssimplemoduleTxSignedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CrosssimplemoduleTxSigned represents a TxSigned event raised by the Crosssimplemodule contract. +type CrosssimplemoduleTxSigned struct { + Signer common.Address + TxID [32]byte + Method uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxSigned is a free log retrieval operation binding the contract event 0x30c2a521823a6b9bc4f65ec80485542760a5639a135db9e69f36d257d9c3a716. +// +// Solidity: event TxSigned(address indexed signer, bytes32 indexed txID, uint8 method) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) FilterTxSigned(opts *bind.FilterOpts, signer []common.Address, txID [][32]byte) (*CrosssimplemoduleTxSignedIterator, error) { + + var signerRule []interface{} + for _, signerItem := range signer { + signerRule = append(signerRule, signerItem) + } + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + + logs, sub, err := _Crosssimplemodule.contract.FilterLogs(opts, "TxSigned", signerRule, txIDRule) + if err != nil { + return nil, err + } + return &CrosssimplemoduleTxSignedIterator{contract: _Crosssimplemodule.contract, event: "TxSigned", logs: logs, sub: sub}, nil +} + +// WatchTxSigned is a free log subscription operation binding the contract event 0x30c2a521823a6b9bc4f65ec80485542760a5639a135db9e69f36d257d9c3a716. +// +// Solidity: event TxSigned(address indexed signer, bytes32 indexed txID, uint8 method) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) WatchTxSigned(opts *bind.WatchOpts, sink chan<- *CrosssimplemoduleTxSigned, signer []common.Address, txID [][32]byte) (event.Subscription, error) { + + var signerRule []interface{} + for _, signerItem := range signer { + signerRule = append(signerRule, signerItem) + } + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + + logs, sub, err := _Crosssimplemodule.contract.WatchLogs(opts, "TxSigned", signerRule, txIDRule) + 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(CrosssimplemoduleTxSigned) + if err := _Crosssimplemodule.contract.UnpackLog(event, "TxSigned", 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 +} + +// ParseTxSigned is a log parse operation binding the contract event 0x30c2a521823a6b9bc4f65ec80485542760a5639a135db9e69f36d257d9c3a716. +// +// Solidity: event TxSigned(address indexed signer, bytes32 indexed txID, uint8 method) +func (_Crosssimplemodule *CrosssimplemoduleFilterer) ParseTxSigned(log types.Log) (*CrosssimplemoduleTxSigned, error) { + event := new(CrosssimplemoduleTxSigned) + if err := _Crosssimplemodule.contract.UnpackLog(event, "TxSigned", log); err != nil { return nil, err } event.Raw = log diff --git a/pkg/contract/txauthmanager/txauthmanager.go b/pkg/contract/txauthmanager/txauthmanager.go new file mode 100644 index 0000000..755f1f9 --- /dev/null +++ b/pkg/contract/txauthmanager/txauthmanager.go @@ -0,0 +1,484 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package txauthmanager + +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 +) + +// AccountData is an auto generated low-level Go binding around an user-defined struct. +type AccountData struct { + Id []byte + AuthType AuthTypeData +} + +// AuthTypeData is an auto generated low-level Go binding around an user-defined struct. +type AuthTypeData struct { + Mode uint8 + Option GoogleProtobufAnyData +} + +// GoogleProtobufAnyData is an auto generated low-level Go binding around an user-defined struct. +type GoogleProtobufAnyData struct { + TypeUrl string + Value []byte +} + +// TxAuthStateData is an auto generated low-level Go binding around an user-defined struct. +type TxAuthStateData struct { + RemainingSigners []AccountData +} + +// TxauthmanagerMetaData contains all meta data concerning the Txauthmanager contract. +var TxauthmanagerMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"getAuthState\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTxAuthState.Data\",\"components\":[{\"name\":\"remaining_signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initAuthState\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"typeUrls\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"verifiers\",\"type\":\"address[]\",\"internalType\":\"contractIAuthExtensionVerifier[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isCompletedAuth\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"sign\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifySignatures\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AckIsNotSuccess\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AllTransactionsConfirmed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ArrayLengthMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AuthAlreadyCompleted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AuthModeMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AuthNotCompleted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AuthStateAlreadyInitialized\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ChannelNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorPhaseNotPrepare\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorStateInconsistent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorStateNotFound\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"CoordinatorTxStatusNotPrepare\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DelegateCallFailed\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"EmptyTypeUrl\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IDNotFound\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignersLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTxIDLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"LinksNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageTimeoutHeight\",\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timeoutVersionHeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MessageTimeoutTimestamp\",\"inputs\":[{\"name\":\"blockTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ModuleAlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ModuleNotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PayloadDecodeFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SignatureVerificationFailed\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"SignerCountMismatch\",\"inputs\":[{\"name\":\"signerCount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"signatureCount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"SignerMustEqualSender\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaticCallFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TPCNotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TooManySigners\",\"inputs\":[{\"name\":\"got\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxAllowed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"Tx0MustBeForSelfChain\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TxAlreadyExists\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxAlreadyVerified\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxIDAlreadyExists\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxIDNotFound\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnexpectedChainID\",\"inputs\":[{\"name\":\"expectedHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"gotHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnexpectedCommitStatus\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedReturnValue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedSourceChannel\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedTypeURL\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnknownCommitProtocol\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VerifierNotFound\",\"inputs\":[{\"name\":\"typeUrl\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"VerifierReturnedFalse\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"typeUrl\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressVerifier\",\"inputs\":[]}]", +} + +// TxauthmanagerABI is the input ABI used to generate the binding from. +// Deprecated: Use TxauthmanagerMetaData.ABI instead. +var TxauthmanagerABI = TxauthmanagerMetaData.ABI + +// Txauthmanager is an auto generated Go binding around an Ethereum contract. +type Txauthmanager struct { + TxauthmanagerCaller // Read-only binding to the contract + TxauthmanagerTransactor // Write-only binding to the contract + TxauthmanagerFilterer // Log filterer for contract events +} + +// TxauthmanagerCaller is an auto generated read-only Go binding around an Ethereum contract. +type TxauthmanagerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TxauthmanagerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TxauthmanagerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TxauthmanagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TxauthmanagerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TxauthmanagerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TxauthmanagerSession struct { + Contract *Txauthmanager // 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 +} + +// TxauthmanagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TxauthmanagerCallerSession struct { + Contract *TxauthmanagerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TxauthmanagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TxauthmanagerTransactorSession struct { + Contract *TxauthmanagerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TxauthmanagerRaw is an auto generated low-level Go binding around an Ethereum contract. +type TxauthmanagerRaw struct { + Contract *Txauthmanager // Generic contract binding to access the raw methods on +} + +// TxauthmanagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TxauthmanagerCallerRaw struct { + Contract *TxauthmanagerCaller // Generic read-only contract binding to access the raw methods on +} + +// TxauthmanagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TxauthmanagerTransactorRaw struct { + Contract *TxauthmanagerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTxauthmanager creates a new instance of Txauthmanager, bound to a specific deployed contract. +func NewTxauthmanager(address common.Address, backend bind.ContractBackend) (*Txauthmanager, error) { + contract, err := bindTxauthmanager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Txauthmanager{TxauthmanagerCaller: TxauthmanagerCaller{contract: contract}, TxauthmanagerTransactor: TxauthmanagerTransactor{contract: contract}, TxauthmanagerFilterer: TxauthmanagerFilterer{contract: contract}}, nil +} + +// NewTxauthmanagerCaller creates a new read-only instance of Txauthmanager, bound to a specific deployed contract. +func NewTxauthmanagerCaller(address common.Address, caller bind.ContractCaller) (*TxauthmanagerCaller, error) { + contract, err := bindTxauthmanager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TxauthmanagerCaller{contract: contract}, nil +} + +// NewTxauthmanagerTransactor creates a new write-only instance of Txauthmanager, bound to a specific deployed contract. +func NewTxauthmanagerTransactor(address common.Address, transactor bind.ContractTransactor) (*TxauthmanagerTransactor, error) { + contract, err := bindTxauthmanager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TxauthmanagerTransactor{contract: contract}, nil +} + +// NewTxauthmanagerFilterer creates a new log filterer instance of Txauthmanager, bound to a specific deployed contract. +func NewTxauthmanagerFilterer(address common.Address, filterer bind.ContractFilterer) (*TxauthmanagerFilterer, error) { + contract, err := bindTxauthmanager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TxauthmanagerFilterer{contract: contract}, nil +} + +// bindTxauthmanager binds a generic wrapper to an already deployed contract. +func bindTxauthmanager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := TxauthmanagerMetaData.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 (_Txauthmanager *TxauthmanagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Txauthmanager.Contract.TxauthmanagerCaller.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 (_Txauthmanager *TxauthmanagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Txauthmanager.Contract.TxauthmanagerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Txauthmanager *TxauthmanagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Txauthmanager.Contract.TxauthmanagerTransactor.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 (_Txauthmanager *TxauthmanagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Txauthmanager.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 (_Txauthmanager *TxauthmanagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Txauthmanager.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Txauthmanager *TxauthmanagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Txauthmanager.Contract.contract.Transact(opts, method, params...) +} + +// GetAuthState is a free data retrieval call binding the contract method 0x28ea75ff. +// +// Solidity: function getAuthState(bytes32 txID) view returns(((bytes,(uint8,(string,bytes)))[])) +func (_Txauthmanager *TxauthmanagerCaller) GetAuthState(opts *bind.CallOpts, txID [32]byte) (TxAuthStateData, error) { + var out []interface{} + err := _Txauthmanager.contract.Call(opts, &out, "getAuthState", txID) + + if err != nil { + return *new(TxAuthStateData), err + } + + out0 := *abi.ConvertType(out[0], new(TxAuthStateData)).(*TxAuthStateData) + + return out0, err + +} + +// GetAuthState is a free data retrieval call binding the contract method 0x28ea75ff. +// +// Solidity: function getAuthState(bytes32 txID) view returns(((bytes,(uint8,(string,bytes)))[])) +func (_Txauthmanager *TxauthmanagerSession) GetAuthState(txID [32]byte) (TxAuthStateData, error) { + return _Txauthmanager.Contract.GetAuthState(&_Txauthmanager.CallOpts, txID) +} + +// GetAuthState is a free data retrieval call binding the contract method 0x28ea75ff. +// +// Solidity: function getAuthState(bytes32 txID) view returns(((bytes,(uint8,(string,bytes)))[])) +func (_Txauthmanager *TxauthmanagerCallerSession) GetAuthState(txID [32]byte) (TxAuthStateData, error) { + return _Txauthmanager.Contract.GetAuthState(&_Txauthmanager.CallOpts, txID) +} + +// IsCompletedAuth is a free data retrieval call binding the contract method 0xdbb8633e. +// +// Solidity: function isCompletedAuth(bytes32 txID) view returns(bool) +func (_Txauthmanager *TxauthmanagerCaller) IsCompletedAuth(opts *bind.CallOpts, txID [32]byte) (bool, error) { + var out []interface{} + err := _Txauthmanager.contract.Call(opts, &out, "isCompletedAuth", txID) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsCompletedAuth is a free data retrieval call binding the contract method 0xdbb8633e. +// +// Solidity: function isCompletedAuth(bytes32 txID) view returns(bool) +func (_Txauthmanager *TxauthmanagerSession) IsCompletedAuth(txID [32]byte) (bool, error) { + return _Txauthmanager.Contract.IsCompletedAuth(&_Txauthmanager.CallOpts, txID) +} + +// IsCompletedAuth is a free data retrieval call binding the contract method 0xdbb8633e. +// +// Solidity: function isCompletedAuth(bytes32 txID) view returns(bool) +func (_Txauthmanager *TxauthmanagerCallerSession) IsCompletedAuth(txID [32]byte) (bool, error) { + return _Txauthmanager.Contract.IsCompletedAuth(&_Txauthmanager.CallOpts, txID) +} + +// InitAuthState is a paid mutator transaction binding the contract method 0x4f61fa8d. +// +// Solidity: function initAuthState(bytes32 txID, (bytes,(uint8,(string,bytes)))[] signers) returns() +func (_Txauthmanager *TxauthmanagerTransactor) InitAuthState(opts *bind.TransactOpts, txID [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.contract.Transact(opts, "initAuthState", txID, signers) +} + +// InitAuthState is a paid mutator transaction binding the contract method 0x4f61fa8d. +// +// Solidity: function initAuthState(bytes32 txID, (bytes,(uint8,(string,bytes)))[] signers) returns() +func (_Txauthmanager *TxauthmanagerSession) InitAuthState(txID [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.Contract.InitAuthState(&_Txauthmanager.TransactOpts, txID, signers) +} + +// InitAuthState is a paid mutator transaction binding the contract method 0x4f61fa8d. +// +// Solidity: function initAuthState(bytes32 txID, (bytes,(uint8,(string,bytes)))[] signers) returns() +func (_Txauthmanager *TxauthmanagerTransactorSession) InitAuthState(txID [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.Contract.InitAuthState(&_Txauthmanager.TransactOpts, txID, signers) +} + +// Initialize is a paid mutator transaction binding the contract method 0x27b7bb1c. +// +// Solidity: function initialize(string[] typeUrls, address[] verifiers) returns() +func (_Txauthmanager *TxauthmanagerTransactor) Initialize(opts *bind.TransactOpts, typeUrls []string, verifiers []common.Address) (*types.Transaction, error) { + return _Txauthmanager.contract.Transact(opts, "initialize", typeUrls, verifiers) +} + +// Initialize is a paid mutator transaction binding the contract method 0x27b7bb1c. +// +// Solidity: function initialize(string[] typeUrls, address[] verifiers) returns() +func (_Txauthmanager *TxauthmanagerSession) Initialize(typeUrls []string, verifiers []common.Address) (*types.Transaction, error) { + return _Txauthmanager.Contract.Initialize(&_Txauthmanager.TransactOpts, typeUrls, verifiers) +} + +// Initialize is a paid mutator transaction binding the contract method 0x27b7bb1c. +// +// Solidity: function initialize(string[] typeUrls, address[] verifiers) returns() +func (_Txauthmanager *TxauthmanagerTransactorSession) Initialize(typeUrls []string, verifiers []common.Address) (*types.Transaction, error) { + return _Txauthmanager.Contract.Initialize(&_Txauthmanager.TransactOpts, typeUrls, verifiers) +} + +// Sign is a paid mutator transaction binding the contract method 0xc4886a6d. +// +// Solidity: function sign(bytes32 txID, (bytes,(uint8,(string,bytes)))[] signers) returns(bool) +func (_Txauthmanager *TxauthmanagerTransactor) Sign(opts *bind.TransactOpts, txID [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.contract.Transact(opts, "sign", txID, signers) +} + +// Sign is a paid mutator transaction binding the contract method 0xc4886a6d. +// +// Solidity: function sign(bytes32 txID, (bytes,(uint8,(string,bytes)))[] signers) returns(bool) +func (_Txauthmanager *TxauthmanagerSession) Sign(txID [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.Contract.Sign(&_Txauthmanager.TransactOpts, txID, signers) +} + +// Sign is a paid mutator transaction binding the contract method 0xc4886a6d. +// +// Solidity: function sign(bytes32 txID, (bytes,(uint8,(string,bytes)))[] signers) returns(bool) +func (_Txauthmanager *TxauthmanagerTransactorSession) Sign(txID [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.Contract.Sign(&_Txauthmanager.TransactOpts, txID, signers) +} + +// VerifySignatures is a paid mutator transaction binding the contract method 0xf957441d. +// +// Solidity: function verifySignatures(bytes32 txIDHash, (bytes,(uint8,(string,bytes)))[] signers) returns() +func (_Txauthmanager *TxauthmanagerTransactor) VerifySignatures(opts *bind.TransactOpts, txIDHash [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.contract.Transact(opts, "verifySignatures", txIDHash, signers) +} + +// VerifySignatures is a paid mutator transaction binding the contract method 0xf957441d. +// +// Solidity: function verifySignatures(bytes32 txIDHash, (bytes,(uint8,(string,bytes)))[] signers) returns() +func (_Txauthmanager *TxauthmanagerSession) VerifySignatures(txIDHash [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.Contract.VerifySignatures(&_Txauthmanager.TransactOpts, txIDHash, signers) +} + +// VerifySignatures is a paid mutator transaction binding the contract method 0xf957441d. +// +// Solidity: function verifySignatures(bytes32 txIDHash, (bytes,(uint8,(string,bytes)))[] signers) returns() +func (_Txauthmanager *TxauthmanagerTransactorSession) VerifySignatures(txIDHash [32]byte, signers []AccountData) (*types.Transaction, error) { + return _Txauthmanager.Contract.VerifySignatures(&_Txauthmanager.TransactOpts, txIDHash, signers) +} + +// TxauthmanagerInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Txauthmanager contract. +type TxauthmanagerInitializedIterator struct { + Event *TxauthmanagerInitialized // 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 *TxauthmanagerInitializedIterator) 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(TxauthmanagerInitialized) + 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(TxauthmanagerInitialized) + 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 *TxauthmanagerInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxauthmanagerInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxauthmanagerInitialized represents a Initialized event raised by the Txauthmanager contract. +type TxauthmanagerInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Txauthmanager *TxauthmanagerFilterer) FilterInitialized(opts *bind.FilterOpts) (*TxauthmanagerInitializedIterator, error) { + + logs, sub, err := _Txauthmanager.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &TxauthmanagerInitializedIterator{contract: _Txauthmanager.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Txauthmanager *TxauthmanagerFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *TxauthmanagerInitialized) (event.Subscription, error) { + + logs, sub, err := _Txauthmanager.contract.WatchLogs(opts, "Initialized") + 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(TxauthmanagerInitialized) + if err := _Txauthmanager.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Txauthmanager *TxauthmanagerFilterer) ParseInitialized(log types.Log) (*TxauthmanagerInitialized, error) { + event := new(TxauthmanagerInitialized) + if err := _Txauthmanager.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/pkg/contract/txmanager/txmanager.go b/pkg/contract/txmanager/txmanager.go new file mode 100644 index 0000000..a1838ea --- /dev/null +++ b/pkg/contract/txmanager/txmanager.go @@ -0,0 +1,1536 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package txmanager + +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 +) + +// AccountData is an auto generated low-level Go binding around an user-defined struct. +type AccountData struct { + Id []byte + AuthType AuthTypeData +} + +// AuthTypeData is an auto generated low-level Go binding around an user-defined struct. +type AuthTypeData struct { + Mode uint8 + Option GoogleProtobufAnyData +} + +// ChannelInfoData is an auto generated low-level Go binding around an user-defined struct. +type ChannelInfoData struct { + Port string + Channel string +} + +// ContractTransactionData is an auto generated low-level Go binding around an user-defined struct. +type ContractTransactionData struct { + CrossChainChannel GoogleProtobufAnyData + Signers []AccountData + CallInfo []byte + ReturnValue ReturnValueData + Links []LinkData +} + +// CoordinatorStateData is an auto generated low-level Go binding around an user-defined struct. +type CoordinatorStateData struct { + CommitProtocol uint8 + Channels []ChannelInfoData + Phase uint8 + Decision uint8 + ConfirmedTxs []uint32 + Acks []uint32 +} + +// GoogleProtobufAnyData is an auto generated low-level Go binding around an user-defined struct. +type GoogleProtobufAnyData struct { + TypeUrl string + Value []byte +} + +// HeightData is an auto generated low-level Go binding around an user-defined struct. +type HeightData struct { + RevisionNumber uint64 + RevisionHeight uint64 +} + +// IbcCoreClientV1HeightData is an auto generated low-level Go binding around an user-defined struct. +type IbcCoreClientV1HeightData struct { + RevisionNumber uint64 + RevisionHeight uint64 +} + +// LinkData is an auto generated low-level Go binding around an user-defined struct. +type LinkData struct { + SrcIndex uint32 +} + +// MsgInitiateTxData is an auto generated low-level Go binding around an user-defined struct. +type MsgInitiateTxData struct { + ChainId string + Nonce uint64 + CommitProtocol uint8 + ContractTransactions []ContractTransactionData + Signers []AccountData + TimeoutHeight IbcCoreClientV1HeightData + TimeoutTimestamp uint64 +} + +// Packet is an auto generated low-level Go binding around an user-defined struct. +type Packet struct { + Sequence uint64 + SourcePort string + SourceChannel string + DestinationPort string + DestinationChannel string + Data []byte + TimeoutHeight HeightData + TimeoutTimestamp uint64 +} + +// ReturnValueData is an auto generated low-level Go binding around an user-defined struct. +type ReturnValueData struct { + Value []byte +} + +// TxmanagerMetaData contains all meta data concerning the Txmanager contract. +var TxmanagerMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"createTx\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"src\",\"type\":\"tuple\",\"internalType\":\"structMsgInitiateTx.Data\",\"components\":[{\"name\":\"chain_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"contract_transactions\",\"type\":\"tuple[]\",\"internalType\":\"structContractTransaction.Data[]\",\"components\":[{\"name\":\"cross_chain_channel\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"call_info\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"return_value\",\"type\":\"tuple\",\"internalType\":\"structReturnValue.Data\",\"components\":[{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"links\",\"type\":\"tuple[]\",\"internalType\":\"structLink.Data[]\",\"components\":[{\"name\":\"src_index\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getCoordinatorState\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structCoordinatorState.Data\",\"components\":[{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"channels\",\"type\":\"tuple[]\",\"internalType\":\"structChannelInfo.Data[]\",\"components\":[{\"name\":\"port\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"channel\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"name\":\"phase\",\"type\":\"uint8\",\"internalType\":\"enumCoordinatorState.CoordinatorPhase\"},{\"name\":\"decision\",\"type\":\"uint8\",\"internalType\":\"enumCoordinatorState.CoordinatorDecision\"},{\"name\":\"confirmed_txs\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"acks\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPacketAcknowledgementCall\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"internalType\":\"enumPacketAcknowledgementCall.CommitStatus\"}],\"outputs\":[{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"handleAcknowledgement\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handlePacket\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[{\"name\":\"acknowledgement\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleTimeout\",\"inputs\":[{\"name\":\"packet\",\"type\":\"tuple\",\"internalType\":\"structPacket\",\"components\":[{\"name\":\"sequence\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sourcePort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sourceChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationPort\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"destinationChannel\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"timeoutHeight\",\"type\":\"tuple\",\"internalType\":\"structHeight.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"handler_\",\"type\":\"address\",\"internalType\":\"contractIIBCHandler\"},{\"name\":\"module_\",\"type\":\"address\",\"internalType\":\"contractIContractModule\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isTxRecorded\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"runTxIfCompleted\",\"inputs\":[{\"name\":\"msg_\",\"type\":\"tuple\",\"internalType\":\"structMsgInitiateTx.Data\",\"components\":[{\"name\":\"chain_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"contract_transactions\",\"type\":\"tuple[]\",\"internalType\":\"structContractTransaction.Data[]\",\"components\":[{\"name\":\"cross_chain_channel\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"call_info\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"return_value\",\"type\":\"tuple\",\"internalType\":\"structReturnValue.Data\",\"components\":[{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"links\",\"type\":\"tuple[]\",\"internalType\":\"structLink.Data[]\",\"components\":[{\"name\":\"src_index\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OnAbort\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OnCommit\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OnContractCommitImmediately\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"},{\"name\":\"txIndex\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"uint8\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":true,\"internalType\":\"bool\"},{\"name\":\"ret\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TxExecuted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"proposer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TxInitiated\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"proposer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"msgData\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structMsgInitiateTx.Data\",\"components\":[{\"name\":\"chain_id\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"nonce\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"commit_protocol\",\"type\":\"uint8\",\"internalType\":\"enumTx.CommitProtocol\"},{\"name\":\"contract_transactions\",\"type\":\"tuple[]\",\"internalType\":\"structContractTransaction.Data[]\",\"components\":[{\"name\":\"cross_chain_channel\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"call_info\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"return_value\",\"type\":\"tuple\",\"internalType\":\"structReturnValue.Data\",\"components\":[{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"links\",\"type\":\"tuple[]\",\"internalType\":\"structLink.Data[]\",\"components\":[{\"name\":\"src_index\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]},{\"name\":\"signers\",\"type\":\"tuple[]\",\"internalType\":\"structAccount.Data[]\",\"components\":[{\"name\":\"id\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"auth_type\",\"type\":\"tuple\",\"internalType\":\"structAuthType.Data\",\"components\":[{\"name\":\"mode\",\"type\":\"uint8\",\"internalType\":\"enumAuthType.AuthMode\"},{\"name\":\"option\",\"type\":\"tuple\",\"internalType\":\"structGoogleProtobufAny.Data\",\"components\":[{\"name\":\"type_url\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}]},{\"name\":\"timeout_height\",\"type\":\"tuple\",\"internalType\":\"structIbcCoreClientV1Height.Data\",\"components\":[{\"name\":\"revision_number\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"revision_height\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"timeout_timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TxSigned\",\"inputs\":[{\"name\":\"signer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"txID\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"method\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumAuthType.AuthMode\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AckIsNotSuccess\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AllTransactionsConfirmed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ArrayLengthMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AuthAlreadyCompleted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AuthModeMismatch\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AuthNotCompleted\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AuthStateAlreadyInitialized\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ChannelNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorPhaseNotPrepare\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorStateInconsistent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CoordinatorStateNotFound\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"CoordinatorTxStatusNotPrepare\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DelegateCallFailed\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"EmptyTypeUrl\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IDNotFound\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignersLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTxIDLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"LinksNotSupported\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageTimeoutHeight\",\"inputs\":[{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timeoutVersionHeight\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"MessageTimeoutTimestamp\",\"inputs\":[{\"name\":\"blockTimestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timeoutTimestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ModuleAlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ModuleNotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PayloadDecodeFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReentrancyGuardReentrantCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SignatureVerificationFailed\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"SignerCountMismatch\",\"inputs\":[{\"name\":\"signerCount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"signatureCount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"SignerMustEqualSender\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaticCallFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TPCNotImplemented\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TooManySigners\",\"inputs\":[{\"name\":\"got\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxAllowed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"Tx0MustBeForSelfChain\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TxAlreadyExists\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxAlreadyVerified\",\"inputs\":[{\"name\":\"txID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxIDAlreadyExists\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"TxIDNotFound\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnexpectedChainID\",\"inputs\":[{\"name\":\"expectedHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"gotHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"UnexpectedCommitStatus\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedReturnValue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedSourceChannel\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedTypeURL\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnknownCommitProtocol\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"VerifierNotFound\",\"inputs\":[{\"name\":\"typeUrl\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"VerifierReturnedFalse\",\"inputs\":[{\"name\":\"txIDHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"typeUrl\",\"type\":\"string\",\"internalType\":\"string\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressVerifier\",\"inputs\":[]}]", +} + +// TxmanagerABI is the input ABI used to generate the binding from. +// Deprecated: Use TxmanagerMetaData.ABI instead. +var TxmanagerABI = TxmanagerMetaData.ABI + +// Txmanager is an auto generated Go binding around an Ethereum contract. +type Txmanager struct { + TxmanagerCaller // Read-only binding to the contract + TxmanagerTransactor // Write-only binding to the contract + TxmanagerFilterer // Log filterer for contract events +} + +// TxmanagerCaller is an auto generated read-only Go binding around an Ethereum contract. +type TxmanagerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TxmanagerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TxmanagerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TxmanagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TxmanagerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TxmanagerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TxmanagerSession struct { + Contract *Txmanager // 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 +} + +// TxmanagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TxmanagerCallerSession struct { + Contract *TxmanagerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TxmanagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TxmanagerTransactorSession struct { + Contract *TxmanagerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TxmanagerRaw is an auto generated low-level Go binding around an Ethereum contract. +type TxmanagerRaw struct { + Contract *Txmanager // Generic contract binding to access the raw methods on +} + +// TxmanagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TxmanagerCallerRaw struct { + Contract *TxmanagerCaller // Generic read-only contract binding to access the raw methods on +} + +// TxmanagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TxmanagerTransactorRaw struct { + Contract *TxmanagerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTxmanager creates a new instance of Txmanager, bound to a specific deployed contract. +func NewTxmanager(address common.Address, backend bind.ContractBackend) (*Txmanager, error) { + contract, err := bindTxmanager(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Txmanager{TxmanagerCaller: TxmanagerCaller{contract: contract}, TxmanagerTransactor: TxmanagerTransactor{contract: contract}, TxmanagerFilterer: TxmanagerFilterer{contract: contract}}, nil +} + +// NewTxmanagerCaller creates a new read-only instance of Txmanager, bound to a specific deployed contract. +func NewTxmanagerCaller(address common.Address, caller bind.ContractCaller) (*TxmanagerCaller, error) { + contract, err := bindTxmanager(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TxmanagerCaller{contract: contract}, nil +} + +// NewTxmanagerTransactor creates a new write-only instance of Txmanager, bound to a specific deployed contract. +func NewTxmanagerTransactor(address common.Address, transactor bind.ContractTransactor) (*TxmanagerTransactor, error) { + contract, err := bindTxmanager(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TxmanagerTransactor{contract: contract}, nil +} + +// NewTxmanagerFilterer creates a new log filterer instance of Txmanager, bound to a specific deployed contract. +func NewTxmanagerFilterer(address common.Address, filterer bind.ContractFilterer) (*TxmanagerFilterer, error) { + contract, err := bindTxmanager(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TxmanagerFilterer{contract: contract}, nil +} + +// bindTxmanager binds a generic wrapper to an already deployed contract. +func bindTxmanager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := TxmanagerMetaData.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 (_Txmanager *TxmanagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Txmanager.Contract.TxmanagerCaller.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 (_Txmanager *TxmanagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Txmanager.Contract.TxmanagerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Txmanager *TxmanagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Txmanager.Contract.TxmanagerTransactor.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 (_Txmanager *TxmanagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Txmanager.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 (_Txmanager *TxmanagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Txmanager.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Txmanager *TxmanagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Txmanager.Contract.contract.Transact(opts, method, params...) +} + +// GetCoordinatorState is a free data retrieval call binding the contract method 0xf8b89d89. +// +// Solidity: function getCoordinatorState(bytes32 txID) view returns((uint8,(string,string)[],uint8,uint8,uint32[],uint32[])) +func (_Txmanager *TxmanagerCaller) GetCoordinatorState(opts *bind.CallOpts, txID [32]byte) (CoordinatorStateData, error) { + var out []interface{} + err := _Txmanager.contract.Call(opts, &out, "getCoordinatorState", txID) + + if err != nil { + return *new(CoordinatorStateData), err + } + + out0 := *abi.ConvertType(out[0], new(CoordinatorStateData)).(*CoordinatorStateData) + + return out0, err + +} + +// GetCoordinatorState is a free data retrieval call binding the contract method 0xf8b89d89. +// +// Solidity: function getCoordinatorState(bytes32 txID) view returns((uint8,(string,string)[],uint8,uint8,uint32[],uint32[])) +func (_Txmanager *TxmanagerSession) GetCoordinatorState(txID [32]byte) (CoordinatorStateData, error) { + return _Txmanager.Contract.GetCoordinatorState(&_Txmanager.CallOpts, txID) +} + +// GetCoordinatorState is a free data retrieval call binding the contract method 0xf8b89d89. +// +// Solidity: function getCoordinatorState(bytes32 txID) view returns((uint8,(string,string)[],uint8,uint8,uint32[],uint32[])) +func (_Txmanager *TxmanagerCallerSession) GetCoordinatorState(txID [32]byte) (CoordinatorStateData, error) { + return _Txmanager.Contract.GetCoordinatorState(&_Txmanager.CallOpts, txID) +} + +// GetPacketAcknowledgementCall is a free data retrieval call binding the contract method 0x34a30a65. +// +// Solidity: function getPacketAcknowledgementCall(uint8 status) pure returns(bytes acknowledgement) +func (_Txmanager *TxmanagerCaller) GetPacketAcknowledgementCall(opts *bind.CallOpts, status uint8) ([]byte, error) { + var out []interface{} + err := _Txmanager.contract.Call(opts, &out, "getPacketAcknowledgementCall", status) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// GetPacketAcknowledgementCall is a free data retrieval call binding the contract method 0x34a30a65. +// +// Solidity: function getPacketAcknowledgementCall(uint8 status) pure returns(bytes acknowledgement) +func (_Txmanager *TxmanagerSession) GetPacketAcknowledgementCall(status uint8) ([]byte, error) { + return _Txmanager.Contract.GetPacketAcknowledgementCall(&_Txmanager.CallOpts, status) +} + +// GetPacketAcknowledgementCall is a free data retrieval call binding the contract method 0x34a30a65. +// +// Solidity: function getPacketAcknowledgementCall(uint8 status) pure returns(bytes acknowledgement) +func (_Txmanager *TxmanagerCallerSession) GetPacketAcknowledgementCall(status uint8) ([]byte, error) { + return _Txmanager.Contract.GetPacketAcknowledgementCall(&_Txmanager.CallOpts, status) +} + +// IsTxRecorded is a free data retrieval call binding the contract method 0x3ef6868c. +// +// Solidity: function isTxRecorded(bytes32 txID) view returns(bool) +func (_Txmanager *TxmanagerCaller) IsTxRecorded(opts *bind.CallOpts, txID [32]byte) (bool, error) { + var out []interface{} + err := _Txmanager.contract.Call(opts, &out, "isTxRecorded", txID) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsTxRecorded is a free data retrieval call binding the contract method 0x3ef6868c. +// +// Solidity: function isTxRecorded(bytes32 txID) view returns(bool) +func (_Txmanager *TxmanagerSession) IsTxRecorded(txID [32]byte) (bool, error) { + return _Txmanager.Contract.IsTxRecorded(&_Txmanager.CallOpts, txID) +} + +// IsTxRecorded is a free data retrieval call binding the contract method 0x3ef6868c. +// +// Solidity: function isTxRecorded(bytes32 txID) view returns(bool) +func (_Txmanager *TxmanagerCallerSession) IsTxRecorded(txID [32]byte) (bool, error) { + return _Txmanager.Contract.IsTxRecorded(&_Txmanager.CallOpts, txID) +} + +// CreateTx is a paid mutator transaction binding the contract method 0x354b898f. +// +// Solidity: function createTx(bytes32 txID, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) src) returns() +func (_Txmanager *TxmanagerTransactor) CreateTx(opts *bind.TransactOpts, txID [32]byte, src MsgInitiateTxData) (*types.Transaction, error) { + return _Txmanager.contract.Transact(opts, "createTx", txID, src) +} + +// CreateTx is a paid mutator transaction binding the contract method 0x354b898f. +// +// Solidity: function createTx(bytes32 txID, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) src) returns() +func (_Txmanager *TxmanagerSession) CreateTx(txID [32]byte, src MsgInitiateTxData) (*types.Transaction, error) { + return _Txmanager.Contract.CreateTx(&_Txmanager.TransactOpts, txID, src) +} + +// CreateTx is a paid mutator transaction binding the contract method 0x354b898f. +// +// Solidity: function createTx(bytes32 txID, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) src) returns() +func (_Txmanager *TxmanagerTransactorSession) CreateTx(txID [32]byte, src MsgInitiateTxData) (*types.Transaction, error) { + return _Txmanager.Contract.CreateTx(&_Txmanager.TransactOpts, txID, src) +} + +// HandleAcknowledgement is a paid mutator transaction binding the contract method 0x5c935c3e. +// +// Solidity: function handleAcknowledgement((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement) returns() +func (_Txmanager *TxmanagerTransactor) HandleAcknowledgement(opts *bind.TransactOpts, packet Packet, acknowledgement []byte) (*types.Transaction, error) { + return _Txmanager.contract.Transact(opts, "handleAcknowledgement", packet, acknowledgement) +} + +// HandleAcknowledgement is a paid mutator transaction binding the contract method 0x5c935c3e. +// +// Solidity: function handleAcknowledgement((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement) returns() +func (_Txmanager *TxmanagerSession) HandleAcknowledgement(packet Packet, acknowledgement []byte) (*types.Transaction, error) { + return _Txmanager.Contract.HandleAcknowledgement(&_Txmanager.TransactOpts, packet, acknowledgement) +} + +// HandleAcknowledgement is a paid mutator transaction binding the contract method 0x5c935c3e. +// +// Solidity: function handleAcknowledgement((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet, bytes acknowledgement) returns() +func (_Txmanager *TxmanagerTransactorSession) HandleAcknowledgement(packet Packet, acknowledgement []byte) (*types.Transaction, error) { + return _Txmanager.Contract.HandleAcknowledgement(&_Txmanager.TransactOpts, packet, acknowledgement) +} + +// HandlePacket is a paid mutator transaction binding the contract method 0xd4c1f976. +// +// Solidity: function handlePacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet) returns(bytes acknowledgement) +func (_Txmanager *TxmanagerTransactor) HandlePacket(opts *bind.TransactOpts, packet Packet) (*types.Transaction, error) { + return _Txmanager.contract.Transact(opts, "handlePacket", packet) +} + +// HandlePacket is a paid mutator transaction binding the contract method 0xd4c1f976. +// +// Solidity: function handlePacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet) returns(bytes acknowledgement) +func (_Txmanager *TxmanagerSession) HandlePacket(packet Packet) (*types.Transaction, error) { + return _Txmanager.Contract.HandlePacket(&_Txmanager.TransactOpts, packet) +} + +// HandlePacket is a paid mutator transaction binding the contract method 0xd4c1f976. +// +// Solidity: function handlePacket((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet) returns(bytes acknowledgement) +func (_Txmanager *TxmanagerTransactorSession) HandlePacket(packet Packet) (*types.Transaction, error) { + return _Txmanager.Contract.HandlePacket(&_Txmanager.TransactOpts, packet) +} + +// HandleTimeout is a paid mutator transaction binding the contract method 0x07ce99d7. +// +// Solidity: function handleTimeout((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet) returns() +func (_Txmanager *TxmanagerTransactor) HandleTimeout(opts *bind.TransactOpts, packet Packet) (*types.Transaction, error) { + return _Txmanager.contract.Transact(opts, "handleTimeout", packet) +} + +// HandleTimeout is a paid mutator transaction binding the contract method 0x07ce99d7. +// +// Solidity: function handleTimeout((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet) returns() +func (_Txmanager *TxmanagerSession) HandleTimeout(packet Packet) (*types.Transaction, error) { + return _Txmanager.Contract.HandleTimeout(&_Txmanager.TransactOpts, packet) +} + +// HandleTimeout is a paid mutator transaction binding the contract method 0x07ce99d7. +// +// Solidity: function handleTimeout((uint64,string,string,string,string,bytes,(uint64,uint64),uint64) packet) returns() +func (_Txmanager *TxmanagerTransactorSession) HandleTimeout(packet Packet) (*types.Transaction, error) { + return _Txmanager.Contract.HandleTimeout(&_Txmanager.TransactOpts, packet) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address handler_, address module_) returns() +func (_Txmanager *TxmanagerTransactor) Initialize(opts *bind.TransactOpts, handler_ common.Address, module_ common.Address) (*types.Transaction, error) { + return _Txmanager.contract.Transact(opts, "initialize", handler_, module_) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address handler_, address module_) returns() +func (_Txmanager *TxmanagerSession) Initialize(handler_ common.Address, module_ common.Address) (*types.Transaction, error) { + return _Txmanager.Contract.Initialize(&_Txmanager.TransactOpts, handler_, module_) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address handler_, address module_) returns() +func (_Txmanager *TxmanagerTransactorSession) Initialize(handler_ common.Address, module_ common.Address) (*types.Transaction, error) { + return _Txmanager.Contract.Initialize(&_Txmanager.TransactOpts, handler_, module_) +} + +// RunTxIfCompleted is a paid mutator transaction binding the contract method 0x97e9734b. +// +// Solidity: function runTxIfCompleted((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns() +func (_Txmanager *TxmanagerTransactor) RunTxIfCompleted(opts *bind.TransactOpts, msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Txmanager.contract.Transact(opts, "runTxIfCompleted", msg_) +} + +// RunTxIfCompleted is a paid mutator transaction binding the contract method 0x97e9734b. +// +// Solidity: function runTxIfCompleted((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns() +func (_Txmanager *TxmanagerSession) RunTxIfCompleted(msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Txmanager.Contract.RunTxIfCompleted(&_Txmanager.TransactOpts, msg_) +} + +// RunTxIfCompleted is a paid mutator transaction binding the contract method 0x97e9734b. +// +// Solidity: function runTxIfCompleted((string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msg_) returns() +func (_Txmanager *TxmanagerTransactorSession) RunTxIfCompleted(msg_ MsgInitiateTxData) (*types.Transaction, error) { + return _Txmanager.Contract.RunTxIfCompleted(&_Txmanager.TransactOpts, msg_) +} + +// TxmanagerInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Txmanager contract. +type TxmanagerInitializedIterator struct { + Event *TxmanagerInitialized // 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 *TxmanagerInitializedIterator) 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(TxmanagerInitialized) + 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(TxmanagerInitialized) + 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 *TxmanagerInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerInitialized represents a Initialized event raised by the Txmanager contract. +type TxmanagerInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Txmanager *TxmanagerFilterer) FilterInitialized(opts *bind.FilterOpts) (*TxmanagerInitializedIterator, error) { + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &TxmanagerInitializedIterator{contract: _Txmanager.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Txmanager *TxmanagerFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *TxmanagerInitialized) (event.Subscription, error) { + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "Initialized") + 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(TxmanagerInitialized) + if err := _Txmanager.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_Txmanager *TxmanagerFilterer) ParseInitialized(log types.Log) (*TxmanagerInitialized, error) { + event := new(TxmanagerInitialized) + if err := _Txmanager.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TxmanagerOnAbortIterator is returned from FilterOnAbort and is used to iterate over the raw logs and unpacked data for OnAbort events raised by the Txmanager contract. +type TxmanagerOnAbortIterator struct { + Event *TxmanagerOnAbort // 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 *TxmanagerOnAbortIterator) 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(TxmanagerOnAbort) + 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(TxmanagerOnAbort) + 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 *TxmanagerOnAbortIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerOnAbortIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerOnAbort represents a OnAbort event raised by the Txmanager contract. +type TxmanagerOnAbort struct { + TxID common.Hash + TxIndex uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOnAbort is a free log retrieval operation binding the contract event 0x250bcd3f1f48512b15dbba0fb804f06878f25675cc2381898c392169d814a6f1. +// +// Solidity: event OnAbort(bytes indexed txID, uint8 indexed txIndex) +func (_Txmanager *TxmanagerFilterer) FilterOnAbort(opts *bind.FilterOpts, txID [][]byte, txIndex []uint8) (*TxmanagerOnAbortIterator, error) { + + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) + } + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "OnAbort", txIDRule, txIndexRule) + if err != nil { + return nil, err + } + return &TxmanagerOnAbortIterator{contract: _Txmanager.contract, event: "OnAbort", logs: logs, sub: sub}, nil +} + +// WatchOnAbort is a free log subscription operation binding the contract event 0x250bcd3f1f48512b15dbba0fb804f06878f25675cc2381898c392169d814a6f1. +// +// Solidity: event OnAbort(bytes indexed txID, uint8 indexed txIndex) +func (_Txmanager *TxmanagerFilterer) WatchOnAbort(opts *bind.WatchOpts, sink chan<- *TxmanagerOnAbort, txID [][]byte, txIndex []uint8) (event.Subscription, error) { + + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) + } + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "OnAbort", txIDRule, txIndexRule) + 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(TxmanagerOnAbort) + if err := _Txmanager.contract.UnpackLog(event, "OnAbort", 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 +} + +// ParseOnAbort is a log parse operation binding the contract event 0x250bcd3f1f48512b15dbba0fb804f06878f25675cc2381898c392169d814a6f1. +// +// Solidity: event OnAbort(bytes indexed txID, uint8 indexed txIndex) +func (_Txmanager *TxmanagerFilterer) ParseOnAbort(log types.Log) (*TxmanagerOnAbort, error) { + event := new(TxmanagerOnAbort) + if err := _Txmanager.contract.UnpackLog(event, "OnAbort", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TxmanagerOnCommitIterator is returned from FilterOnCommit and is used to iterate over the raw logs and unpacked data for OnCommit events raised by the Txmanager contract. +type TxmanagerOnCommitIterator struct { + Event *TxmanagerOnCommit // 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 *TxmanagerOnCommitIterator) 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(TxmanagerOnCommit) + 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(TxmanagerOnCommit) + 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 *TxmanagerOnCommitIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerOnCommitIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerOnCommit represents a OnCommit event raised by the Txmanager contract. +type TxmanagerOnCommit struct { + TxID common.Hash + TxIndex uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOnCommit is a free log retrieval operation binding the contract event 0x7aaf0b63467fb40eac34c045248842f31e4e1edff7f0dd939f7ddeeddd83adc0. +// +// Solidity: event OnCommit(bytes indexed txID, uint8 indexed txIndex) +func (_Txmanager *TxmanagerFilterer) FilterOnCommit(opts *bind.FilterOpts, txID [][]byte, txIndex []uint8) (*TxmanagerOnCommitIterator, error) { + + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) + } + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "OnCommit", txIDRule, txIndexRule) + if err != nil { + return nil, err + } + return &TxmanagerOnCommitIterator{contract: _Txmanager.contract, event: "OnCommit", logs: logs, sub: sub}, nil +} + +// WatchOnCommit is a free log subscription operation binding the contract event 0x7aaf0b63467fb40eac34c045248842f31e4e1edff7f0dd939f7ddeeddd83adc0. +// +// Solidity: event OnCommit(bytes indexed txID, uint8 indexed txIndex) +func (_Txmanager *TxmanagerFilterer) WatchOnCommit(opts *bind.WatchOpts, sink chan<- *TxmanagerOnCommit, txID [][]byte, txIndex []uint8) (event.Subscription, error) { + + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) + } + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "OnCommit", txIDRule, txIndexRule) + 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(TxmanagerOnCommit) + if err := _Txmanager.contract.UnpackLog(event, "OnCommit", 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 +} + +// ParseOnCommit is a log parse operation binding the contract event 0x7aaf0b63467fb40eac34c045248842f31e4e1edff7f0dd939f7ddeeddd83adc0. +// +// Solidity: event OnCommit(bytes indexed txID, uint8 indexed txIndex) +func (_Txmanager *TxmanagerFilterer) ParseOnCommit(log types.Log) (*TxmanagerOnCommit, error) { + event := new(TxmanagerOnCommit) + if err := _Txmanager.contract.UnpackLog(event, "OnCommit", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TxmanagerOnContractCommitImmediatelyIterator is returned from FilterOnContractCommitImmediately and is used to iterate over the raw logs and unpacked data for OnContractCommitImmediately events raised by the Txmanager contract. +type TxmanagerOnContractCommitImmediatelyIterator struct { + Event *TxmanagerOnContractCommitImmediately // 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 *TxmanagerOnContractCommitImmediatelyIterator) 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(TxmanagerOnContractCommitImmediately) + 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(TxmanagerOnContractCommitImmediately) + 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 *TxmanagerOnContractCommitImmediatelyIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerOnContractCommitImmediatelyIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerOnContractCommitImmediately represents a OnContractCommitImmediately event raised by the Txmanager contract. +type TxmanagerOnContractCommitImmediately struct { + TxID common.Hash + TxIndex uint8 + Success bool + Ret []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOnContractCommitImmediately is a free log retrieval operation binding the contract event 0x7da7723d423258c97d02fba73c0951597dc48566af572d5cb8e2698c22102e61. +// +// Solidity: event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret) +func (_Txmanager *TxmanagerFilterer) FilterOnContractCommitImmediately(opts *bind.FilterOpts, txID [][]byte, txIndex []uint8, success []bool) (*TxmanagerOnContractCommitImmediatelyIterator, error) { + + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) + } + var successRule []interface{} + for _, successItem := range success { + successRule = append(successRule, successItem) + } + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "OnContractCommitImmediately", txIDRule, txIndexRule, successRule) + if err != nil { + return nil, err + } + return &TxmanagerOnContractCommitImmediatelyIterator{contract: _Txmanager.contract, event: "OnContractCommitImmediately", logs: logs, sub: sub}, nil +} + +// WatchOnContractCommitImmediately is a free log subscription operation binding the contract event 0x7da7723d423258c97d02fba73c0951597dc48566af572d5cb8e2698c22102e61. +// +// Solidity: event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret) +func (_Txmanager *TxmanagerFilterer) WatchOnContractCommitImmediately(opts *bind.WatchOpts, sink chan<- *TxmanagerOnContractCommitImmediately, txID [][]byte, txIndex []uint8, success []bool) (event.Subscription, error) { + + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + var txIndexRule []interface{} + for _, txIndexItem := range txIndex { + txIndexRule = append(txIndexRule, txIndexItem) + } + var successRule []interface{} + for _, successItem := range success { + successRule = append(successRule, successItem) + } + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "OnContractCommitImmediately", txIDRule, txIndexRule, successRule) + 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(TxmanagerOnContractCommitImmediately) + if err := _Txmanager.contract.UnpackLog(event, "OnContractCommitImmediately", 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 +} + +// ParseOnContractCommitImmediately is a log parse operation binding the contract event 0x7da7723d423258c97d02fba73c0951597dc48566af572d5cb8e2698c22102e61. +// +// Solidity: event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret) +func (_Txmanager *TxmanagerFilterer) ParseOnContractCommitImmediately(log types.Log) (*TxmanagerOnContractCommitImmediately, error) { + event := new(TxmanagerOnContractCommitImmediately) + if err := _Txmanager.contract.UnpackLog(event, "OnContractCommitImmediately", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TxmanagerTxExecutedIterator is returned from FilterTxExecuted and is used to iterate over the raw logs and unpacked data for TxExecuted events raised by the Txmanager contract. +type TxmanagerTxExecutedIterator struct { + Event *TxmanagerTxExecuted // 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 *TxmanagerTxExecutedIterator) 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(TxmanagerTxExecuted) + 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(TxmanagerTxExecuted) + 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 *TxmanagerTxExecutedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerTxExecutedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerTxExecuted represents a TxExecuted event raised by the Txmanager contract. +type TxmanagerTxExecuted struct { + TxID []byte + Proposer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxExecuted is a free log retrieval operation binding the contract event 0xdf7ae1f6bc0bafd42f6b0ffe61265f1f2b82ec85389dbacc0664f47af522db18. +// +// Solidity: event TxExecuted(bytes txID, address indexed proposer) +func (_Txmanager *TxmanagerFilterer) FilterTxExecuted(opts *bind.FilterOpts, proposer []common.Address) (*TxmanagerTxExecutedIterator, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "TxExecuted", proposerRule) + if err != nil { + return nil, err + } + return &TxmanagerTxExecutedIterator{contract: _Txmanager.contract, event: "TxExecuted", logs: logs, sub: sub}, nil +} + +// WatchTxExecuted is a free log subscription operation binding the contract event 0xdf7ae1f6bc0bafd42f6b0ffe61265f1f2b82ec85389dbacc0664f47af522db18. +// +// Solidity: event TxExecuted(bytes txID, address indexed proposer) +func (_Txmanager *TxmanagerFilterer) WatchTxExecuted(opts *bind.WatchOpts, sink chan<- *TxmanagerTxExecuted, proposer []common.Address) (event.Subscription, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "TxExecuted", proposerRule) + 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(TxmanagerTxExecuted) + if err := _Txmanager.contract.UnpackLog(event, "TxExecuted", 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 +} + +// ParseTxExecuted is a log parse operation binding the contract event 0xdf7ae1f6bc0bafd42f6b0ffe61265f1f2b82ec85389dbacc0664f47af522db18. +// +// Solidity: event TxExecuted(bytes txID, address indexed proposer) +func (_Txmanager *TxmanagerFilterer) ParseTxExecuted(log types.Log) (*TxmanagerTxExecuted, error) { + event := new(TxmanagerTxExecuted) + if err := _Txmanager.contract.UnpackLog(event, "TxExecuted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TxmanagerTxInitiatedIterator is returned from FilterTxInitiated and is used to iterate over the raw logs and unpacked data for TxInitiated events raised by the Txmanager contract. +type TxmanagerTxInitiatedIterator struct { + Event *TxmanagerTxInitiated // 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 *TxmanagerTxInitiatedIterator) 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(TxmanagerTxInitiated) + 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(TxmanagerTxInitiated) + 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 *TxmanagerTxInitiatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerTxInitiatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerTxInitiated represents a TxInitiated event raised by the Txmanager contract. +type TxmanagerTxInitiated struct { + TxID []byte + Proposer common.Address + MsgData MsgInitiateTxData + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxInitiated is a free log retrieval operation binding the contract event 0x82b61ce957ceac1596e6ab9a00110d416225ef3b28693a337d32eede878df6cf. +// +// Solidity: event TxInitiated(bytes txID, address indexed proposer, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msgData) +func (_Txmanager *TxmanagerFilterer) FilterTxInitiated(opts *bind.FilterOpts, proposer []common.Address) (*TxmanagerTxInitiatedIterator, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "TxInitiated", proposerRule) + if err != nil { + return nil, err + } + return &TxmanagerTxInitiatedIterator{contract: _Txmanager.contract, event: "TxInitiated", logs: logs, sub: sub}, nil +} + +// WatchTxInitiated is a free log subscription operation binding the contract event 0x82b61ce957ceac1596e6ab9a00110d416225ef3b28693a337d32eede878df6cf. +// +// Solidity: event TxInitiated(bytes txID, address indexed proposer, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msgData) +func (_Txmanager *TxmanagerFilterer) WatchTxInitiated(opts *bind.WatchOpts, sink chan<- *TxmanagerTxInitiated, proposer []common.Address) (event.Subscription, error) { + + var proposerRule []interface{} + for _, proposerItem := range proposer { + proposerRule = append(proposerRule, proposerItem) + } + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "TxInitiated", proposerRule) + 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(TxmanagerTxInitiated) + if err := _Txmanager.contract.UnpackLog(event, "TxInitiated", 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 +} + +// ParseTxInitiated is a log parse operation binding the contract event 0x82b61ce957ceac1596e6ab9a00110d416225ef3b28693a337d32eede878df6cf. +// +// Solidity: event TxInitiated(bytes txID, address indexed proposer, (string,uint64,uint8,((string,bytes),(bytes,(uint8,(string,bytes)))[],bytes,(bytes),(uint32)[])[],(bytes,(uint8,(string,bytes)))[],(uint64,uint64),uint64) msgData) +func (_Txmanager *TxmanagerFilterer) ParseTxInitiated(log types.Log) (*TxmanagerTxInitiated, error) { + event := new(TxmanagerTxInitiated) + if err := _Txmanager.contract.UnpackLog(event, "TxInitiated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// TxmanagerTxSignedIterator is returned from FilterTxSigned and is used to iterate over the raw logs and unpacked data for TxSigned events raised by the Txmanager contract. +type TxmanagerTxSignedIterator struct { + Event *TxmanagerTxSigned // 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 *TxmanagerTxSignedIterator) 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(TxmanagerTxSigned) + 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(TxmanagerTxSigned) + 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 *TxmanagerTxSignedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *TxmanagerTxSignedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// TxmanagerTxSigned represents a TxSigned event raised by the Txmanager contract. +type TxmanagerTxSigned struct { + Signer common.Address + TxID [32]byte + Method uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTxSigned is a free log retrieval operation binding the contract event 0x30c2a521823a6b9bc4f65ec80485542760a5639a135db9e69f36d257d9c3a716. +// +// Solidity: event TxSigned(address indexed signer, bytes32 indexed txID, uint8 method) +func (_Txmanager *TxmanagerFilterer) FilterTxSigned(opts *bind.FilterOpts, signer []common.Address, txID [][32]byte) (*TxmanagerTxSignedIterator, error) { + + var signerRule []interface{} + for _, signerItem := range signer { + signerRule = append(signerRule, signerItem) + } + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + + logs, sub, err := _Txmanager.contract.FilterLogs(opts, "TxSigned", signerRule, txIDRule) + if err != nil { + return nil, err + } + return &TxmanagerTxSignedIterator{contract: _Txmanager.contract, event: "TxSigned", logs: logs, sub: sub}, nil +} + +// WatchTxSigned is a free log subscription operation binding the contract event 0x30c2a521823a6b9bc4f65ec80485542760a5639a135db9e69f36d257d9c3a716. +// +// Solidity: event TxSigned(address indexed signer, bytes32 indexed txID, uint8 method) +func (_Txmanager *TxmanagerFilterer) WatchTxSigned(opts *bind.WatchOpts, sink chan<- *TxmanagerTxSigned, signer []common.Address, txID [][32]byte) (event.Subscription, error) { + + var signerRule []interface{} + for _, signerItem := range signer { + signerRule = append(signerRule, signerItem) + } + var txIDRule []interface{} + for _, txIDItem := range txID { + txIDRule = append(txIDRule, txIDItem) + } + + logs, sub, err := _Txmanager.contract.WatchLogs(opts, "TxSigned", signerRule, txIDRule) + 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(TxmanagerTxSigned) + if err := _Txmanager.contract.UnpackLog(event, "TxSigned", 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 +} + +// ParseTxSigned is a log parse operation binding the contract event 0x30c2a521823a6b9bc4f65ec80485542760a5639a135db9e69f36d257d9c3a716. +// +// Solidity: event TxSigned(address indexed signer, bytes32 indexed txID, uint8 method) +func (_Txmanager *TxmanagerFilterer) ParseTxSigned(log types.Log) (*TxmanagerTxSigned, error) { + event := new(TxmanagerTxSigned) + if err := _Txmanager.contract.UnpackLog(event, "TxSigned", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/pkg/testing/chain_test.go b/pkg/testing/chain_test.go index 9260bac..36b7662 100644 --- a/pkg/testing/chain_test.go +++ b/pkg/testing/chain_test.go @@ -6,12 +6,10 @@ import ( "errors" "fmt" "math/big" - "strings" "testing" "time" "github.com/avast/retry-go" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" @@ -22,25 +20,10 @@ import ( "github.com/datachainlab/cross-solidity/pkg/contract/crosssimplemodule" "github.com/datachainlab/cross-solidity/pkg/contract/ownableibchandler" + "github.com/datachainlab/cross-solidity/pkg/contract/txmanager" "github.com/datachainlab/cross-solidity/pkg/wallet" ) -var ( - abiEventOnContractCall abi.Event -) - -func init() { - var ok bool - parsedCrossModuleABI, err := abi.JSON(strings.NewReader(crosssimplemodule.CrosssimplemoduleABI)) - if err != nil { - panic(err) - } - abiEventOnContractCall, ok = parsedCrossModuleABI.Events["OnContractCall"] - if !ok { - panic("OnContractCall not found") - } -} - type Chain struct { chainID int64 mnemonicPhrase string @@ -51,6 +34,7 @@ type Chain struct { // Core modules IBCHandler ownableibchandler.Ownableibchandler + TxManager txmanager.Txmanager // App modules CrossSimpleModule crosssimplemodule.Crosssimplemodule @@ -90,7 +74,7 @@ func (chain *Chain) TxSyncIfNoError(ctx context.Context) func(tx *gethtypes.Tran } } -func (chain *Chain) findEventOnContractCall(ctx context.Context, txID []byte) (*crosssimplemodule.CrosssimplemoduleOnContractCall, error) { +func (chain *Chain) findEventOnContractCommitImmediately(ctx context.Context, txID []byte) (*crosssimplemodule.CrosssimplemoduleOnContractCommitImmediately, error) { filter, err := crosssimplemodule.NewCrosssimplemoduleFilterer( chain.ContractConfig.GetCrossSimpleModuleAddress(), chain.ETHClient, ) @@ -100,7 +84,7 @@ func (chain *Chain) findEventOnContractCall(ctx context.Context, txID []byte) (* idHash := crypto.Keccak256Hash(txID) - iter, err := filter.FilterOnContractCall( + iter, err := filter.FilterOnContractCommitImmediately( &bind.FilterOpts{Context: ctx}, [][]byte{txID}, // txId nil, // txIndex @@ -113,13 +97,36 @@ func (chain *Chain) findEventOnContractCall(ctx context.Context, txID []byte) (* for iter.Next() { ev := iter.Event - if ev.TxId == idHash { + if ev.TxID == idHash { return ev, nil } } return nil, fmt.Errorf("event not found: txID(hash)=%s", idHash.Hex()) } +func (chain *Chain) findEventTxInitiated(ctx context.Context, proposer common.Address) (*crosssimplemodule.CrosssimplemoduleTxInitiated, error) { + filter, err := crosssimplemodule.NewCrosssimplemoduleFilterer( + chain.ContractConfig.GetCrossSimpleModuleAddress(), chain.ETHClient, + ) + if err != nil { + return nil, err + } + + iter, err := filter.FilterTxInitiated( + &bind.FilterOpts{Context: ctx, Start: 0}, // Start from block 0 + []common.Address{proposer}, // Filter by indexed proposer + ) + if err != nil { + return nil, err + } + defer iter.Close() + + for iter.Next() { + return iter.Event, nil + } + return nil, fmt.Errorf("event TxInitiated not found for proposer %s", proposer.Hex()) +} + func (chain *Chain) TxOpts(ctx context.Context, index uint32) *bind.TransactOpts { return makeGenTxOpts(big.NewInt(chain.chainID), chain.prvKey(index))(ctx) } @@ -185,6 +192,7 @@ func makeGenTxOpts(chainID *big.Int, prv *ecdsa.PrivateKey) GenTxOpts { type ContractConfig interface { GetIBCHandlerAddress() common.Address GetCrossSimpleModuleAddress() common.Address + GetTxManagerAddress() common.Address } func NewChain(t *testing.T, rpcAddr string, mnemonicPhrase string, ccfg ContractConfig) *Chain { @@ -196,6 +204,10 @@ func NewChain(t *testing.T, rpcAddr string, mnemonicPhrase string, ccfg Contract if err != nil { panic(err) } + txManager, err := txmanager.NewTxmanager(ccfg.GetTxManagerAddress(), ethc) + if err != nil { + panic(err) + } id, err := ethc.ChainID(context.Background()) if err != nil { panic(err) @@ -204,6 +216,7 @@ func NewChain(t *testing.T, rpcAddr string, mnemonicPhrase string, ccfg Contract ETHClient: ethc, CrossSimpleModule: *crossMod, ContractConfig: ccfg, + TxManager: *txManager, chainID: id.Int64(), mnemonicPhrase: mnemonicPhrase, diff --git a/pkg/testing/cross_test.go b/pkg/testing/cross_test.go index e0bdb59..7e88889 100644 --- a/pkg/testing/cross_test.go +++ b/pkg/testing/cross_test.go @@ -2,6 +2,7 @@ package testing import ( "context" + "encoding/base64" "fmt" "math/big" "testing" @@ -65,11 +66,11 @@ func (suite *CrossTestSuite) TestRecvPacket() { )) // 3. check if a fired event matches expected one - event, err := suite.chain.findEventOnContractCall(ctx, txID) + event, err := suite.chain.findEventOnContractCommitImmediately(ctx, txID) suite.Require().NoError(err) suite.Require().True(event.Success) suite.Require().Equal(event.Ret, successMsg) - suite.Require().Equal(event.TxId, crypto.Keccak256Hash(txID)) + suite.Require().Equal(event.TxID, crypto.Keccak256Hash(txID)) suite.Require().Equal(event.TxIndex, uint8(1)) } @@ -93,11 +94,11 @@ func (suite *CrossTestSuite) TestRecvPacket() { )) // 3. check if a fired event matches expected one - event, err := suite.chain.findEventOnContractCall(ctx, txID) + event, err := suite.chain.findEventOnContractCommitImmediately(ctx, txID) suite.Require().NoError(err) suite.Require().False(event.Success) suite.Require().Empty(event.Ret) - suite.Require().Equal(event.TxId, crypto.Keccak256Hash(txID)) + suite.Require().Equal(event.TxID, crypto.Keccak256Hash(txID)) suite.Require().Equal(event.TxIndex, uint8(1)) } } @@ -107,7 +108,7 @@ func (suite *CrossTestSuite) TestPBSerialization() { // check if the serialization of a successful ack is correct { - ack, err := suite.chain.CrossSimpleModule.GetPacketAcknowledgementCall( + ack, err := suite.chain.TxManager.GetPacketAcknowledgementCall( suite.chain.CallOpts(ctx, 0), uint8(simpletypes.COMMIT_STATUS_OK), ) @@ -121,7 +122,7 @@ func (suite *CrossTestSuite) TestPBSerialization() { // check if the serialization of a failure ack is correct { - ack, err := suite.chain.CrossSimpleModule.GetPacketAcknowledgementCall( + ack, err := suite.chain.TxManager.GetPacketAcknowledgementCall( suite.chain.CallOpts(ctx, 0), uint8(simpletypes.COMMIT_STATUS_FAILED), ) @@ -144,6 +145,87 @@ func (suite *CrossTestSuite) createPacket(txID []byte, callInfo []byte) packets. return packets.NewPacketData(nil, pdc) } +func (suite *CrossTestSuite) TestInitiateTx() { + ctx := context.Background() + opts := suite.chain.LegacyTxOpts(ctx, 0) + + decodeB64 := func(s string) []byte { + b, err := base64.StdEncoding.DecodeString(s) + suite.Require().NoError(err) + return b + } + + xcc1, err := xcctypes.PackCrossChainChannel(&xcctypes.ChannelInfo{ + Port: "", + Channel: "", + }) + suite.Require().NoError(err) + + xcc2, err := xcctypes.PackCrossChainChannel(&xcctypes.ChannelInfo{ + Port: "cross", + Channel: "channel-0", + }) + suite.Require().NoError(err) + + signer1 := crosssimplemodule.AccountData{ + Id: decodeB64("0/syrvWS1CkCswOi9XwXq+gd+dIByQLeH9t/qFrDXqE="), + AuthType: crosssimplemodule.AuthTypeData{ + Mode: uint8(authtypes.AuthMode_AUTH_MODE_LOCAL), + }, + } + + signer2 := crosssimplemodule.AccountData{ + Id: decodeB64("y+1kWxwaYlTxFJ31HTWRxrOAMAc="), + AuthType: crosssimplemodule.AuthTypeData{ + Mode: uint8(authtypes.AuthMode_AUTH_MODE_LOCAL), + }, + } + + ct1 := crosssimplemodule.ContractTransactionData{ + CrossChainChannel: crosssimplemodule.GoogleProtobufAnyData{ + TypeUrl: xcc1.TypeUrl, + Value: xcc1.Value, + }, + Signers: []crosssimplemodule.AccountData{signer1}, + CallInfo: decodeB64("eyJtZXRob2QiOiJ0cmFuc2ZlciIsImFyZ3MiOlsiNzkwOGE5ZGY5MzJkYmUwZjk5Nzg5NGE0MjMwOTdjYjViYTUxYWI0MDliZTAwZmM1YmZhODJkMjJmNDMyZjJiYiIsIjEwIl19"), + Links: []crosssimplemodule.LinkData{}, + } + + ct2 := crosssimplemodule.ContractTransactionData{ + CrossChainChannel: crosssimplemodule.GoogleProtobufAnyData{ + TypeUrl: xcc2.TypeUrl, + Value: xcc2.Value, + }, + Signers: []crosssimplemodule.AccountData{signer2}, + CallInfo: decodeB64("+DuU3VEJ0FrDV+RGmSpg5kdkBBoOhSmMdHJhbnNmZXJGcm9t2JQAcxVAzWBgmR1rnFfOKVmY2bwvq4IGug=="), + Links: []crosssimplemodule.LinkData{}, + } + + msg := crosssimplemodule.MsgInitiateTxData{ + ChainId: fmt.Sprintf("%d", suite.chain.chainID), + Nonce: 0, + CommitProtocol: 1, // SIMPLE_COMMIT_PROTOCOL + ContractTransactions: []crosssimplemodule.ContractTransactionData{ct1, ct2}, + Signers: []crosssimplemodule.AccountData{signer1}, + TimeoutHeight: crosssimplemodule.IbcCoreClientV1HeightData{ + RevisionNumber: 0, + RevisionHeight: 0, + }, + TimeoutTimestamp: 0, + } + + err = suite.chain.TxSyncIfNoError(ctx)( + suite.chain.CrossSimpleModule.InitiateTx(opts, msg), + ) + + suite.Require().NoError(err) + + event, err := suite.chain.findEventTxInitiated(ctx, opts.From) + suite.Require().NoError(err) + suite.Require().Equal(opts.From, event.Proposer) + suite.Require().NotEmpty(event.TxID) +} + func TestChainTestSuite(t *testing.T) { suite.Run(t, new(CrossTestSuite)) } diff --git a/proto/cross/core/atomic/simple/AtomicSimple.proto b/proto/cross/core/atomic/simple/AtomicSimple.proto index 1bed1d1..aee06cd 100644 --- a/proto/cross/core/atomic/simple/AtomicSimple.proto +++ b/proto/cross/core/atomic/simple/AtomicSimple.proto @@ -3,6 +3,8 @@ syntax = "proto3"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; import "cross/core/auth/Auth.proto"; +import "cross/core/tx/Tx.proto"; +import "cross/core/xcc/XCC.proto"; message PacketData { option (gogoproto.goproto_getters) = false; @@ -27,7 +29,7 @@ message HeaderField { } message PacketDataCall { - option (gogoproto.equal) = false; + option (gogoproto.equal) = false; message ResolvedContractTransaction { option (gogoproto.equal) = false; @@ -44,11 +46,11 @@ message PacketDataCall { } message PacketAcknowledgementCall { - option (gogoproto.equal) = false; + option (gogoproto.equal) = false; enum CommitStatus { option (gogoproto.goproto_enum_prefix) = false; - + COMMIT_STATUS_UNKNOWN = 0; COMMIT_STATUS_OK = 1; COMMIT_STATUS_FAILED = 2; @@ -57,6 +59,65 @@ message PacketAcknowledgementCall { CommitStatus status = 1; } -message ReturnValue { - bytes value = 1; +message QueryCoordinatorStateRequest { + bytes tx_id = 1 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxID"]; +} + +message QueryCoordinatorStateResponse { + CoordinatorState coodinator_state = 1 [(gogoproto.nullable) = false]; +} + +message CoordinatorState { + option (gogoproto.equal) = false; + + Tx.CommitProtocol commit_protocol = 1; + repeated ChannelInfo channels = 2 [(gogoproto.nullable) = false]; + + enum CoordinatorPhase { + option (gogoproto.goproto_enum_prefix) = false; + + COORDINATOR_PHASE_UNKNOWN = 0; + COORDINATOR_PHASE_PREPARE = 1; + COORDINATOR_PHASE_COMMIT = 2; + } + + CoordinatorPhase phase = 3; + + enum CoordinatorDecision { + option (gogoproto.goproto_enum_prefix) = false; + + COORDINATOR_DECISION_UNKNOWN = 0; + COORDINATOR_DECISION_COMMIT = 1; + COORDINATOR_DECISION_ABORT = 2; + } + + CoordinatorDecision decision = 4; + repeated uint32 confirmed_txs = 5 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxIndex"]; + repeated uint32 acks = 6 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxIndex"]; +} + +message ContractTransactionState { + option (gogoproto.equal) = false; + + enum ContractTransactionStatus { + option (gogoproto.goproto_enum_prefix) = false; + + CONTRACT_TRANSACTION_STATUS_UNKNOWN = 0; + CONTRACT_TRANSACTION_STATUS_PREPARE = 1; + CONTRACT_TRANSACTION_STATUS_COMMIT = 2; + CONTRACT_TRANSACTION_STATUS_ABORT = 3; + } + + ContractTransactionStatus status = 1; + + enum PrepareResult { + option (gogoproto.goproto_enum_prefix) = false; + + PREPARE_RESULT_UNKNOWN = 0; + PREPARE_RESULT_OK = 1; + PREPARE_RESULT_FAILED = 2; + } + PrepareResult prepare_result = 2; + + ChannelInfo coordinator_channel = 3 [(gogoproto.nullable) = false]; } diff --git a/proto/cross/core/auth/Auth.proto b/proto/cross/core/auth/Auth.proto index b64c4f8..0ed7f9b 100644 --- a/proto/cross/core/auth/Auth.proto +++ b/proto/cross/core/auth/Auth.proto @@ -1,11 +1,53 @@ syntax = "proto3"; -import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; +import "gogoproto/gogo.proto"; +import "ibc/core/client/v1/client.proto"; option go_package = "github.com/datachainlab/cross/x/core/auth/types"; option (gogoproto.goproto_getters_all) = false; +message MsgSignTx { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + bytes txID = 1 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxID"]; + repeated bytes signers = 2 [(gogoproto.casttype) = "AccountID"]; + ibc.core.client.v1.Height timeout_height = 3 + [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false]; + uint64 timeout_timestamp = 4 + [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; +} + +message MsgSignTxResponse { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + bool tx_auth_completed = 1; + string log = 2; +} + +message MsgExtSignTx { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + bytes txID = 1 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxID"]; + repeated Account signers = 2 [(gogoproto.nullable) = false]; +} + +message MsgExtSignTxResponse { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; +} + +message QueryTxAuthStateRequest { + bytes txID = 1 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxID"]; +} + +message QueryTxAuthStateResponse { + TxAuthState tx_auth_state = 1; +} + message Account { option (gogoproto.equal) = true; bytes id = 1 [(gogoproto.casttype) = "AccountID"]; @@ -13,14 +55,21 @@ message Account { } message AuthType { + option (gogoproto.equal) = true; + enum AuthMode { AUTH_MODE_UNSPECIFIED = 0; AUTH_MODE_LOCAL = 1; AUTH_MODE_CHANNEL = 2; AUTH_MODE_EXTENSION = 3; - } + } - option (gogoproto.equal) = true; AuthMode mode = 1; google.protobuf.Any option = 2 [(gogoproto.nullable) = true]; // xcc or extension_type_url } + +message TxAuthState { + option (gogoproto.equal) = false; + + repeated Account remaining_signers = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/cross/core/initiator/Initiator.proto b/proto/cross/core/initiator/Initiator.proto new file mode 100644 index 0000000..15d0b0a --- /dev/null +++ b/proto/cross/core/initiator/Initiator.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; + +import "google/protobuf/any.proto"; +import "gogoproto/gogo.proto"; +import "ibc/core/client/v1/client.proto"; +import "cross/core/tx/Tx.proto"; +import "cross/core/auth/Auth.proto"; + +option go_package = "github.com/datachainlab/cross/x/core/initiator/types"; +option (gogoproto.goproto_getters_all) = false; + +message MsgInitiateTx { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string chain_id = 1; + uint64 nonce = 2; + + Tx.CommitProtocol commit_protocol = 3; + + repeated ContractTransaction contract_transactions = 4 [(gogoproto.nullable) = false]; + + repeated Account signers = 5 [(gogoproto.nullable) = false]; + + ibc.core.client.v1.Height timeout_height = 6 + [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false]; + + uint64 timeout_timestamp = 7 + [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; +} + +message MsgInitiateTxResponse { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + bytes txID = 1 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxID"]; + + enum InitiateTxStatus { + option (gogoproto.goproto_enum_prefix) = false; + + INITIATE_TX_STATUS_UNKNOWN = 0; + INITIATE_TX_STATUS_PENDING = 1; + INITIATE_TX_STATUS_VERIFIED = 2; + } + + InitiateTxStatus status = 2; +} + +message QuerySelfXCCRequest {} + +message QuerySelfXCCResponse { + google.protobuf.Any xcc = 1 [(gogoproto.nullable) = true]; +} + +message ContractTransaction { + option (gogoproto.equal) = false; + + google.protobuf.Any cross_chain_channel = 1 [(gogoproto.nullable) = true]; + repeated Account signers = 2 [(gogoproto.nullable) = false]; + bytes call_info = 3 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/tx/types.ContractCallInfo"]; + ReturnValue return_value = 4; + repeated Link links = 5 [(gogoproto.nullable) = false]; +} + +message Link { + uint32 src_index = 1; +} + +message GenesisState {} + +message InitiateTxState { + option (gogoproto.equal) = false; + + MsgInitiateTxResponse.InitiateTxStatus status = 1; + + MsgInitiateTx msg = 2 [(gogoproto.nullable) = false]; +} diff --git a/proto/cross/core/tx/Tx.proto b/proto/cross/core/tx/Tx.proto new file mode 100644 index 0000000..cfb2aeb --- /dev/null +++ b/proto/cross/core/tx/Tx.proto @@ -0,0 +1,58 @@ +syntax = "proto3"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "ibc/core/client/v1/client.proto"; +import "cross/core/auth/Auth.proto"; + +option go_package = "github.com/datachainlab/cross/x/core/tx/types"; +option (gogoproto.goproto_getters_all) = false; + +message Tx { + option (gogoproto.equal) = false; + + bytes id = 1 [(gogoproto.casttype) = "github.com/datachainlab/cross/x/core/types.TxID"]; + + enum CommitProtocol { + option (gogoproto.goproto_enum_prefix) = false; + + COMMIT_PROTOCOL_UNKNOWN = 0; + COMMIT_PROTOCOL_SIMPLE = 1; + COMMIT_PROTOCOL_TPC = 2; + } + + CommitProtocol commit_protocol = 2; + + repeated ResolvedContractTransaction contract_transactions = 3 [(gogoproto.nullable) = false]; + + ibc.core.client.v1.Height timeout_height = 4 + [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false]; + + uint64 timeout_timestamp = 5 + [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; +} + +message ResolvedContractTransaction { + option (gogoproto.equal) = false; + + google.protobuf.Any cross_chain_channel = 1 [(gogoproto.nullable) = true]; + repeated Account signers = 2 [(gogoproto.nullable) = false]; + bytes call_info = 3 [(gogoproto.casttype) = "ContractCallInfo"]; + ReturnValue return_value = 4; + repeated google.protobuf.Any call_results = 5 [(gogoproto.nullable) = false]; +} + +message ReturnValue { + bytes value = 1; +} + +message ConstantValueCallResult { + google.protobuf.Any cross_chain_channel = 1 [(gogoproto.nullable) = false]; + bytes k = 2; + bytes v = 3; +} + +message ContractCallResult { + bytes data = 1; + repeated google.protobuf.Any events = 2 [(gogoproto.nullable) = false]; +} diff --git a/proto/cross/core/xcc/XCC.proto b/proto/cross/core/xcc/XCC.proto new file mode 100644 index 0000000..65f45b8 --- /dev/null +++ b/proto/cross/core/xcc/XCC.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/datachainlab/cross/x/core/xcc/types"; +option (gogoproto.goproto_getters_all) = false; + +message ChannelInfo { + string port = 1; + string channel = 2; +} diff --git a/script/DeployAll.s.sol b/script/DeployAll.s.sol index 888db14..c299593 100644 --- a/script/DeployAll.s.sol +++ b/script/DeployAll.s.sol @@ -30,10 +30,13 @@ import { } from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/OwnableIBCHandler.sol"; // === App === -import {IContractModule} from "src/core/IContractModule.sol"; import {CrossSimpleModule} from "src/core/CrossSimpleModule.sol"; +import {TxAuthManager} from "src/core/TxAuthManager.sol"; +import {TxManager} from "src/core/TxManager.sol"; import {MockClient} from "@hyperledger-labs/yui-ibc-solidity/contracts/clients/mock/MockClient.sol"; import {MockCrossContract} from "src/example/MockCrossContract.sol"; +import {SampleExtensionVerifier} from "src/example/SampleExtensionVerifier.sol"; +import {IAuthExtensionVerifier} from "src/core/IAuthExtensionVerifier.sol"; import {IIBCModuleInitializer} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/26-router/IIBCModule.sol"; import {ILightClient} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/02-client/ILightClient.sol"; @@ -43,6 +46,7 @@ contract DeployAll is Script, Config { IBCHandler public ibcHandler; MockCrossContract public mockApp; CrossSimpleModule public crossSimpleModule; + TxManager public txManager; MockClient public mockClient; // ---------- helpers ---------- @@ -63,19 +67,36 @@ contract DeployAll is Script, Config { function _deployApp(IBCHandler handler, bool debugMode) internal - returns (MockCrossContract, CrossSimpleModule, MockClient) + returns (MockCrossContract, CrossSimpleModule, TxManager, MockClient) { console2.log("==> 02_DeployApp"); MockCrossContract app = new MockCrossContract(); console2.log(" MockCrossContract:", address(app)); - CrossSimpleModule module = new CrossSimpleModule(handler, IContractModule(address(app)), debugMode); + SampleExtensionVerifier verifier = new SampleExtensionVerifier(); + console2.log(" SampleExtensionVerifier:", address(verifier)); + + string[] memory typeUrls = new string[](1); + typeUrls[0] = "/verifier.sample.extension"; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](1); + verifiers[0] = IAuthExtensionVerifier(verifier); + + TxAuthManager txAuthManager = new TxAuthManager(); + console2.log(" TxAuthManager:", address(txAuthManager)); + + TxManager txManager = new TxManager(); + console2.log(" TxManager:", address(txManager)); + + CrossSimpleModule module = new CrossSimpleModule( + handler, address(txAuthManager), address(txManager), app, typeUrls, verifiers, debugMode + ); console2.log(" CrossSimpleModule:", address(module)); MockClient mclient = new MockClient(address(handler)); console2.log(" MockClient:", address(mclient)); - return (app, module, mclient); + return (app, module, txManager, mclient); } function _initialize( @@ -144,7 +165,7 @@ contract DeployAll is Script, Config { ) internal { vm.startBroadcast(deployerPk); ibcHandler = _deployCore(); - (mockApp, crossSimpleModule, mockClient) = _deployApp(ibcHandler, debugMode); + (mockApp, crossSimpleModule, txManager, mockClient) = _deployApp(ibcHandler, debugMode); _initialize(ibcHandler, crossSimpleModule, portCross, mockClientType, mockClient); vm.stopBroadcast(); } @@ -155,6 +176,7 @@ contract DeployAll is Script, Config { config.set("ibc_handler", address(ibcHandler)); config.set("mock_cross_contract", address(mockApp)); config.set("cross_simple_module", address(crossSimpleModule)); + config.set("tx_manager", address(txManager)); config.set("mock_client", address(mockClient)); // Meta diff --git a/script/confgen.js b/script/confgen.js index bcd0a6d..713dc87 100644 --- a/script/confgen.js +++ b/script/confgen.js @@ -97,22 +97,24 @@ function loadAddressesFromToml(tomlPath, chainId) { } const ibc = addrSec.ibc_handler; const cross = addrSec.cross_simple_module; + const txManager = addrSec.tx_manager; - if (!ibc || !cross) { - console.error(`missing ibc_handler or cross_simple_module in [${chainId}.address]`); + if (!ibc || !cross || !txManager) { + console.error(`missing ibc_handler or cross_simple_module or tx_manager in [${chainId}.address]`); process.exit(1); } - return { ibc, cross }; + return { ibc, cross, txManager }; } (async () => { - const { ibc, cross } = loadAddressesFromToml(DEPLOYMENTS_TOML, CHAIN_ID); + const { ibc, cross, txManager } = loadAddressesFromToml(DEPLOYMENTS_TOML, CHAIN_ID); const targets = makePairs(CONF_TPL.split(":")); for (const [outPath, tplPath] of targets) { const str = await renderFile(tplPath, { IBCHandlerAddress: ibc, CrossSimpleModuleAddress: cross, + TxManagerAddress: txManager, }); fs.mkdirSync(path.dirname(outPath), { recursive: true }); fs.writeFileSync(outPath, str); diff --git a/script/template/contract.go.tpl b/script/template/contract.go.tpl index 5d19e9f..4f713bf 100644 --- a/script/template/contract.go.tpl +++ b/script/template/contract.go.tpl @@ -7,6 +7,7 @@ import ( const ( IBCHandlerAddress = "<%= IBCHandlerAddress; %>" CrossSimpleModuleAddress = "<%= CrossSimpleModuleAddress; %>" + TxManagerAddress = "<%= TxManagerAddress; %>" ) type contractConfig struct{} @@ -20,3 +21,7 @@ func (contractConfig) GetIBCHandlerAddress() common.Address { func (contractConfig) GetCrossSimpleModuleAddress() common.Address { return common.HexToAddress(CrossSimpleModuleAddress) } + +func (contractConfig) GetTxManagerAddress() common.Address { + return common.HexToAddress(TxManagerAddress) +} diff --git a/src/core/Authenticator.sol b/src/core/Authenticator.sol new file mode 100644 index 0000000..cbf3e03 --- /dev/null +++ b/src/core/Authenticator.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IAuthenticator} from "./IAuthenticator.sol"; +import {TxAuthManagerBase} from "./TxAuthManagerBase.sol"; +import {TxManagerBase} from "./TxManagerBase.sol"; +import {ICrossError} from "./ICrossError.sol"; +import {ICrossEvent} from "./ICrossEvent.sol"; + +import { + AuthType, + MsgSignTx, + MsgSignTxResponse, + MsgExtSignTx, + MsgExtSignTxResponse, + QueryTxAuthStateRequest, + QueryTxAuthStateResponse, + Account, + TxAuthState +} from "../proto/cross/core/auth/Auth.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; + +abstract contract Authenticator is IAuthenticator, TxAuthManagerBase, TxManagerBase, ICrossError, ICrossEvent { + function signTx(MsgSignTx.Data calldata msg_) external override returns (MsgSignTxResponse.Data memory) { + bytes32 txID = _decodeTxID(msg_.txID); + + if (msg_.signers.length != 1) { + revert InvalidSignersLength(); + } + + bytes memory expectedSignerId = abi.encodePacked(msg.sender); + if (keccak256(msg_.signers[0]) != keccak256(expectedSignerId)) { + revert SignerMustEqualSender(); + } + + Account.Data[] memory accounts = _buildLocalAccounts(msg_.signers); + + bool completed = _sign(txID, accounts); + if (completed) { + emit TxAuthCompleted(txID); + } + + emit TxSigned(msg.sender, txID, AuthType.AuthMode.AUTH_MODE_LOCAL); + + return MsgSignTxResponse.Data({tx_auth_completed: completed, log: ""}); + } + + function extSignTx(MsgExtSignTx.Data calldata msg_) external override returns (MsgExtSignTxResponse.Data memory) { + bytes32 txID = _decodeTxID(msg_.txID); + + _verifySignatures(txID, msg_.signers); + + bool completed = _sign(txID, msg_.signers); + if (completed) { + emit TxAuthCompleted(txID); + } + + emit TxSigned(msg.sender, txID, AuthType.AuthMode.AUTH_MODE_EXTENSION); + + return MsgExtSignTxResponse.Data({x: true}); + } + + function txAuthState(QueryTxAuthStateRequest.Data calldata req_) + external + override + returns (QueryTxAuthStateResponse.Data memory resp) + { + bytes32 txID = _decodeTxID(req_.txID); + + TxAuthState.Data memory state = _getAuthState(txID); + + return QueryTxAuthStateResponse.Data({tx_auth_state: state}); + } + + function _decodeTxID(bytes calldata rawID) internal pure returns (bytes32) { + if (rawID.length != 32) { + revert InvalidTxIDLength(); + } + return abi.decode(rawID, (bytes32)); + } + + function _buildLocalAccounts(bytes[] calldata signerIDs) internal pure returns (Account.Data[] memory) { + AuthType.Data memory localAuthType = AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: GoogleProtobufAny.Data({type_url: "", value: ""}) + }); + + Account.Data[] memory accounts = new Account.Data[](signerIDs.length); + for (uint256 i = 0; i < signerIDs.length; ++i) { + accounts[i] = Account.Data({id: signerIDs[i], auth_type: localAuthType}); + } + return accounts; + } +} diff --git a/src/core/ContractModuleBase.sol b/src/core/ContractModuleBase.sol new file mode 100644 index 0000000..50b41f8 --- /dev/null +++ b/src/core/ContractModuleBase.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IContractModule, CrossContext} from "./IContractModule.sol"; + +abstract contract ContractModuleBase is IContractModule { + function onContractCommitImmediately(CrossContext calldata context, bytes calldata callInfo) + external + override + returns (bytes memory) + { + _authorize(context, callInfo); + return _onContractCommitImmediately(context, callInfo); + } + + function onContractPrepare(CrossContext calldata context, bytes calldata callInfo) + external + override + returns (bytes memory) + { + _authorize(context, callInfo); + return _onContractPrepare(context, callInfo); + } + + function _authorize(CrossContext calldata context, bytes calldata callInfo) internal virtual; + + function _onContractCommitImmediately(CrossContext calldata context, bytes calldata callInfo) + internal + virtual + returns (bytes memory); + + function _onContractPrepare(CrossContext calldata context, bytes calldata callInfo) + internal + virtual + returns (bytes memory); +} diff --git a/src/core/Coordinator.sol b/src/core/Coordinator.sol new file mode 100644 index 0000000..55ccd88 --- /dev/null +++ b/src/core/Coordinator.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {ICoordinator} from "./ICoordinator.sol"; +import {TxManagerBase} from "./TxManagerBase.sol"; +import {TxAuthManagerBase} from "./TxAuthManagerBase.sol"; +import {ICrossError} from "./ICrossError.sol"; +import {ICrossEvent} from "./ICrossEvent.sol"; +import {TxIDUtils} from "./TxIDUtils.sol"; + +import { + QueryCoordinatorStateRequest, + QueryCoordinatorStateResponse, + CoordinatorState +} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; + +abstract contract Coordinator is ICoordinator, TxAuthManagerBase, TxManagerBase, ICrossError, ICrossEvent { + using TxIDUtils for MsgInitiateTx.Data; + + function executeTx(MsgInitiateTx.Data calldata msg_) external override { + uint64 rh = msg_.timeout_height.revision_height; + if (rh != 0 && (block.number + 1 > uint256(rh))) { + revert MessageTimeoutHeight(block.number, rh); + } + // slither-disable-next-line timestamp + if (msg_.timeout_timestamp > 0 && (block.timestamp + 1 > msg_.timeout_timestamp)) { + revert MessageTimeoutTimestamp(block.timestamp, msg_.timeout_timestamp); + } + + bytes32 txID = msg_.computeTxId(); + + if (!_isTxRecorded(txID)) revert TxIDNotFound(txID); + + if (!_isCompletedAuth(txID)) revert AuthNotCompleted(txID); + _runTxIfCompleted(txID, msg_); + + emit TxExecuted(abi.encodePacked(txID), msg.sender); + } + + function coordinatorState(QueryCoordinatorStateRequest.Data calldata req) + external + view + override + returns (QueryCoordinatorStateResponse.Data memory) + { + if (req.tx_id.length != 32) { + revert InvalidTxIDLength(); + } + bytes32 txID = abi.decode(req.tx_id, (bytes32)); + + CoordinatorState.Data memory state = _getCoordinatorState(txID); + + return QueryCoordinatorStateResponse.Data({coodinator_state: state}); + } +} diff --git a/src/core/CrossModule.sol b/src/core/CrossModule.sol index 29f0bd5..81ae423 100644 --- a/src/core/CrossModule.sol +++ b/src/core/CrossModule.sol @@ -13,20 +13,41 @@ import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-chann import "./PacketHandler.sol"; import "./IBCKeeper.sol"; -abstract contract CrossModule is AccessControl, IIBCModule, IBCKeeper, PacketHandler { +import {Initiator} from "./Initiator.sol"; +import {Authenticator} from "./Authenticator.sol"; +import {Coordinator} from "./Coordinator.sol"; +import {DelegatedLogicHandler} from "./DelegatedLogicHandler.sol"; +import {IContractModule} from "./IContractModule.sol"; +import {IAuthExtensionVerifier} from "./IAuthExtensionVerifier.sol"; + +abstract contract CrossModule is + AccessControl, + IIBCModule, + Initiator, + Authenticator, + Coordinator, + DelegatedLogicHandler +{ bytes32 public constant IBC_ROLE = keccak256("IBC_ROLE"); - constructor(IIBCHandler ibcHandler_) IBCKeeper(ibcHandler_) { + constructor( + IIBCHandler ibcHandler_, + address txAuthManager_, + address txManager_, + IContractModule contractModule_, + string[] memory authTypeUrls_, + IAuthExtensionVerifier[] memory authVerifiers_ + ) Initiator() DelegatedLogicHandler(txAuthManager_, txManager_) { + _initializeTxAuthManager(authTypeUrls_, authVerifiers_); + _initializeTxManager(ibcHandler_, contractModule_); _grantRole(IBC_ROLE, address(ibcHandler_)); } - function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, IERC165) returns (bool) { - return interfaceId == type(IIBCModule).interfaceId || interfaceId == type(IIBCModuleInitializer).interfaceId - || super.supportsInterface(interfaceId); + function supportsInterface(bytes4 interfaceID) public view virtual override(AccessControl, IERC165) returns (bool) { + return interfaceID == type(IIBCModule).interfaceId || interfaceID == type(IIBCModuleInitializer).interfaceId + || super.supportsInterface(interfaceID); } - // function initiateTx() external {} - /// Module callbacks /// function onRecvPacket( @@ -39,7 +60,7 @@ abstract contract CrossModule is AccessControl, IIBCModule, IBCKeeper, PacketHan returns (bytes memory acknowledgement) { require(hasRole(IBC_ROLE, _msgSender()), "caller must have the IBC role"); - return handlePacket(packet); + return _handlePacket(packet); } function onAcknowledgementPacket( @@ -52,7 +73,7 @@ abstract contract CrossModule is AccessControl, IIBCModule, IBCKeeper, PacketHan override { require(hasRole(IBC_ROLE, _msgSender()), "caller must have the IBC role"); - handleAcknowledgement(packet, acknowledgement); + _handleAcknowledgement(packet, acknowledgement); } function onTimeoutPacket( @@ -64,7 +85,7 @@ abstract contract CrossModule is AccessControl, IIBCModule, IBCKeeper, PacketHan override { require(hasRole(IBC_ROLE, _msgSender()), "caller must have the IBC role"); - handleTimeout(packet); + _handleTimeout(packet); } function onChanOpenInit(IIBCModuleInitializer.MsgOnChanOpenInit calldata msg_) diff --git a/src/core/CrossSimpleModule.sol b/src/core/CrossSimpleModule.sol index 3c9310f..2464ead 100644 --- a/src/core/CrossSimpleModule.sol +++ b/src/core/CrossSimpleModule.sol @@ -7,21 +7,18 @@ import "./SimpleContractRegistry.sol"; import "./IContractModule.sol"; import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; -contract CrossSimpleModule is CrossModule, SimpleContractRegistry, TxAtomicSimple { - constructor(IIBCHandler ibcHandler_, IContractModule module, bool debugMode) CrossModule(ibcHandler_) { +contract CrossSimpleModule is CrossModule { + constructor( + IIBCHandler ibcHandler_, + address txAuthManager_, + address txManager_, + IContractModule module_, + string[] memory authTypeUrls_, + IAuthExtensionVerifier[] memory authVerifiers_, + bool debugMode + ) CrossModule(ibcHandler_, txAuthManager_, txManager_, module_, authTypeUrls_, authVerifiers_) { if (debugMode) { _grantRole(IBC_ROLE, _msgSender()); } - registerModule(module); - } - - // ---- debug for serialization ---- - function getPacketAcknowledgementCall(PacketAcknowledgementCall.CommitStatus status) - public - pure - returns (bytes memory acknowledgement) - { - PacketAcknowledgementCall.Data memory ack = PacketAcknowledgementCall.Data({status: status}); - return packPacketAcknowledgementCall(ack); } } diff --git a/src/core/CrossStore.sol b/src/core/CrossStore.sol new file mode 100644 index 0000000..66cc397 --- /dev/null +++ b/src/core/CrossStore.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IAuthExtensionVerifier} from "./IAuthExtensionVerifier.sol"; +import {IContractModule} from "./IContractModule.sol"; +import {MsgInitiateTxResponse, Tx} from "../proto/cross/core/initiator/Initiator.sol"; +import {Account} from "../proto/cross/core/auth/Auth.sol"; +import {CoordinatorState, ContractTransactionState} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {ChannelInfo} from "../proto/cross/core/xcc/XCC.sol"; +import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; + +abstract contract CrossStore { + // keccak256(abi.encode(uint256(keccak256("cross.core.auth")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 internal constant AUTH_STORAGE_LOCATION = + hex"93e3b8eb4220ad7cd6d04c9032dc8d35824a37bf01220f3aeab27e9ece04f300"; + + // keccak256(abi.encode(uint256(keccak256("cross.core.tx")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 internal constant TX_STORAGE_LOCATION = + hex"2af14e14eac421b9203c410963a611c3e22a3e7dd2f462f3872422d801fd5a00"; + + // keccak256(abi.encode(uint256(keccak256("cross.core.coord")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 internal constant COORD_STORAGE_LOCATION = + hex"ef61b39f0bec0016a7c6e65e3ee8d2ea1b2327afbd737de3be2c6827c42f9600"; + + struct AuthStorage { + mapping(string => IAuthExtensionVerifier) authVerifiers; + mapping(bytes32 => mapping(bytes32 => bool)) remaining; + mapping(bytes32 => uint256) remainingCount; + mapping(bytes32 => bool) authInitialized; + mapping(bytes32 => Account.Data[]) requiredAccounts; + } + + struct TxStorage { + mapping(bytes32 => Account.Data[]) txCoordSigners; + mapping(bytes32 => MsgInitiateTxResponse.InitiateTxStatus) txStatus; + mapping(bytes32 => mapping(uint256 => ContractTransactionState.Data)) states; + IContractModule contractModule; + IIBCHandler ibcHandler; + } + + struct CoordStorage { + mapping(bytes32 => CoordStateCompact) compactStates; + } + + /** + * @dev Compact version of CoordinatorState.Data optimized for 1:1 COMMIT_PROTOCOL_SIMPLE. + * Note: Extending to multi-participant 2PC will require a storage redesign. + */ + struct CoordStateCompact { + Tx.CommitProtocol commitProtocol; + CoordinatorState.CoordinatorPhase phase; + CoordinatorState.CoordinatorDecision decision; + + string participantPort; + string participantChannel; + + uint8 confirmedMask; // bit0=coord, bit1=participant + uint8 ackMask; // bit0=coord, bit1=participant + } + + function _getAuthStorage() internal pure returns (AuthStorage storage $) { + // solhint-disable-next-line no-inline-assembly + assembly { $.slot := AUTH_STORAGE_LOCATION } + } + + function _getTxStorage() internal pure returns (TxStorage storage $) { + // solhint-disable-next-line no-inline-assembly + assembly { $.slot := TX_STORAGE_LOCATION } + } + + function _getCoordStorage() internal pure returns (CoordStorage storage $) { + // solhint-disable-next-line no-inline-assembly + assembly { $.slot := COORD_STORAGE_LOCATION } + } + + function _loadCoordinatorState(bytes32 txID) internal view returns (CoordinatorState.Data memory data) { + CoordStorage storage $ = _getCoordStorage(); + CoordStateCompact storage compact = $.compactStates[txID]; + + data.commit_protocol = compact.commitProtocol; + data.phase = compact.phase; + data.decision = compact.decision; + + data.channels = new ChannelInfo.Data[](2); + data.channels[0] = ChannelInfo.Data("", ""); + data.channels[1] = ChannelInfo.Data(compact.participantPort, compact.participantChannel); + + data.confirmed_txs = _maskToUint32Array(compact.confirmedMask); + data.acks = _maskToUint32Array(compact.ackMask); + + return data; + } + + function _saveCoordinatorState(bytes32 txID, CoordinatorState.Data memory data) internal { + CoordStorage storage $ = _getCoordStorage(); + CoordStateCompact storage compact = $.compactStates[txID]; + + compact.commitProtocol = data.commit_protocol; + compact.phase = data.phase; + compact.decision = data.decision; + + if (data.channels.length > 1) { + compact.participantPort = data.channels[1].port; + compact.participantChannel = data.channels[1].channel; + } + + compact.confirmedMask = _uint32ArrayToMask(data.confirmed_txs); + compact.ackMask = _uint32ArrayToMask(data.acks); + } + + function _maskToUint32Array(uint8 mask) internal pure returns (uint32[] memory) { + uint256 count = 0; + if ((mask & 0x01) != 0) ++count; + if ((mask & 0x02) != 0) ++count; + + uint32[] memory arr = new uint32[](count); + uint256 idx = 0; + if ((mask & 0x01) != 0) { + arr[idx] = 0; + ++idx; + } + if ((mask & 0x02) != 0) { + arr[idx] = 1; + ++idx; + } + return arr; + } + + function _uint32ArrayToMask(uint32[] memory arr) internal pure returns (uint8 mask) { + for (uint256 i = 0; i < arr.length;) { + if (arr[i] == 0) mask |= 0x01; + else if (arr[i] == 1) mask |= 0x02; + unchecked { + ++i; + } + } + } +} diff --git a/src/core/DelegatedLogicHandler.sol b/src/core/DelegatedLogicHandler.sol new file mode 100644 index 0000000..f536744 --- /dev/null +++ b/src/core/DelegatedLogicHandler.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable avoid-low-level-calls,no-inline-assembly +pragma solidity ^0.8.20; + +import {TxAuthManagerBase} from "./TxAuthManagerBase.sol"; +import {TxManagerBase} from "./TxManagerBase.sol"; +import {ITxAuthManager} from "./ITxAuthManager.sol"; +import {ITxManager} from "./ITxManager.sol"; +import {ICrossError} from "./ICrossError.sol"; +import {PacketHandler} from "./PacketHandler.sol"; +import {IContractModule} from "./IContractModule.sol"; +import {IAuthExtensionVerifier} from "./IAuthExtensionVerifier.sol"; + +import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; + +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; +import {Account, TxAuthState} from "../proto/cross/core/auth/Auth.sol"; +import {CoordinatorState} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; + +abstract contract DelegatedLogicHandler is TxAuthManagerBase, TxManagerBase, PacketHandler, ICrossError { + address public immutable TX_AUTH_MANAGER; + address public immutable TX_MANAGER; + + modifier onlySelf() { + if (msg.sender != address(this)) { + revert UnauthorizedCaller(msg.sender); + } + _; + } + + constructor(address txAuthManager_, address txManager_) { + TX_AUTH_MANAGER = txAuthManager_; + TX_MANAGER = txManager_; + } + + function _initializeTxManager(IIBCHandler handler, IContractModule module) internal { + _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.initialize.selector, handler, module)); + } + + function _initializeTxAuthManager(string[] memory typeUrls, IAuthExtensionVerifier[] memory verifiers) internal { + _delegateWithData( + TX_AUTH_MANAGER, abi.encodeWithSelector(ITxAuthManager.initialize.selector, typeUrls, verifiers) + ); + } + + function _initAuthState(bytes32 txID, Account.Data[] memory signers) internal virtual override { + _delegateWithData(TX_AUTH_MANAGER, abi.encodeWithSelector(ITxAuthManager.initAuthState.selector, txID, signers)); + } + + function _sign(bytes32 txID, Account.Data[] memory signers) internal virtual override returns (bool) { + bytes memory ret = + _delegateWithData(TX_AUTH_MANAGER, abi.encodeWithSelector(ITxAuthManager.sign.selector, txID, signers)); + return abi.decode(ret, (bool)); + } + + function _isCompletedAuth(bytes32 txID) internal view virtual override returns (bool) { + bytes memory ret = _staticCallSelf(abi.encodeWithSelector(this.__isCompletedAuth.selector, txID)); + return abi.decode(ret, (bool)); + } + + /** + * @dev Internal function called via staticcall to read state via delegatecall. + * * NOTE: Since this function is called via `address(this).staticcall`, + * the `msg.sender` inside the delegated implementation (TxAuthManager) + * will be THIS contract address, NOT the original caller. + * Do not rely on `msg.sender` for access control in the implementation logic. + */ + function __isCompletedAuth(bytes32 txID) external onlySelf returns (bool) { + bytes memory ret = + _delegateWithData(TX_AUTH_MANAGER, abi.encodeWithSelector(ITxAuthManager.isCompletedAuth.selector, txID)); + return abi.decode(ret, (bool)); + } + + function _getAuthState(bytes32 txID) internal view virtual override returns (TxAuthState.Data memory) { + bytes memory ret = _staticCallSelf(abi.encodeWithSelector(this.__getAuthState.selector, txID)); + return abi.decode(ret, (TxAuthState.Data)); + } + + /** + * @dev Internal function called via staticcall to read state via delegatecall. + * * NOTE: Since this function is called via `address(this).staticcall`, + * the `msg.sender` inside the delegated implementation (TxAuthManager) + * will be THIS contract address, NOT the original caller. + * Do not rely on `msg.sender` for access control in the implementation logic. + */ + function __getAuthState(bytes32 txID) external onlySelf returns (TxAuthState.Data memory) { + bytes memory ret = + _delegateWithData(TX_AUTH_MANAGER, abi.encodeWithSelector(ITxAuthManager.getAuthState.selector, txID)); + return abi.decode(ret, (TxAuthState.Data)); + } + + function _verifySignatures(bytes32 txIDHash, Account.Data[] calldata signers) internal virtual override { + _delegateWithData( + TX_AUTH_MANAGER, abi.encodeWithSelector(ITxAuthManager.verifySignatures.selector, txIDHash, signers) + ); + } + + function _createTx(bytes32 txID, MsgInitiateTx.Data calldata src) internal virtual override { + _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.createTx.selector, txID, src)); + } + + function _runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal virtual override { + _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.runTxIfCompleted.selector, txID, msg_)); + } + + function _isTxRecorded(bytes32 txID) internal view virtual override returns (bool) { + bytes memory ret = _staticCallSelf(abi.encodeWithSelector(this.__isTxRecorded.selector, txID)); + return abi.decode(ret, (bool)); + } + + /** + * @dev Internal function called via staticcall to read state via delegatecall. + * * NOTE: Since this function is called via `address(this).staticcall`, + * the `msg.sender` inside the delegated implementation (TxManager) + * will be THIS contract address, NOT the original caller. + * Do not rely on `msg.sender` for access control in the implementation logic. + */ + function __isTxRecorded(bytes32 txID) external onlySelf returns (bool) { + bytes memory ret = _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.isTxRecorded.selector, txID)); + return abi.decode(ret, (bool)); + } + + function _handlePacket(Packet calldata packet) internal virtual override returns (bytes memory acknowledgement) { + bytes memory ret = + _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.handlePacket.selector, packet)); + return abi.decode(ret, (bytes)); + } + + function _handleAcknowledgement(Packet calldata packet, bytes calldata acknowledgement) internal virtual override { + _delegateWithData( + TX_MANAGER, abi.encodeWithSelector(ITxManager.handleAcknowledgement.selector, packet, acknowledgement) + ); + } + + function _handleTimeout(Packet calldata packet) internal virtual override { + _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.handleTimeout.selector, packet)); + } + + function _getCoordinatorState(bytes32 txID) internal view virtual override returns (CoordinatorState.Data memory) { + bytes memory ret = _staticCallSelf(abi.encodeWithSelector(this.__getCoordinatorState.selector, txID)); + return abi.decode(ret, (CoordinatorState.Data)); + } + + /** + * @dev Internal function called via staticcall to read state via delegatecall. + * * NOTE: Since this function is called via `address(this).staticcall`, + * the `msg.sender` inside the delegated implementation (TxManager) + * will be THIS contract address, NOT the original caller. + * Do not rely on `msg.sender` for access control in the implementation logic. + */ + function __getCoordinatorState(bytes32 txID) external onlySelf returns (CoordinatorState.Data memory) { + bytes memory ret = + _delegateWithData(TX_MANAGER, abi.encodeWithSelector(ITxManager.getCoordinatorState.selector, txID)); + return abi.decode(ret, (CoordinatorState.Data)); + } + + function _delegateWithData(address impl, bytes memory data) internal returns (bytes memory) { + (bool success, bytes memory returndata) = impl.delegatecall(data); + if (!success) { + if (returndata.length > 0) { + // bubble up the revert reason from the callee + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + // no revert data from callee (e.g. out-of-gas in callee or explicit revert() without reason) + revert DelegateCallFailed(impl); + } + } + return returndata; + } + + function _staticCallSelf(bytes memory callData) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = address(this).staticcall(callData); + if (!success) { + if (returndata.length > 0) { + // bubble up the revert reason from the callee + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + // no revert data from callee (e.g. out-of-gas in callee or explicit revert() without reason) + revert StaticCallFailed(); + } + } + return returndata; + } +} diff --git a/src/core/IAuthExtensionVerifier.sol b/src/core/IAuthExtensionVerifier.sol new file mode 100644 index 0000000..c58f94e --- /dev/null +++ b/src/core/IAuthExtensionVerifier.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Account} from "../proto/cross/core/auth/Auth.sol"; + +interface IAuthExtensionVerifier { + function verify(bytes32 txIDHash, Account.Data calldata signer) external view returns (bool isValid); +} diff --git a/src/core/IAuthenticator.sol b/src/core/IAuthenticator.sol new file mode 100644 index 0000000..ab54fa8 --- /dev/null +++ b/src/core/IAuthenticator.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { + MsgSignTx, + MsgSignTxResponse, + MsgExtSignTx, + MsgExtSignTxResponse, + QueryTxAuthStateRequest, + QueryTxAuthStateResponse +} from "../proto/cross/core/auth/Auth.sol"; + +interface IAuthenticator { + function signTx(MsgSignTx.Data calldata msg_) external returns (MsgSignTxResponse.Data memory); + + // IBC signing is not supported + // function ibcSignTx(MsgIBCSignTx.Data calldata msg_) + // external + // returns (MsgIBCSignTxResponse.Data memory); + + function extSignTx(MsgExtSignTx.Data calldata msg_) external returns (MsgExtSignTxResponse.Data memory); + + function txAuthState(QueryTxAuthStateRequest.Data calldata req_) + external + returns (QueryTxAuthStateResponse.Data memory); +} diff --git a/src/core/IBCKeeper.sol b/src/core/IBCKeeper.sol index 6c013b0..b468a0b 100644 --- a/src/core/IBCKeeper.sol +++ b/src/core/IBCKeeper.sol @@ -2,16 +2,16 @@ pragma solidity ^0.8.20; import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; +import {CrossStore} from "./CrossStore.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; // IBCKeeper keeps the contracts of IBC -abstract contract IBCKeeper { - IIBCHandler internal immutable IBC_HANDLER; - - constructor(IIBCHandler handler_) { - IBC_HANDLER = handler_; +abstract contract IBCKeeper is Initializable, CrossStore { + function __initIBCKeeper(IIBCHandler handler_) internal onlyInitializing { + _getTxStorage().ibcHandler = handler_; } function getIBCHandler() internal view returns (IIBCHandler) { - return IBC_HANDLER; + return _getTxStorage().ibcHandler; } } diff --git a/src/core/IContractModule.sol b/src/core/IContractModule.sol index a9ce041..3ac0e85 100644 --- a/src/core/IContractModule.sol +++ b/src/core/IContractModule.sol @@ -5,24 +5,29 @@ import "../proto/cross/core/auth/Auth.sol"; // IContractModule defines the expected interface of a contract module on Cross Framework interface IContractModule { - // onContractCall is a callback function that is called at the commit(simple-commit) phase - function onContractCall(CrossContext calldata context, bytes calldata callInfo) external returns (bytes memory); + // onContractCommitImmediately is a callback function that is called on the participant chain to execute the transaction logic immediately + // This function is intended to be used only in the simple-commit protocol + function onContractCommitImmediately(CrossContext calldata context, bytes calldata callInfo) + external + returns (bytes memory); - // // onContractPrepare is a callback function that is called at the prepare(2pc) phase - // function onContractPrepare(CrossContext calldata context, bytes calldata callInfo) external returns (bytes memory); + // onContractPrepare is a callback function that is called at the prepare(2pc) phase + function onContractPrepare(CrossContext calldata context, bytes calldata callInfo) external returns (bytes memory); // // onCommit is a callback function that is called at the commit(2pc) phase - // // It is expected that it commits the changes in the contract module - // function onCommit(CrossContext calldata context) external; + // It is expected that it commits the changes in the contract module + // IMPORTANT: This function MUST NOT revert. + function onCommit(CrossContext calldata context) external; - // // onAbort is a callback function that is called at the commit(2pc) phase - // // It is expected that it aborts the changes in the contract module - // function onAbort(CrossContext calldata context) external; + // onAbort is a callback function that is called at the commit(2pc) phase + // It is expected that it aborts the changes in the contract module + // IMPORTANT: This function MUST NOT revert. + function onAbort(CrossContext calldata context) external; } // CrossContext is a context in cross-chain transaction struct CrossContext { - bytes txId; + bytes txID; uint8 txIndex; Account.Data[] signers; } diff --git a/src/core/ICoordinator.sol b/src/core/ICoordinator.sol new file mode 100644 index 0000000..34170e2 --- /dev/null +++ b/src/core/ICoordinator.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { + QueryCoordinatorStateRequest, + QueryCoordinatorStateResponse +} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; + +interface ICoordinator { + function executeTx(MsgInitiateTx.Data calldata msg_) external; + + function coordinatorState(QueryCoordinatorStateRequest.Data calldata req) + external + view + returns (QueryCoordinatorStateResponse.Data memory); +} diff --git a/src/core/ICrossError.sol b/src/core/ICrossError.sol new file mode 100644 index 0000000..ec7eeed --- /dev/null +++ b/src/core/ICrossError.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +interface ICrossError { + error DelegateCallFailed(address target); + error StaticCallFailed(); + error UnauthorizedCaller(address caller); + error UnexpectedChainID(bytes32 expectedHash, bytes32 gotHash); + error MessageTimeoutHeight(uint256 blockNumber, uint64 timeoutVersionHeight); + error MessageTimeoutTimestamp(uint256 blockTimestamp, uint64 timeoutTimestamp); + error TxIDAlreadyExists(bytes32 txIDHash); + error TxIDNotFound(bytes32 txIDHash); + error AuthStateAlreadyInitialized(bytes32 txID); + error IDNotFound(bytes32 txID); + error InvalidTxIDLength(); + error InvalidSignersLength(); + error SignerMustEqualSender(); + error AuthAlreadyCompleted(bytes32 txID); + error AuthNotCompleted(bytes32 txID); + error TxAlreadyExists(bytes32 txID); + error TxAlreadyVerified(bytes32 txID); + error CoordinatorStateNotFound(bytes32 txID); + error SignerCountMismatch(uint256 signerCount, uint256 signatureCount); + error AuthModeMismatch(); + error VerifierNotFound(string typeUrl); + error SignatureVerificationFailed(bytes32 txID); + error ArrayLengthMismatch(); + error EmptyTypeUrl(); + error ZeroAddressVerifier(); + error VerifierReturnedFalse(bytes32 txIDHash, string typeUrl); + error TooManySigners(uint256 got, uint256 maxAllowed); + error TPCNotImplemented(); + error UnknownCommitProtocol(); + error LinksNotSupported(); + error Tx0MustBeForSelfChain(); + error UnexpectedReturnValue(); + error ChannelNotFound(); + error AckIsNotSuccess(); + error CoordinatorPhaseNotPrepare(); + error AllTransactionsConfirmed(); + error UnexpectedSourceChannel(); + error UnexpectedCommitStatus(); + error CoordinatorStateInconsistent(); + error CoordinatorTxStatusNotPrepare(); + error ModuleAlreadyInitialized(); + error ModuleNotInitialized(); + error PayloadDecodeFailed(); + error UnexpectedTypeURL(); + error NotImplemented(); +} diff --git a/src/core/ICrossEvent.sol b/src/core/ICrossEvent.sol new file mode 100644 index 0000000..c40fe45 --- /dev/null +++ b/src/core/ICrossEvent.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {AuthType} from "../proto/cross/core/auth/Auth.sol"; +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; + +interface ICrossEvent { + event OnContractCommitImmediately(bytes indexed txID, uint8 indexed txIndex, bool indexed success, bytes ret); + event OnCommit(bytes indexed txID, uint8 indexed txIndex); + event OnAbort(bytes indexed txID, uint8 indexed txIndex); + event TxSigned(address indexed signer, bytes32 indexed txID, AuthType.AuthMode method); + event TxAuthCompleted(bytes32 indexed txID); + event TxInitiated(bytes txID, address indexed proposer, MsgInitiateTx.Data msgData); + event TxExecuted(bytes txID, address indexed proposer); +} diff --git a/src/core/IInitiator.sol b/src/core/IInitiator.sol new file mode 100644 index 0000000..2d7baa5 --- /dev/null +++ b/src/core/IInitiator.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {MsgInitiateTx, MsgInitiateTxResponse, QuerySelfXCCResponse} from "../proto/cross/core/initiator/Initiator.sol"; + +interface IInitiator { + function initiateTx(MsgInitiateTx.Data calldata msg_) external returns (MsgInitiateTxResponse.Data memory resp); + + function selfXCC() external view returns (QuerySelfXCCResponse.Data memory resp); +} diff --git a/src/core/ITxAuthManager.sol b/src/core/ITxAuthManager.sol new file mode 100644 index 0000000..e73b82d --- /dev/null +++ b/src/core/ITxAuthManager.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Account, TxAuthState} from "../proto/cross/core/auth/Auth.sol"; +import {IAuthExtensionVerifier} from "./IAuthExtensionVerifier.sol"; + +interface ITxAuthManager { + function initialize(string[] calldata typeUrls, IAuthExtensionVerifier[] calldata verifiers) external; + function initAuthState(bytes32 txID, Account.Data[] calldata signers) external; + function isCompletedAuth(bytes32 txID) external view returns (bool); + function sign(bytes32 txID, Account.Data[] calldata signers) external returns (bool); + function getAuthState(bytes32 txID) external view returns (TxAuthState.Data memory); + function verifySignatures(bytes32 txIDHash, Account.Data[] calldata signers) external; +} diff --git a/src/core/ITxManager.sol b/src/core/ITxManager.sol new file mode 100644 index 0000000..06b343c --- /dev/null +++ b/src/core/ITxManager.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IContractModule} from "./IContractModule.sol"; +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; +import {CoordinatorState} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; + +interface ITxManager { + function initialize(IIBCHandler handler, IContractModule module) external; + function createTx(bytes32 txID, MsgInitiateTx.Data calldata src) external; + function runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) external; + function isTxRecorded(bytes32 txID) external view returns (bool); + function getCoordinatorState(bytes32 txID) external view returns (CoordinatorState.Data memory); + function handlePacket(Packet calldata packet) external returns (bytes memory acknowledgement); + function handleAcknowledgement(Packet calldata packet, bytes calldata acknowledgement) external; + function handleTimeout(Packet calldata packet) external; +} diff --git a/src/core/Initiator.sol b/src/core/Initiator.sol new file mode 100644 index 0000000..68034d9 --- /dev/null +++ b/src/core/Initiator.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IInitiator} from "./IInitiator.sol"; +import {TxAuthManagerBase} from "./TxAuthManagerBase.sol"; +import {TxManagerBase} from "./TxManagerBase.sol"; +import {ICrossError} from "./ICrossError.sol"; +import {ICrossEvent} from "./ICrossEvent.sol"; +import {TxIDUtils} from "./TxIDUtils.sol"; + +import {MsgInitiateTx, MsgInitiateTxResponse, QuerySelfXCCResponse} from "../proto/cross/core/initiator/Initiator.sol"; +import {Account} from "../proto/cross/core/auth/Auth.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {ChannelInfo} from "../proto/cross/core/xcc/XCC.sol"; + +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +abstract contract Initiator is IInitiator, TxAuthManagerBase, TxManagerBase, ReentrancyGuard, ICrossError, ICrossEvent { + using TxIDUtils for MsgInitiateTx.Data; + + bytes32 public immutable CHAIN_ID_HASH; + + constructor() { + CHAIN_ID_HASH = keccak256(bytes(Strings.toString(block.chainid))); + } + + function initiateTx(MsgInitiateTx.Data calldata msg_) + external + override + nonReentrant + returns (MsgInitiateTxResponse.Data memory resp) + { + // chain_id check + bytes32 got = keccak256(bytes(msg_.chain_id)); + if (got != CHAIN_ID_HASH) revert UnexpectedChainID(CHAIN_ID_HASH, got); + + // timeouts + uint64 rh = msg_.timeout_height.revision_height; + if (rh != 0 && (block.number + 1 > uint256(rh))) { + revert MessageTimeoutHeight(block.number, rh); + } + // slither-disable-next-line timestamp + if (msg_.timeout_timestamp > 0 && (block.timestamp + 1 > msg_.timeout_timestamp)) { + revert MessageTimeoutTimestamp(block.timestamp, msg_.timeout_timestamp); + } + + // generate txID + bytes32 txID = msg_.computeTxId(); + if (_isTxRecorded(txID)) revert TxIDAlreadyExists(txID); + + // persist as PENDING + _createTx(txID, msg_); + + // auth init & sign + Account.Data[] memory required = _getRequiredAccounts(msg_); + _initAuthState(txID, required); + bool completed = _sign(txID, msg_.signers); + + bytes memory txIDBytes = abi.encodePacked(txID); + emit TxInitiated(txIDBytes, msg.sender, msg_); + + if (completed) { + return MsgInitiateTxResponse.Data({ + txID: txIDBytes, status: MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED + }); + } + return MsgInitiateTxResponse.Data({ + txID: txIDBytes, status: MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING + }); + } + + function selfXCC() external view virtual override returns (QuerySelfXCCResponse.Data memory) { + ChannelInfo.Data memory channelInfo = ChannelInfo.Data({port: "", channel: ""}); + + string memory typeURL = "/cross.core.xcc.ChannelInfo"; + bytes memory value = ChannelInfo.encode(channelInfo); + + GoogleProtobufAny.Data memory anyXCC = GoogleProtobufAny.Data({type_url: typeURL, value: value}); + + return QuerySelfXCCResponse.Data({xcc: anyXCC}); + } + + function _getRequiredAccounts(MsgInitiateTx.Data calldata msg_) internal pure returns (Account.Data[] memory out) { + uint256 upper = 0; + for (uint256 i = 0; i < msg_.contract_transactions.length; ++i) { + upper += msg_.contract_transactions[i].signers.length; + } + out = new Account.Data[](upper); + uint256 n = 0; + + for (uint256 i = 0; i < msg_.contract_transactions.length; ++i) { + Account.Data[] memory rs = msg_.contract_transactions[i].signers; + for (uint256 j = 0; j < rs.length; ++j) { + out[n] = rs[j]; + ++n; + } + } + return out; + } +} diff --git a/src/core/PacketHandler.sol b/src/core/PacketHandler.sol index 6874942..9a8091f 100644 --- a/src/core/PacketHandler.sol +++ b/src/core/PacketHandler.sol @@ -5,7 +5,7 @@ import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-chann // PacketHandler is a handler that handles a packet and acknowledgement abstract contract PacketHandler { - function handlePacket(Packet memory packet) internal virtual returns (bytes memory acknowledgement); - function handleAcknowledgement(Packet memory packet, bytes memory acknowledgement) internal virtual; - function handleTimeout(Packet calldata packet) internal virtual; + function _handlePacket(Packet calldata packet) internal virtual returns (bytes memory acknowledgement); + function _handleAcknowledgement(Packet calldata packet, bytes calldata acknowledgement) internal virtual; + function _handleTimeout(Packet calldata packet) internal virtual; } diff --git a/src/core/SimpleContractRegistry.sol b/src/core/SimpleContractRegistry.sol index adf0e6d..da86abd 100644 --- a/src/core/SimpleContractRegistry.sol +++ b/src/core/SimpleContractRegistry.sol @@ -3,19 +3,19 @@ pragma solidity ^0.8.20; import "./ContractRegistry.sol"; import "./IContractModule.sol"; +import {CrossStore} from "./CrossStore.sol"; +import {ICrossError} from "./ICrossError.sol"; import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; // SimpleContractRegistry is a simple registry that implements ContractRegistry -abstract contract SimpleContractRegistry is ContractRegistry { - // it keeps only one module. - IContractModule internal contractModule; +// it keeps only one module. +abstract contract SimpleContractRegistry is Initializable, CrossStore, ContractRegistry, ICrossError { + function registerModule(IContractModule module) internal virtual override onlyInitializing { + CrossStore.TxStorage storage t = _getTxStorage(); - error ModuleAlreadyInitialized(); - error ModuleNotInitialized(); - - function registerModule(IContractModule module) internal virtual override { - if (address(contractModule) != address(0)) revert ModuleAlreadyInitialized(); - contractModule = module; + if (address(t.contractModule) != address(0)) revert ModuleAlreadyInitialized(); + t.contractModule = module; } function getModule( @@ -26,7 +26,9 @@ abstract contract SimpleContractRegistry is ContractRegistry { override returns (IContractModule) { - if (address(contractModule) == address(0)) revert ModuleNotInitialized(); - return contractModule; + CrossStore.TxStorage storage t = _getTxStorage(); + + if (address(t.contractModule) == address(0)) revert ModuleNotInitialized(); + return t.contractModule; } } diff --git a/src/core/TxAtomicSimple.sol b/src/core/TxAtomicSimple.sol index 62d7e8e..4937bbd 100644 --- a/src/core/TxAtomicSimple.sol +++ b/src/core/TxAtomicSimple.sol @@ -1,71 +1,442 @@ // SPDX-License-Identifier: Apache-2.0 +// solhint-disable function-max-lines pragma solidity ^0.8.20; import {GoogleProtobufAny as Any} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {Height} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/Client.sol"; import "./PacketHandler.sol"; import "./ContractRegistry.sol"; import "./IContractModule.sol"; import "./IBCKeeper.sol"; +import {TxRunnerBase} from "./TxRunnerBase.sol"; +import {ICrossError} from "./ICrossError.sol"; +import {ICrossEvent} from "./ICrossEvent.sol"; -import "../proto/cross/core/atomic/simple/AtomicSimple.sol"; +import { + PacketData, + Header, + HeaderField, + Acknowledgement, + PacketAcknowledgementCall, + PacketDataCall, + PacketDataCallResolvedContractTransaction, + CoordinatorState, + ContractTransactionState +} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; -// TxAtomicSimple implements PacketHandler that supports simple-commit protocol -abstract contract TxAtomicSimple is IBCKeeper, PacketHandler, ContractRegistry { - // it's defined at simple-commit protocol +import {MsgInitiateTx, Tx, ContractTransaction} from "../proto/cross/core/initiator/Initiator.sol"; +import {ChannelInfo} from "../proto/cross/core/xcc/XCC.sol"; + +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +// TxAtomicSimple implements PacketHandler and TxRunnerBase supporting the simple-commit protocol +abstract contract TxAtomicSimple is + Initializable, + IBCKeeper, + PacketHandler, + TxRunnerBase, + ContractRegistry, + ICrossError, + ICrossEvent +{ + function __initTxAtomicSimple(IIBCHandler handler_, IContractModule module) internal virtual onlyInitializing { + __initIBCKeeper(handler_); + registerModule(module); + } + + uint8 private constant TX_INDEX_COORDINATOR = 0; uint8 private constant TX_INDEX_PARTICIPANT = 1; - error PayloadDecodeFailed(); - error UnexpectedTypeURL(); - error NotImplemented(); + function _runTx(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal virtual override { + if (msg_.commit_protocol == Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE) { + _runSimpleProtocol(txID, msg_); + } else if (msg_.commit_protocol == Tx.CommitProtocol.COMMIT_PROTOCOL_TPC) { + revert TPCNotImplemented(); + } else { + revert UnknownCommitProtocol(); + } + } + + function _runSimpleProtocol(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal { + TxStorage storage txStorage = _getTxStorage(); + + if (msg_.contract_transactions.length != 2) { + revert ArrayLengthMismatch(); + } + + if (msg_.timeout_height.revision_height > 0 && block.number > msg_.timeout_height.revision_height - 1) { + revert MessageTimeoutHeight(block.number, msg_.timeout_height.revision_height); + } + + // slither-disable-next-line timestamp + if (msg_.timeout_timestamp > 0 && block.timestamp > msg_.timeout_timestamp - 1) { + revert MessageTimeoutTimestamp(block.timestamp, msg_.timeout_timestamp); + } + + if (_loadCoordinatorState(txID).commit_protocol != Tx.CommitProtocol.COMMIT_PROTOCOL_UNKNOWN) { + revert TxIDAlreadyExists(txID); + } + + // --- 2. Setup Transaction & XCC --- + + ContractTransaction.Data calldata tx0 = msg_.contract_transactions[TX_INDEX_COORDINATOR]; + ContractTransaction.Data calldata tx1 = msg_.contract_transactions[TX_INDEX_PARTICIPANT]; + + // Simple protocol does not support links + if (tx0.links.length > 0 || tx1.links.length > 0) { + revert LinksNotSupported(); + } + + ChannelInfo.Data memory ch0 = ChannelInfo.decode(tx0.cross_chain_channel.value); + ChannelInfo.Data memory ch1 = ChannelInfo.decode(tx1.cross_chain_channel.value); + + // Ensure tx0 points to self (empty port/channel) + if (bytes(ch0.port).length != 0 || bytes(ch0.channel).length != 0) { + revert Tx0MustBeForSelfChain(); + } + + // --- 3. Local Prepare (Coordinator) --- + + CoordinatorState.CoordinatorPhase phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_UNKNOWN; + CoordinatorState.CoordinatorDecision decision = + CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN; + bool prepareOK = false; + + // Use a block scope to avoid "Stack Too Deep" error by limiting the lifetime of temporary variables + { + // Dummy packet for getModule (local execution) + Height.Data memory emptyHeight = Height.Data(0, 0); + // TODO: SimpleContractRegistry is designed to have only a single ContractModule, + // but it is not correct to force that assumption on the caller as well. + // We should generate a proper Packet instead of dummyPacket to support multiple modules. + Packet memory dummyPacket = Packet({ + sequence: 0, + sourcePort: "", + sourceChannel: "", + destinationPort: "", + destinationChannel: "", + data: bytes(""), + timeoutHeight: emptyHeight, + timeoutTimestamp: 0 + }); + + IContractModule module = getModule(dummyPacket); + if (address(module) == address(0)) { + revert ModuleNotInitialized(); + } + + // slither-disable-next-line reentrancy-no-eth + try module.onContractPrepare( + CrossContext({txID: abi.encodePacked(txID), txIndex: TX_INDEX_COORDINATOR, signers: tx0.signers}), + tx0.call_info + ) returns (bytes memory callResult) { + if (tx0.return_value.value.length > 0) { + if (keccak256(tx0.return_value.value) != keccak256(callResult)) { + revert UnexpectedReturnValue(); + } + } + prepareOK = true; + phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE; + decision = CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN; + } catch { + prepareOK = false; + phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_COMMIT; + decision = CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_ABORT; + } + } + + // --- 4. Send IBC Packet (only if prepareOK) --- + + if (prepareOK) { + // slither-disable-next-line unused-return + (, bool found) = getIBCHandler().getChannel(ch1.port, ch1.channel); + if (!found) { + revert ChannelNotFound(); + } - event OnContractCall(bytes indexed txId, uint8 indexed txIndex, bool indexed success, bytes ret); + // Construct PacketDataCall + PacketDataCall.Data memory callData = PacketDataCall.Data({ + tx_id: abi.encodePacked(txID), + tx: PacketDataCallResolvedContractTransaction.Data({ + cross_chain_channel: tx1.cross_chain_channel, + signers: tx1.signers, + call_info: tx1.call_info, + return_value: tx1.return_value, + objects: new GoogleProtobufAny.Data[](0) + }) + }); + + // Wrap in Any + // solhint-disable-next-line gas-small-strings + Any.Data memory anyPayload = Any.Data({ + type_url: "/cross.core.atomic.simple.PacketDataCall", value: PacketDataCall.encode(callData) + }); + + // Wrap in PacketData + Header.Data memory header = Header.Data({fields: new HeaderField.Data[](0)}); + PacketData.Data memory pd = PacketData.Data({header: header, payload: Any.encode(anyPayload)}); + + bytes memory finalPacketData = PacketData.encode(pd); + + // slither-disable-next-line unused-return reentrancy-no-eth + getIBCHandler() + .sendPacket( + ch1.port, + ch1.channel, + // Simple protocol does not support packet timeouts + Height.Data(0, type(uint64).max), + 0, + finalPacketData + ); + } + + // --- 5. Save CoordinatorState --- + + ChannelInfo.Data[] memory channels = new ChannelInfo.Data[](2); + channels[0] = ch0; + channels[1] = ch1; + + uint32[] memory confirmedTxs = new uint32[](1); + confirmedTxs[0] = TX_INDEX_COORDINATOR; + + uint32[] memory acks; + if (!prepareOK) { + acks = new uint32[](2); + acks[0] = TX_INDEX_COORDINATOR; + acks[1] = TX_INDEX_PARTICIPANT; + } else { + acks = new uint32[](0); + } + + CoordinatorState.Data memory newState = CoordinatorState.Data({ + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + channels: channels, + phase: phase, + decision: decision, + confirmed_txs: confirmedTxs, + acks: acks + }); + + _saveCoordinatorState(txID, newState); + + // --- 6. Save ContractTransactionState --- + + ContractTransactionState.ContractTransactionStatus status; + ContractTransactionState.PrepareResult prepareStatus; + + if (prepareOK) { + status = ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_PREPARE; + prepareStatus = ContractTransactionState.PrepareResult.PREPARE_RESULT_OK; + } else { + status = ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_ABORT; + prepareStatus = ContractTransactionState.PrepareResult.PREPARE_RESULT_FAILED; + } + + txStorage.states[txID][TX_INDEX_COORDINATOR] = + ContractTransactionState.Data({status: status, prepare_result: prepareStatus, coordinator_channel: ch0}); + } + + /** + * @dev Participant side: Receive PacketDataCall, execute onContractCall, and return ACK. + */ + function _handlePacket(Packet calldata packet) internal virtual override returns (bytes memory acknowledgement) { + PacketAcknowledgementCall.Data memory ack = + PacketAcknowledgementCall.Data({status: PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED}); - function handlePacket(Packet memory packet) internal virtual override returns (bytes memory acknowledgement) { IContractModule module = getModule(packet); PacketData.Data memory pd = PacketData.decode(packet.data); - if (pd.payload.length == 0) revert PayloadDecodeFailed(); + if (pd.payload.length == 0) return packPacketAcknowledgementCall(ack); Any.Data memory anyPayload = Any.decode(pd.payload); // TODO should be more gas efficient // solhint-disable-next-line gas-small-strings if (sha256(bytes(anyPayload.type_url)) != sha256(bytes("/cross.core.atomic.simple.PacketDataCall"))) { - revert UnexpectedTypeURL(); + return packPacketAcknowledgementCall(ack); } PacketDataCall.Data memory pdc = PacketDataCall.decode(anyPayload.value); - PacketAcknowledgementCall.Data memory ack = - PacketAcknowledgementCall.Data({status: PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_UNKNOWN}); - try module.onContractCall( + try module.onContractCommitImmediately( CrossContext(pdc.tx_id, TX_INDEX_PARTICIPANT, pdc.tx.signers), pdc.tx.call_info ) returns (bytes memory ret) { ack.status = PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK; // slither-disable-next-line reentrancy-events - emit OnContractCall(pdc.tx_id, TX_INDEX_PARTICIPANT, true, ret); + emit OnContractCommitImmediately(pdc.tx_id, TX_INDEX_PARTICIPANT, true, ret); } catch (bytes memory) { ack.status = PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED; // slither-disable-next-line reentrancy-events - emit OnContractCall(pdc.tx_id, TX_INDEX_PARTICIPANT, false, new bytes(0)); + emit OnContractCommitImmediately(pdc.tx_id, TX_INDEX_PARTICIPANT, false, new bytes(0)); } return packPacketAcknowledgementCall(ack); } - function handleAcknowledgement( - Packet memory, - /*packet*/ - bytes memory /*acknowledgement*/ - ) - internal - virtual - override - { - revert NotImplemented(); + /** + * @dev Coordinator side: Handle ACK, update CoordinatorState, and execute Commit/Abort. + */ + function _handleAcknowledgement(Packet calldata packet, bytes calldata acknowledgement) internal virtual override { + // --- 1. Decode Acknowledgement --- + + Acknowledgement.Data memory ackOuter = Acknowledgement.decode(acknowledgement); + // Simple protocol assumes is_success=true + if (!ackOuter.is_success) { + revert AckIsNotSuccess(); + } + + PacketData.Data memory ackPd = PacketData.decode(ackOuter.result); + if (ackPd.payload.length == 0) revert PayloadDecodeFailed(); + + Any.Data memory ackAny = Any.decode(ackPd.payload); + // solhint-disable-next-line gas-small-strings + if (sha256(bytes(ackAny.type_url)) != sha256(bytes("/cross.core.atomic.simple.PacketAcknowledgementCall"))) { + revert UnexpectedTypeURL(); + } + + PacketAcknowledgementCall.Data memory ack = PacketAcknowledgementCall.decode(ackAny.value); + + // --- 2. Recover txID from original Packet --- + + PacketData.Data memory callPd = PacketData.decode(packet.data); + if (callPd.payload.length == 0) revert PayloadDecodeFailed(); + + Any.Data memory callAny = Any.decode(callPd.payload); + // solhint-disable-next-line gas-small-strings + if (sha256(bytes(callAny.type_url)) != sha256(bytes("/cross.core.atomic.simple.PacketDataCall"))) { + revert UnexpectedTypeURL(); + } + PacketDataCall.Data memory pdc = PacketDataCall.decode(callAny.value); + + if (pdc.tx_id.length != 32) { + revert InvalidTxIDLength(); + } + bytes32 txID = abi.decode(pdc.tx_id, (bytes32)); + + // --- 3. Retrieve & Validate CoordinatorState --- + + TxStorage storage txStorage = _getTxStorage(); + + CoordinatorState.Data memory cs = _loadCoordinatorState(txID); + if (cs.commit_protocol == Tx.CommitProtocol.COMMIT_PROTOCOL_UNKNOWN) { + revert CoordinatorStateNotFound(txID); + } + + if (cs.phase != CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE) { + revert CoordinatorPhaseNotPrepare(); + } + + bool allPreparesAlreadyConfirmed = + _containsUint32(cs.confirmed_txs, TX_INDEX_COORDINATOR) + && _containsUint32(cs.confirmed_txs, TX_INDEX_PARTICIPANT); + if (allPreparesAlreadyConfirmed) { + revert AllTransactionsConfirmed(); + } + + // --- 4. Validate Channel --- + // slither-disable-next-line unused-return + (, bool found) = getIBCHandler().getChannel(packet.sourcePort, packet.sourceChannel); + if (!found) { + revert ChannelNotFound(); + } + + // Verify Participant channel matches + require(cs.channels.length == 2, "channels length must be 2"); + ChannelInfo.Data memory expectedParticipantChannel = cs.channels[TX_INDEX_PARTICIPANT]; + + if ( + keccak256(bytes(expectedParticipantChannel.port)) != keccak256(bytes(packet.sourcePort)) + || keccak256(bytes(expectedParticipantChannel.channel)) != keccak256(bytes(packet.sourceChannel)) + ) { + revert UnexpectedSourceChannel(); + } + + // Mark Participant prepare as confirmed + cs.confirmed_txs = _addToUint32Array(cs.confirmed_txs, TX_INDEX_PARTICIPANT); + + // --- 5. Determine Commit/Abort based on ACK --- + + bool isCommittable = false; + + if (ack.status == PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK) { + cs.decision = CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_COMMIT; + isCommittable = true; + } else if (ack.status == PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED) { + cs.decision = CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_ABORT; + isCommittable = false; + } else { + revert UnexpectedCommitStatus(); + } + + cs.phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_COMMIT; + + // Set ACK flags + cs.acks = _addToUint32Array(cs.acks, TX_INDEX_COORDINATOR); + cs.acks = _addToUint32Array(cs.acks, TX_INDEX_PARTICIPANT); + + _saveCoordinatorState(txID, cs); + + bool allPrepares = + _containsUint32(cs.confirmed_txs, TX_INDEX_COORDINATOR) + && _containsUint32(cs.confirmed_txs, TX_INDEX_PARTICIPANT); + bool allCommits = + _containsUint32(cs.acks, TX_INDEX_COORDINATOR) && _containsUint32(cs.acks, TX_INDEX_PARTICIPANT); + if (!allPrepares || !allCommits) { + revert CoordinatorStateInconsistent(); + } + + // --- 6. Execute Local Commit/Abort --- + + ContractTransactionState.Data storage txState = txStorage.states[txID][TX_INDEX_COORDINATOR]; + + if (txState.status != ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_PREPARE) { + revert CoordinatorTxStatusNotPrepare(); + } + + // Dummy packet for getModule + Height.Data memory emptyHeight = Height.Data(0, 0); + // TODO: SimpleContractRegistry is designed to have only a single ContractModule, + // but it is not correct to force that assumption on the caller as well. + // We should generate a proper Packet instead of dummyPacket to support multiple modules. + Packet memory dummyPacket = Packet({ + sequence: 0, + sourcePort: "", + sourceChannel: "", + destinationPort: "", + destinationChannel: "", + data: bytes(""), + timeoutHeight: emptyHeight, + timeoutTimestamp: 0 + }); + + IContractModule module = getModule(dummyPacket); + if (address(module) == address(0)) { + revert ModuleNotInitialized(); + } + + Account.Data[] storage txCoordSigners = txStorage.txCoordSigners[txID]; + + CrossContext memory ctx = + CrossContext({txID: abi.encodePacked(txID), txIndex: TX_INDEX_COORDINATOR, signers: txCoordSigners}); + + if (isCommittable) { + // Commit + module.onCommit(ctx); + txState.status = ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_COMMIT; + // slither-disable-next-line reentrancy-events + emit OnCommit(abi.encodePacked(txID), TX_INDEX_COORDINATOR); + } else { + // Abort + module.onAbort(ctx); + txState.status = ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_ABORT; + // slither-disable-next-line reentrancy-events + emit OnAbort(abi.encodePacked(txID), TX_INDEX_COORDINATOR); + } + // gas optimization: clean up txCoordSigners storage + delete txStorage.txCoordSigners[txID]; } - function handleTimeout( + function _handleTimeout( Packet calldata /*packet*/ ) internal @@ -75,6 +446,27 @@ abstract contract TxAtomicSimple is IBCKeeper, PacketHandler, ContractRegistry { revert NotImplemented(); } + // --- Helpers --- + + function _containsUint32(uint32[] memory arr, uint32 value) internal view returns (bool) { + for (uint256 i = 0; i < arr.length; ++i) { + if (arr[i] == value) return true; + } + return false; + } + + function _addToUint32Array(uint32[] memory arr, uint32 val) internal view returns (uint32[] memory) { + if (_containsUint32(arr, val)) { + return arr; + } + uint32[] memory newArr = new uint32[](arr.length + 1); + for (uint256 i = 0; i < arr.length; ++i) { + newArr[i] = arr[i]; + } + newArr[arr.length] = val; + return newArr; + } + function packPacketAcknowledgementCall(PacketAcknowledgementCall.Data memory ack) internal pure diff --git a/src/core/TxAuthManager.sol b/src/core/TxAuthManager.sol new file mode 100644 index 0000000..c97f3e1 --- /dev/null +++ b/src/core/TxAuthManager.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {TxAuthManagerBase} from "./TxAuthManagerBase.sol"; +import {CrossStore} from "./CrossStore.sol"; +import {Account, TxAuthState, AuthType} from "../proto/cross/core/auth/Auth.sol"; +import {ITxAuthManager} from "./ITxAuthManager.sol"; +import {IAuthExtensionVerifier} from "./IAuthExtensionVerifier.sol"; +import {ICrossError} from "./ICrossError.sol"; + +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +contract TxAuthManager is Initializable, TxAuthManagerBase, CrossStore, ITxAuthManager, ICrossError { + uint256 private constant MAX_SIGNERS_PER_TX = 32; + + function initialize(string[] calldata typeUrls, IAuthExtensionVerifier[] calldata verifiers) public initializer { + if (typeUrls.length != verifiers.length) revert ArrayLengthMismatch(); + + CrossStore.AuthStorage storage s = _getAuthStorage(); + + for (uint256 i = 0; i < typeUrls.length; ++i) { + string memory typeUrl = typeUrls[i]; + IAuthExtensionVerifier verifier = verifiers[i]; + + if (bytes(typeUrl).length == 0) revert EmptyTypeUrl(); + if (address(verifier) == address(0)) revert ZeroAddressVerifier(); + + s.authVerifiers[typeUrl] = verifier; + } + } + + function initAuthState(bytes32 txID, Account.Data[] calldata signers) external override { + _initAuthState(txID, signers); + } + + function isCompletedAuth(bytes32 txID) external view override returns (bool) { + return _isCompletedAuth(txID); + } + + function sign(bytes32 txID, Account.Data[] calldata signers) external override returns (bool) { + return _sign(txID, signers); + } + + function getAuthState(bytes32 txID) external view override returns (TxAuthState.Data memory) { + return _getAuthState(txID); + } + + function verifySignatures(bytes32 txIDHash, Account.Data[] calldata signers) external override { + _verifySignatures(txIDHash, signers); + } + + function _initAuthState(bytes32 txID, Account.Data[] memory signers) internal virtual override { + CrossStore.AuthStorage storage s = _getAuthStorage(); + if (s.authInitialized[txID]) revert AuthStateAlreadyInitialized(txID); + _setStateFromRemainingList(s, txID, signers); + s.authInitialized[txID] = true; + } + + function _isCompletedAuth(bytes32 txID) internal view virtual override returns (bool) { + CrossStore.AuthStorage storage s = _getAuthStorage(); + if (!s.authInitialized[txID]) revert IDNotFound(txID); + return s.remainingCount[txID] == 0; + } + + function _sign(bytes32 txID, Account.Data[] memory signers) internal virtual override returns (bool) { + CrossStore.AuthStorage storage s = _getAuthStorage(); + if (!s.authInitialized[txID]) revert IDNotFound(txID); + if (s.remainingCount[txID] == 0) revert AuthAlreadyCompleted(txID); + + for (uint256 i = 0; i < signers.length; ++i) { + bytes32 key = _accountKey(signers[i]); + if (s.remaining[txID][key]) { + s.remaining[txID][key] = false; + --s.remainingCount[txID]; + if (s.remainingCount[txID] == 0) return true; + } + } + return s.remainingCount[txID] == 0; + } + + function _getAuthState(bytes32 txID) internal view virtual override returns (TxAuthState.Data memory) { + CrossStore.AuthStorage storage s = _getAuthStorage(); + if (!s.authInitialized[txID]) revert IDNotFound(txID); + Account.Data[] memory remains = _getRemainingSigners(s, txID); + return TxAuthState.Data({remaining_signers: remains}); + } + + function _verifySignatures(bytes32 txIDHash, Account.Data[] calldata signers) internal virtual override { + uint256 len = signers.length; + + if (len > MAX_SIGNERS_PER_TX) { + revert TooManySigners(len, MAX_SIGNERS_PER_TX); + } + + CrossStore.AuthStorage storage s = _getAuthStorage(); + + // slither-disable-start calls-loop + for (uint256 i = 0; i < len; ++i) { + Account.Data calldata signer = signers[i]; + + if (signer.auth_type.mode != AuthType.AuthMode.AUTH_MODE_EXTENSION) { + revert AuthModeMismatch(); + } + + string calldata typeUrl = signer.auth_type.option.type_url; + IAuthExtensionVerifier verifier = s.authVerifiers[typeUrl]; + if (address(verifier) == address(0)) { + revert VerifierNotFound(typeUrl); + } + + bool verified = verifier.verify(txIDHash, signer); + if (!verified) { + revert VerifierReturnedFalse(txIDHash, typeUrl); + } + } + // slither-disable-end calls-loop + } + + function _getRemainingSigners(CrossStore.AuthStorage storage s, bytes32 txID) + internal + view + returns (Account.Data[] memory out) + { + uint256 total = s.requiredAccounts[txID].length; + uint256 need = s.remainingCount[txID]; + out = new Account.Data[](need); + uint256 p = 0; + for (uint256 i = 0; i < total; ++i) { + Account.Data memory acc = s.requiredAccounts[txID][i]; + if (s.remaining[txID][_accountKey(acc)]) { + out[p] = acc; + ++p; + if (p == need) break; + } + } + } + + function _setStateFromRemainingList(CrossStore.AuthStorage storage s, bytes32 txID, Account.Data[] memory list) + internal + { + for (uint256 i = 0; i < list.length; ++i) { + bytes32 key = _accountKey(list[i]); + if (!s.remaining[txID][key]) { + s.remaining[txID][key] = true; + ++s.remainingCount[txID]; + s.requiredAccounts[txID].push(list[i]); + } + } + } + + function _accountKey(Account.Data memory a) internal pure returns (bytes32) { + if (a.auth_type.mode == AuthType.AuthMode.AUTH_MODE_EXTENSION) { + return keccak256(abi.encode( + a.id, + a.auth_type.mode, + a.auth_type.option.type_url + )); + } + return keccak256(abi.encode(a.id, a.auth_type)); + } +} diff --git a/src/core/TxAuthManagerBase.sol b/src/core/TxAuthManagerBase.sol new file mode 100644 index 0000000..dbba8f1 --- /dev/null +++ b/src/core/TxAuthManagerBase.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Account, TxAuthState} from "../proto/cross/core/auth/Auth.sol"; + +abstract contract TxAuthManagerBase { + function _initAuthState(bytes32 txID, Account.Data[] memory signers) internal virtual; + function _isCompletedAuth(bytes32 txID) internal view virtual returns (bool); + function _sign(bytes32 txID, Account.Data[] memory signers) internal virtual returns (bool); + function _getAuthState(bytes32 txID) internal view virtual returns (TxAuthState.Data memory); + function _verifySignatures(bytes32 txIDHash, Account.Data[] calldata signers) internal virtual; +} diff --git a/src/core/TxIDUtils.sol b/src/core/TxIDUtils.sol new file mode 100644 index 0000000..3dc5090 --- /dev/null +++ b/src/core/TxIDUtils.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; + +library TxIDUtils { + function computeTxId(MsgInitiateTx.Data calldata msg_) internal pure returns (bytes32) { + return sha256(MsgInitiateTx.encode(msg_)); + } +} diff --git a/src/core/TxManager.sol b/src/core/TxManager.sol new file mode 100644 index 0000000..b21c1e5 --- /dev/null +++ b/src/core/TxManager.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {TxManagerBase} from "./TxManagerBase.sol"; +import {CrossStore} from "./CrossStore.sol"; +import {ITxManager} from "./ITxManager.sol"; +import {IContractModule} from "./IContractModule.sol"; +import {SimpleContractRegistry} from "./SimpleContractRegistry.sol"; +import {TxAtomicSimple} from "./TxAtomicSimple.sol"; + +import {MsgInitiateTx, MsgInitiateTxResponse} from "../proto/cross/core/initiator/Initiator.sol"; +import {Account} from "../proto/cross/core/auth/Auth.sol"; +import {PacketAcknowledgementCall, CoordinatorState} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {Tx} from "../proto/cross/core/tx/Tx.sol"; + +import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; +import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; + +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; + +contract TxManager is + Initializable, + ReentrancyGuard, + TxManagerBase, + ITxManager, + TxAtomicSimple, + SimpleContractRegistry +{ + function initialize(IIBCHandler handler_, IContractModule module_) public initializer { + __initTxAtomicSimple(handler_, module_); + } + + function createTx(bytes32 txID, MsgInitiateTx.Data calldata src) external override { + _createTx(txID, src); + } + + function runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) external override nonReentrant { + _runTxIfCompleted(txID, msg_); + } + + function isTxRecorded(bytes32 txID) external view override returns (bool) { + return _isTxRecorded(txID); + } + + function getCoordinatorState(bytes32 txID) external view returns (CoordinatorState.Data memory) { + return _getCoordinatorState(txID); + } + + function handlePacket(Packet calldata packet) external returns (bytes memory acknowledgement) { + return _handlePacket(packet); + } + + function handleAcknowledgement(Packet calldata packet, bytes calldata acknowledgement) external { + _handleAcknowledgement(packet, acknowledgement); + } + + function handleTimeout(Packet calldata packet) external { + _handleTimeout(packet); + } + + function _createTx(bytes32 txID, MsgInitiateTx.Data calldata src) internal virtual override { + CrossStore.TxStorage storage t = _getTxStorage(); + if (t.txStatus[txID] != MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN) { + revert TxAlreadyExists(txID); + } + + if (src.contract_transactions.length > 0) { + _storeCoordSigners(t, txID, src.contract_transactions[0].signers); + } + + t.txStatus[txID] = MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING; + } + + function _runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal virtual override { + CrossStore.TxStorage storage t = _getTxStorage(); + if (!_isTxRecorded(txID)) return; + if (t.txStatus[txID] == MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED) return; + t.txStatus[txID] = MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED; + _runTx(txID, msg_); + } + + function _isTxRecorded(bytes32 txID) internal view virtual override returns (bool) { + CrossStore.TxStorage storage t = _getTxStorage(); + return t.txStatus[txID] != MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN; + } + + function _getCoordinatorState(bytes32 txID) internal view override returns (CoordinatorState.Data memory) { + CoordinatorState.Data memory state = _loadCoordinatorState(txID); + if (state.commit_protocol == Tx.CommitProtocol.COMMIT_PROTOCOL_UNKNOWN) { + revert CoordinatorStateNotFound(txID); + } + return state; + } + + function _storeCoordSigners(CrossStore.TxStorage storage t, bytes32 txID, Account.Data[] calldata signers) private { + Account.Data[] storage dst = t.txCoordSigners[txID]; + while (dst.length > 0) dst.pop(); + for (uint256 i = 0; i < signers.length; ++i) { + dst.push(signers[i]); + } + } + + // ---- debug for serialization ---- + function getPacketAcknowledgementCall(PacketAcknowledgementCall.CommitStatus status) + public + pure + returns (bytes memory acknowledgement) + { + PacketAcknowledgementCall.Data memory ack = PacketAcknowledgementCall.Data({status: status}); + return packPacketAcknowledgementCall(ack); + } +} diff --git a/src/core/TxManagerBase.sol b/src/core/TxManagerBase.sol new file mode 100644 index 0000000..c97926a --- /dev/null +++ b/src/core/TxManagerBase.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; +import {CoordinatorState} from "../proto/cross/core/atomic/simple/AtomicSimple.sol"; + +abstract contract TxManagerBase { + function _createTx(bytes32 txID, MsgInitiateTx.Data calldata src) internal virtual; + function _runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal virtual; + function _isTxRecorded(bytes32 txID) internal view virtual returns (bool); + function _getCoordinatorState(bytes32 txID) internal view virtual returns (CoordinatorState.Data memory); +} diff --git a/src/core/TxRunnerBase.sol b/src/core/TxRunnerBase.sol new file mode 100644 index 0000000..f6d4401 --- /dev/null +++ b/src/core/TxRunnerBase.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {MsgInitiateTx} from "../proto/cross/core/initiator/Initiator.sol"; + +abstract contract TxRunnerBase { + function _runTx(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal virtual; +} diff --git a/src/example/ERC20TransferModule.sol b/src/example/ERC20TransferModule.sol new file mode 100644 index 0000000..0418f95 --- /dev/null +++ b/src/example/ERC20TransferModule.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {ContractModuleBase} from "../core/ContractModuleBase.sol"; +import {CrossContext} from "../core/IContractModule.sol"; + +abstract contract ERC20TransferModule is Initializable, ContractModuleBase, Ownable { + using SafeERC20 for IERC20; + + error ERC20TransferModuleInvalidCallInfo(); + error ERC20TransferModuleTxAlreadyPending(); + error ERC20TransferModuleUnauthorized(); + error ERC20TransferModuleNotInitialized(); + error ERC20TransferModuleInvalidAddress(); + + event ERC20TransferModuleInitialized(address indexed crossModule, address indexed token); + + struct PendingTx { + address from; + address to; + uint256 amount; + } + + // txID => PendingTx + mapping(bytes32 => PendingTx) public pendingTxs; + + address public crossModule; + IERC20 public token; + + constructor() Ownable(msg.sender) {} + + modifier onlyCrossModule() { + if (crossModule == address(0)) revert ERC20TransferModuleNotInitialized(); + if (msg.sender != crossModule) revert ERC20TransferModuleUnauthorized(); + _; + } + + function initialize(address _crossModule, address _token) external initializer onlyOwner { + if (_crossModule == address(0) || _token == address(0)) { + revert ERC20TransferModuleInvalidAddress(); + } + crossModule = _crossModule; + token = IERC20(_token); + + emit ERC20TransferModuleInitialized(_crossModule, _token); + } + + function decodeCallInfo(bytes calldata callInfo) + public + pure + virtual + returns (address from, address to, uint256 amount) + { + if (callInfo.length != 96) revert ERC20TransferModuleInvalidCallInfo(); + return abi.decode(callInfo, (address, address, uint256)); + } + + function _onContractCommitImmediately( + CrossContext calldata, + /*context*/ + bytes calldata callInfo + ) + internal + virtual + override + onlyCrossModule + returns (bytes memory) + { + (address from, address to, uint256 amount) = decodeCallInfo(callInfo); + + // IMPORTANT: The implementing contract MUST ensure in `_authorize` that the `from` address corresponds to the authenticated signer. + // slither-disable-next-line arbitrary-send-erc20 + token.safeTransferFrom(from, to, amount); + + return ""; + } + + function _onContractPrepare(CrossContext calldata context, bytes calldata callInfo) + internal + virtual + override + onlyCrossModule + returns (bytes memory) + { + bytes32 txID = abi.decode(context.txID, (bytes32)); + + if (pendingTxs[txID].from != address(0)) revert ERC20TransferModuleTxAlreadyPending(); + + (address from, address to, uint256 amount) = decodeCallInfo(callInfo); + + pendingTxs[txID] = PendingTx({from: from, to: to, amount: amount}); + + // IMPORTANT: The implementing contract MUST ensure in `_authorize` that the `from` address corresponds to the authenticated signer. + // slither-disable-next-line arbitrary-send-erc20 + token.safeTransferFrom(from, address(this), amount); + + return ""; + } + + function onCommit(CrossContext calldata context) external virtual override onlyCrossModule { + bytes32 txID = abi.decode(context.txID, (bytes32)); + PendingTx memory pending = pendingTxs[txID]; + + if (pending.from != address(0)) { + delete pendingTxs[txID]; + // Transfer locked tokens to the destination + token.safeTransfer(pending.to, pending.amount); + } + } + + function onAbort(CrossContext calldata context) external virtual override onlyCrossModule { + bytes32 txID = abi.decode(context.txID, (bytes32)); + PendingTx memory pending = pendingTxs[txID]; + + if (pending.from != address(0)) { + delete pendingTxs[txID]; + // Refund tokens to the sender + token.safeTransfer(pending.from, pending.amount); + } + } +} diff --git a/src/example/MockCrossContract.sol b/src/example/MockCrossContract.sol index d229bf7..5994ec1 100644 --- a/src/example/MockCrossContract.sol +++ b/src/example/MockCrossContract.sol @@ -5,7 +5,7 @@ import "../core/IContractModule.sol"; import "../proto/cross/core/auth/Auth.sol"; contract MockCrossContract is IContractModule { - function onContractCall(CrossContext calldata context, bytes calldata callInfo) + function onContractCommitImmediately(CrossContext calldata context, bytes calldata callInfo) external override returns (bytes memory) @@ -20,4 +20,29 @@ contract MockCrossContract is IContractModule { revert("callInfo must be 0x01"); } } + + function onCommit( + CrossContext calldata /*context*/ + ) + external + override + {} + function onAbort( + CrossContext calldata /*context*/ + ) + external + override + {} + + function onContractPrepare( + CrossContext calldata, + /*context*/ + bytes calldata /*callInfo*/ + ) + external + override + returns (bytes memory) + { + return bytes("mock prepare succeed"); + } } diff --git a/src/example/SampleExtensionVerifier.sol b/src/example/SampleExtensionVerifier.sol new file mode 100644 index 0000000..6e0deba --- /dev/null +++ b/src/example/SampleExtensionVerifier.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {IAuthExtensionVerifier} from "../core/IAuthExtensionVerifier.sol"; +import {AuthType, Account} from "../proto/cross/core/auth/Auth.sol"; + +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; + +contract SampleExtensionVerifier is IAuthExtensionVerifier { + /** + * Expected inputs: + * + * param txIDHash (1st argument, ignored in this implementation) + * - Hash that uniquely identifies the transaction being verified. + * - Not used in this sample implementation, but expected to be passed so + * the caller can associate verification with a specific transaction. + * + * param signer (2nd argument: Account.Data) + * - signer.id: + * - 20-byte value representing the signer’s Ethereum address. + * - Must satisfy: signer.id.length == 20. + * - The expected address is reconstructed as: address(bytes20(signer.id)). + * + * - signer.auth_type.mode: + * - Must be AuthType.AuthMode.AUTH_MODE_EXTENSION. + * - Any other mode is treated as invalid and verification will fail. + * + * - signer.auth_type.option.value: + * - ABI-encoded as: abi.encode(signature, signMSG). + * * signature: + * - ECDSA signature over signMSG, in standard Ethereum format + * (65 bytes: r(32) | s(32) | v(1)). + * * signMSG: + * - 32-byte message hash that was signed. + * - On-chain, this contract applies: + * MessageHashUtils.toEthSignedMessageHash(signMSG) + * and expects `signature` to be a valid Ethereum signed message + * for that value. + * + * Return value: + * - true: + * - When the recovered address from the signature is non-zero and + * exactly matches address(bytes20(signer.id)). + * - false: + * - When: + * * auth_type.mode is not AUTH_MODE_EXTENSION, or + * * signer.id length is not 20 bytes, or + * * signature recovery fails, or + * * the recovered address does not match the expected address. + */ + function verify( + bytes32, + /*txIDHash*/ + Account.Data calldata signer + ) + external + view + override + returns (bool isValid) + { + if (signer.auth_type.mode != AuthType.AuthMode.AUTH_MODE_EXTENSION) { + return false; + } + + (bytes memory signature, bytes32 signMSG) = abi.decode(signer.auth_type.option.value, (bytes, bytes32)); + + if (signer.id.length != 20) { + return false; + } + address expectedAddress = address(bytes20(signer.id)); + + bytes32 messageHash = MessageHashUtils.toEthSignedMessageHash(signMSG); + + address recoveredAddress = ECDSA.recover(messageHash, signature); + + return recoveredAddress == expectedAddress; + } +} diff --git a/src/proto/cross/core/atomic/simple/AtomicSimple.sol b/src/proto/cross/core/atomic/simple/AtomicSimple.sol index dd8c106..b7ed651 100644 --- a/src/proto/cross/core/atomic/simple/AtomicSimple.sol +++ b/src/proto/cross/core/atomic/simple/AtomicSimple.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; - import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; import "../../auth/Auth.sol"; +import "../../tx/Tx.sol"; +import "../../xcc/XCC.sol"; library PacketData { //struct definition @@ -599,7 +600,6 @@ library Header { if (r.fields.length != 0) { for (i = 0; i < r.fields.length; i++) { pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); - pointer += HeaderField._encode_nested(r.fields[i], pointer, bs); } } @@ -1434,7 +1434,6 @@ library PacketDataCallResolvedContractTransaction { if (r.signers.length != 0) { for (i = 0; i < r.signers.length; i++) { pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); - pointer += Account._encode_nested(r.signers[i], pointer, bs); } } @@ -1449,7 +1448,6 @@ library PacketDataCallResolvedContractTransaction { if (r.objects.length != 0) { for (i = 0; i < r.objects.length; i++) { pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); - pointer += GoogleProtobufAny._encode_nested(r.objects[i], pointer, bs); } } @@ -1848,10 +1846,10 @@ library PacketAcknowledgementCall { } //library PacketAcknowledgementCall -library ReturnValue { +library QueryCoordinatorStateRequest { //struct definition struct Data { - bytes value; + bytes tx_id; } // Decoder section @@ -1897,7 +1895,7 @@ library ReturnValue { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_value(pointer, bs, r); + pointer += _read_tx_id(pointer, bs, r); } else { pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } @@ -1914,9 +1912,9 @@ library ReturnValue { * @param r The in-memory struct * @return The number of bytes decoded */ - function _read_value(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + function _read_tx_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - r.value = x; + r.tx_id = x; return sz; } @@ -1949,9 +1947,9 @@ library ReturnValue { uint256 offset = p; uint256 pointer = p; - if (r.value.length != 0) { + if (r.tx_id.length != 0) { pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); - pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.tx_id, pointer, bs); } return pointer - offset; } @@ -1992,13 +1990,13 @@ library ReturnValue { */ function _estimate(Data memory r) internal pure returns (uint256) { uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.tx_id.length); return e; } // empty checker function _empty(Data memory r) internal pure returns (bool) { - if (r.value.length != 0) { + if (r.tx_id.length != 0) { return false; } @@ -2012,7 +2010,1231 @@ library ReturnValue { * @param output The in-storage struct */ function store(Data memory input, Data storage output) internal { - output.value = input.value; + output.tx_id = input.tx_id; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library QueryCoordinatorStateRequest + +library QueryCoordinatorStateResponse { + //struct definition + struct Data { + CoordinatorState.Data coodinator_state; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_coodinator_state(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_coodinator_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (CoordinatorState.Data memory x, uint256 sz) = _decode_CoordinatorState(p, bs); + r.coodinator_state = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CoordinatorState(uint256 p, bytes memory bs) + internal + pure + returns (CoordinatorState.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CoordinatorState.Data memory r,) = CoordinatorState._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += CoordinatorState._encode_nested(r.coodinator_state, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(CoordinatorState._estimate(r.coodinator_state)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + CoordinatorState.store(input.coodinator_state, output.coodinator_state); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library QueryCoordinatorStateResponse + +library CoordinatorState { + //enum definition + // Solidity enum definitions + enum CoordinatorPhase { + COORDINATOR_PHASE_UNKNOWN, + COORDINATOR_PHASE_PREPARE, + COORDINATOR_PHASE_COMMIT + } + + // Solidity enum encoder + function encode_CoordinatorPhase(CoordinatorPhase x) internal pure returns (int32) { + if (x == CoordinatorPhase.COORDINATOR_PHASE_UNKNOWN) { + return 0; + } + + if (x == CoordinatorPhase.COORDINATOR_PHASE_PREPARE) { + return 1; + } + + if (x == CoordinatorPhase.COORDINATOR_PHASE_COMMIT) { + return 2; + } + revert(); + } + + // Solidity enum decoder + function decode_CoordinatorPhase(int64 x) internal pure returns (CoordinatorPhase) { + if (x == 0) { + return CoordinatorPhase.COORDINATOR_PHASE_UNKNOWN; + } + + if (x == 1) { + return CoordinatorPhase.COORDINATOR_PHASE_PREPARE; + } + + if (x == 2) { + return CoordinatorPhase.COORDINATOR_PHASE_COMMIT; + } + revert(); + } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_CoordinatorPhase(CoordinatorPhase[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint256 i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_CoordinatorPhase(a[i])); + } + return e; + } + + // Solidity enum definitions + enum CoordinatorDecision { + COORDINATOR_DECISION_UNKNOWN, + COORDINATOR_DECISION_COMMIT, + COORDINATOR_DECISION_ABORT + } + + // Solidity enum encoder + function encode_CoordinatorDecision(CoordinatorDecision x) internal pure returns (int32) { + if (x == CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN) { + return 0; + } + + if (x == CoordinatorDecision.COORDINATOR_DECISION_COMMIT) { + return 1; + } + + if (x == CoordinatorDecision.COORDINATOR_DECISION_ABORT) { + return 2; + } + revert(); + } + + // Solidity enum decoder + function decode_CoordinatorDecision(int64 x) internal pure returns (CoordinatorDecision) { + if (x == 0) { + return CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN; + } + + if (x == 1) { + return CoordinatorDecision.COORDINATOR_DECISION_COMMIT; + } + + if (x == 2) { + return CoordinatorDecision.COORDINATOR_DECISION_ABORT; + } + revert(); + } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_CoordinatorDecision(CoordinatorDecision[] memory a) + internal + pure + returns (uint256) + { + uint256 e = 0; + for (uint256 i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_CoordinatorDecision(a[i])); + } + return e; + } + + //struct definition + struct Data { + Tx.CommitProtocol commit_protocol; + ChannelInfo.Data[] channels; + CoordinatorState.CoordinatorPhase phase; + CoordinatorState.CoordinatorDecision decision; + uint32[] confirmed_txs; + uint32[] acks; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[7] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_commit_protocol(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_channels(pointer, bs, nil(), counters); + } else if (fieldId == 3) { + pointer += _read_phase(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_decision(pointer, bs, r); + } else if (fieldId == 5) { + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + pointer += _read_packed_repeated_confirmed_txs(pointer, bs, r); + } else { + pointer += _read_unpacked_repeated_confirmed_txs(pointer, bs, nil(), counters); + } + } else if (fieldId == 6) { + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + pointer += _read_packed_repeated_acks(pointer, bs, r); + } else { + pointer += _read_unpacked_repeated_acks(pointer, bs, nil(), counters); + } + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.channels.length == 0); + r.channels = new ChannelInfo.Data[](counters[2]); + } + if (counters[5] > 0) { + require(r.confirmed_txs.length == 0); + r.confirmed_txs = new uint32[](counters[5]); + } + if (counters[6] > 0) { + require(r.acks.length == 0); + r.acks = new uint32[](counters[6]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_channels(pointer, bs, r, counters); + } else if (fieldId == 5 && wireType != ProtoBufRuntime.WireType.LengthDelim) { + pointer += _read_unpacked_repeated_confirmed_txs(pointer, bs, r, counters); + } else if (fieldId == 6 && wireType != ProtoBufRuntime.WireType.LengthDelim) { + pointer += _read_unpacked_repeated_acks(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_commit_protocol(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + Tx.CommitProtocol x = Tx.decode_CommitProtocol(tmp); + r.commit_protocol = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_channels(uint256 p, bytes memory bs, Data memory r, uint256[7] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ChannelInfo.Data memory x, uint256 sz) = _decode_ChannelInfo(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.channels[r.channels.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_phase(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + CoordinatorState.CoordinatorPhase x = decode_CoordinatorPhase(tmp); + r.phase = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_decision(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + CoordinatorState.CoordinatorDecision x = decode_CoordinatorDecision(tmp); + r.decision = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_confirmed_txs( + uint256 p, + bytes memory bs, + Data memory r, + uint256[7] memory counters + ) internal pure returns (uint256) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (uint32 x, uint256 sz) = ProtoBufRuntime._decode_uint32(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.confirmed_txs[r.confirmed_txs.length - counters[5]] = x; + counters[5] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_packed_repeated_confirmed_txs(uint256 p, bytes memory bs, Data memory r) + internal + pure + returns (uint256) + { + (uint256 len, uint256 size) = ProtoBufRuntime._decode_varint(p, bs); + p += size; + uint256 count = ProtoBufRuntime._count_packed_repeated_varint(p, len, bs); + r.confirmed_txs = new uint32[](count); + for (uint256 i = 0; i < count; i++) { + (uint32 x, uint256 sz) = ProtoBufRuntime._decode_uint32(p, bs); + p += sz; + r.confirmed_txs[i] = x; + } + return size + len; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_acks(uint256 p, bytes memory bs, Data memory r, uint256[7] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (uint32 x, uint256 sz) = ProtoBufRuntime._decode_uint32(p, bs); + if (isNil(r)) { + counters[6] += 1; + } else { + r.acks[r.acks.length - counters[6]] = x; + counters[6] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_packed_repeated_acks(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint256 len, uint256 size) = ProtoBufRuntime._decode_varint(p, bs); + p += size; + uint256 count = ProtoBufRuntime._count_packed_repeated_varint(p, len, bs); + r.acks = new uint32[](count); + for (uint256 i = 0; i < count; i++) { + (uint32 x, uint256 sz) = ProtoBufRuntime._decode_uint32(p, bs); + p += sz; + r.acks[i] = x; + } + return size + len; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ChannelInfo(uint256 p, bytes memory bs) internal pure returns (ChannelInfo.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ChannelInfo.Data memory r,) = ChannelInfo._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (uint256(r.commit_protocol) != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_commit_protocol = Tx.encode_CommitProtocol(r.commit_protocol); + pointer += ProtoBufRuntime._encode_enum(_enum_commit_protocol, pointer, bs); + } + if (r.channels.length != 0) { + for (i = 0; i < r.channels.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ChannelInfo._encode_nested(r.channels[i], pointer, bs); + } + } + if (uint256(r.phase) != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_phase = encode_CoordinatorPhase(r.phase); + pointer += ProtoBufRuntime._encode_enum(_enum_phase, pointer, bs); + } + if (uint256(r.decision) != 0) { + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_decision = encode_CoordinatorDecision(r.decision); + pointer += ProtoBufRuntime._encode_enum(_enum_decision, pointer, bs); + } + if (r.confirmed_txs.length != 0) { + pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_varint( + ProtoBufRuntime._estimate_packed_repeated_uint32(r.confirmed_txs), pointer, bs + ); + for (i = 0; i < r.confirmed_txs.length; i++) { + pointer += ProtoBufRuntime._encode_uint32(r.confirmed_txs[i], pointer, bs); + } + } + if (r.acks.length != 0) { + pointer += ProtoBufRuntime._encode_key(6, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_varint( + ProtoBufRuntime._estimate_packed_repeated_uint32(r.acks), pointer, bs + ); + for (i = 0; i < r.acks.length; i++) { + pointer += ProtoBufRuntime._encode_uint32(r.acks[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_enum(Tx.encode_CommitProtocol(r.commit_protocol)); + for (i = 0; i < r.channels.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(ChannelInfo._estimate(r.channels[i])); + } + e += 1 + ProtoBufRuntime._sz_enum(encode_CoordinatorPhase(r.phase)); + e += 1 + ProtoBufRuntime._sz_enum(encode_CoordinatorDecision(r.decision)); + e += 1 + ProtoBufRuntime._sz_lendelim(ProtoBufRuntime._estimate_packed_repeated_uint32(r.confirmed_txs)); + e += 1 + ProtoBufRuntime._sz_lendelim(ProtoBufRuntime._estimate_packed_repeated_uint32(r.acks)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (uint256(r.commit_protocol) != 0) { + return false; + } + + if (r.channels.length != 0) { + return false; + } + + if (uint256(r.phase) != 0) { + return false; + } + + if (uint256(r.decision) != 0) { + return false; + } + + if (r.confirmed_txs.length != 0) { + return false; + } + + if (r.acks.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.commit_protocol = input.commit_protocol; + + for (uint256 i2 = 0; i2 < input.channels.length; i2++) { + output.channels.push(input.channels[i2]); + } + + output.phase = input.phase; + output.decision = input.decision; + output.confirmed_txs = input.confirmed_txs; + output.acks = input.acks; + } + + //array helpers for Channels + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addChannels(Data memory self, ChannelInfo.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + ChannelInfo.Data[] memory tmp = new ChannelInfo.Data[](self.channels.length + 1); + for (uint256 i = 0; i < self.channels.length; i++) { + tmp[i] = self.channels[i]; + } + tmp[self.channels.length] = value; + self.channels = tmp; + } + + //array helpers for ConfirmedTxs + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addConfirmedTxs(Data memory self, uint32 value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + uint32[] memory tmp = new uint32[](self.confirmed_txs.length + 1); + for (uint256 i = 0; i < self.confirmed_txs.length; i++) { + tmp[i] = self.confirmed_txs[i]; + } + tmp[self.confirmed_txs.length] = value; + self.confirmed_txs = tmp; + } + + //array helpers for Acks + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addAcks(Data memory self, uint32 value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + uint32[] memory tmp = new uint32[](self.acks.length + 1); + for (uint256 i = 0; i < self.acks.length; i++) { + tmp[i] = self.acks[i]; + } + tmp[self.acks.length] = value; + self.acks = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CoordinatorState + +library ContractTransactionState { + //enum definition + // Solidity enum definitions + enum ContractTransactionStatus { + CONTRACT_TRANSACTION_STATUS_UNKNOWN, + CONTRACT_TRANSACTION_STATUS_PREPARE, + CONTRACT_TRANSACTION_STATUS_COMMIT, + CONTRACT_TRANSACTION_STATUS_ABORT + } + + // Solidity enum encoder + function encode_ContractTransactionStatus(ContractTransactionStatus x) internal pure returns (int32) { + if (x == ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_UNKNOWN) { + return 0; + } + + if (x == ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_PREPARE) { + return 1; + } + + if (x == ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_COMMIT) { + return 2; + } + + if (x == ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_ABORT) { + return 3; + } + revert(); + } + + // Solidity enum decoder + function decode_ContractTransactionStatus(int64 x) internal pure returns (ContractTransactionStatus) { + if (x == 0) { + return ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_UNKNOWN; + } + + if (x == 1) { + return ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_PREPARE; + } + + if (x == 2) { + return ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_COMMIT; + } + + if (x == 3) { + return ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_ABORT; + } + revert(); + } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_ContractTransactionStatus(ContractTransactionStatus[] memory a) + internal + pure + returns (uint256) + { + uint256 e = 0; + for (uint256 i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_ContractTransactionStatus(a[i])); + } + return e; + } + + // Solidity enum definitions + enum PrepareResult { + PREPARE_RESULT_UNKNOWN, + PREPARE_RESULT_OK, + PREPARE_RESULT_FAILED + } + + // Solidity enum encoder + function encode_PrepareResult(PrepareResult x) internal pure returns (int32) { + if (x == PrepareResult.PREPARE_RESULT_UNKNOWN) { + return 0; + } + + if (x == PrepareResult.PREPARE_RESULT_OK) { + return 1; + } + + if (x == PrepareResult.PREPARE_RESULT_FAILED) { + return 2; + } + revert(); + } + + // Solidity enum decoder + function decode_PrepareResult(int64 x) internal pure returns (PrepareResult) { + if (x == 0) { + return PrepareResult.PREPARE_RESULT_UNKNOWN; + } + + if (x == 1) { + return PrepareResult.PREPARE_RESULT_OK; + } + + if (x == 2) { + return PrepareResult.PREPARE_RESULT_FAILED; + } + revert(); + } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_PrepareResult(PrepareResult[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint256 i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_PrepareResult(a[i])); + } + return e; + } + + //struct definition + struct Data { + ContractTransactionState.ContractTransactionStatus status; + ContractTransactionState.PrepareResult prepare_result; + ChannelInfo.Data coordinator_channel; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_status(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_prepare_result(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_coordinator_channel(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_status(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + ContractTransactionState.ContractTransactionStatus x = decode_ContractTransactionStatus(tmp); + r.status = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_prepare_result(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + ContractTransactionState.PrepareResult x = decode_PrepareResult(tmp); + r.prepare_result = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_coordinator_channel(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (ChannelInfo.Data memory x, uint256 sz) = _decode_ChannelInfo(p, bs); + r.coordinator_channel = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ChannelInfo(uint256 p, bytes memory bs) internal pure returns (ChannelInfo.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ChannelInfo.Data memory r,) = ChannelInfo._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (uint256(r.status) != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_status = encode_ContractTransactionStatus(r.status); + pointer += ProtoBufRuntime._encode_enum(_enum_status, pointer, bs); + } + if (uint256(r.prepare_result) != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_prepare_result = encode_PrepareResult(r.prepare_result); + pointer += ProtoBufRuntime._encode_enum(_enum_prepare_result, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ChannelInfo._encode_nested(r.coordinator_channel, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_enum(encode_ContractTransactionStatus(r.status)); + e += 1 + ProtoBufRuntime._sz_enum(encode_PrepareResult(r.prepare_result)); + e += 1 + ProtoBufRuntime._sz_lendelim(ChannelInfo._estimate(r.coordinator_channel)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (uint256(r.status) != 0) { + return false; + } + + if (uint256(r.prepare_result) != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.status = input.status; + output.prepare_result = input.prepare_result; + ChannelInfo.store(input.coordinator_channel, output.coordinator_channel); } //utility functions @@ -2037,4 +3259,4 @@ library ReturnValue { } } } -//library ReturnValue +//library ContractTransactionState diff --git a/src/proto/cross/core/auth/Auth.sol b/src/proto/cross/core/auth/Auth.sol index 7c3c903..dc1f6bc 100644 --- a/src/proto/cross/core/auth/Auth.sol +++ b/src/proto/cross/core/auth/Auth.sol @@ -1,8 +1,1410 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import "../../../ibc/core/client/v1/client.sol"; + +library MsgSignTx { + //struct definition + struct Data { + bytes txID; + bytes[] signers; + IbcCoreClientV1Height.Data timeout_height; + uint64 timeout_timestamp; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_txID(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, nil(), counters); + } else if (fieldId == 3) { + pointer += _read_timeout_height(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_timeout_timestamp(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.signers.length == 0); + r.signers = new bytes[](counters[2]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_txID(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.txID = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_signers(uint256 p, bytes memory bs, Data memory r, uint256[5] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.signers[r.signers.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_timeout_height(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (IbcCoreClientV1Height.Data memory x, uint256 sz) = _decode_IbcCoreClientV1Height(p, bs); + r.timeout_height = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_timeout_timestamp(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint64 x, uint256 sz) = ProtoBufRuntime._decode_uint64(p, bs); + r.timeout_timestamp = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_IbcCoreClientV1Height(uint256 p, bytes memory bs) + internal + pure + returns (IbcCoreClientV1Height.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (IbcCoreClientV1Height.Data memory r,) = IbcCoreClientV1Height._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.txID.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.txID, pointer, bs); + } + if (r.signers.length != 0) { + for (i = 0; i < r.signers.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.signers[i], pointer, bs); + } + } + + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += IbcCoreClientV1Height._encode_nested(r.timeout_height, pointer, bs); + + if (r.timeout_timestamp != 0) { + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint64(r.timeout_timestamp, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.txID.length); + for (i = 0; i < r.signers.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(r.signers[i].length); + } + e += 1 + ProtoBufRuntime._sz_lendelim(IbcCoreClientV1Height._estimate(r.timeout_height)); + e += 1 + ProtoBufRuntime._sz_uint64(r.timeout_timestamp); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.txID.length != 0) { + return false; + } + + if (r.signers.length != 0) { + return false; + } + + if (r.timeout_timestamp != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.txID = input.txID; + output.signers = input.signers; + IbcCoreClientV1Height.store(input.timeout_height, output.timeout_height); + output.timeout_timestamp = input.timeout_timestamp; + } + + //array helpers for Signers + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addSigners(Data memory self, bytes memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + bytes[] memory tmp = new bytes[](self.signers.length + 1); + for (uint256 i = 0; i < self.signers.length; i++) { + tmp[i] = self.signers[i]; + } + tmp[self.signers.length] = value; + self.signers = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library MsgSignTx + +library MsgSignTxResponse { + //struct definition + struct Data { + bool tx_auth_completed; + string log; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_tx_auth_completed(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_log(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_tx_auth_completed(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bool x, uint256 sz) = ProtoBufRuntime._decode_bool(p, bs); + r.tx_auth_completed = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_log(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.log = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (r.tx_auth_completed != false) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_bool(r.tx_auth_completed, pointer, bs); + } + if (bytes(r.log).length != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.log, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + 1; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.log).length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.tx_auth_completed != false) { + return false; + } + + if (bytes(r.log).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.tx_auth_completed = input.tx_auth_completed; + output.log = input.log; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library MsgSignTxResponse + +library MsgExtSignTx { + //struct definition + struct Data { + bytes txID; + Account.Data[] signers; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_txID(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, nil(), counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.signers.length == 0); + r.signers = new Account.Data[](counters[2]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_txID(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.txID = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_signers(uint256 p, bytes memory bs, Data memory r, uint256[3] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (Account.Data memory x, uint256 sz) = _decode_Account(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.signers[r.signers.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_Account(uint256 p, bytes memory bs) internal pure returns (Account.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Account.Data memory r,) = Account._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.txID.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.txID, pointer, bs); + } + if (r.signers.length != 0) { + for (i = 0; i < r.signers.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += Account._encode_nested(r.signers[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.txID.length); + for (i = 0; i < r.signers.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Account._estimate(r.signers[i])); + } + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.txID.length != 0) { + return false; + } + + if (r.signers.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.txID = input.txID; + + for (uint256 i2 = 0; i2 < input.signers.length; i2++) { + output.signers.push(input.signers[i2]); + } + } + + //array helpers for Signers + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addSigners(Data memory self, Account.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + Account.Data[] memory tmp = new Account.Data[](self.signers.length + 1); + for (uint256 i = 0; i < self.signers.length; i++) { + tmp[i] = self.signers[i]; + } + tmp[self.signers.length] = value; + self.signers = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library MsgExtSignTx + +library MsgExtSignTxResponse { + //struct definition + struct Data { + bool x; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + } + return (r, sz); + } + + // field readers + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory /* r */ + ) + internal + pure + returns (uint256) + { + uint256 e; + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal {} + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library MsgExtSignTxResponse + +library QueryTxAuthStateRequest { + //struct definition + struct Data { + bytes txID; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_txID(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_txID(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.txID = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (r.txID.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.txID, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.txID.length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.txID.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.txID = input.txID; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library QueryTxAuthStateRequest + +library QueryTxAuthStateResponse { + //struct definition + struct Data { + TxAuthState.Data tx_auth_state; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_tx_auth_state(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_tx_auth_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (TxAuthState.Data memory x, uint256 sz) = _decode_TxAuthState(p, bs); + r.tx_auth_state = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_TxAuthState(uint256 p, bytes memory bs) internal pure returns (TxAuthState.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (TxAuthState.Data memory r,) = TxAuthState._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += TxAuthState._encode_nested(r.tx_auth_state, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(TxAuthState._estimate(r.tx_auth_state)); + return e; + } + // empty checker -import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; -import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + TxAuthState.store(input.tx_auth_state, output.tx_auth_state); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library QueryTxAuthStateResponse library Account { //struct definition @@ -528,3 +1930,265 @@ library AuthType { } } //library AuthType + +library TxAuthState { + //struct definition + struct Data { + Account.Data[] remaining_signers; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[2] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_unpacked_repeated_remaining_signers(pointer, bs, nil(), counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[1] > 0) { + require(r.remaining_signers.length == 0); + r.remaining_signers = new Account.Data[](counters[1]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_unpacked_repeated_remaining_signers(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_remaining_signers( + uint256 p, + bytes memory bs, + Data memory r, + uint256[2] memory counters + ) internal pure returns (uint256) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (Account.Data memory x, uint256 sz) = _decode_Account(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.remaining_signers[r.remaining_signers.length - counters[1]] = x; + counters[1] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_Account(uint256 p, bytes memory bs) internal pure returns (Account.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Account.Data memory r,) = Account._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.remaining_signers.length != 0) { + for (i = 0; i < r.remaining_signers.length; i++) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += Account._encode_nested(r.remaining_signers[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + for (i = 0; i < r.remaining_signers.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Account._estimate(r.remaining_signers[i])); + } + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.remaining_signers.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + for (uint256 i1 = 0; i1 < input.remaining_signers.length; i1++) { + output.remaining_signers.push(input.remaining_signers[i1]); + } + } + + //array helpers for RemainingSigners + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addRemainingSigners(Data memory self, Account.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + Account.Data[] memory tmp = new Account.Data[](self.remaining_signers.length + 1); + for (uint256 i = 0; i < self.remaining_signers.length; i++) { + tmp[i] = self.remaining_signers[i]; + } + tmp[self.remaining_signers.length] = value; + self.remaining_signers = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library TxAuthState diff --git a/src/proto/cross/core/initiator/Initiator.sol b/src/proto/cross/core/initiator/Initiator.sol new file mode 100644 index 0000000..a9d6b93 --- /dev/null +++ b/src/proto/cross/core/initiator/Initiator.sol @@ -0,0 +1,2196 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import "../../../ibc/core/client/v1/client.sol"; +import "../tx/Tx.sol"; +import "../auth/Auth.sol"; + +library MsgInitiateTx { + //struct definition + struct Data { + string chain_id; + uint64 nonce; + Tx.CommitProtocol commit_protocol; + ContractTransaction.Data[] contract_transactions; + Account.Data[] signers; + IbcCoreClientV1Height.Data timeout_height; + uint64 timeout_timestamp; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[8] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_chain_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_nonce(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_commit_protocol(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_unpacked_repeated_contract_transactions(pointer, bs, nil(), counters); + } else if (fieldId == 5) { + pointer += _read_unpacked_repeated_signers(pointer, bs, nil(), counters); + } else if (fieldId == 6) { + pointer += _read_timeout_height(pointer, bs, r); + } else if (fieldId == 7) { + pointer += _read_timeout_timestamp(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[4] > 0) { + require(r.contract_transactions.length == 0); + r.contract_transactions = new ContractTransaction.Data[](counters[4]); + } + if (counters[5] > 0) { + require(r.signers.length == 0); + r.signers = new Account.Data[](counters[5]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 4) { + pointer += _read_unpacked_repeated_contract_transactions(pointer, bs, r, counters); + } else if (fieldId == 5) { + pointer += _read_unpacked_repeated_signers(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_chain_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.chain_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_nonce(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint64 x, uint256 sz) = ProtoBufRuntime._decode_uint64(p, bs); + r.nonce = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_commit_protocol(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + Tx.CommitProtocol x = Tx.decode_CommitProtocol(tmp); + r.commit_protocol = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_contract_transactions( + uint256 p, + bytes memory bs, + Data memory r, + uint256[8] memory counters + ) internal pure returns (uint256) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ContractTransaction.Data memory x, uint256 sz) = _decode_ContractTransaction(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.contract_transactions[r.contract_transactions.length - counters[4]] = x; + counters[4] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_signers(uint256 p, bytes memory bs, Data memory r, uint256[8] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (Account.Data memory x, uint256 sz) = _decode_Account(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.signers[r.signers.length - counters[5]] = x; + counters[5] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_timeout_height(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (IbcCoreClientV1Height.Data memory x, uint256 sz) = _decode_IbcCoreClientV1Height(p, bs); + r.timeout_height = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_timeout_timestamp(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint64 x, uint256 sz) = ProtoBufRuntime._decode_uint64(p, bs); + r.timeout_timestamp = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ContractTransaction(uint256 p, bytes memory bs) + internal + pure + returns (ContractTransaction.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ContractTransaction.Data memory r,) = ContractTransaction._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_Account(uint256 p, bytes memory bs) internal pure returns (Account.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Account.Data memory r,) = Account._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_IbcCoreClientV1Height(uint256 p, bytes memory bs) + internal + pure + returns (IbcCoreClientV1Height.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (IbcCoreClientV1Height.Data memory r,) = IbcCoreClientV1Height._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (bytes(r.chain_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.chain_id, pointer, bs); + } + if (r.nonce != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint64(r.nonce, pointer, bs); + } + if (uint256(r.commit_protocol) != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_commit_protocol = Tx.encode_CommitProtocol(r.commit_protocol); + pointer += ProtoBufRuntime._encode_enum(_enum_commit_protocol, pointer, bs); + } + if (r.contract_transactions.length != 0) { + for (i = 0; i < r.contract_transactions.length; i++) { + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ContractTransaction._encode_nested(r.contract_transactions[i], pointer, bs); + } + } + if (r.signers.length != 0) { + for (i = 0; i < r.signers.length; i++) { + pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += Account._encode_nested(r.signers[i], pointer, bs); + } + } + + pointer += ProtoBufRuntime._encode_key(6, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += IbcCoreClientV1Height._encode_nested(r.timeout_height, pointer, bs); + + if (r.timeout_timestamp != 0) { + pointer += ProtoBufRuntime._encode_key(7, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint64(r.timeout_timestamp, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.chain_id).length); + e += 1 + ProtoBufRuntime._sz_uint64(r.nonce); + e += 1 + ProtoBufRuntime._sz_enum(Tx.encode_CommitProtocol(r.commit_protocol)); + for (i = 0; i < r.contract_transactions.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(ContractTransaction._estimate(r.contract_transactions[i])); + } + for (i = 0; i < r.signers.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Account._estimate(r.signers[i])); + } + e += 1 + ProtoBufRuntime._sz_lendelim(IbcCoreClientV1Height._estimate(r.timeout_height)); + e += 1 + ProtoBufRuntime._sz_uint64(r.timeout_timestamp); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.chain_id).length != 0) { + return false; + } + + if (r.nonce != 0) { + return false; + } + + if (uint256(r.commit_protocol) != 0) { + return false; + } + + if (r.contract_transactions.length != 0) { + return false; + } + + if (r.signers.length != 0) { + return false; + } + + if (r.timeout_timestamp != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.chain_id = input.chain_id; + output.nonce = input.nonce; + output.commit_protocol = input.commit_protocol; + + for (uint256 i4 = 0; i4 < input.contract_transactions.length; i4++) { + output.contract_transactions.push(input.contract_transactions[i4]); + } + + for (uint256 i5 = 0; i5 < input.signers.length; i5++) { + output.signers.push(input.signers[i5]); + } + + IbcCoreClientV1Height.store(input.timeout_height, output.timeout_height); + output.timeout_timestamp = input.timeout_timestamp; + } + + //array helpers for ContractTransactions + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addContractTransactions(Data memory self, ContractTransaction.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + ContractTransaction.Data[] memory tmp = new ContractTransaction.Data[](self.contract_transactions.length + 1); + for (uint256 i = 0; i < self.contract_transactions.length; i++) { + tmp[i] = self.contract_transactions[i]; + } + tmp[self.contract_transactions.length] = value; + self.contract_transactions = tmp; + } + + //array helpers for Signers + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addSigners(Data memory self, Account.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + Account.Data[] memory tmp = new Account.Data[](self.signers.length + 1); + for (uint256 i = 0; i < self.signers.length; i++) { + tmp[i] = self.signers[i]; + } + tmp[self.signers.length] = value; + self.signers = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library MsgInitiateTx + +library MsgInitiateTxResponse { + //enum definition + // Solidity enum definitions + enum InitiateTxStatus { + INITIATE_TX_STATUS_UNKNOWN, + INITIATE_TX_STATUS_PENDING, + INITIATE_TX_STATUS_VERIFIED + } + + // Solidity enum encoder + function encode_InitiateTxStatus(InitiateTxStatus x) internal pure returns (int32) { + if (x == InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN) { + return 0; + } + + if (x == InitiateTxStatus.INITIATE_TX_STATUS_PENDING) { + return 1; + } + + if (x == InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED) { + return 2; + } + revert(); + } + + // Solidity enum decoder + function decode_InitiateTxStatus(int64 x) internal pure returns (InitiateTxStatus) { + if (x == 0) { + return InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN; + } + + if (x == 1) { + return InitiateTxStatus.INITIATE_TX_STATUS_PENDING; + } + + if (x == 2) { + return InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED; + } + revert(); + } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_InitiateTxStatus(InitiateTxStatus[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint256 i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_InitiateTxStatus(a[i])); + } + return e; + } + + //struct definition + struct Data { + bytes txID; + MsgInitiateTxResponse.InitiateTxStatus status; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_txID(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_status(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_txID(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.txID = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_status(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + MsgInitiateTxResponse.InitiateTxStatus x = decode_InitiateTxStatus(tmp); + r.status = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (r.txID.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.txID, pointer, bs); + } + if (uint256(r.status) != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_status = encode_InitiateTxStatus(r.status); + pointer += ProtoBufRuntime._encode_enum(_enum_status, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.txID.length); + e += 1 + ProtoBufRuntime._sz_enum(encode_InitiateTxStatus(r.status)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.txID.length != 0) { + return false; + } + + if (uint256(r.status) != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.txID = input.txID; + output.status = input.status; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library MsgInitiateTxResponse + +library QuerySelfXCCRequest { + //struct definition + struct Data { + bool x; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + } + return (r, sz); + } + + // field readers + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory /* r */ + ) + internal + pure + returns (uint256) + { + uint256 e; + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal {} + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library QuerySelfXCCRequest + +library QuerySelfXCCResponse { + //struct definition + struct Data { + GoogleProtobufAny.Data xcc; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_xcc(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_xcc(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.xcc = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.xcc, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.xcc)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + GoogleProtobufAny.store(input.xcc, output.xcc); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library QuerySelfXCCResponse + +library ContractTransaction { + //struct definition + struct Data { + GoogleProtobufAny.Data cross_chain_channel; + Account.Data[] signers; + bytes call_info; + ReturnValue.Data return_value; + Link.Data[] links; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[6] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_cross_chain_channel(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, nil(), counters); + } else if (fieldId == 3) { + pointer += _read_call_info(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_return_value(pointer, bs, r); + } else if (fieldId == 5) { + pointer += _read_unpacked_repeated_links(pointer, bs, nil(), counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.signers.length == 0); + r.signers = new Account.Data[](counters[2]); + } + if (counters[5] > 0) { + require(r.links.length == 0); + r.links = new Link.Data[](counters[5]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, r, counters); + } else if (fieldId == 5) { + pointer += _read_unpacked_repeated_links(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_cross_chain_channel(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.cross_chain_channel = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_signers(uint256 p, bytes memory bs, Data memory r, uint256[6] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (Account.Data memory x, uint256 sz) = _decode_Account(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.signers[r.signers.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_call_info(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.call_info = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_return_value(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (ReturnValue.Data memory x, uint256 sz) = _decode_ReturnValue(p, bs); + r.return_value = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_links(uint256 p, bytes memory bs, Data memory r, uint256[6] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (Link.Data memory x, uint256 sz) = _decode_Link(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.links[r.links.length - counters[5]] = x; + counters[5] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_Account(uint256 p, bytes memory bs) internal pure returns (Account.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Account.Data memory r,) = Account._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ReturnValue(uint256 p, bytes memory bs) internal pure returns (ReturnValue.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ReturnValue.Data memory r,) = ReturnValue._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_Link(uint256 p, bytes memory bs) internal pure returns (Link.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Link.Data memory r,) = Link._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.cross_chain_channel, pointer, bs); + + if (r.signers.length != 0) { + for (i = 0; i < r.signers.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += Account._encode_nested(r.signers[i], pointer, bs); + } + } + if (r.call_info.length != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.call_info, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ReturnValue._encode_nested(r.return_value, pointer, bs); + + if (r.links.length != 0) { + for (i = 0; i < r.links.length; i++) { + pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += Link._encode_nested(r.links[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.cross_chain_channel)); + for (i = 0; i < r.signers.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Account._estimate(r.signers[i])); + } + e += 1 + ProtoBufRuntime._sz_lendelim(r.call_info.length); + e += 1 + ProtoBufRuntime._sz_lendelim(ReturnValue._estimate(r.return_value)); + for (i = 0; i < r.links.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Link._estimate(r.links[i])); + } + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.signers.length != 0) { + return false; + } + + if (r.call_info.length != 0) { + return false; + } + + if (r.links.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + GoogleProtobufAny.store(input.cross_chain_channel, output.cross_chain_channel); + + for (uint256 i2 = 0; i2 < input.signers.length; i2++) { + output.signers.push(input.signers[i2]); + } + + output.call_info = input.call_info; + ReturnValue.store(input.return_value, output.return_value); + + for (uint256 i5 = 0; i5 < input.links.length; i5++) { + output.links.push(input.links[i5]); + } + } + + //array helpers for Signers + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addSigners(Data memory self, Account.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + Account.Data[] memory tmp = new Account.Data[](self.signers.length + 1); + for (uint256 i = 0; i < self.signers.length; i++) { + tmp[i] = self.signers[i]; + } + tmp[self.signers.length] = value; + self.signers = tmp; + } + + //array helpers for Links + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addLinks(Data memory self, Link.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + Link.Data[] memory tmp = new Link.Data[](self.links.length + 1); + for (uint256 i = 0; i < self.links.length; i++) { + tmp[i] = self.links[i]; + } + tmp[self.links.length] = value; + self.links = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ContractTransaction + +library Link { + //struct definition + struct Data { + uint32 src_index; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_src_index(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_src_index(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint32 x, uint256 sz) = ProtoBufRuntime._decode_uint32(p, bs); + r.src_index = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (r.src_index != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint32(r.src_index, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_uint32(r.src_index); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.src_index != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.src_index = input.src_index; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library Link + +library GenesisState { + //struct definition + struct Data { + bool x; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + } + return (r, sz); + } + + // field readers + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory /* r */ + ) + internal + pure + returns (uint256) + { + uint256 e; + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal {} + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library GenesisState + +library InitiateTxState { + //struct definition + struct Data { + MsgInitiateTxResponse.InitiateTxStatus status; + MsgInitiateTx.Data msg; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_status(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_msg(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_status(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + MsgInitiateTxResponse.InitiateTxStatus x = MsgInitiateTxResponse.decode_InitiateTxStatus(tmp); + r.status = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_msg(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (MsgInitiateTx.Data memory x, uint256 sz) = _decode_MsgInitiateTx(p, bs); + r.msg = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_MsgInitiateTx(uint256 p, bytes memory bs) + internal + pure + returns (MsgInitiateTx.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (MsgInitiateTx.Data memory r,) = MsgInitiateTx._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (uint256(r.status) != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_status = MsgInitiateTxResponse.encode_InitiateTxStatus(r.status); + pointer += ProtoBufRuntime._encode_enum(_enum_status, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += MsgInitiateTx._encode_nested(r.msg, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_enum(MsgInitiateTxResponse.encode_InitiateTxStatus(r.status)); + e += 1 + ProtoBufRuntime._sz_lendelim(MsgInitiateTx._estimate(r.msg)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (uint256(r.status) != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.status = input.status; + MsgInitiateTx.store(input.msg, output.msg); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library InitiateTxState diff --git a/src/proto/cross/core/tx/Tx.sol b/src/proto/cross/core/tx/Tx.sol new file mode 100644 index 0000000..314bbb9 --- /dev/null +++ b/src/proto/cross/core/tx/Tx.sol @@ -0,0 +1,1627 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import "../../../ibc/core/client/v1/client.sol"; +import "../auth/Auth.sol"; + +library Tx { + //enum definition + // Solidity enum definitions + enum CommitProtocol { + COMMIT_PROTOCOL_UNKNOWN, + COMMIT_PROTOCOL_SIMPLE, + COMMIT_PROTOCOL_TPC + } + + // Solidity enum encoder + function encode_CommitProtocol(CommitProtocol x) internal pure returns (int32) { + if (x == CommitProtocol.COMMIT_PROTOCOL_UNKNOWN) { + return 0; + } + + if (x == CommitProtocol.COMMIT_PROTOCOL_SIMPLE) { + return 1; + } + + if (x == CommitProtocol.COMMIT_PROTOCOL_TPC) { + return 2; + } + revert(); + } + + // Solidity enum decoder + function decode_CommitProtocol(int64 x) internal pure returns (CommitProtocol) { + if (x == 0) { + return CommitProtocol.COMMIT_PROTOCOL_UNKNOWN; + } + + if (x == 1) { + return CommitProtocol.COMMIT_PROTOCOL_SIMPLE; + } + + if (x == 2) { + return CommitProtocol.COMMIT_PROTOCOL_TPC; + } + revert(); + } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_CommitProtocol(CommitProtocol[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint256 i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_CommitProtocol(a[i])); + } + return e; + } + + //struct definition + struct Data { + bytes id; + Tx.CommitProtocol commit_protocol; + ResolvedContractTransaction.Data[] contract_transactions; + IbcCoreClientV1Height.Data timeout_height; + uint64 timeout_timestamp; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[6] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_commit_protocol(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_unpacked_repeated_contract_transactions(pointer, bs, nil(), counters); + } else if (fieldId == 4) { + pointer += _read_timeout_height(pointer, bs, r); + } else if (fieldId == 5) { + pointer += _read_timeout_timestamp(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[3] > 0) { + require(r.contract_transactions.length == 0); + r.contract_transactions = new ResolvedContractTransaction.Data[](counters[3]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 3) { + pointer += _read_unpacked_repeated_contract_transactions(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_commit_protocol(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + Tx.CommitProtocol x = decode_CommitProtocol(tmp); + r.commit_protocol = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_contract_transactions( + uint256 p, + bytes memory bs, + Data memory r, + uint256[6] memory counters + ) internal pure returns (uint256) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ResolvedContractTransaction.Data memory x, uint256 sz) = _decode_ResolvedContractTransaction(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.contract_transactions[r.contract_transactions.length - counters[3]] = x; + counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_timeout_height(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (IbcCoreClientV1Height.Data memory x, uint256 sz) = _decode_IbcCoreClientV1Height(p, bs); + r.timeout_height = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_timeout_timestamp(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint64 x, uint256 sz) = ProtoBufRuntime._decode_uint64(p, bs); + r.timeout_timestamp = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ResolvedContractTransaction(uint256 p, bytes memory bs) + internal + pure + returns (ResolvedContractTransaction.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ResolvedContractTransaction.Data memory r,) = ResolvedContractTransaction._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_IbcCoreClientV1Height(uint256 p, bytes memory bs) + internal + pure + returns (IbcCoreClientV1Height.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (IbcCoreClientV1Height.Data memory r,) = IbcCoreClientV1Height._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.id.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.id, pointer, bs); + } + if (uint256(r.commit_protocol) != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.Varint, pointer, bs); + int32 _enum_commit_protocol = encode_CommitProtocol(r.commit_protocol); + pointer += ProtoBufRuntime._encode_enum(_enum_commit_protocol, pointer, bs); + } + if (r.contract_transactions.length != 0) { + for (i = 0; i < r.contract_transactions.length; i++) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ResolvedContractTransaction._encode_nested(r.contract_transactions[i], pointer, bs); + } + } + + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += IbcCoreClientV1Height._encode_nested(r.timeout_height, pointer, bs); + + if (r.timeout_timestamp != 0) { + pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint64(r.timeout_timestamp, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.id.length); + e += 1 + ProtoBufRuntime._sz_enum(encode_CommitProtocol(r.commit_protocol)); + for (i = 0; i < r.contract_transactions.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(ResolvedContractTransaction._estimate(r.contract_transactions[i])); + } + e += 1 + ProtoBufRuntime._sz_lendelim(IbcCoreClientV1Height._estimate(r.timeout_height)); + e += 1 + ProtoBufRuntime._sz_uint64(r.timeout_timestamp); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.id.length != 0) { + return false; + } + + if (uint256(r.commit_protocol) != 0) { + return false; + } + + if (r.contract_transactions.length != 0) { + return false; + } + + if (r.timeout_timestamp != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.id = input.id; + output.commit_protocol = input.commit_protocol; + + for (uint256 i3 = 0; i3 < input.contract_transactions.length; i3++) { + output.contract_transactions.push(input.contract_transactions[i3]); + } + + IbcCoreClientV1Height.store(input.timeout_height, output.timeout_height); + output.timeout_timestamp = input.timeout_timestamp; + } + + //array helpers for ContractTransactions + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addContractTransactions(Data memory self, ResolvedContractTransaction.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + ResolvedContractTransaction.Data[] memory tmp = + new ResolvedContractTransaction.Data[](self.contract_transactions.length + 1); + for (uint256 i = 0; i < self.contract_transactions.length; i++) { + tmp[i] = self.contract_transactions[i]; + } + tmp[self.contract_transactions.length] = value; + self.contract_transactions = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library Tx + +library ResolvedContractTransaction { + //struct definition + struct Data { + GoogleProtobufAny.Data cross_chain_channel; + Account.Data[] signers; + bytes call_info; + ReturnValue.Data return_value; + GoogleProtobufAny.Data[] call_results; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[6] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_cross_chain_channel(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, nil(), counters); + } else if (fieldId == 3) { + pointer += _read_call_info(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_return_value(pointer, bs, r); + } else if (fieldId == 5) { + pointer += _read_unpacked_repeated_call_results(pointer, bs, nil(), counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.signers.length == 0); + r.signers = new Account.Data[](counters[2]); + } + if (counters[5] > 0) { + require(r.call_results.length == 0); + r.call_results = new GoogleProtobufAny.Data[](counters[5]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_signers(pointer, bs, r, counters); + } else if (fieldId == 5) { + pointer += _read_unpacked_repeated_call_results(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_cross_chain_channel(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.cross_chain_channel = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_signers(uint256 p, bytes memory bs, Data memory r, uint256[6] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (Account.Data memory x, uint256 sz) = _decode_Account(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.signers[r.signers.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_call_info(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.call_info = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_return_value(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (ReturnValue.Data memory x, uint256 sz) = _decode_ReturnValue(p, bs); + r.return_value = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_call_results( + uint256 p, + bytes memory bs, + Data memory r, + uint256[6] memory counters + ) internal pure returns (uint256) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.call_results[r.call_results.length - counters[5]] = x; + counters[5] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_Account(uint256 p, bytes memory bs) internal pure returns (Account.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Account.Data memory r,) = Account._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ReturnValue(uint256 p, bytes memory bs) internal pure returns (ReturnValue.Data memory, uint256) { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ReturnValue.Data memory r,) = ReturnValue._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.cross_chain_channel, pointer, bs); + + if (r.signers.length != 0) { + for (i = 0; i < r.signers.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += Account._encode_nested(r.signers[i], pointer, bs); + } + } + if (r.call_info.length != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.call_info, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ReturnValue._encode_nested(r.return_value, pointer, bs); + + if (r.call_results.length != 0) { + for (i = 0; i < r.call_results.length; i++) { + pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.call_results[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.cross_chain_channel)); + for (i = 0; i < r.signers.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Account._estimate(r.signers[i])); + } + e += 1 + ProtoBufRuntime._sz_lendelim(r.call_info.length); + e += 1 + ProtoBufRuntime._sz_lendelim(ReturnValue._estimate(r.return_value)); + for (i = 0; i < r.call_results.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.call_results[i])); + } + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.signers.length != 0) { + return false; + } + + if (r.call_info.length != 0) { + return false; + } + + if (r.call_results.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + GoogleProtobufAny.store(input.cross_chain_channel, output.cross_chain_channel); + + for (uint256 i2 = 0; i2 < input.signers.length; i2++) { + output.signers.push(input.signers[i2]); + } + + output.call_info = input.call_info; + ReturnValue.store(input.return_value, output.return_value); + + for (uint256 i5 = 0; i5 < input.call_results.length; i5++) { + output.call_results.push(input.call_results[i5]); + } + } + + //array helpers for Signers + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addSigners(Data memory self, Account.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + Account.Data[] memory tmp = new Account.Data[](self.signers.length + 1); + for (uint256 i = 0; i < self.signers.length; i++) { + tmp[i] = self.signers[i]; + } + tmp[self.signers.length] = value; + self.signers = tmp; + } + + //array helpers for CallResults + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addCallResults(Data memory self, GoogleProtobufAny.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + GoogleProtobufAny.Data[] memory tmp = new GoogleProtobufAny.Data[](self.call_results.length + 1); + for (uint256 i = 0; i < self.call_results.length; i++) { + tmp[i] = self.call_results[i]; + } + tmp[self.call_results.length] = value; + self.call_results = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ResolvedContractTransaction + +library ReturnValue { + //struct definition + struct Data { + bytes value; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_value(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_value(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.value = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (r.value.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.value.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.value = input.value; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ReturnValue + +library ConstantValueCallResult { + //struct definition + struct Data { + GoogleProtobufAny.Data cross_chain_channel; + bytes k; + bytes v; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_cross_chain_channel(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_k(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_v(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_cross_chain_channel(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.cross_chain_channel = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_k(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.k = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_v(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.v = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.cross_chain_channel, pointer, bs); + + if (r.k.length != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.k, pointer, bs); + } + if (r.v.length != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.v, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.cross_chain_channel)); + e += 1 + ProtoBufRuntime._sz_lendelim(r.k.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.v.length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.k.length != 0) { + return false; + } + + if (r.v.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + GoogleProtobufAny.store(input.cross_chain_channel, output.cross_chain_channel); + output.k = input.k; + output.v = input.v; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ConstantValueCallResult + +library ContractCallResult { + //struct definition + struct Data { + bytes data; + GoogleProtobufAny.Data[] events; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_data(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_events(pointer, bs, nil(), counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.events.length == 0); + r.events = new GoogleProtobufAny.Data[](counters[2]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_events(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_data(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.data = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_events(uint256 p, bytes memory bs, Data memory r, uint256[3] memory counters) + internal + pure + returns (uint256) + { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.events[r.events.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.data.length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.data, pointer, bs); + } + if (r.events.length != 0) { + for (i = 0; i < r.events.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.events[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.data.length); + for (i = 0; i < r.events.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.events[i])); + } + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.data.length != 0) { + return false; + } + + if (r.events.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.data = input.data; + + for (uint256 i2 = 0; i2 < input.events.length; i2++) { + output.events.push(input.events[i2]); + } + } + + //array helpers for Events + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addEvents(Data memory self, GoogleProtobufAny.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + GoogleProtobufAny.Data[] memory tmp = new GoogleProtobufAny.Data[](self.events.length + 1); + for (uint256 i = 0; i < self.events.length; i++) { + tmp[i] = self.events[i]; + } + tmp[self.events.length] = value; + self.events = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ContractCallResult diff --git a/src/proto/cross/core/xcc/XCC.sol b/src/proto/cross/core/xcc/XCC.sol new file mode 100644 index 0000000..16f3ada --- /dev/null +++ b/src/proto/cross/core/xcc/XCC.sol @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; + +library ChannelInfo { + //struct definition + struct Data { + string port; + string channel; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_port(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_channel(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_port(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.port = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_channel(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.channel = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.port).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.port, pointer, bs); + } + if (bytes(r.channel).length != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.channel, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.port).length); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.channel).length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.port).length != 0) { + return false; + } + + if (bytes(r.channel).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.port = input.port; + output.channel = input.channel; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ChannelInfo diff --git a/src/proto/ibc/core/client/v1/client.sol b/src/proto/ibc/core/client/v1/client.sol new file mode 100644 index 0000000..208fabd --- /dev/null +++ b/src/proto/ibc/core/client/v1/client.sol @@ -0,0 +1,2408 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/ProtoBufRuntime.sol"; +import "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; + +library IbcCoreClientV1IdentifiedClientState { + //struct definition + struct Data { + string client_id; + GoogleProtobufAny.Data client_state; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_client_state(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.client_state = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.client_state, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.client_state)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.client_id).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.client_id = input.client_id; + GoogleProtobufAny.store(input.client_state, output.client_state); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1IdentifiedClientState + +library IbcCoreClientV1ConsensusStateWithHeight { + //struct definition + struct Data { + IbcCoreClientV1Height.Data height; + GoogleProtobufAny.Data consensus_state; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_height(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_consensus_state(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_height(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (IbcCoreClientV1Height.Data memory x, uint256 sz) = _decode_IbcCoreClientV1Height(p, bs); + r.height = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_consensus_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.consensus_state = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_IbcCoreClientV1Height(uint256 p, bytes memory bs) + internal + pure + returns (IbcCoreClientV1Height.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (IbcCoreClientV1Height.Data memory r,) = IbcCoreClientV1Height._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += IbcCoreClientV1Height._encode_nested(r.height, pointer, bs); + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.consensus_state, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(IbcCoreClientV1Height._estimate(r.height)); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.consensus_state)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + IbcCoreClientV1Height.store(input.height, output.height); + GoogleProtobufAny.store(input.consensus_state, output.consensus_state); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1ConsensusStateWithHeight + +library IbcCoreClientV1ClientConsensusStates { + //struct definition + struct Data { + string client_id; + IbcCoreClientV1ConsensusStateWithHeight.Data[] consensus_states; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_unpacked_repeated_consensus_states(pointer, bs, nil(), counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + pointer = offset; + if (counters[2] > 0) { + require(r.consensus_states.length == 0); + r.consensus_states = new IbcCoreClientV1ConsensusStateWithHeight.Data[](counters[2]); + } + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 2) { + pointer += _read_unpacked_repeated_consensus_states(pointer, bs, r, counters); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_unpacked_repeated_consensus_states( + uint256 p, + bytes memory bs, + Data memory r, + uint256[3] memory counters + ) internal pure returns (uint256) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (IbcCoreClientV1ConsensusStateWithHeight.Data memory x, uint256 sz) = + _decode_IbcCoreClientV1ConsensusStateWithHeight(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.consensus_states[r.consensus_states.length - counters[2]] = x; + counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_IbcCoreClientV1ConsensusStateWithHeight(uint256 p, bytes memory bs) + internal + pure + returns (IbcCoreClientV1ConsensusStateWithHeight.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (IbcCoreClientV1ConsensusStateWithHeight.Data memory r,) = + IbcCoreClientV1ConsensusStateWithHeight._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + if (r.consensus_states.length != 0) { + for (i = 0; i < r.consensus_states.length; i++) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += IbcCoreClientV1ConsensusStateWithHeight._encode_nested(r.consensus_states[i], pointer, bs); + } + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + for (i = 0; i < r.consensus_states.length; i++) { + e += 1 + + ProtoBufRuntime._sz_lendelim(IbcCoreClientV1ConsensusStateWithHeight._estimate(r.consensus_states[i])); + } + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.client_id).length != 0) { + return false; + } + + if (r.consensus_states.length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.client_id = input.client_id; + + for (uint256 i2 = 0; i2 < input.consensus_states.length; i2++) { + output.consensus_states.push(input.consensus_states[i2]); + } + } + + //array helpers for ConsensusStates + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addConsensusStates(Data memory self, IbcCoreClientV1ConsensusStateWithHeight.Data memory value) + internal + pure + { + /** + * First resize the array. Then add the new element to the end. + */ + IbcCoreClientV1ConsensusStateWithHeight.Data[] memory tmp = + new IbcCoreClientV1ConsensusStateWithHeight.Data[](self.consensus_states.length + 1); + for (uint256 i = 0; i < self.consensus_states.length; i++) { + tmp[i] = self.consensus_states[i]; + } + tmp[self.consensus_states.length] = value; + self.consensus_states = tmp; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1ClientConsensusStates + +library IbcCoreClientV1ClientUpdateProposal { + //struct definition + struct Data { + string title; + string description; + string client_id; + GoogleProtobufAny.Data header; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_title(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_description(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_header(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_title(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.title = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_description(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.description = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_header(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.header = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.title).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.title, pointer, bs); + } + if (bytes(r.description).length != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.description, pointer, bs); + } + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.header, pointer, bs); + + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.title).length); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.description).length); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.header)); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.title).length != 0) { + return false; + } + + if (bytes(r.description).length != 0) { + return false; + } + + if (bytes(r.client_id).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.title = input.title; + output.description = input.description; + output.client_id = input.client_id; + GoogleProtobufAny.store(input.header, output.header); + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1ClientUpdateProposal + +library IbcCoreClientV1MsgCreateClient { + //struct definition + struct Data { + string client_id; + GoogleProtobufAny.Data client_state; + GoogleProtobufAny.Data consensus_state; + string signer; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_client_state(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_consensus_state(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_signer(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.client_state = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_consensus_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.consensus_state = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_signer(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.signer = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.client_state, pointer, bs); + + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.consensus_state, pointer, bs); + + if (bytes(r.signer).length != 0) { + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.signer, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.client_state)); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.consensus_state)); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.signer).length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.client_id).length != 0) { + return false; + } + + if (bytes(r.signer).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.client_id = input.client_id; + GoogleProtobufAny.store(input.client_state, output.client_state); + GoogleProtobufAny.store(input.consensus_state, output.consensus_state); + output.signer = input.signer; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1MsgCreateClient + +library IbcCoreClientV1MsgUpdateClient { + //struct definition + struct Data { + string client_id; + GoogleProtobufAny.Data header; + string signer; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_header(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_signer(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_header(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.header = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_signer(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.signer = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.header, pointer, bs); + + if (bytes(r.signer).length != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.signer, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.header)); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.signer).length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.client_id).length != 0) { + return false; + } + + if (bytes(r.signer).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.client_id = input.client_id; + GoogleProtobufAny.store(input.header, output.header); + output.signer = input.signer; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1MsgUpdateClient + +library IbcCoreClientV1MsgUpgradeClient { + //struct definition + struct Data { + string client_id; + GoogleProtobufAny.Data client_state; + IbcCoreClientV1Height.Data upgrade_height; + bytes proof_upgrade; + string signer; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_client_state(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_upgrade_height(pointer, bs, r); + } else if (fieldId == 4) { + pointer += _read_proof_upgrade(pointer, bs, r); + } else if (fieldId == 5) { + pointer += _read_signer(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_state(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.client_state = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_upgrade_height(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (IbcCoreClientV1Height.Data memory x, uint256 sz) = _decode_IbcCoreClientV1Height(p, bs); + r.upgrade_height = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_proof_upgrade(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.proof_upgrade = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_signer(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.signer = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_IbcCoreClientV1Height(uint256 p, bytes memory bs) + internal + pure + returns (IbcCoreClientV1Height.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (IbcCoreClientV1Height.Data memory r,) = IbcCoreClientV1Height._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.client_state, pointer, bs); + + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += IbcCoreClientV1Height._encode_nested(r.upgrade_height, pointer, bs); + + if (r.proof_upgrade.length != 0) { + pointer += ProtoBufRuntime._encode_key(4, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_bytes(r.proof_upgrade, pointer, bs); + } + if (bytes(r.signer).length != 0) { + pointer += ProtoBufRuntime._encode_key(5, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.signer, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.client_state)); + e += 1 + ProtoBufRuntime._sz_lendelim(IbcCoreClientV1Height._estimate(r.upgrade_height)); + e += 1 + ProtoBufRuntime._sz_lendelim(r.proof_upgrade.length); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.signer).length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.client_id).length != 0) { + return false; + } + + if (r.proof_upgrade.length != 0) { + return false; + } + + if (bytes(r.signer).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.client_id = input.client_id; + GoogleProtobufAny.store(input.client_state, output.client_state); + IbcCoreClientV1Height.store(input.upgrade_height, output.upgrade_height); + output.proof_upgrade = input.proof_upgrade; + output.signer = input.signer; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1MsgUpgradeClient + +library IbcCoreClientV1MsgSubmitMisbehaviour { + //struct definition + struct Data { + string client_id; + GoogleProtobufAny.Data misbehaviour; + string signer; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_client_id(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_misbehaviour(pointer, bs, r); + } else if (fieldId == 3) { + pointer += _read_signer(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_client_id(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.client_id = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_misbehaviour(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (GoogleProtobufAny.Data memory x, uint256 sz) = _decode_GoogleProtobufAny(p, bs); + r.misbehaviour = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_signer(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + r.signer = x; + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_GoogleProtobufAny(uint256 p, bytes memory bs) + internal + pure + returns (GoogleProtobufAny.Data memory, uint256) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (GoogleProtobufAny.Data memory r,) = GoogleProtobufAny._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (bytes(r.client_id).length != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.client_id, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += GoogleProtobufAny._encode_nested(r.misbehaviour, pointer, bs); + + if (bytes(r.signer).length != 0) { + pointer += ProtoBufRuntime._encode_key(3, ProtoBufRuntime.WireType.LengthDelim, pointer, bs); + pointer += ProtoBufRuntime._encode_string(r.signer, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.client_id).length); + e += 1 + ProtoBufRuntime._sz_lendelim(GoogleProtobufAny._estimate(r.misbehaviour)); + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.signer).length); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (bytes(r.client_id).length != 0) { + return false; + } + + if (bytes(r.signer).length != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.client_id = input.client_id; + GoogleProtobufAny.store(input.misbehaviour, output.misbehaviour); + output.signer = input.signer; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1MsgSubmitMisbehaviour + +library IbcCoreClientV1Height { + //struct definition + struct Data { + uint64 revision_number; + uint64 revision_height; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x,) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x,) = _decode(32, bs, bs.length); + store(x, self); + } + + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint256) { + Data memory r; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_revision_number(pointer, bs, r); + } else if (fieldId == 2) { + pointer += _read_revision_height(pointer, bs, r); + } else { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_revision_number(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint64 x, uint256 sz) = ProtoBufRuntime._decode_uint64(p, bs); + r.revision_number = x; + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_revision_height(uint256 p, bytes memory bs, Data memory r) internal pure returns (uint256) { + (uint64 x, uint256 sz) = ProtoBufRuntime._decode_uint64(p, bs); + r.revision_height = x; + return sz; + } + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + uint256 offset = p; + uint256 pointer = p; + + if (r.revision_number != 0) { + pointer += ProtoBufRuntime._encode_key(1, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint64(r.revision_number, pointer, bs); + } + if (r.revision_height != 0) { + pointer += ProtoBufRuntime._encode_key(2, ProtoBufRuntime.WireType.Varint, pointer, bs); + pointer += ProtoBufRuntime._encode_uint64(r.revision_height, pointer, bs); + } + return pointer - offset; + } + + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint256) { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate(Data memory r) internal pure returns (uint256) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_uint64(r.revision_number); + e += 1 + ProtoBufRuntime._sz_uint64(r.revision_height); + return e; + } + // empty checker + + function _empty(Data memory r) internal pure returns (bool) { + if (r.revision_number != 0) { + return false; + } + + if (r.revision_height != 0) { + return false; + } + + return true; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.revision_number = input.revision_number; + output.revision_height = input.revision_height; + } + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library IbcCoreClientV1Height diff --git a/test/Authenticator.t.sol b/test/Authenticator.t.sol new file mode 100644 index 0000000..081c353 --- /dev/null +++ b/test/Authenticator.t.sol @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, var-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/Authenticator.sol"; +import {TxManagerBase} from "../src/core/TxManagerBase.sol"; +import {TxAuthManagerBase} from "../src/core/TxAuthManagerBase.sol"; + +import {MsgInitiateTx} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {ICrossError} from "../src/core/ICrossError.sol"; +import {ICrossEvent} from "../src/core/ICrossEvent.sol"; +import { + Account as AuthAccount, + AuthType, + TxAuthState, + MsgSignTx, + MsgSignTxResponse, + MsgExtSignTx, + QueryTxAuthStateRequest, + QueryTxAuthStateResponse, + GoogleProtobufAny +} from "../src/proto/cross/core/auth/Auth.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; +import {CoordinatorState} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; + +contract MockTxManager is TxManagerBase { + bytes32 public lastRunTxID; + uint256 public runTxCount; + + function _createTx( + bytes32, + /*txID*/ + MsgInitiateTx.Data calldata /*src*/ + ) + internal + virtual + override + {} + + function _runTxIfCompleted(bytes32, MsgInitiateTx.Data calldata) internal virtual override {} + + function _isTxRecorded( + bytes32 /*txID*/ + ) + internal + view + virtual + override + returns (bool) + { + return false; + } + + function _getCoordinatorState( + bytes32 /*txID*/ + ) + internal + view + virtual + override + returns (CoordinatorState.Data memory) + { + CoordinatorState.Data memory dummy; + return dummy; + } +} + +contract MockTxAuthManager is TxAuthManagerBase { + mapping(bytes32 => bool) public completed; + bool private _signReturns = false; + bool private _verifyShouldRevert = false; + TxAuthState.Data private _mockAuthState; + + error MockVerifyError(); + + function _initAuthState( + bytes32, + /*txID*/ + Account.Data[] memory /*signers*/ + ) + internal + virtual + override + {} + + function _isCompletedAuth( + bytes32 /*txID*/ + ) + internal + view + virtual + override + returns (bool) + { + return false; + } + + function _sign( + bytes32 txID, + Account.Data[] memory /*signers*/ + ) + internal + virtual + override + returns (bool) + { + if (_signReturns) { + completed[txID] = true; + } + return _signReturns; + } + + function _getAuthState(bytes32) internal view virtual override returns (TxAuthState.Data memory) { + return _mockAuthState; + } + + function _verifySignatures( + bytes32, + /*txIDHash*/ + AuthAccount.Data[] calldata + /*signers*/ + ) + internal + virtual + override + { + if (_verifyShouldRevert) { + revert MockVerifyError(); + } + } + + function setSignReturns(bool returnsValue) public { + _signReturns = returnsValue; + } + + function setVerifyShouldRevert(bool shouldRevert) public { + _verifyShouldRevert = shouldRevert; + } + + function setMockAuthState(TxAuthState.Data memory state) public { + _mockAuthState = state; + } +} + +contract AuthenticatorHarness is Authenticator, MockTxAuthManager, MockTxManager { + function exposed_decodeTxID(bytes calldata rawID) public pure returns (bytes32) { + return _decodeTxID(rawID); + } + + function exposed_buildLocalAccounts(bytes[] calldata signerIDs) public pure returns (AuthAccount.Data[] memory) { + return _buildLocalAccounts(signerIDs); + } +} + +contract AuthenticatorTest is Test, ICrossError, ICrossEvent { + AuthenticatorHarness private harness; + MsgSignTx.Data private baseMsg; + bytes32 private txID; + MsgExtSignTx.Data private extMsg; + bytes32 private extTxID; + + bytes private signerABytes = bytes("signerA"); + bytes private signerBBytes = bytes("signerB"); + + function setUp() public { + harness = new AuthenticatorHarness(); + + bytes memory expectedSignerId = abi.encodePacked(address(this)); + + bytes[] memory signers = new bytes[](1); + signers[0] = expectedSignerId; + + bytes32 rawTxID = bytes32("test-tx-id"); + txID = rawTxID; + + baseMsg = MsgSignTx.Data({ + txID: abi.encodePacked(rawTxID), + signers: signers, + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0 + }); + + bytes32 rawExtTxID = bytes32("ext-test-tx-id"); + extTxID = rawExtTxID; + + AuthAccount.Data[] memory extSigners = new AuthAccount.Data[](1); + extSigners[0] = AuthAccount.Data({ + id: signerABytes, + auth_type: AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, + option: GoogleProtobufAny.Data({type_url: "/verifier/test", value: ""}) + }) + }); + + extMsg = MsgExtSignTx.Data({txID: abi.encodePacked(rawExtTxID), signers: extSigners}); + } + + function test_signTx_SucceedsAsPending() public { + harness.setSignReturns(false); + + MsgSignTxResponse.Data memory resp = harness.signTx(baseMsg); + assertFalse(resp.tx_auth_completed, "response should indicate not completed"); + assertEq(resp.log, "", "log should be empty"); + assertFalse(harness.completed(txID), "Mock: auth should not be completed"); + assertEq(harness.runTxCount(), 0, "Mock: runTxIfCompleted should not be called"); + } + + function test_signTx_SucceedsAsCompletedAndEmitsEvent() public { + harness.setSignReturns(true); + + vm.expectEmit(address(harness)); + emit TxAuthCompleted(txID); + + vm.expectEmit(address(harness)); + emit TxSigned(address(this), txID, AuthType.AuthMode.AUTH_MODE_LOCAL); + + MsgSignTxResponse.Data memory resp = harness.signTx(baseMsg); + + assertTrue(resp.tx_auth_completed, "response should indicate completed"); + assertEq(resp.log, "", "log should be empty"); + assertTrue(harness.completed(txID), "Mock: auth should be completed"); + } + + function test_signTx_RevertsIf_TxIDLengthInvalid() public { + baseMsg.txID = bytes("short-id"); + + vm.expectRevert(InvalidTxIDLength.selector); + harness.signTx(baseMsg); + } + + function test_signTx_RevertsIf_SignersLengthZero() public { + baseMsg.signers = new bytes[](0); + + vm.expectRevert(ICrossError.InvalidSignersLength.selector); + harness.signTx(baseMsg); + } + + function test_signTx_RevertsIf_SignersLengthMultiple() public { + bytes[] memory signers = new bytes[](2); + signers[0] = signerABytes; + signers[1] = signerBBytes; + baseMsg.signers = signers; + + vm.expectRevert(ICrossError.InvalidSignersLength.selector); + harness.signTx(baseMsg); + } + + function test_signTx_RevertsIf_SignerNotEqualSender() public { + bytes[] memory signers = new bytes[](1); + signers[0] = abi.encodePacked(address(0x12345)); + baseMsg.signers = signers; + + vm.expectRevert(ICrossError.SignerMustEqualSender.selector); + harness.signTx(baseMsg); + } + + function test_extSignTx_SucceedsAsPending() public { + harness.setSignReturns(false); + vm.expectEmit(address(harness)); + emit TxSigned(address(this), extTxID, AuthType.AuthMode.AUTH_MODE_EXTENSION); + + MsgExtSignTxResponse.Data memory resp = harness.extSignTx(extMsg); + + assertTrue(resp.x, "response.x should be true"); + assertFalse(harness.completed(extTxID), "Mock: auth should not be completed"); + assertEq(harness.runTxCount(), 0, "Mock: runTxIfCompleted should not be called"); + } + + function test_extSignTx_SucceedsAsCompletedAndEmitsEvent() public { + harness.setSignReturns(true); + + vm.expectEmit(address(harness)); + emit TxAuthCompleted(extTxID); + + vm.expectEmit(address(harness)); + emit TxSigned(address(this), extTxID, AuthType.AuthMode.AUTH_MODE_EXTENSION); + + MsgExtSignTxResponse.Data memory resp = harness.extSignTx(extMsg); + + assertTrue(resp.x, "response.x should be true"); + assertTrue(harness.completed(extTxID), "Mock: auth should be completed"); + } + + function test_extSignTx_RevertsIf_TxIDLengthInvalid() public { + extMsg.txID = new bytes(33); + + vm.expectRevert(InvalidTxIDLength.selector); + harness.extSignTx(extMsg); + } + + function test_extSignTx_RevertsIf_VerificationFails() public { + harness.setVerifyShouldRevert(true); + + vm.expectRevert(MockTxAuthManager.MockVerifyError.selector); + harness.extSignTx(extMsg); + } + + function test_decodeTxID_SucceedsWith32Bytes() public { + bytes32 expected = keccak256("valid-id"); + bytes memory input = abi.encodePacked(expected); + + bytes32 actual = harness.exposed_decodeTxID(input); + assertEq(actual, expected, "Should return correct bytes32 for 32-byte input"); + } + + function test_decodeTxID_RevertsIf_LengthIsZero() public { + bytes memory input = ""; + + vm.expectRevert(InvalidTxIDLength.selector); + harness.exposed_decodeTxID(input); + } + + function test_decodeTxID_RevertsIf_LengthIsShort() public { + bytes memory input = new bytes(31); + + vm.expectRevert(InvalidTxIDLength.selector); + harness.exposed_decodeTxID(input); + } + + function test_decodeTxID_RevertsIf_LengthIsLong() public { + bytes memory input = new bytes(33); + + vm.expectRevert(InvalidTxIDLength.selector); + harness.exposed_decodeTxID(input); + } + + function test_txAuthState_ReturnsState() public { + bytes32 queryTxID = bytes32("query-tx"); + + AuthAccount.Data[] memory remainingSigners = new AuthAccount.Data[](1); + remainingSigners[0] = AuthAccount.Data({ + id: signerBBytes, + auth_type: AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: GoogleProtobufAny.Data({type_url: "", value: ""}) + }) + }); + TxAuthState.Data memory expectedState = TxAuthState.Data({remaining_signers: remainingSigners}); + + harness.setMockAuthState(expectedState); + + QueryTxAuthStateRequest.Data memory req; + req.txID = abi.encodePacked(queryTxID); + + QueryTxAuthStateResponse.Data memory resp = harness.txAuthState(req); + + assertEq(resp.tx_auth_state.remaining_signers.length, 1, "Remaining signers length mismatch"); + assertEq(resp.tx_auth_state.remaining_signers[0].id, signerBBytes, "Remaining signer ID mismatch"); + assertEq( + uint256(resp.tx_auth_state.remaining_signers[0].auth_type.mode), + uint256(AuthType.AuthMode.AUTH_MODE_LOCAL), + "Remaining signer auth mode mismatch" + ); + } + + function test_txAuthState_RevertsIf_TxIDLengthInvalid() public { + QueryTxAuthStateRequest.Data memory req; + req.txID = ""; + + vm.expectRevert(InvalidTxIDLength.selector); + harness.txAuthState(req); + } + + function test_buildLocalAccounts_BuildsCorrectly() public { + bytes[] memory signerIDs = new bytes[](2); + signerIDs[0] = signerABytes; + signerIDs[1] = signerBBytes; + + AuthAccount.Data[] memory accounts = harness.exposed_buildLocalAccounts(signerIDs); + + assertEq(accounts.length, 2, "Array length mismatch"); + + assertEq(accounts[0].id, signerABytes, "Signer A ID mismatch"); + assertEq( + uint256(accounts[0].auth_type.mode), + uint256(AuthType.AuthMode.AUTH_MODE_LOCAL), + "Signer A auth type mismatch" + ); + assertEq(accounts[0].auth_type.option.type_url, "", "Signer A option type_url should be empty"); + assertEq(accounts[0].auth_type.option.value, "", "Signer A option value should be empty"); + + assertEq(accounts[1].id, signerBBytes, "Signer B ID mismatch"); + assertEq( + uint256(accounts[1].auth_type.mode), + uint256(AuthType.AuthMode.AUTH_MODE_LOCAL), + "Signer B auth type mismatch" + ); + assertEq(accounts[1].auth_type.option.type_url, "", "Signer B option type_url should be empty"); + assertEq(accounts[1].auth_type.option.value, "", "Signer B option value should be empty"); + } +} diff --git a/test/ContractModuleBase.t.sol b/test/ContractModuleBase.t.sol new file mode 100644 index 0000000..1409ed4 --- /dev/null +++ b/test/ContractModuleBase.t.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/ContractModuleBase.sol"; +import {CrossContext} from "../src/core/IContractModule.sol"; +import {Account as AuthAccount} from "../src/proto/cross/core/auth/Auth.sol"; + +contract ContractModuleBaseHarness is ContractModuleBase { + bool public authorizeResult = true; + bool public authorizeCalled = false; + + // Implement abstract functions + function onCommit(CrossContext calldata) external override {} + function onAbort(CrossContext calldata) external override {} + + function setAuthorizeResult(bool result) external { + authorizeResult = result; + } + + function _authorize(CrossContext calldata, bytes calldata) internal virtual override { + authorizeCalled = true; + if (!authorizeResult) { + revert("Unauthorized"); + } + } + + function _onContractCommitImmediately(CrossContext calldata, bytes calldata) + internal + virtual + override + returns (bytes memory) + { + return hex"AA"; + } + + function _onContractPrepare(CrossContext calldata, bytes calldata) + internal + virtual + override + returns (bytes memory) + { + return hex"BB"; + } +} + +contract ContractModuleBaseTest is Test { + ContractModuleBaseHarness private harness; + CrossContext private context; + + function setUp() public { + harness = new ContractModuleBaseHarness(); + + // Setup dummy context + AuthAccount.Data[] memory signers; + context = CrossContext({txID: hex"00", txIndex: 0, signers: signers}); + } + + function test_onContractCommitImmediately_CallsAuthorizeAndImplementation() public { + harness.setAuthorizeResult(true); + + bytes memory ret = harness.onContractCommitImmediately(context, ""); + + assertTrue(harness.authorizeCalled(), "_authorize should be called"); + assertEq(ret, hex"AA", "Should return implementation result"); + } + + function test_onContractCommitImmediately_RevertsWhen_AuthorizeFails() public { + harness.setAuthorizeResult(false); + + vm.expectRevert("Unauthorized"); + harness.onContractCommitImmediately(context, ""); + } + + function test_onContractPrepare_CallsAuthorizeAndImplementation() public { + harness.setAuthorizeResult(true); + + bytes memory ret = harness.onContractPrepare(context, ""); + + assertTrue(harness.authorizeCalled(), "_authorize should be called"); + assertEq(ret, hex"BB", "Should return implementation result"); + } + + function test_onContractPrepare_RevertsWhen_AuthorizeFails() public { + harness.setAuthorizeResult(false); + + vm.expectRevert("Unauthorized"); + harness.onContractPrepare(context, ""); + } +} diff --git a/test/Coordinator.t.sol b/test/Coordinator.t.sol new file mode 100644 index 0000000..5e3b20c --- /dev/null +++ b/test/Coordinator.t.sol @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/Coordinator.sol"; +import "../src/core/TxManagerBase.sol"; +import "../src/core/TxAuthManagerBase.sol"; +import {ICrossError} from "../src/core/ICrossError.sol"; +import {ICrossEvent} from "../src/core/ICrossEvent.sol"; +import { + QueryCoordinatorStateRequest, + QueryCoordinatorStateResponse, + CoordinatorState +} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {MsgInitiateTx, ContractTransaction} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {Tx} from "../src/proto/cross/core/tx/Tx.sol"; +import {Account as AuthAccount} from "../src/proto/cross/core/auth/Auth.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; + +contract MockTxManager is TxManagerBase, ICrossError { + mapping(bytes32 => CoordinatorState.Data) internal mockStates; + mapping(bytes32 => bool) internal recordedTxs; + mapping(bytes32 => bool) internal stateExists; + uint256 public runCount; + + function setCoordinatorState(bytes32 txID, CoordinatorState.Data memory data) public { + mockStates[txID] = data; + stateExists[txID] = true; + } + + function setTxRecorded(bytes32 txID, bool recorded) public { + recordedTxs[txID] = recorded; + } + + function _getCoordinatorState(bytes32 txID) internal view virtual override returns (CoordinatorState.Data memory) { + if (!stateExists[txID]) { + revert CoordinatorStateNotFound(txID); + } + return mockStates[txID]; + } + + function _createTx(bytes32, MsgInitiateTx.Data calldata) internal virtual override {} + + function _runTxIfCompleted(bytes32, MsgInitiateTx.Data calldata) internal virtual override { + ++runCount; + } + + function _isTxRecorded(bytes32 txID) internal view virtual override returns (bool) { + return recordedTxs[txID]; + } +} + +contract MockTxAuthManager is TxAuthManagerBase { + mapping(bytes32 => bool) internal completedAuths; + + function setCompletedAuth(bytes32 txID, bool completed) public { + completedAuths[txID] = completed; + } + + function _initAuthState(bytes32, Account.Data[] memory) internal virtual override {} + + function _sign(bytes32, Account.Data[] memory) internal virtual override returns (bool) { + return true; + } + + function _getAuthState(bytes32) internal view virtual override returns (TxAuthState.Data memory) { + TxAuthState.Data memory state; + return state; + } + function _verifySignatures(bytes32, Account.Data[] calldata) internal virtual override {} + + function _isCompletedAuth(bytes32 txID) internal view virtual override returns (bool) { + return completedAuths[txID]; + } +} + +contract CoordinatorHarness is Coordinator, MockTxManager, MockTxAuthManager {} + +contract CoordinatorTest is Test, ICrossError, ICrossEvent { + CoordinatorHarness private harness; + MsgInitiateTx.Data private dummyMsg; + bytes32 private txID; + + function setUp() public { + harness = new CoordinatorHarness(); + + dummyMsg = MsgInitiateTx.Data({ + chain_id: "test-chain", + nonce: 1, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0, + signers: new AuthAccount.Data[](0), + contract_transactions: new ContractTransaction.Data[](0) + }); + + txID = sha256(MsgInitiateTx.encode(dummyMsg)); + } + + function test_executeTx_Succeeds() public { + harness.setTxRecorded(txID, true); + harness.setCompletedAuth(txID, true); + + vm.expectEmit(address(harness)); + emit TxExecuted(abi.encodePacked(txID), address(this)); + + harness.executeTx(dummyMsg); + + assertEq(harness.runCount(), 1, "runTxIfCompleted should be called"); + } + + function test_executeTx_RevertIf_TimeoutHeight() public { + dummyMsg.timeout_height.revision_height = uint64(block.number); + + vm.expectRevert( + abi.encodeWithSelector(MessageTimeoutHeight.selector, block.number, dummyMsg.timeout_height.revision_height) + ); + harness.executeTx(dummyMsg); + } + + function test_executeTx_RevertIf_TimeoutTimestamp() public { + dummyMsg.timeout_timestamp = uint64(block.timestamp); + + vm.expectRevert( + abi.encodeWithSelector(MessageTimeoutTimestamp.selector, block.timestamp, dummyMsg.timeout_timestamp) + ); + harness.executeTx(dummyMsg); + } + + function test_executeTx_RevertIf_TxNotRecorded() public { + harness.setTxRecorded(txID, false); + harness.setCompletedAuth(txID, true); + + vm.expectRevert(abi.encodeWithSelector(TxIDNotFound.selector, txID)); + harness.executeTx(dummyMsg); + } + + function test_executeTx_RevertIf_AuthNotCompleted() public { + harness.setTxRecorded(txID, true); + harness.setCompletedAuth(txID, false); + + vm.expectRevert(abi.encodeWithSelector(AuthNotCompleted.selector, txID)); + harness.executeTx(dummyMsg); + } + + function test_coordinatorState_ReturnsCorrectState() public { + CoordinatorState.Data memory expectedState; + expectedState.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE; + expectedState.phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE; + expectedState.decision = CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_COMMIT; + + harness.setCoordinatorState(txID, expectedState); + + QueryCoordinatorStateRequest.Data memory req; + req.tx_id = abi.encodePacked(txID); + + QueryCoordinatorStateResponse.Data memory resp = harness.coordinatorState(req); + + assertEq( + uint256(resp.coodinator_state.commit_protocol), + uint256(expectedState.commit_protocol), + "Commit protocol mismatch" + ); + assertEq(uint256(resp.coodinator_state.phase), uint256(expectedState.phase), "Phase mismatch"); + assertEq(uint256(resp.coodinator_state.decision), uint256(expectedState.decision), "Decision mismatch"); + } + + function test_coordinatorState_RevertIf_TxIDLengthInvalid_TooShort() public { + QueryCoordinatorStateRequest.Data memory req; + req.tx_id = hex"1234"; + + vm.expectRevert(InvalidTxIDLength.selector); + harness.coordinatorState(req); + } + + function test_coordinatorState_RevertIf_TxIDLengthInvalid_TooLong() public { + QueryCoordinatorStateRequest.Data memory req; + req.tx_id = new bytes(33); + + vm.expectRevert(InvalidTxIDLength.selector); + harness.coordinatorState(req); + } + + function test_coordinatorState_RevertIf_TxIDLengthInvalid_Empty() public { + QueryCoordinatorStateRequest.Data memory req; + req.tx_id = ""; + + vm.expectRevert(InvalidTxIDLength.selector); + harness.coordinatorState(req); + } + + function test_coordinatorState_RevertIf_StateNotFound() public { + QueryCoordinatorStateRequest.Data memory req; + req.tx_id = abi.encodePacked(txID); + + vm.expectRevert(abi.encodeWithSelector(CoordinatorStateNotFound.selector, txID)); + harness.coordinatorState(req); + } +} diff --git a/test/CrossModule.t.sol b/test/CrossModule.t.sol index a8d8095..7265bdb 100644 --- a/test/CrossModule.t.sol +++ b/test/CrossModule.t.sol @@ -22,10 +22,17 @@ contract TestableCrossModule is CrossModule { uint256 public timeoutCount; bytes public lastAckArg; - constructor(IIBCHandler h) CrossModule(h) {} - - function handlePacket( - Packet memory /*packet*/ + constructor( + IIBCHandler h, + address txAuthManager_, + address txManager_, + IContractModule module_, + string[] memory authTypeUrls_, + IAuthExtensionVerifier[] memory authVerifiers_ + ) CrossModule(h, txAuthManager_, txManager_, module_, authTypeUrls_, authVerifiers_) {} + + function _handlePacket( + Packet calldata /*packet*/ ) internal virtual @@ -36,10 +43,10 @@ contract TestableCrossModule is CrossModule { return bytes("ack-ok"); } - function handleAcknowledgement( - Packet memory, + function _handleAcknowledgement( + Packet calldata, /*packet*/ - bytes memory acknowledgement + bytes calldata acknowledgement ) internal virtual @@ -49,7 +56,7 @@ contract TestableCrossModule is CrossModule { lastAckArg = acknowledgement; } - function handleTimeout( + function _handleTimeout( Packet calldata /*packet*/ ) internal @@ -67,7 +74,14 @@ contract CrossModuleTest is Test { function setUp() public { handler = new DummyHandler(); - mod = new TestableCrossModule(IIBCHandler(address(handler))); + mod = new TestableCrossModule( + IIBCHandler(address(handler)), + address(0), + address(0), + IContractModule(address(0)), + new string[](0), + new IAuthExtensionVerifier[](0) + ); } function test_constructor_GrantsIbcRoleToHandler() public { diff --git a/test/CrossSimpleModule.t.sol b/test/CrossSimpleModule.t.sol index 41ed24c..4d4e138 100644 --- a/test/CrossSimpleModule.t.sol +++ b/test/CrossSimpleModule.t.sol @@ -7,6 +7,7 @@ import "forge-std/src/Test.sol"; import "../src/core/CrossSimpleModule.sol"; import "../src/core/IContractModule.sol"; import "../src/core/TxAtomicSimple.sol"; +import "../src/core/ICrossError.sol"; import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; @@ -14,7 +15,7 @@ contract DummyHandler {} contract DummyModule is IContractModule { // do nothing implementation - function onContractCall( + function onContractCommitImmediately( CrossContext calldata, /*context*/ bytes calldata /*callInfo*/ @@ -25,25 +26,50 @@ contract DummyModule is IContractModule { { return ""; } -} -contract CrossSimpleModuleHarness is CrossSimpleModule { - constructor(IIBCHandler h, IContractModule m, bool debugMode) CrossSimpleModule(h, m, debugMode) {} + function onAbort( + CrossContext calldata /*context*/ + ) + external + override + {} + function onCommit( + CrossContext calldata /*context*/ + ) + external + override + {} - function exposed_getModule(Packet calldata p) external returns (IContractModule) { - return getModule(p); + function onContractPrepare( + CrossContext calldata, + /*context*/ + bytes calldata /*callInfo*/ + ) + external + override + returns (bytes memory) + { + return ""; } +} - function exposed_registerModule(IContractModule m) external { - registerModule(m); - } +contract CrossSimpleModuleHarness is CrossSimpleModule { + constructor( + IIBCHandler h, + address txAuthManager_, + address txManager_, + IContractModule module_, + string[] memory authTypeUrls_, + IAuthExtensionVerifier[] memory authVerifiers_, + bool debugMode + ) CrossSimpleModule(h, txAuthManager_, txManager_, module_, authTypeUrls_, authVerifiers_, debugMode) {} function workaround_hasIbcRole(address a) external view returns (bool) { return hasRole(IBC_ROLE, a); } } -contract CrossSimpleModuleTest is Test { +contract CrossSimpleModuleTest is Test, ICrossError { DummyHandler private handler; DummyModule private moduleImpl; Packet internal _emptyPacket; @@ -53,46 +79,31 @@ contract CrossSimpleModuleTest is Test { moduleImpl = new DummyModule(); } - function test_constructor_RegistersModuleAndGetReturnsSameAddress() public { - CrossSimpleModuleHarness harness = - new CrossSimpleModuleHarness(IIBCHandler(address(handler)), IContractModule(address(moduleImpl)), false); - - IContractModule got = harness.exposed_getModule(_emptyPacket); - assertEq(address(got), address(moduleImpl), "must register"); - } - function test_constructor_GrantsIbcRoleWhenDebugModeTrue() public { - CrossSimpleModuleHarness harness = - new CrossSimpleModuleHarness(IIBCHandler(address(handler)), IContractModule(address(moduleImpl)), true); + CrossSimpleModuleHarness harness = new CrossSimpleModuleHarness( + IIBCHandler(address(handler)), + address(0), + address(0), + moduleImpl, + new string[](0), + new IAuthExtensionVerifier[](0), + true + ); assertTrue(harness.workaround_hasIbcRole(address(this)), "role on debug"); } function test_constructor_DoesNotGrantIbcRoleWhenDebugModeFalse() public { - CrossSimpleModuleHarness harness = - new CrossSimpleModuleHarness(IIBCHandler(address(handler)), IContractModule(address(moduleImpl)), false); + CrossSimpleModuleHarness harness = new CrossSimpleModuleHarness( + IIBCHandler(address(handler)), + address(0), + address(0), + moduleImpl, + new string[](0), + new IAuthExtensionVerifier[](0), + false + ); assertFalse(harness.workaround_hasIbcRole(address(this)), "no role on debug"); } - - function test_register_RevertOn_SecondInitialization() public { - CrossSimpleModuleHarness harness = - new CrossSimpleModuleHarness(IIBCHandler(address(handler)), IContractModule(address(moduleImpl)), false); - - vm.expectRevert(SimpleContractRegistry.ModuleAlreadyInitialized.selector); - harness.exposed_registerModule(IContractModule(address(moduleImpl))); - } - - function test_getPacketAcknowledgementCall_DifferentStatusesProduceDifferentBytes() public { - CrossSimpleModuleHarness harness = - new CrossSimpleModuleHarness(IIBCHandler(address(handler)), IContractModule(address(moduleImpl)), false); - - bytes memory a = harness.getPacketAcknowledgementCall(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); - bytes memory b = - harness.getPacketAcknowledgementCall(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED); - - assertGt(a.length, 0, "ack nonempty"); - assertGt(b.length, 0, "ack nonempty"); - assertFalse(keccak256(a) == keccak256(b), "diff enc"); - } } diff --git a/test/CrossStore.t.sol b/test/CrossStore.t.sol new file mode 100644 index 0000000..b48c285 --- /dev/null +++ b/test/CrossStore.t.sol @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/CrossStore.sol"; +import {MsgInitiateTxResponse} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {CoordinatorState} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; + +contract CrossStoreHarness is CrossStore { + //--- Auth Storage Accessors --- + function writeAuth(bytes32 txID, bool val) public { + AuthStorage storage s = _getAuthStorage(); + s.authInitialized[txID] = val; + } + + function readAuth(bytes32 txID) public view returns (bool) { + AuthStorage storage s = _getAuthStorage(); + return s.authInitialized[txID]; + } + + //--- Tx Storage Accessors --- + function writeTx(bytes32 txID, MsgInitiateTxResponse.InitiateTxStatus status) public { + TxStorage storage s = _getTxStorage(); + s.txStatus[txID] = status; + } + + function readTx(bytes32 txID) public view returns (MsgInitiateTxResponse.InitiateTxStatus) { + TxStorage storage s = _getTxStorage(); + return s.txStatus[txID]; + } + + //--- Coord Storage Accessors --- + function writeCoord(bytes32 txID, CoordinatorState.CoordinatorPhase phase) public { + CoordStorage storage s = _getCoordStorage(); + s.compactStates[txID].phase = phase; + } + + function readCoord(bytes32 txID) public view returns (CoordinatorState.CoordinatorPhase) { + CoordStorage storage s = _getCoordStorage(); + return s.compactStates[txID].phase; + } + + //--- Coord Storage Logic Exposers --- + function exposed_loadCoordinatorState(bytes32 txID) public view returns (CoordinatorState.Data memory) { + return _loadCoordinatorState(txID); + } + + function exposed_saveCoordinatorState(bytes32 txID, CoordinatorState.Data memory data) public { + _saveCoordinatorState(txID, data); + } + + function exposed_maskToUint32Array(uint8 mask) public pure returns (uint32[] memory) { + return _maskToUint32Array(mask); + } + + function exposed_uint32ArrayToMask(uint32[] memory arr) public pure returns (uint8 mask) { + return _uint32ArrayToMask(arr); + } +} + +contract CrossStoreTest is Test { + CrossStoreHarness private harness; + + bytes32 private keyAuth = keccak256("key.auth"); + bytes32 private keyTx = keccak256("key.tx"); + bytes32 private keyCoord = keccak256("key.coord"); + + function setUp() public { + harness = new CrossStoreHarness(); + + harness.writeAuth(keyAuth, true); + harness.writeTx(keyTx, MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED); + harness.writeCoord(keyCoord, CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + } + + function test_getAuthStorage_IsIsolated() public view { + assertTrue(harness.readAuth(keyAuth), "Auth write failed"); + assertFalse(harness.readAuth(keyTx), "Auth storage collision with Tx"); + assertFalse(harness.readAuth(keyCoord), "Auth storage collision with Coord"); + } + + function test_getTxStorage_IsIsolated() public view { + assertEq( + uint256(harness.readTx(keyTx)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED), + "Tx write failed" + ); + assertEq( + uint256(harness.readTx(keyAuth)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN), + "Tx storage collision with Auth" + ); + assertEq( + uint256(harness.readTx(keyCoord)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN), + "Tx storage collision with Coord" + ); + } + + function test_getCoordStorage_IsIsolated() public view { + assertEq( + uint256(harness.readCoord(keyCoord)), + uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE), + "Coord write failed" + ); + assertEq( + uint256(harness.readCoord(keyAuth)), + uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_UNKNOWN), + "Coord storage collision with Auth" + ); + assertEq( + uint256(harness.readCoord(keyTx)), + uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_UNKNOWN), + "Coord storage collision with Tx" + ); + } + + function test_maskToUint32Array_Empty() public view { + uint32[] memory res = harness.exposed_maskToUint32Array(0x00); + assertEq(res.length, 0, "Should return empty array for mask 0x00"); + } + + function test_maskToUint32Array_CoordinatorOnly() public view { + uint32[] memory res = harness.exposed_maskToUint32Array(0x01); + assertEq(res.length, 1, "Array length mismatch"); + assertEq(res[0], 0, "Index 0 should be TX_INDEX_COORDINATOR (0)"); + } + + function test_maskToUint32Array_ParticipantOnly() public view { + uint32[] memory res = harness.exposed_maskToUint32Array(0x02); + assertEq(res.length, 1, "Array length mismatch"); + assertEq(res[0], 1, "Index 0 should be TX_INDEX_PARTICIPANT (1)"); + } + + function test_maskToUint32Array_Both() public view { + uint32[] memory res = harness.exposed_maskToUint32Array(0x03); + assertEq(res.length, 2, "Array length mismatch"); + assertEq(res[0], 0, "First element mismatch"); + assertEq(res[1], 1, "Second element mismatch"); + } + + function test_uint32ArrayToMask_Empty() public view { + uint32[] memory arr = new uint32[](0); + assertEq(harness.exposed_uint32ArrayToMask(arr), 0x00, "Empty array should yield mask 0x00"); + } + + function test_uint32ArrayToMask_CoordinatorOnly() public view { + uint32[] memory arr = new uint32[](1); + arr[0] = 0; + assertEq(harness.exposed_uint32ArrayToMask(arr), 0x01, "Mask mismatch for Coordinator"); + } + + function test_uint32ArrayToMask_ParticipantOnly() public view { + uint32[] memory arr = new uint32[](1); + arr[0] = 1; + assertEq(harness.exposed_uint32ArrayToMask(arr), 0x02, "Mask mismatch for Participant"); + } + + function test_uint32ArrayToMask_Both() public view { + uint32[] memory arr = new uint32[](2); + arr[0] = 0; + arr[1] = 1; + assertEq(harness.exposed_uint32ArrayToMask(arr), 0x03, "Mask mismatch for Both"); + } + + function test_uint32ArrayToMask_BothReversedOrder() public view { + uint32[] memory arr = new uint32[](2); + arr[0] = 1; + arr[1] = 0; + assertEq(harness.exposed_uint32ArrayToMask(arr), 0x03, "Mask should be 0x03 regardless of order"); + } + + function test_SaveAndLoad_CoordinatorState() public { + bytes32 txId = keccak256("tx.save.load"); + + CoordinatorState.Data memory original; + original.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE; + original.phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE; + original.decision = CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN; + + original.channels = new ChannelInfo.Data[](2); + original.channels[0] = ChannelInfo.Data("", ""); + original.channels[1] = ChannelInfo.Data("port-1", "channel-1"); + + original.confirmed_txs = new uint32[](1); + original.confirmed_txs[0] = 0; + + harness.exposed_saveCoordinatorState(txId, original); + + CoordinatorState.Data memory loaded = harness.exposed_loadCoordinatorState(txId); + assertEq(uint256(loaded.commit_protocol), uint256(original.commit_protocol)); + assertEq(loaded.channels[1].port, "port-1"); + assertEq(loaded.confirmed_txs.length, 1); + assertEq(loaded.confirmed_txs[0], 0); + } + + function test_SaveLoad_DataLossChannel0() public { + bytes32 txId = keccak256("tx.dataloss.ch0"); + CoordinatorState.Data memory data = _createEmptyData(); + + data.channels = new ChannelInfo.Data[](2); + data.channels[0] = ChannelInfo.Data("should-be-lost", "lost-channel"); + data.channels[1] = ChannelInfo.Data("port-1", "channel-1"); + + harness.exposed_saveCoordinatorState(txId, data); + + CoordinatorState.Data memory loaded = harness.exposed_loadCoordinatorState(txId); + + assertEq(loaded.channels[0].port, "", "Channel0 port should be lost"); + assertEq(loaded.channels[0].channel, "", "Channel0 channel should be lost"); + assertEq(loaded.channels[1].port, "port-1"); + } + + function test_SaveLoad_DataLossExtraChannels() public { + bytes32 txId = keccak256("tx.dataloss.extra_ch"); + CoordinatorState.Data memory data = _createEmptyData(); + + data.channels = new ChannelInfo.Data[](3); + data.channels[0] = ChannelInfo.Data("", ""); + data.channels[1] = ChannelInfo.Data("port-1", "channel-1"); + data.channels[2] = ChannelInfo.Data("port-2", "channel-2"); + + harness.exposed_saveCoordinatorState(txId, data); + + CoordinatorState.Data memory loaded = harness.exposed_loadCoordinatorState(txId); + + assertEq(loaded.channels.length, 2, "Extra channels should be truncated to 2"); + } + + function test_SaveLoad_DataLossUnsupportedIndices() public { + bytes32 txId = keccak256("tx.dataloss.indices"); + CoordinatorState.Data memory data = _createEmptyData(); + + data.confirmed_txs = new uint32[](3); + data.confirmed_txs[0] = 0; + data.confirmed_txs[1] = 1; + data.confirmed_txs[2] = 2; + + harness.exposed_saveCoordinatorState(txId, data); + + CoordinatorState.Data memory loaded = harness.exposed_loadCoordinatorState(txId); + + assertEq(loaded.confirmed_txs.length, 2, "Index 2 should be lost"); + assertEq(loaded.confirmed_txs[0], 0); + assertEq(loaded.confirmed_txs[1], 1); + } + + function _createEmptyData() internal pure returns (CoordinatorState.Data memory) { + return CoordinatorState.Data({ + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + phase: CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE, + decision: CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN, + channels: new ChannelInfo.Data[](0), + confirmed_txs: new uint32[](0), + acks: new uint32[](0) + }); + } +} diff --git a/test/DelegatedLogicHandler.t.sol b/test/DelegatedLogicHandler.t.sol new file mode 100644 index 0000000..07f0fcc --- /dev/null +++ b/test/DelegatedLogicHandler.t.sol @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings, no-inline-assembly +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/DelegatedLogicHandler.sol"; +import {ITxAuthManager} from "../src/core/ITxAuthManager.sol"; +import {ITxManager} from "../src/core/ITxManager.sol"; +import {ICrossError} from "../src/core/ICrossError.sol"; +import { + MsgInitiateTx, + MsgInitiateTxResponse, + ContractTransaction +} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {Account as AuthAccount, AuthType, TxAuthState} from "../src/proto/cross/core/auth/Auth.sol"; +import {Tx} from "../src/proto/cross/core/tx/Tx.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; +import {CoordinatorState} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {Height} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/Client.sol"; + +contract MockStore { + struct AuthStorage { + mapping(bytes32 => uint256) callCounts; + mapping(bytes32 => bool) initialized; + } + + struct TxStorage { + mapping(bytes32 => MsgInitiateTxResponse.InitiateTxStatus) status; + mapping(bytes32 => uint64) nonce; + mapping(bytes32 => CoordinatorState.Data) coordStates; + uint256 handlePacketCount; + uint256 handleAckCount; + uint256 handleTimeoutCount; + } + + AuthStorage internal authStorage; + TxStorage internal txStorage; +} + +contract MockTxAuthManager is ITxAuthManager, MockStore { + function initialize(string[] calldata, IAuthExtensionVerifier[] calldata) external override { + // No-op + } + + function initAuthState(bytes32 txID, AuthAccount.Data[] calldata) external override { + ++authStorage.callCounts[txID]; + authStorage.initialized[txID] = true; + } + + function sign(bytes32 txID, AuthAccount.Data[] calldata) external override returns (bool) { + ++authStorage.callCounts[txID]; + return true; + } + + function isCompletedAuth( + bytes32 /*txID*/ + ) + external + pure + override + returns (bool) + { + return true; + } + + function getAuthState( + bytes32 /*txID*/ + ) + external + pure + override + returns (TxAuthState.Data memory) + { + AuthAccount.Data[] memory remaining = new AuthAccount.Data[](1); + GoogleProtobufAny.Data memory emptyAny = GoogleProtobufAny.Data({type_url: "", value: ""}); + AuthType.Data memory localAuthType = AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: emptyAny}); + remaining[0] = AuthAccount.Data({id: bytes("signerA"), auth_type: localAuthType}); + + return TxAuthState.Data({remaining_signers: remaining}); + } + + function verifySignatures(bytes32 txIDHash, AuthAccount.Data[] calldata) external override { + ++authStorage.callCounts[txIDHash]; + } +} + +contract MockTxManager is ITxManager, MockStore { + function initialize(IIBCHandler, IContractModule) external override { + // No-op + } + + function createTx(bytes32 txID, MsgInitiateTx.Data calldata src) external override { + txStorage.status[txID] = MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING; + txStorage.nonce[txID] = src.nonce; + } + + function runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata) external override { + txStorage.status[txID] = MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED; + txStorage.nonce[txID] = 1; + } + + function isTxRecorded( + bytes32 /*txID*/ + ) + external + pure + override + returns (bool) + { + return true; + } + + function getCoordinatorState(bytes32 txID) external view override returns (CoordinatorState.Data memory) { + return txStorage.coordStates[txID]; + } + + function handlePacket(Packet calldata) external override returns (bytes memory) { + ++txStorage.handlePacketCount; + return hex"1234"; + } + + function handleAcknowledgement(Packet calldata, bytes calldata) external override { + ++txStorage.handleAckCount; + } + + function handleTimeout(Packet calldata) external override { + ++txStorage.handleTimeoutCount; + } +} + +contract MockSuccessContract { + function getBool() public pure returns (bool) { + return true; + } + + function getUint() public pure returns (uint256) { + return 12345; + } +} + +contract MockRevertContract { + function revertNow(string memory reason) public pure { + revert(reason); + } +} + +contract MockRevertEmpty { + function revertNow() public pure { + assembly { + revert(0, 0) + } + } +} + +contract DelegatedLogicHandlerHarness is DelegatedLogicHandler, MockStore { + uint256 public internalState; + + constructor(address txAuthManager_, address txManager_) DelegatedLogicHandler(txAuthManager_, txManager_) {} + + function exposed_initAuthState(bytes32 txID, AuthAccount.Data[] memory signers) public { + _initAuthState(txID, signers); + } + + function exposed_sign(bytes32 txID, AuthAccount.Data[] memory signers) public returns (bool) { + return _sign(txID, signers); + } + + function exposed_isCompletedAuth(bytes32 txID) public returns (bool) { + return _isCompletedAuth(txID); + } + + function exposed_getAuthState(bytes32 txID) public returns (TxAuthState.Data memory) { + return _getAuthState(txID); + } + + function exposed_verifySignatures(bytes32 txIDHash, AuthAccount.Data[] calldata signers) public { + _verifySignatures(txIDHash, signers); + } + + function exposed_createTx(bytes32 txID, MsgInitiateTx.Data calldata src) public { + _createTx(txID, src); + } + + function exposed_runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) public { + _runTxIfCompleted(txID, msg_); + } + + function exposed_isTxRecorded(bytes32 txID) public returns (bool) { + return _isTxRecorded(txID); + } + + function exposed_getCoordinatorState(bytes32 txID) public returns (CoordinatorState.Data memory) { + return _getCoordinatorState(txID); + } + + function exposed_handlePacket(Packet calldata packet) public returns (bytes memory) { + return _handlePacket(packet); + } + + function exposed_handleAcknowledgement(Packet calldata packet, bytes calldata acknowledgement) public { + _handleAcknowledgement(packet, acknowledgement); + } + + function exposed_handleTimeout(Packet calldata packet) public { + _handleTimeout(packet); + } + + function exposed_delegateWithData(address impl, bytes memory data) public returns (bytes memory) { + return _delegateWithData(impl, data); + } + + function exposed_staticCallSelf(bytes memory callData) public view returns (bytes memory) { + return _staticCallSelf(callData); + } + + function echo(uint256 val) external pure returns (uint256) { + return val; + } + + function triggerRevert(string calldata reason) external pure { + revert(reason); + } + + function revertEmpty() external pure { + assembly { + revert(0, 0) + } + } + + function stateChange(uint256 val) external { + internalState = val; + } + + function setCoordState(bytes32 txID, CoordinatorState.Data calldata data) external { + txStorage.coordStates[txID] = data; + } + + function readAuth_callCount(bytes32 txID) public view returns (uint256) { + return authStorage.callCounts[txID]; + } + + function readAuth_initialized(bytes32 txID) public view returns (bool) { + return authStorage.initialized[txID]; + } + + function readTx_status(bytes32 txID) public view returns (MsgInitiateTxResponse.InitiateTxStatus) { + return txStorage.status[txID]; + } + + function readTx_nonce(bytes32 txID) public view returns (uint64) { + return txStorage.nonce[txID]; + } + + function readTx_handlePacketCount() public view returns (uint256) { + return txStorage.handlePacketCount; + } + + function readTx_handleAckCount() public view returns (uint256) { + return txStorage.handleAckCount; + } + + function readTx_handleTimeoutCount() public view returns (uint256) { + return txStorage.handleTimeoutCount; + } +} + +contract DelegatedLogicHandlerTest is Test, ICrossError { + MockTxAuthManager private mockAuth; + MockTxManager private mockTx; + DelegatedLogicHandlerHarness private harness; + + bytes32 private txID = keccak256("test_tx_id"); + AuthAccount.Data[] private signers; + MsgInitiateTx.Data private txMsg; + Packet private dummyPacket; + + function setUp() public { + mockAuth = new MockTxAuthManager(); + mockTx = new MockTxManager(); + harness = new DelegatedLogicHandlerHarness(address(mockAuth), address(mockTx)); + + GoogleProtobufAny.Data memory emptyAny = GoogleProtobufAny.Data({type_url: "", value: ""}); + AuthType.Data memory localAuthType = AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: emptyAny}); + signers = new AuthAccount.Data[](1); + signers[0] = AuthAccount.Data({id: bytes("signerA"), auth_type: localAuthType}); + + txMsg = MsgInitiateTx.Data({ + chain_id: "test-chain", + nonce: 123, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0, + signers: signers, + contract_transactions: new ContractTransaction.Data[](0) + }); + + dummyPacket = Packet({ + sequence: 1, + sourcePort: "src", + sourceChannel: "channel-0", + destinationPort: "dst", + destinationChannel: "channel-1", + data: hex"00", + timeoutHeight: Height.Data(0, 0), + timeoutTimestamp: 0 + }); + } + + function test_initAuthState_DelegatesToAuthManager() public { + harness.exposed_initAuthState(txID, signers); + + assertEq(harness.readAuth_callCount(txID), 1, "AuthManager.initAuthState should be called once"); + assertTrue(harness.readAuth_initialized(txID), "authInitialized mismatch"); + } + + function test_sign_DelegatesToAuthManager() public { + bool result = harness.exposed_sign(txID, signers); + + assertTrue(result, "Return value mismatch"); + assertEq(harness.readAuth_callCount(txID), 1, "AuthManager.sign should be called once"); + } + + function test_isCompletedAuth_DelegatesToAuthManager() public { + vm.expectCall(address(mockAuth), abi.encodeWithSelector(ITxAuthManager.isCompletedAuth.selector, txID)); + + bool result = harness.exposed_isCompletedAuth(txID); + + assertTrue(result, "Return value mismatch"); + } + + function test_getAuthState_DelegatesToAuthManager() public { + vm.expectCall(address(mockAuth), abi.encodeWithSelector(ITxAuthManager.getAuthState.selector, txID)); + + TxAuthState.Data memory result = harness.exposed_getAuthState(txID); + + assertEq(result.remaining_signers.length, 1, "Return value (signers length) mismatch"); + assertEq(result.remaining_signers[0].id, signers[0].id, "Return value (signer id) mismatch"); + } + + function test_verifySignatures_DelegatesToAuthManager() public { + harness.exposed_verifySignatures(txID, signers); + + assertEq(harness.readAuth_callCount(txID), 1, "AuthManager.verifySignatures should be called once"); + } + + function test_createTx_DelegatesToTxManager() public { + harness.exposed_createTx(txID, txMsg); + + assertEq( + uint256(harness.readTx_status(txID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING), + "Status should be PENDING" + ); + assertEq(harness.readTx_nonce(txID), txMsg.nonce, "nonce mismatch"); + } + + function test_runTxIfCompleted_DelegatesToTxManager() public { + bytes32 expectedTxID = sha256(MsgInitiateTx.encode(txMsg)); + + harness.exposed_runTxIfCompleted(expectedTxID, txMsg); + + assertEq( + uint256(harness.readTx_status(expectedTxID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED), + "Status should be VERIFIED" + ); + + assertEq(harness.readTx_nonce(expectedTxID), 1, "runTxIfCompleted call count mismatch"); + } + + function test_isTxRecorded_DelegatesToTxManager() public { + vm.expectCall(address(mockTx), abi.encodeWithSelector(ITxManager.isTxRecorded.selector, txID)); + + bool result = harness.exposed_isTxRecorded(txID); + + assertTrue(result, "Return value mismatch"); + } + + function test_handlePacket_DelegatesToTxManager() public { + bytes memory ack = harness.exposed_handlePacket(dummyPacket); + + assertEq(harness.readTx_handlePacketCount(), 1, "handlePacket call count mismatch"); + assertEq(ack, hex"1234", "Acknowledgement return value mismatch"); + } + + function test_handleAcknowledgement_DelegatesToTxManager() public { + harness.exposed_handleAcknowledgement(dummyPacket, hex"beef"); + + assertEq(harness.readTx_handleAckCount(), 1, "handleAcknowledgement call count mismatch"); + } + + function test_handleTimeout_DelegatesToTxManager() public { + harness.exposed_handleTimeout(dummyPacket); + + assertEq(harness.readTx_handleTimeoutCount(), 1, "handleTimeout call count mismatch"); + } + + function test_getCoordinatorState_DelegatesToTxManager() public { + CoordinatorState.Data memory expected; + expected.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE; + expected.phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE; + harness.setCoordState(txID, expected); + + vm.expectCall(address(mockTx), abi.encodeWithSelector(ITxManager.getCoordinatorState.selector, txID)); + CoordinatorState.Data memory actual = harness.exposed_getCoordinatorState(txID); + + assertEq(uint256(actual.commit_protocol), uint256(expected.commit_protocol), "Commit protocol mismatch"); + assertEq(uint256(actual.phase), uint256(expected.phase), "Phase mismatch"); + } + + function test_delegateWithData_SucceedsAndReturnsData() public { + MockSuccessContract successMock = new MockSuccessContract(); + + bytes memory dataBool = abi.encodeWithSelector(successMock.getBool.selector); + bytes memory retBool = harness.exposed_delegateWithData(address(successMock), dataBool); + + assertEq(retBool, abi.encode(true), "Return data for bool mismatch"); + + bytes memory dataUint = abi.encodeWithSelector(successMock.getUint.selector); + bytes memory retUint = harness.exposed_delegateWithData(address(successMock), dataUint); + + assertEq(retUint, abi.encode(12345), "Return data for uint mismatch"); + } + + function test_delegateWithData_RevertWhen_TargetReverts() public { + MockRevertContract reverter = new MockRevertContract(); + string memory reason = "TestRevert"; + bytes memory data = abi.encodeWithSelector(reverter.revertNow.selector, reason); + + vm.expectRevert(bytes(reason)); + harness.exposed_delegateWithData(address(reverter), data); + } + + function test_delegateWithData_RevertIf_DelegateCallFails() public { + MockRevertEmpty reverter = new MockRevertEmpty(); + bytes memory data = abi.encodeWithSelector(reverter.revertNow.selector); + + vm.expectRevert(abi.encodeWithSelector(DelegateCallFailed.selector, address(reverter))); + harness.exposed_delegateWithData(address(reverter), data); + } + + function test_staticCallSelf_Succeeds() public { + uint256 input = 999; + bytes memory callData = abi.encodeWithSelector(harness.echo.selector, input); + + bytes memory ret = harness.exposed_staticCallSelf(callData); + uint256 decoded = abi.decode(ret, (uint256)); + + assertEq(decoded, input, "staticCallSelf return value mismatch"); + } + + function test_staticCallSelf_RevertsIf_TargetReverts() public { + string memory reason = "StaticCallError"; + bytes memory callData = abi.encodeWithSelector(harness.triggerRevert.selector, reason); + + vm.expectRevert(bytes(reason)); + harness.exposed_staticCallSelf(callData); + } + + function test_staticCallSelf_RevertsIf_CallFailsEmpty() public { + bytes memory callData = abi.encodeWithSelector(harness.revertEmpty.selector); + + vm.expectRevert(StaticCallFailed.selector); + harness.exposed_staticCallSelf(callData); + } + + function test_staticCallSelf_RevertsIf_OnStateChange() public { + uint256 newVal = 777; + bytes memory callData = abi.encodeWithSelector(harness.stateChange.selector, newVal); + + vm.expectRevert(StaticCallFailed.selector); + harness.exposed_staticCallSelf(callData); + } + + function test_isCompletedAuth_RevertIf_CalledExternally() public { + // Test: __isCompletedAuth + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, address(this))); + harness.__isCompletedAuth(txID); + } + + function test_getAuthState_RevertIf_CalledExternally() public { + // Test: __getAuthState + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, address(this))); + harness.__getAuthState(txID); + } + + function test_isTxRecorded_RevertIf_CalledExternally() public { + // Test: __isTxRecorded + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, address(this))); + harness.__isTxRecorded(txID); + } + + function test_getCoordinatorState_RevertIf_CalledExternally() public { + // Test: __getCoordinatorState + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, address(this))); + harness.__getCoordinatorState(txID); + } +} diff --git a/test/ERC20TransferModule.t.sol b/test/ERC20TransferModule.t.sol new file mode 100644 index 0000000..148dc74 --- /dev/null +++ b/test/ERC20TransferModule.t.sol @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import {ERC20TransferModule} from "../src/example/ERC20TransferModule.sol"; +import {CrossContext} from "../src/core/IContractModule.sol"; +import {Account as AuthAccount, AuthType} from "../src/proto/cross/core/auth/Auth.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +contract MockERC20 is ERC20 { + constructor() ERC20("Mock Token", "MCK") {} + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } +} + +contract ERC20TransferModuleHarness is ERC20TransferModule { + function _authorize(CrossContext calldata, bytes calldata) internal pure override { + // allow all for testing + } +} + +contract ERC20TransferModuleTest is Test { + ERC20TransferModuleHarness private harness; + MockERC20 private token; + + address private sender; + address private receiver; + bytes32 private constant TX_ID_RAW = keccak256("test_tx"); + bytes private txID; + + uint256 private constant AMOUNT = 100 ether; + uint256 private constant INITIAL_BALANCE = 1000 ether; + + function setUp() public { + sender = makeAddr("sender"); + receiver = makeAddr("receiver"); + txID = abi.encode(TX_ID_RAW); + + token = new MockERC20(); + + harness = new ERC20TransferModuleHarness(); + harness.initialize(address(this), address(token)); + + token.mint(sender, INITIAL_BALANCE); + } + + // --- Helper Functions --- + + function _createContext(address _signer) internal view returns (CrossContext memory) { + AuthAccount.Data[] memory signers; + + if (_signer != address(0)) { + signers = new AuthAccount.Data[](1); + signers[0] = AuthAccount.Data({ + id: abi.encodePacked(_signer), + auth_type: AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: GoogleProtobufAny.Data({type_url: "", value: ""}) + }) + }); + } else { + signers = new AuthAccount.Data[](0); + } + + return CrossContext({txID: txID, txIndex: 0, signers: signers}); + } + + function _createCallInfo(address _from, address _to, uint256 _amount) internal pure returns (bytes memory) { + return abi.encode(_from, _to, _amount); + } + + // --- Initialization Tests --- + + function test_initialize_Success() public { + ERC20TransferModuleHarness newHarness = new ERC20TransferModuleHarness(); + address crossModule = makeAddr("newCrossModule"); + address newToken = makeAddr("newToken"); + + vm.expectEmit(address(newHarness)); + emit ERC20TransferModule.ERC20TransferModuleInitialized(crossModule, newToken); + + newHarness.initialize(crossModule, newToken); + + assertEq(newHarness.crossModule(), crossModule); + assertEq(address(newHarness.token()), newToken); + } + + function test_initialize_RevertWhen_InvalidAddress() public { + ERC20TransferModuleHarness newHarness = new ERC20TransferModuleHarness(); + address validAddress = makeAddr("valid"); + + // 1. CrossModule is zero + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleInvalidAddress.selector); + newHarness.initialize(address(0), validAddress); + + // 2. Token is zero + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleInvalidAddress.selector); + newHarness.initialize(validAddress, address(0)); + } + + function test_initialize_RevertWhen_AlreadyInitialized() public { + vm.expectRevert(Initializable.InvalidInitialization.selector); + harness.initialize(address(this), address(token)); + } + + function test_initialize_RevertWhen_CallerIsNotOwner() public { + ERC20TransferModuleHarness newHarness = new ERC20TransferModuleHarness(); + + address attacker = makeAddr("attacker"); + address crossModule = makeAddr("crossModule"); + address newToken = makeAddr("newToken"); + + vm.prank(attacker); + + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, attacker)); + + newHarness.initialize(crossModule, newToken); + } + + // --- Decode Tests --- + + function test_decodeCallInfo_Success() public view { + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + (address from, address to, uint256 amount) = harness.decodeCallInfo(callInfo); + + assertEq(from, sender); + assertEq(to, receiver); + assertEq(amount, AMOUNT); + } + + function test_decodeCallInfo_RevertWhen_InvalidLength() public { + bytes memory invalidCallInfo = abi.encode(receiver, AMOUNT); + + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleInvalidCallInfo.selector); + harness.decodeCallInfo(invalidCallInfo); + } + + // --- Immediate Commit Tests --- + + function test_onContractCommitImmediately_Success() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + uint256 senderPreBalance = token.balanceOf(sender); + uint256 receiverPreBalance = token.balanceOf(receiver); + + vm.prank(sender); + token.approve(address(harness), AMOUNT); + + harness.onContractCommitImmediately(context, callInfo); + + assertEq(token.balanceOf(sender), senderPreBalance - AMOUNT); + assertEq(token.balanceOf(receiver), receiverPreBalance + AMOUNT); + assertEq(token.balanceOf(address(harness)), 0); + } + + function test_onContractCommitImmediately_RevertWhen_InsufficientAllowance() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientAllowance.selector, + address(harness), // spender (Module) + 0, // allowance + AMOUNT // needed + ) + ); + harness.onContractCommitImmediately(context, callInfo); + } + + function test_onContractCommitImmediately_RevertWhen_CalledByOthers() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + address unauthorized = makeAddr("unauthorized"); + vm.prank(unauthorized); + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleUnauthorized.selector); + harness.onContractCommitImmediately(context, callInfo); + } + + function test_onContractCommitImmediately_RevertWhen_NotInitialized() public { + ERC20TransferModuleHarness uninitHarness = new ERC20TransferModuleHarness(); + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleNotInitialized.selector); + uninitHarness.onContractCommitImmediately(context, callInfo); + } + + // --- Prepare Tests --- + + function test_onContractPrepare_Success() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.prank(sender); + token.approve(address(harness), AMOUNT); + + harness.onContractPrepare(context, callInfo); + + assertEq(token.balanceOf(sender), INITIAL_BALANCE - AMOUNT, "Sender balance should decrease"); + assertEq(token.balanceOf(address(harness)), AMOUNT, "Module should hold locked tokens"); + + (address pendingFrom, address pendingTo, uint256 pendingAmount) = harness.pendingTxs(TX_ID_RAW); + assertEq(pendingFrom, sender); + assertEq(pendingTo, receiver); + assertEq(pendingAmount, AMOUNT); + } + + function test_onContractPrepare_RevertWhen_InsufficientAllowance() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientAllowance.selector, + address(harness), // spender + 0, // allowance + AMOUNT // needed + ) + ); + harness.onContractPrepare(context, callInfo); + } + + function test_onContractPrepare_RevertWhen_InsufficientBalance() public { + uint256 tooMuchAmount = INITIAL_BALANCE + 1; + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, tooMuchAmount); + + vm.prank(sender); + token.approve(address(harness), tooMuchAmount); + + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientBalance.selector, + sender, // sender + INITIAL_BALANCE, // balance + tooMuchAmount // needed + ) + ); + harness.onContractPrepare(context, callInfo); + } + + function test_onContractPrepare_RevertWhen_TxAlreadyPending() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.prank(sender); + token.approve(address(harness), AMOUNT * 2); + + harness.onContractPrepare(context, callInfo); + + (address pendingFrom,,) = harness.pendingTxs(TX_ID_RAW); + assertEq(pendingFrom, sender); + + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleTxAlreadyPending.selector); + harness.onContractPrepare(context, callInfo); + } + + function test_onContractPrepare_RevertWhen_CalledByOthers() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + address unauthorized = makeAddr("unauthorized"); + vm.prank(unauthorized); + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleUnauthorized.selector); + harness.onContractPrepare(context, callInfo); + } + + function test_onContractPrepare_RevertWhen_NotInitialized() public { + ERC20TransferModuleHarness uninitHarness = new ERC20TransferModuleHarness(); + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleNotInitialized.selector); + uninitHarness.onContractPrepare(context, callInfo); + } + + // --- Commit Tests --- + + function test_onCommit_Success() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.prank(sender); + token.approve(address(harness), AMOUNT); + + harness.onContractPrepare(context, callInfo); + + assertEq(token.balanceOf(address(harness)), AMOUNT); + + harness.onCommit(context); + + assertEq(token.balanceOf(address(harness)), 0, "Module should release tokens"); + assertEq(token.balanceOf(receiver), AMOUNT, "Receiver should receive tokens"); + assertEq(token.balanceOf(sender), INITIAL_BALANCE - AMOUNT, "Sender balance should decrease"); + + (address pendingFrom,,) = harness.pendingTxs(TX_ID_RAW); + assertEq(pendingFrom, address(0), "Pending state should be deleted"); + } + + function test_onCommit_DoNothingWhenTxNotFound() public { + bytes32 unknownTxIdRaw = keccak256("unknown"); + CrossContext memory context = + CrossContext({txID: abi.encode(unknownTxIdRaw), txIndex: 0, signers: new AuthAccount.Data[](0)}); + + harness.onCommit(context); + + assertEq(token.balanceOf(address(harness)), 0); + assertEq(token.balanceOf(sender), INITIAL_BALANCE); + assertEq(token.balanceOf(receiver), 0); + } + + function test_onCommit_RevertWhen_CalledByOthers() public { + CrossContext memory context = _createContext(sender); + + address unauthorized = makeAddr("unauthorized"); + vm.prank(unauthorized); + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleUnauthorized.selector); + harness.onCommit(context); + } + + function test_onCommit_RevertWhen_NotInitialized() public { + ERC20TransferModuleHarness uninitHarness = new ERC20TransferModuleHarness(); + CrossContext memory context = _createContext(sender); + + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleNotInitialized.selector); + uninitHarness.onCommit(context); + } + + // --- Abort Tests --- + + function test_onAbort_Success() public { + CrossContext memory context = _createContext(sender); + bytes memory callInfo = _createCallInfo(sender, receiver, AMOUNT); + + vm.prank(sender); + token.approve(address(harness), AMOUNT); + + harness.onContractPrepare(context, callInfo); + + uint256 senderBalanceAfterLock = token.balanceOf(sender); + + assertEq(token.balanceOf(address(harness)), AMOUNT); + + harness.onAbort(context); + + assertEq(token.balanceOf(address(harness)), 0, "Module should release tokens"); + assertEq(token.balanceOf(sender), senderBalanceAfterLock + AMOUNT, "Sender should be refunded"); + assertEq(token.balanceOf(receiver), 0, "Receiver should not receive tokens"); + + (address pendingFrom,,) = harness.pendingTxs(TX_ID_RAW); + assertEq(pendingFrom, address(0), "Pending state should be deleted"); + } + + function test_onAbort_DoNothingWhenTxNotFound() public { + bytes32 unknownTxIdRaw = keccak256("unknown"); + CrossContext memory context = + CrossContext({txID: abi.encode(unknownTxIdRaw), txIndex: 0, signers: new AuthAccount.Data[](0)}); + + harness.onAbort(context); + + assertEq(token.balanceOf(address(harness)), 0); + assertEq(token.balanceOf(sender), INITIAL_BALANCE); + assertEq(token.balanceOf(receiver), 0); + } + + function test_onAbort_RevertWhen_CalledByOthers() public { + CrossContext memory context = _createContext(sender); + + address unauthorized = makeAddr("unauthorized"); + vm.prank(unauthorized); + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleUnauthorized.selector); + harness.onAbort(context); + } + + function test_onAbort_RevertWhen_NotInitialized() public { + ERC20TransferModuleHarness uninitHarness = new ERC20TransferModuleHarness(); + CrossContext memory context = _createContext(sender); + + vm.expectRevert(ERC20TransferModule.ERC20TransferModuleNotInitialized.selector); + uninitHarness.onAbort(context); + } +} diff --git a/test/IBCKeeper.t.sol b/test/IBCKeeper.t.sol index ac7cba3..7267830 100644 --- a/test/IBCKeeper.t.sol +++ b/test/IBCKeeper.t.sol @@ -4,11 +4,14 @@ pragma solidity ^0.8.20; import "forge-std/src/Test.sol"; import "../src/core/IBCKeeper.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; contract DummyHandler {} contract IBCKeeperHarness is IBCKeeper { - constructor(IIBCHandler h) IBCKeeper(h) {} + function exposed_initIBCKeeper(IIBCHandler handler) public initializer { + __initIBCKeeper(handler); + } function exposed_getIBCHandler() external view returns (address) { return address(getIBCHandler()); @@ -21,7 +24,8 @@ contract IBCKeeperTest is Test { function setUp() public { dummy = new DummyHandler(); - keeper = new IBCKeeperHarness(IIBCHandler(address(dummy))); + keeper = new IBCKeeperHarness(); + keeper.exposed_initIBCKeeper(IIBCHandler(address(dummy))); } function test_getIBCHandler_ReturnsSameAddress() public view { @@ -29,8 +33,14 @@ contract IBCKeeperTest is Test { assertEq(h, address(dummy)); } - function test_constructor_AllowsZeroAddress() public { - IBCKeeperHarness k = new IBCKeeperHarness(IIBCHandler(address(0))); + function test_exposed_initIBCKeeper_AllowsZeroAddress() public { + IBCKeeperHarness k = new IBCKeeperHarness(); + k.exposed_initIBCKeeper(IIBCHandler(address(0))); assertEq(k.exposed_getIBCHandler(), address(0)); } + + function test_exposed_initIBCKeeper_RevertOn_SecondInitialization() public { + vm.expectRevert(Initializable.InvalidInitialization.selector); + keeper.exposed_initIBCKeeper(IIBCHandler(address(dummy))); + } } diff --git a/test/Initiator.t.sol b/test/Initiator.t.sol new file mode 100644 index 0000000..eda022f --- /dev/null +++ b/test/Initiator.t.sol @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/Initiator.sol"; +import {TxManagerBase} from "../src/core/TxManagerBase.sol"; +import {TxAuthManagerBase} from "../src/core/TxAuthManagerBase.sol"; +import {ICrossEvent} from "../src/core/ICrossEvent.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +import { + MsgInitiateTx, + MsgInitiateTxResponse, + ContractTransaction, + QuerySelfXCCResponse +} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {Account as AuthAccount, AuthType, TxAuthState} from "../src/proto/cross/core/auth/Auth.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {Tx} from "../src/proto/cross/core/tx/Tx.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; +import {ChannelInfo} from "../src/proto/cross/core/xcc/XCC.sol"; +import {CoordinatorState} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; + +contract MockTxManager is TxManagerBase { + mapping(bytes32 => bool) public txExists; + bytes32 public lastCreatedtxID; + bytes32 public lastRuntxID; + uint256 public createTxCount; + uint256 public runTxCount; + + function _createTx(bytes32 txID, MsgInitiateTx.Data calldata) internal virtual override { + txExists[txID] = true; + lastCreatedtxID = txID; + ++createTxCount; + } + + function _runTxIfCompleted(bytes32 txID, MsgInitiateTx.Data calldata msg_) internal virtual override {} + + function _isTxRecorded(bytes32 txID) internal view virtual override returns (bool) { + return txExists[txID]; + } + + function _getCoordinatorState( + bytes32 /*txID*/ + ) + internal + view + virtual + override + returns (CoordinatorState.Data memory) + { + CoordinatorState.Data memory dummy; + return dummy; + } + + function setTxExists(bytes32 txID, bool exists) public { + txExists[txID] = exists; + } +} + +contract MockTxAuthManager is TxAuthManagerBase { + mapping(bytes32 => bool) public completed; + bytes32 public lastInittxID; + bool private _signReturns = false; + + function _initAuthState(bytes32 txID, AuthAccount.Data[] memory) internal virtual override { + lastInittxID = txID; + completed[txID] = false; + } + + function _isCompletedAuth(bytes32 txID) internal view virtual override returns (bool) { + return completed[txID]; + } + + function _sign(bytes32 txID, AuthAccount.Data[] memory) internal virtual override returns (bool) { + if (_signReturns) { + completed[txID] = true; + } + return _signReturns; + } + + function _getAuthState(bytes32) internal view virtual override returns (TxAuthState.Data memory) { + revert("MockTxAuthManager._getAuthState not implemented"); + } + + function _verifySignatures(bytes32, AuthAccount.Data[] calldata) internal virtual override { + revert("MockTxAuthManager._verifySignatures not implemented"); + } + + function setSignReturns(bool returnsValue) public { + _signReturns = returnsValue; + } +} + +/** + * @dev Initiatorとモックを組み合わせたテストハーネス + */ +contract InitiatorHarness is Initiator, MockTxAuthManager, MockTxManager { + function exposed_getRequiredAccounts(MsgInitiateTx.Data calldata msg_) + public + pure + returns (AuthAccount.Data[] memory out) + { + return _getRequiredAccounts(msg_); + } +} + +contract InitiatorTest is Test, ICrossEvent { + InitiatorHarness private harness; + MsgInitiateTx.Data private baseMsg; + AuthAccount.Data private signerA; + AuthAccount.Data private signerB; + AuthType.Data private localAuthType; + string private chainIDStr; + + function setUp() public { + harness = new InitiatorHarness(); + + GoogleProtobufAny.Data memory emptyAny = GoogleProtobufAny.Data({type_url: "", value: ""}); + localAuthType = AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: emptyAny}); + + signerA = AuthAccount.Data({id: bytes("signerA"), auth_type: localAuthType}); + signerB = AuthAccount.Data({id: bytes("signerB"), auth_type: localAuthType}); + + chainIDStr = Strings.toString(block.chainid); + + AuthAccount.Data[] memory signers; + + ContractTransaction.Data[] memory txs = new ContractTransaction.Data[](1); + txs[0].signers = new AuthAccount.Data[](1); + txs[0].signers[0] = signerA; + + baseMsg = MsgInitiateTx.Data({ + chain_id: chainIDStr, + nonce: 1, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + timeout_height: IbcCoreClientV1Height.Data(0, uint64(block.number + 100)), + timeout_timestamp: uint64(block.timestamp + 100), + signers: signers, + contract_transactions: txs + }); + } + + function test_constructor_SetsChainIDHash() public view { + bytes32 expected = keccak256(bytes(chainIDStr)); + assertEq(harness.CHAIN_ID_HASH(), expected, "CHAIN_ID_HASH mismatch"); + } + + function test_selfXCC_ReturnsCorrectChannelInfo() public view { + string memory expectedTypeURL = "/cross.core.xcc.ChannelInfo"; + bytes memory expectedValue = ChannelInfo.encode(ChannelInfo.Data({port: "", channel: ""})); + + QuerySelfXCCResponse.Data memory resp = harness.selfXCC(); + + assertEq(resp.xcc.type_url, expectedTypeURL, "type_url mismatch"); + assertEq(resp.xcc.value, expectedValue, "value mismatch"); + } + + function test_initiateTx_SucceedsAsPendingWhenSignersNotMet() public { + bytes32 txIDHash = sha256(MsgInitiateTx.encode(baseMsg)); + + harness.setSignReturns(false); + + vm.expectEmit(true, false, false, true, address(harness)); + emit TxInitiated(abi.encodePacked(txIDHash), address(this), baseMsg); + + MsgInitiateTxResponse.Data memory resp = harness.initiateTx(baseMsg); + + assertEq( + uint256(resp.status), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING), + "Status should be PENDING" + ); + assertTrue(harness.txExists(txIDHash), "Mock: tx should be recorded"); + assertFalse(harness.completed(txIDHash), "Mock: auth should not be completed"); + assertEq(harness.createTxCount(), 1, "Mock: _createTx should be called once"); + assertEq(harness.lastInittxID(), txIDHash, "Mock: _initAuthState should be called with txID"); + assertEq(harness.runTxCount(), 0, "Mock: _runTxIfCompleted should not be called"); + } + + function test_initiateTx_SucceedsAsVerifiedWhenSignersMet() public { + bytes32 txIDHash = sha256(MsgInitiateTx.encode(baseMsg)); + + harness.setSignReturns(true); + + vm.expectEmit(true, false, false, true, address(harness)); + emit TxInitiated(abi.encodePacked(txIDHash), address(this), baseMsg); + + MsgInitiateTxResponse.Data memory resp = harness.initiateTx(baseMsg); + + assertEq( + uint256(resp.status), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED), + "Status should be VERIFIED" + ); + assertTrue(harness.txExists(txIDHash), "Mock: tx should be recorded"); + assertTrue(harness.completed(txIDHash), "Mock: auth should be completed"); + assertEq(harness.createTxCount(), 1, "Mock: _createTx should be called once"); + assertEq(harness.lastInittxID(), txIDHash, "Mock: _initAuthState should be called with txID"); + } + + function test_initiateTx_RevertWhen_ChainIDMismatch() public { + baseMsg.chain_id = "wrong-chain"; + + bytes32 expectedHash = keccak256(bytes(chainIDStr)); + bytes32 gotHash = keccak256(bytes("wrong-chain")); + + vm.expectRevert(abi.encodeWithSelector(ICrossError.UnexpectedChainID.selector, expectedHash, gotHash)); + harness.initiateTx(baseMsg); + } + + function test_initiateTx_RevertWhen_TimeoutHeightExpired() public { + baseMsg.timeout_height.revision_height = uint64(block.number); + + vm.expectRevert( + abi.encodeWithSelector( + ICrossError.MessageTimeoutHeight.selector, block.number, baseMsg.timeout_height.revision_height + ) + ); + harness.initiateTx(baseMsg); + } + + function test_initiateTx_RevertWhen_TimeoutTimestampExpired() public { + baseMsg.timeout_timestamp = uint64(block.timestamp); + + vm.expectRevert( + abi.encodeWithSelector( + ICrossError.MessageTimeoutTimestamp.selector, block.timestamp, baseMsg.timeout_timestamp + ) + ); + harness.initiateTx(baseMsg); + } + + function test_initiateTx_RevertWhen_txIDAlreadyExists() public { + bytes32 txIDHash = sha256(MsgInitiateTx.encode(baseMsg)); + + harness.setTxExists(txIDHash, true); + + vm.expectRevert(abi.encodeWithSelector(ICrossError.TxIDAlreadyExists.selector, txIDHash)); + harness.initiateTx(baseMsg); + } + + function test_getRequiredAccounts_AggregatesSigners() public { + baseMsg.contract_transactions = new ContractTransaction.Data[](2); + baseMsg.contract_transactions[0].signers = new AuthAccount.Data[](2); + baseMsg.contract_transactions[0].signers[0] = signerA; + baseMsg.contract_transactions[0].signers[1] = signerB; + + baseMsg.contract_transactions[1].signers = new AuthAccount.Data[](1); + AuthAccount.Data memory signerC = AuthAccount.Data({id: bytes("signerC"), auth_type: localAuthType}); + baseMsg.contract_transactions[1].signers[0] = signerC; + + AuthAccount.Data[] memory required = harness.exposed_getRequiredAccounts(baseMsg); + + assertEq(required.length, 3, "Should aggregate 3 signers"); + assertEq(required[0].id, signerA.id, "Signer A missing"); + assertEq(required[1].id, signerB.id, "Signer B missing"); + assertEq(required[2].id, signerC.id, "Signer C missing"); + } + + function test_getRequiredAccounts_ReturnsEmptyArrayWhenNoTxs() public { + baseMsg.contract_transactions = new ContractTransaction.Data[](0); + + AuthAccount.Data[] memory required = harness.exposed_getRequiredAccounts(baseMsg); + + assertEq(required.length, 0, "Should return empty array for zero transactions"); + } + + function test_getRequiredAccounts_ReturnsEmptyArrayWhenNoSigners() public { + baseMsg.contract_transactions = new ContractTransaction.Data[](2); + baseMsg.contract_transactions[0].signers = new AuthAccount.Data[](0); + baseMsg.contract_transactions[1].signers = new AuthAccount.Data[](0); + + AuthAccount.Data[] memory required = harness.exposed_getRequiredAccounts(baseMsg); + + assertEq(required.length, 0, "Should return empty array for zero signers"); + } +} diff --git a/test/MockCrossContract.t.sol b/test/MockCrossContract.t.sol index a2d3154..6f07a0b 100644 --- a/test/MockCrossContract.t.sol +++ b/test/MockCrossContract.t.sol @@ -27,59 +27,59 @@ contract MockCrossContractTest is Test { AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); signers[0] = _mkSigner(id, mode); - ctx = CrossContext({txId: hex"11", txIndex: 1, signers: signers}); + ctx = CrossContext({txID: hex"11", txIndex: 1, signers: signers}); } - function test_onContractCall_ReturnsExpectedBytes() public { + function test_onContractCommitImmediately_ReturnsExpectedBytes() public { CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); bytes memory callInfo = hex"01"; - bytes memory ret = mock.onContractCall(ctx, callInfo); + bytes memory ret = mock.onContractCommitImmediately(ctx, callInfo); assertEq(ret, bytes("mock call succeed")); } - function test_onContractCall_RevertWhen_SignersLenIsZero() public { + function test_onContractCommitImmediately_RevertWhen_SignersLenIsZero() public { AuthAccount.Data[] memory signers = new AuthAccount.Data[](0); - CrossContext memory ctx = CrossContext({txId: hex"22", txIndex: 1, signers: signers}); + CrossContext memory ctx = CrossContext({txID: hex"22", txIndex: 1, signers: signers}); vm.expectRevert(bytes("signers length must be 1")); - mock.onContractCall(ctx, hex"01"); + mock.onContractCommitImmediately(ctx, hex"01"); } - function test_onContractCall_RevertWhen_SignersLenIsTwo() public { + function test_onContractCommitImmediately_RevertWhen_SignersLenIsTwo() public { AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); signers[0] = _mkSigner(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); signers[1] = _mkSigner(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); - CrossContext memory ctx = CrossContext({txId: hex"33", txIndex: 1, signers: signers}); + CrossContext memory ctx = CrossContext({txID: hex"33", txIndex: 1, signers: signers}); vm.expectRevert(bytes("signers length must be 1")); - mock.onContractCall(ctx, hex"01"); + mock.onContractCommitImmediately(ctx, hex"01"); } - function test_onContractCall_RevertWhen_AuthModeIsNotChannel() public { + function test_onContractCommitImmediately_RevertWhen_AuthModeIsNotChannel() public { CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_EXTENSION); vm.expectRevert(bytes("auth mode must be CHANNEL")); - mock.onContractCall(ctx, hex"01"); + mock.onContractCommitImmediately(ctx, hex"01"); } - function test_onContractCall_RevertWhen_UnexpectedAccountId() public { + function test_onContractCommitImmediately_RevertWhen_UnexpectedAccountId() public { CrossContext memory ctx = _mkContextSingle(bytes("hacker"), AuthType.AuthMode.AUTH_MODE_CHANNEL); vm.expectRevert(bytes("unexpected account ID")); - mock.onContractCall(ctx, hex"01"); + mock.onContractCommitImmediately(ctx, hex"01"); } - function test_onContractCall_RevertWhen_CallInfoLenIsZero() public { + function test_onContractCommitImmediately_RevertWhen_CallInfoLenIsZero() public { CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); vm.expectRevert(bytes("the length of callInfo must be 1")); - mock.onContractCall(ctx, bytes("")); + mock.onContractCommitImmediately(ctx, bytes("")); } - function test_onContractCall_RevertWhen_CallInfoLenIsTwo() public { + function test_onContractCommitImmediately_RevertWhen_CallInfoLenIsTwo() public { CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); bytes memory callInfo = new bytes(2); @@ -87,13 +87,34 @@ contract MockCrossContractTest is Test { callInfo[1] = 0x02; vm.expectRevert(bytes("the length of callInfo must be 1")); - mock.onContractCall(ctx, callInfo); + mock.onContractCommitImmediately(ctx, callInfo); } - function test_onContractCall_RevertWhen_CallInfoIsNot0x01() public { + function test_onContractCommitImmediately_RevertWhen_CallInfoIsNot0x01() public { CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); vm.expectRevert(bytes("callInfo must be 0x01")); - mock.onContractCall(ctx, hex"02"); + mock.onContractCommitImmediately(ctx, hex"02"); + } + + function test_onCommit_Succeeds() public { + CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); + // onCommit is empty in MockCrossContract, so we just verify it doesn't revert + mock.onCommit(ctx); + } + + function test_onAbort_Succeeds() public { + CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); + // onAbort is empty in MockCrossContract, so we just verify it doesn't revert + mock.onAbort(ctx); + } + + function test_onContractPrepare_ReturnsExpectedBytes() public { + CrossContext memory ctx = _mkContextSingle(bytes("tester"), AuthType.AuthMode.AUTH_MODE_CHANNEL); + bytes memory callInfo = hex"00"; + + bytes memory ret = mock.onContractPrepare(ctx, callInfo); + + assertEq(ret, bytes("mock prepare succeed")); } } diff --git a/test/SampleExtensionVerifier.sol b/test/SampleExtensionVerifier.sol new file mode 100644 index 0000000..92bea78 --- /dev/null +++ b/test/SampleExtensionVerifier.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; + +import {SampleExtensionVerifier} from "../src/example/SampleExtensionVerifier.sol"; +import {Account as AuthAccount, AuthType} from "../src/proto/cross/core/auth/Auth.sol"; + +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +contract SampleExtensionVerifierTest is Test { + SampleExtensionVerifier private verifier; + + uint256 private signerPrivateKey = 0xBAD_5EED; + address private signerAddress; + + bytes32 private txIDHash = keccak256("test_tx_id_hash"); + bytes32 private signMsg = keccak256("message_to_be_signed"); + bytes32 private ethSignedMsgHash; + bytes private validSignature; + + AuthAccount.Data private baseAuthAccount; + + function setUp() public { + verifier = new SampleExtensionVerifier(); + + signerAddress = vm.addr(signerPrivateKey); + + ethSignedMsgHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", signMsg)); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, ethSignedMsgHash); + validSignature = abi.encodePacked(r, s, v); + + GoogleProtobufAny.Data memory option = GoogleProtobufAny.Data({ + type_url: "SampleExtensionVerifier", + value: abi.encode(validSignature, signMsg) // (bytes, bytes32) + }); + + AuthType.Data memory authType = AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, option: option}); + + baseAuthAccount = AuthAccount.Data({id: abi.encodePacked(signerAddress), auth_type: authType}); + } + + function test_verify_SucceedsWhenSignatureIsValid() public view { + bool isValid = verifier.verify(txIDHash, baseAuthAccount); + assertTrue(isValid, "Signature should be valid"); + } + + function test_verify_ReturnsFalseWhenAuthModeIsNotExtension() public view { + AuthAccount.Data memory modifiedAuthAccount = baseAuthAccount; + modifiedAuthAccount.auth_type.mode = AuthType.AuthMode.AUTH_MODE_LOCAL; + + bool isValid = verifier.verify(txIDHash, modifiedAuthAccount); + assertFalse(isValid, "Should return false if mode is not EXTENSION"); + } + + function test_verify_ReturnsFalseWhenSignerIdMismatch() public view { + AuthAccount.Data memory modifiedAuthAccount = baseAuthAccount; + address otherAddress = address(0xDEADBEEF); + modifiedAuthAccount.id = abi.encodePacked(otherAddress); + + bool isValid = verifier.verify(txIDHash, modifiedAuthAccount); + assertFalse(isValid, "Should return false if signer.id does not match recovered address"); + } + + function test_verify_ReturnsFalseWhenSignerIdIsInvalidLength() public view { + AuthAccount.Data memory modifiedAuthAccount = baseAuthAccount; + modifiedAuthAccount.id = bytes("not-an-address"); + + bool isValid = verifier.verify(txIDHash, modifiedAuthAccount); + assertFalse(isValid, "Should return false if signer.id length is not 20"); + } + + function test_verify_ReturnsFalseWhenSignedMsgMismatch() public view { + AuthAccount.Data memory modifiedAuthAccount = baseAuthAccount; + bytes32 otherMsg = keccak256("other_message"); + + modifiedAuthAccount.auth_type.option.value = abi.encode(validSignature, otherMsg); + + bool isValid = verifier.verify(txIDHash, modifiedAuthAccount); + assertFalse(isValid, "Should return false if sign_msg does not match signature"); + } + + function test_verify_RevertsWhen_SignatureIsInvalidLength() public { + AuthAccount.Data memory modifiedAccount = baseAuthAccount; + bytes memory invalidSignature = hex"1234"; + modifiedAccount.auth_type.option.value = abi.encode(invalidSignature, signMsg); + + vm.expectRevert(abi.encodeWithSelector(ECDSA.ECDSAInvalidSignatureLength.selector, 2)); + verifier.verify(txIDHash, modifiedAccount); + } + + function test_verify_RevertsWhen_SignatureIsIncorrect() public { + AuthAccount.Data memory modifiedAccount = baseAuthAccount; + + bytes32 r = bytes32(validSignature); + bytes32 sTampered = r; + uint8 v = 28; + + bytes memory tamperedSignature = abi.encodePacked(r, sTampered, v); + modifiedAccount.auth_type.option.value = abi.encode(tamperedSignature, signMsg); + + vm.expectRevert(abi.encodeWithSelector(ECDSA.ECDSAInvalidSignatureS.selector, sTampered)); + verifier.verify(txIDHash, modifiedAccount); + } + + function test_verify_RevertsWhen_OptionDataIsMalformed() public { + AuthAccount.Data memory modifiedAuthAccount = baseAuthAccount; + + modifiedAuthAccount.auth_type.option.value = bytes("this is not abi encoded"); + + vm.expectRevert(); + verifier.verify(txIDHash, modifiedAuthAccount); + } +} diff --git a/test/SimpleContractRegistry.t.sol b/test/SimpleContractRegistry.t.sol index 8cfc741..a6bce96 100644 --- a/test/SimpleContractRegistry.t.sol +++ b/test/SimpleContractRegistry.t.sol @@ -6,11 +6,13 @@ import "forge-std/src/Test.sol"; import "../src/core/SimpleContractRegistry.sol"; import "../src/core/IContractModule.sol"; +import "../src/core/ICrossError.sol"; import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; contract DummyModule is IContractModule { // do nothing implementation - function onContractCall( + function onContractCommitImmediately( CrossContext calldata, /*context*/ bytes calldata /*callInfo*/ @@ -21,23 +23,33 @@ contract DummyModule is IContractModule { { return ""; } + function onAbort(CrossContext calldata context) external override {} + function onCommit(CrossContext calldata context) external override {} + + function onContractPrepare( + CrossContext calldata, + /*context*/ + bytes calldata /*callInfo*/ + ) + external + override + returns (bytes memory) + { + return ""; + } } contract SimpleContractRegistryHarness is SimpleContractRegistry { - function exposed_registerModule(IContractModule m) external { + function exposed_registerModule(IContractModule m) external initializer { registerModule(m); } function exposed_getModule(Packet calldata p) external returns (IContractModule) { return getModule(p); } - - function workaround_moduleAddr() external view returns (address) { - return address(contractModule); - } } -contract SimpleContractRegistryTest is Test { +contract SimpleContractRegistryTest is Test, ICrossError { DummyModule private dummy; SimpleContractRegistryHarness private registry; @@ -49,7 +61,7 @@ contract SimpleContractRegistryTest is Test { } function test_get_RevertWhen_NotInitialized() public { - vm.expectRevert(SimpleContractRegistry.ModuleNotInitialized.selector); + vm.expectRevert(ModuleNotInitialized.selector); registry.exposed_getModule(_emptyPacket); } @@ -60,7 +72,6 @@ contract SimpleContractRegistryTest is Test { IContractModule got = registry.exposed_getModule(_emptyPacket); assertEq(address(got), address(m)); - assertEq(registry.workaround_moduleAddr(), address(m)); } function test_register_RevertOn_SecondInitialization() public { @@ -68,7 +79,7 @@ contract SimpleContractRegistryTest is Test { registry.exposed_registerModule(m); - vm.expectRevert(SimpleContractRegistry.ModuleAlreadyInitialized.selector); + vm.expectRevert(Initializable.InvalidInitialization.selector); registry.exposed_registerModule(m); } diff --git a/test/TxAtomicSimple.t.sol b/test/TxAtomicSimple.t.sol index 40c886a..1c76820 100644 --- a/test/TxAtomicSimple.t.sol +++ b/test/TxAtomicSimple.t.sol @@ -1,103 +1,250 @@ // SPDX-License-Identifier: Apache-2.0 -// solhint-disable one-contract-per-file, func-name-mixedcase +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings, function-max-lines pragma solidity ^0.8.20; import "forge-std/src/Test.sol"; import "../src/core/TxAtomicSimple.sol"; import "../src/core/IContractModule.sol"; -import "../src/core/IBCKeeper.sol"; -import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; +import "../src/core/ICrossError.sol"; +import "../src/core/ICrossEvent.sol"; import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; - -import "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; +import {Height} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/Client.sol"; +import {Channel, ChannelCounterparty} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/Channel.sol"; + +import { + PacketData, + Header, + HeaderField, + Acknowledgement, + PacketAcknowledgementCall, + PacketDataCall, + PacketDataCallResolvedContractTransaction, + CoordinatorState, + ContractTransactionState +} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; import {GoogleProtobufAny as Any} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; import {Account as AuthAccount} from "../src/proto/cross/core/auth/Auth.sol"; +import {MsgInitiateTx, ContractTransaction, ReturnValue, Link} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {Tx} from "../src/proto/cross/core/tx/Tx.sol"; +import {ChannelInfo} from "../src/proto/cross/core/xcc/XCC.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; + +// --- Mocks --- + +contract MockIBCHandler { + bool public foundChannel = true; + bytes32 public lastSentPacketHash; + + function setFoundChannel(bool b) external { + foundChannel = b; + } + + function sendPacket(string calldata, string calldata, Height.Data calldata, uint64, bytes calldata data) + external + returns (uint64) + { + lastSentPacketHash = keccak256(data); + return 1; + } -contract DummyHandler {} + function getChannel(string calldata, string calldata) external view returns (Channel.Data memory, bool) { + return ( + Channel.Data( + Channel.State.STATE_OPEN, + Channel.Order.ORDER_UNORDERED, + ChannelCounterparty.Data("", ""), + new string[](0), + "", + 0 + ), + foundChannel + ); + } +} -contract SuccessModule is IContractModule { +contract MockModule is IContractModule { bytes public retBytes; + bool public prepareResult = true; + + uint256 public onContractCommitImmediatelyCallCount; + uint256 public onCommitCallCount; + uint256 public onAbortCallCount; + uint256 public onContractPrepareCallCount; + + bool public revertOnCommitImmediately; + bool public revertOnCommit; + bool public revertOnAbort; constructor(bytes memory r) { retBytes = r; } - function onContractCall( - CrossContext calldata, - /*context*/ - bytes calldata /*callInfo*/ - ) + function setPrepareResult(bool b) external { + prepareResult = b; + } + + function setRevertOnCommitImmediately(bool b) external { + revertOnCommitImmediately = b; + } + + function setRevertOnCommit(bool b) external { + revertOnCommit = b; + } + + function setRevertOnAbort(bool b) external { + revertOnAbort = b; + } + + function onContractCommitImmediately(CrossContext calldata, bytes calldata) external - view + override returns (bytes memory) { + ++onContractCommitImmediatelyCallCount; + if (revertOnCommitImmediately) { + revert("MockModule: CommitImmediately failed"); + } return retBytes; } -} -contract RevertingModule is IContractModule { - function onContractCall( - CrossContext calldata, - /*context*/ - bytes calldata /*callInfo*/ - ) - external - pure - returns (bytes memory) - { - revert("boom"); + function onAbort(CrossContext calldata) external override { + ++onAbortCallCount; + if (revertOnAbort) { + revert("MockModule: OnAbort failed"); + } + } + + function onCommit(CrossContext calldata) external override { + ++onCommitCallCount; + if (revertOnCommit) { + revert("MockModule: OnCommit failed"); + } + } + + function onContractPrepare(CrossContext calldata, bytes calldata) external override returns (bytes memory) { + ++onContractPrepareCallCount; + if (!prepareResult) { + revert("MockModule: Prepare failed"); + } + return retBytes; } } -contract TxAtomicSimpleHarness is TxAtomicSimple { +abstract contract MockContractRegistry is ContractRegistry { IContractModule internal _module; - constructor(IIBCHandler h) IBCKeeper(h) {} - function registerModule(IContractModule module) internal override { _module = module; } - function getModule( - Packet memory /*packet*/ - ) - internal - override - returns (IContractModule) - { + function getModule(Packet memory) internal view override returns (IContractModule) { return _module; } - function exposed_handlePacket(Packet calldata p) external returns (bytes memory ack) { - return handlePacket(p); + function setModule(IContractModule module) external { + _module = module; + } +} + +// --- Harness --- + +contract TxAtomicSimpleHarness is TxAtomicSimple, MockContractRegistry { + function initialize(IIBCHandler handler, IContractModule module) public initializer { + __initTxAtomicSimple(handler, module); + } + + function exposed_runTx(bytes32 txID, MsgInitiateTx.Data calldata msg_) external { + _runTx(txID, msg_); + } + + function exposed_handlePacket(Packet calldata p) external returns (bytes memory) { + return _handlePacket(p); } - function exposed_handleAcknowledgement(Packet calldata p, bytes calldata ackBytes) external { - handleAcknowledgement(p, ackBytes); + function exposed_handleAcknowledgement(Packet calldata p, bytes calldata ack) external { + _handleAcknowledgement(p, ack); } function exposed_handleTimeout(Packet calldata p) external { - handleTimeout(p); + _handleTimeout(p); + } + + function setCoordinatorState(bytes32 txID, CoordinatorState.Data calldata state) external { + _saveCoordinatorState(txID, state); + } + + function setContractTxState(bytes32 txID, uint8 index, ContractTransactionState.Data calldata state) external { + _getTxStorage().states[txID][index] = state; } - function workaround_setModule(IContractModule m) external { - _module = m; + function getCoordState(bytes32 txID) external view returns (CoordinatorState.Data memory) { + return _loadCoordinatorState(txID); + } + + function getContractTxState(bytes32 txID, uint8 index) + external + view + returns (ContractTransactionState.Data memory) + { + return _getTxStorage().states[txID][index]; } } -contract TxAtomicSimpleTest is Test { - DummyHandler private handler; +contract TxAtomicSimpleTest is Test, ICrossError, ICrossEvent { TxAtomicSimpleHarness private harness; + MockIBCHandler private mockHandler; + MockModule private mockModule; - event OnContractCall(bytes indexed txId, uint8 indexed txIndex, bool indexed success, bytes ret); + bytes32 private constant TX_ID = keccak256("test-tx"); function setUp() public { - handler = new DummyHandler(); - harness = new TxAtomicSimpleHarness(IIBCHandler(address(handler))); + mockHandler = new MockIBCHandler(); + mockModule = new MockModule(hex"01"); + harness = new TxAtomicSimpleHarness(); + harness.initialize(IIBCHandler(address(mockHandler)), IContractModule(address(mockModule))); } - function _mkPacketWithCall(bytes memory txId, bytes memory callInfo) internal pure returns (Packet memory p) { + // --- Helpers --- + + function _createValidSimpleMsg() internal view returns (MsgInitiateTx.Data memory) { + ContractTransaction.Data[] memory txs = new ContractTransaction.Data[](2); + + // Tx0: Local (Coordinator) + txs[0] = ContractTransaction.Data({ + cross_chain_channel: Any.Data("", ChannelInfo.encode(ChannelInfo.Data("", ""))), + signers: new AuthAccount.Data[](0), + call_info: hex"", + return_value: ReturnValue.Data(""), + links: new Link.Data[](0) + }); + + // Tx1: Remote (Participant) + txs[1] = ContractTransaction.Data({ + cross_chain_channel: Any.Data("", ChannelInfo.encode(ChannelInfo.Data("port-1", "channel-1"))), + signers: new AuthAccount.Data[](0), + call_info: hex"", + return_value: ReturnValue.Data(""), + links: new Link.Data[](0) + }); + + return MsgInitiateTx.Data({ + chain_id: "chain", + nonce: 1, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + contract_transactions: txs, + signers: new AuthAccount.Data[](0), + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0 + }); + } + + function _createPacket(bytes32 txId, bytes memory callInfo, string memory srcPort, string memory srcChannel) + internal + pure + returns (Packet memory) + { Any.Data memory emptyAny = Any.Data({type_url: "", value: ""}); ReturnValue.Data memory emptyRet = ReturnValue.Data({value: ""}); @@ -113,18 +260,31 @@ contract TxAtomicSimpleTest is Test { objects: objects }); - PacketDataCall.Data memory callData = PacketDataCall.Data({tx_id: txId, tx: txResolved}); + PacketDataCall.Data memory callData = PacketDataCall.Data({tx_id: abi.encode(txId), tx: txResolved}); + + bytes memory payload = + Any.encode(Any.Data("/cross.core.atomic.simple.PacketDataCall", PacketDataCall.encode(callData))); + bytes memory data = PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), payload)); + + return Packet({ + sequence: 1, + sourcePort: srcPort, + sourceChannel: srcChannel, + destinationPort: "dst", + destinationChannel: "dst", + data: data, + timeoutHeight: Height.Data(0, 0), + timeoutTimestamp: 0 + }); + } - bytes memory anyPayload = Any.encode( - // solhint-disable-next-line gas-small-strings - Any.Data({type_url: "/cross.core.atomic.simple.PacketDataCall", value: PacketDataCall.encode(callData)}) + function _createAck(PacketAcknowledgementCall.CommitStatus status) internal pure returns (bytes memory) { + PacketAcknowledgementCall.Data memory pac = PacketAcknowledgementCall.Data(status); + bytes memory payload = Any.encode( + Any.Data("/cross.core.atomic.simple.PacketAcknowledgementCall", PacketAcknowledgementCall.encode(pac)) ); - - HeaderField.Data[] memory fields; - bytes memory packetDataBytes = - PacketData.encode(PacketData.Data({header: Header.Data({fields: fields}), payload: anyPayload})); - - p.data = packetDataBytes; + bytes memory res = PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), payload)); + return Acknowledgement.encode(Acknowledgement.Data(true, res)); } function _decodeAckStatus(bytes memory ack) internal pure returns (PacketAcknowledgementCall.CommitStatus) { @@ -135,16 +295,39 @@ contract TxAtomicSimpleTest is Test { return pac.status; } - function test_handlePacket_ReturnsOkAndEmitsEventWhenModuleSucceeds() public { - bytes memory ret = hex"010203"; - harness.workaround_setModule(new SuccessModule(ret)); + function _setupCoordStateForAck(CoordinatorState.CoordinatorPhase phase) internal { + ChannelInfo.Data[] memory channels = new ChannelInfo.Data[](2); + channels[0] = ChannelInfo.Data("", ""); + channels[1] = ChannelInfo.Data("port-1", "channel-1"); + + uint32[] memory confirmed = new uint32[](1); + confirmed[0] = 0; // TX_INDEX_COORDINATOR + + CoordinatorState.Data memory cs = CoordinatorState.Data({ + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + channels: channels, + phase: phase, + decision: CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_UNKNOWN, + confirmed_txs: confirmed, + acks: new uint32[](0) + }); + harness.setCoordinatorState(TX_ID, cs); + + ContractTransactionState.Data memory ts = ContractTransactionState.Data({ + status: ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_PREPARE, + prepare_result: ContractTransactionState.PrepareResult.PREPARE_RESULT_OK, + coordinator_channel: channels[0] + }); + harness.setContractTxState(TX_ID, 0, ts); + } - bytes memory txId = hex"deadbeef"; - bytes memory callInfo = hex"c0ffee"; - Packet memory packet = _mkPacketWithCall(txId, callInfo); + // --- handlePacket --- + + function test_handlePacket_ReturnsOkAndEmitsEventWhenModuleSucceeds() public { + Packet memory packet = _createPacket(TX_ID, hex"c0ffee", "port-1", "channel-1"); vm.expectEmit(address(harness)); - emit OnContractCall(txId, 1, true, ret); + emit OnContractCommitImmediately(abi.encodePacked(TX_ID), 1, true, hex"01"); bytes memory ack = harness.exposed_handlePacket(packet); @@ -153,17 +336,18 @@ contract TxAtomicSimpleTest is Test { uint256(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK), "ACK should be OK" ); + assertEq( + mockModule.onContractCommitImmediatelyCallCount(), 1, "onContractCommitImmediately should be called once" + ); } function test_handlePacket_ReturnsFailedAndEmitsEventWhenModuleReverts() public { - harness.workaround_setModule(new RevertingModule()); + mockModule.setRevertOnCommitImmediately(true); - bytes memory txId = hex"bead"; - bytes memory callInfo = hex"00"; - Packet memory packet = _mkPacketWithCall(txId, callInfo); + Packet memory packet = _createPacket(TX_ID, hex"00", "port-1", "channel-1"); vm.expectEmit(address(harness)); - emit OnContractCall(txId, 1, false, ""); + emit OnContractCommitImmediately(abi.encodePacked(TX_ID), 1, false, ""); bytes memory ack = harness.exposed_handlePacket(packet); @@ -172,20 +356,26 @@ contract TxAtomicSimpleTest is Test { uint256(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED), "ACK should be FAILED" ); + assertEq(mockModule.onContractCommitImmediatelyCallCount(), 0, "Counter should be 0 due to revert rollback"); } - function test_handlePacket_RevertWhen_PayloadEmpty() public { + function test_handlePacket_ReturnsFailedWhenPayloadEmpty() public { HeaderField.Data[] memory fields; bytes memory packetDataBytes = PacketData.encode(PacketData.Data({header: Header.Data({fields: fields}), payload: bytes("")})); Packet memory p; p.data = packetDataBytes; - vm.expectRevert(TxAtomicSimple.PayloadDecodeFailed.selector); - harness.exposed_handlePacket(p); + bytes memory ack = harness.exposed_handlePacket(p); + + assertEq( + uint256(_decodeAckStatus(ack)), + uint256(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED), + "ACK should be FAILED when payload is empty" + ); } - function test_handlePacket_RevertWhen_TypeURLUnexpected() public { + function test_handlePacket_ReturnsFailedWhenTypeURLUnexpected() public { bytes memory bogus = Any.encode(Any.Data({type_url: "/not.expected", value: hex"01"})); HeaderField.Data[] memory fields; bytes memory packetDataBytes = @@ -193,19 +383,455 @@ contract TxAtomicSimpleTest is Test { Packet memory p; p.data = packetDataBytes; - vm.expectRevert(TxAtomicSimple.UnexpectedTypeURL.selector); - harness.exposed_handlePacket(p); - } + bytes memory ack = harness.exposed_handlePacket(p); - function test_handleAcknowledgement_RevertOn_NotImplemented() public { - Packet memory p; - vm.expectRevert(TxAtomicSimple.NotImplemented.selector); - harness.exposed_handleAcknowledgement(p, hex""); + assertEq( + uint256(_decodeAckStatus(ack)), + uint256(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED), + "ACK should be FAILED when TypeURL is unexpected" + ); } + // --- handleTimeout --- + function test_handleTimeout_RevertOn_NotImplemented() public { Packet memory p; - vm.expectRevert(TxAtomicSimple.NotImplemented.selector); + vm.expectRevert(NotImplemented.selector); harness.exposed_handleTimeout(p); } + + // --- _runTx (Simple Protocol) Tests --- + + function test_runTx_SucceedsAndSendsPacket() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + + harness.exposed_runTx(TX_ID, msg_); + + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + assertEq(uint256(cs.phase), uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE)); + assertEq(uint256(cs.commit_protocol), uint256(Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE)); + assertNotEq(mockHandler.lastSentPacketHash(), bytes32(0), "Packet should be sent"); + assertEq(mockModule.onContractPrepareCallCount(), 1, "onContractPrepare should be called once"); + } + + function test_runTx_RevertWhen_SignerLenMismatch() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + // Add 3rd transaction + ContractTransaction.Data[] memory txs = new ContractTransaction.Data[](3); + txs[0] = msg_.contract_transactions[0]; + txs[1] = msg_.contract_transactions[1]; + txs[2] = msg_.contract_transactions[1]; + msg_.contract_transactions = txs; + + vm.expectRevert(ArrayLengthMismatch.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_Tx0NotLocal() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + // Set port/channel for tx0 (should be empty for coordinator) + msg_.contract_transactions[0].cross_chain_channel.value = + ChannelInfo.encode(ChannelInfo.Data({port: "p", channel: "c"})); + + vm.expectRevert(Tx0MustBeForSelfChain.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_PrepareFailed() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + mockModule.setPrepareResult(false); + + harness.exposed_runTx(TX_ID, msg_); + + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + // Should transition to COMMIT phase with ABORT decision immediately + assertEq(uint256(cs.phase), uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_COMMIT)); + assertEq(uint256(cs.decision), uint256(CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_ABORT)); + assertEq(mockModule.onContractPrepareCallCount(), 0, "Counter should be 0 due to revert rollback"); + } + + function test_runTx_RevertWhen_TPCNotImplemented() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + msg_.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_TPC; + + vm.expectRevert(TPCNotImplemented.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_UnknownCommitProtocol() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + msg_.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_UNKNOWN; + + vm.expectRevert(UnknownCommitProtocol.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_TimeoutHeight() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + msg_.timeout_height.revision_height = 100; + + vm.roll(101); // Block number > timeout + + vm.expectRevert(abi.encodeWithSelector(MessageTimeoutHeight.selector, 101, 100)); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_TimeoutTimestamp() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + msg_.timeout_timestamp = 1000; + + vm.warp(1001); // Timestamp > timeout + + vm.expectRevert(abi.encodeWithSelector(MessageTimeoutTimestamp.selector, 1001, 1000)); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_TxIDAlreadyExists() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + + vm.expectRevert(abi.encodeWithSelector(TxIDAlreadyExists.selector, TX_ID)); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_LinksNotSupported() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + + // Add a link to the first transaction + Link.Data[] memory links = new Link.Data[](1); + links[0] = Link.Data({src_index: 1}); + msg_.contract_transactions[0].links = links; + + vm.expectRevert(LinksNotSupported.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_ModuleNotInitialized() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + + // Unregister module + harness.setModule(IContractModule(address(0))); + + vm.expectRevert(ModuleNotInitialized.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_ChannelNotFound() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + + // Mock handler fails to find channel + mockHandler.setFoundChannel(false); + + vm.expectRevert(ChannelNotFound.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + function test_runTx_RevertWhen_UnexpectedReturnValue() public { + MsgInitiateTx.Data memory msg_ = _createValidSimpleMsg(); + + // MockModule returns hex"01" by default (set in setUp) + // Set expectation to something else to trigger error + msg_.contract_transactions[0].return_value = ReturnValue.Data(hex"02"); + + vm.expectRevert(UnexpectedReturnValue.selector); + harness.exposed_runTx(TX_ID, msg_); + } + + // --- _handleAcknowledgement Tests --- + + function test_handleAck_Success() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectEmit(address(harness)); + emit OnCommit(abi.encodePacked(TX_ID), 0); + + harness.exposed_handleAcknowledgement(p, ack); + + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + assertEq(uint256(cs.phase), uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_COMMIT)); + assertEq(uint256(cs.decision), uint256(CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_COMMIT)); + + assertEq(mockModule.onCommitCallCount(), 1, "onCommit should be called once"); + assertEq(mockModule.onAbortCallCount(), 0, "onAbort should not be called"); + } + + function test_handleAck_Failure() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED); + + vm.expectEmit(address(harness)); + emit OnAbort(abi.encodePacked(TX_ID), 0); + + harness.exposed_handleAcknowledgement(p, ack); + + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + assertEq(uint256(cs.phase), uint256(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_COMMIT)); + assertEq(uint256(cs.decision), uint256(CoordinatorState.CoordinatorDecision.COORDINATOR_DECISION_ABORT)); + + assertEq(mockModule.onAbortCallCount(), 1, "onAbort should be called once"); + assertEq(mockModule.onCommitCallCount(), 0, "onCommit should not be called"); + } + + function test_handleAck_RevertWhen_AckIsNotSuccess() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + + // Create an Ack with is_success = false + bytes memory res = hex""; + bytes memory ack = Acknowledgement.encode(Acknowledgement.Data(false, res)); + + vm.expectRevert(AckIsNotSuccess.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_AckPayloadDecodeFailed() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + + // PacketData with empty payload + bytes memory emptyPayload = + PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), bytes(""))); + bytes memory ack = Acknowledgement.encode(Acknowledgement.Data(true, emptyPayload)); + + vm.expectRevert(PayloadDecodeFailed.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_AckTypeURLUnexpected() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + + // Wrong type URL + PacketAcknowledgementCall.Data memory pac = + PacketAcknowledgementCall.Data(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + bytes memory payload = Any.encode(Any.Data("/wrong.type.url", PacketAcknowledgementCall.encode(pac))); + bytes memory res = PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), payload)); + bytes memory ack = Acknowledgement.encode(Acknowledgement.Data(true, res)); + + vm.expectRevert(UnexpectedTypeURL.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_PacketPayloadDecodeFailed() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Create packet with empty payload data + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + p.data = PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), bytes(""))); + + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(PayloadDecodeFailed.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_PacketTypeURLUnexpected() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Packet with wrong type URL + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + + PacketDataCall.Data memory pdc = PacketDataCall.Data({ + tx_id: abi.encode(TX_ID), + tx: PacketDataCallResolvedContractTransaction.Data( + Any.Data("", ""), new AuthAccount.Data[](0), "", ReturnValue.Data(""), new Any.Data[](0) + ) + }); + + bytes memory payload = Any.encode(Any.Data("/wrong.packet.type", PacketDataCall.encode(pdc))); + bytes memory data = PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), payload)); + p.data = data; + + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(UnexpectedTypeURL.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_InvalidTxIDLength() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Packet with wrong TxID length (empty bytes instead of 32 bytes) + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + + PacketDataCall.Data memory pdc = PacketDataCall.Data({ + tx_id: hex"", // Empty ID + tx: PacketDataCallResolvedContractTransaction.Data( + Any.Data("", ""), new AuthAccount.Data[](0), "", ReturnValue.Data(""), new Any.Data[](0) + ) + }); + + bytes memory payload = + Any.encode(Any.Data("/cross.core.atomic.simple.PacketDataCall", PacketDataCall.encode(pdc))); + bytes memory data = PacketData.encode(PacketData.Data(Header.Data(new HeaderField.Data[](0)), payload)); + p.data = data; + + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(InvalidTxIDLength.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_CoordinatorStateNotFound() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Set protocol to unknown to simulate state not found + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + cs.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_UNKNOWN; + harness.setCoordinatorState(TX_ID, cs); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(abi.encodeWithSelector(CoordinatorStateNotFound.selector, TX_ID)); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_CoordinatorPhaseNotPrepare() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_COMMIT); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(CoordinatorPhaseNotPrepare.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_AllTransactionsConfirmed() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Mark both as confirmed + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + uint32[] memory allConfirmed = new uint32[](2); + allConfirmed[0] = 0; // Coordinator + allConfirmed[1] = 1; // Participant + cs.confirmed_txs = allConfirmed; + harness.setCoordinatorState(TX_ID, cs); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(AllTransactionsConfirmed.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_ChannelNotFound() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + // Mock Handler returns not found + mockHandler.setFoundChannel(false); + + vm.expectRevert(ChannelNotFound.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_ChannelMismatch() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-bad", "channel-bad"); // Wrong channel + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(UnexpectedSourceChannel.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_UnexpectedCommitStatus() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + + // Status UNKNOWN (0) + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_UNKNOWN); + + vm.expectRevert(UnexpectedCommitStatus.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_CoordinatorStateInconsistent() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Remove coordinator confirmation to trigger inconsistency + // (logic expects that if we are here, we are adding participant confirmation, so we should have coordinator confirmed) + CoordinatorState.Data memory cs = harness.getCoordState(TX_ID); + cs.confirmed_txs = new uint32[](0); // Empty confirmation + harness.setCoordinatorState(TX_ID, cs); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(CoordinatorStateInconsistent.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_CoordinatorTxStatusNotPrepare() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + // Set local tx state to something else (e.g. ABORT) + ContractTransactionState.Data memory ts = harness.getContractTxState(TX_ID, 0); + ts.status = ContractTransactionState.ContractTransactionStatus.CONTRACT_TRANSACTION_STATUS_ABORT; + harness.setContractTxState(TX_ID, 0, ts); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(CoordinatorTxStatusNotPrepare.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_ModuleNotInitialized() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + // Unregister module + harness.setModule(IContractModule(address(0))); + + vm.expectRevert(ModuleNotInitialized.selector); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_StateNotFound() public { + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + vm.expectRevert(abi.encodeWithSelector(CoordinatorStateNotFound.selector, TX_ID)); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_OnCommitReverts() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + mockModule.setRevertOnCommit(true); + + vm.expectRevert("MockModule: OnCommit failed"); + harness.exposed_handleAcknowledgement(p, ack); + } + + function test_handleAck_RevertWhen_OnAbortReverts() public { + _setupCoordStateForAck(CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE); + + Packet memory p = _createPacket(TX_ID, "", "port-1", "channel-1"); + bytes memory ack = _createAck(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED); + + mockModule.setRevertOnAbort(true); + + vm.expectRevert("MockModule: OnAbort failed"); + harness.exposed_handleAcknowledgement(p, ack); + } } diff --git a/test/TxAuthManager.t.sol b/test/TxAuthManager.t.sol new file mode 100644 index 0000000..f7360fb --- /dev/null +++ b/test/TxAuthManager.t.sol @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings, function-max-lines +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import {ICrossError} from "../src/core/ICrossError.sol"; +import "../src/core/TxAuthManager.sol"; +import {Account as AuthAccount, TxAuthState, AuthType} from "../src/proto/cross/core/auth/Auth.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +contract MockValidVerifier is IAuthExtensionVerifier { + function verify(bytes32, AuthAccount.Data calldata) external view override returns (bool) { + return true; + } +} + +contract MockInvalidVerifier is IAuthExtensionVerifier { + function verify(bytes32, AuthAccount.Data calldata) external view override returns (bool) { + return false; + } +} + +contract MockRevertingVerifier is IAuthExtensionVerifier { + function verify(bytes32, AuthAccount.Data calldata) external view override returns (bool) { + revert("MockRevertingVerifier: Staticcall failed"); + } +} + +contract TxAuthManagerHarness is TxAuthManager { + function exposed_accountKey(AuthAccount.Data memory a) public pure returns (bytes32) { + return _accountKey(a); + } + + function exposed_getRemainingSigners(bytes32 txID) public view returns (AuthAccount.Data[] memory out) { + CrossStore.AuthStorage storage s = _getAuthStorage(); + return _getRemainingSigners(s, txID); + } + + function exposed_setStateFromRemainingList(bytes32 txID, AuthAccount.Data[] memory signers) public { + CrossStore.AuthStorage storage s = _getAuthStorage(); + _setStateFromRemainingList(s, txID, signers); + } +} + +contract TxAuthManagerTest is Test, ICrossError { + TxAuthManagerHarness private harness; + bytes32 private txID = keccak256("test_tx_id"); + + // Auth Types + AuthType.Data private localAuthType; + AuthType.Data private extAuthTypeValid; + AuthType.Data private extAuthTypeInvalid; + AuthType.Data private extAuthTypeReverting; + AuthType.Data private extAuthTypeNotFound; + + // Signer Accounts + AuthAccount.Data private signerA; + AuthAccount.Data private signerB; + AuthAccount.Data private signerC; + AuthAccount.Data private extSignerAValid; + AuthAccount.Data private extSignerBValid; + AuthAccount.Data private extSignerInvalid; + AuthAccount.Data private extSignerReverting; + AuthAccount.Data private extSignerNotFound; + + // Verifier URLs + string private constant URL_VALID = "/verifier/valid"; + string private constant URL_INVALID = "/verifier/invalid"; + string private constant URL_REVERTING = "/verifier/reverting"; + string private constant URL_NOT_FOUND = "/verifier/notfound"; + + function setUp() public { + // 1. Deploy Mock Verifiers + MockValidVerifier validVerifier = new MockValidVerifier(); + MockInvalidVerifier invalidVerifier = new MockInvalidVerifier(); + MockRevertingVerifier revertingVerifier = new MockRevertingVerifier(); + + // 2. Setup Verifier Arrays + string[] memory typeUrls = new string[](3); + typeUrls[0] = URL_VALID; + typeUrls[1] = URL_INVALID; + typeUrls[2] = URL_REVERTING; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](3); + verifiers[0] = IAuthExtensionVerifier(validVerifier); + verifiers[1] = IAuthExtensionVerifier(invalidVerifier); + verifiers[2] = IAuthExtensionVerifier(revertingVerifier); + + // 3. Deploy Harness + harness = new TxAuthManagerHarness(); + harness.initialize(typeUrls, verifiers); + + // 4. Setup Auth Types + GoogleProtobufAny.Data memory emptyAny = GoogleProtobufAny.Data({type_url: "", value: ""}); + localAuthType = AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: emptyAny}); + + extAuthTypeValid = AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, + option: GoogleProtobufAny.Data({type_url: URL_VALID, value: ""}) + }); + extAuthTypeInvalid = AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, + option: GoogleProtobufAny.Data({type_url: URL_INVALID, value: ""}) + }); + extAuthTypeReverting = AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, + option: GoogleProtobufAny.Data({type_url: URL_REVERTING, value: ""}) + }); + extAuthTypeNotFound = AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, + option: GoogleProtobufAny.Data({type_url: URL_NOT_FOUND, value: ""}) + }); + + // 5. Setup Signer Accounts + signerA = AuthAccount.Data({id: bytes("signerA"), auth_type: localAuthType}); + signerB = AuthAccount.Data({id: bytes("signerB"), auth_type: localAuthType}); + signerC = AuthAccount.Data({id: bytes("signerC"), auth_type: localAuthType}); + + extSignerAValid = AuthAccount.Data({id: bytes("extSignerA"), auth_type: extAuthTypeValid}); + extSignerBValid = AuthAccount.Data({id: bytes("extSignerB"), auth_type: extAuthTypeValid}); + extSignerInvalid = AuthAccount.Data({id: bytes("extSignerInvalid"), auth_type: extAuthTypeInvalid}); + extSignerReverting = AuthAccount.Data({id: bytes("extSignerReverting"), auth_type: extAuthTypeReverting}); + extSignerNotFound = AuthAccount.Data({id: bytes("extSignerNotFound"), auth_type: extAuthTypeNotFound}); + } + + function test_initialize_SucceedsWithEmptyArrays() public { + string[] memory typeUrls = new string[](0); + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](0); + + TxAuthManagerHarness localHarness = new TxAuthManagerHarness(); + localHarness.initialize(typeUrls, verifiers); + assertTrue(address(localHarness) != address(0), "Harness should deploy"); + } + + function test_initialize_SucceedsAndEmitsEvents() public { + string[] memory typeUrls = new string[](2); + typeUrls[0] = URL_VALID; + typeUrls[1] = URL_INVALID; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](2); + IAuthExtensionVerifier verifier1 = new MockValidVerifier(); + IAuthExtensionVerifier verifier2 = new MockInvalidVerifier(); + verifiers[0] = verifier1; + verifiers[1] = verifier2; + + TxAuthManagerHarness localHarness = new TxAuthManagerHarness(); + localHarness.initialize(typeUrls, verifiers); + assertTrue(address(localHarness) != address(0), "Harness should deploy"); + } + + function test_initialize_RevertWhen_AlreadyInitialized() public { + string[] memory typeUrls = new string[](1); + typeUrls[0] = URL_VALID; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](1); + verifiers[0] = new MockValidVerifier(); + + TxAuthManagerHarness localHarness = new TxAuthManagerHarness(); + localHarness.initialize(typeUrls, verifiers); + + vm.expectRevert(Initializable.InvalidInitialization.selector); + localHarness.initialize(typeUrls, verifiers); + } + + function test_initialize_RevertWhen_ArrayLengthMismatch() public { + string[] memory typeUrls = new string[](1); + typeUrls[0] = URL_VALID; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](2); + verifiers[0] = new MockValidVerifier(); + verifiers[1] = new MockValidVerifier(); + + TxAuthManagerHarness localHarness = new TxAuthManagerHarness(); + + vm.expectRevert(ArrayLengthMismatch.selector); + localHarness.initialize(typeUrls, verifiers); + } + + function test_initialize_RevertWhen_EmptyTypeUrl() public { + string[] memory typeUrls = new string[](1); + typeUrls[0] = ""; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](1); + verifiers[0] = new MockValidVerifier(); + + TxAuthManagerHarness localHarness = new TxAuthManagerHarness(); + + vm.expectRevert(EmptyTypeUrl.selector); + localHarness.initialize(typeUrls, verifiers); + } + + function test_initialize_RevertWhen_ZeroAddressVerifier() public { + string[] memory typeUrls = new string[](1); + typeUrls[0] = URL_VALID; + + IAuthExtensionVerifier[] memory verifiers = new IAuthExtensionVerifier[](1); + verifiers[0] = IAuthExtensionVerifier(address(0)); // Zero address + + TxAuthManagerHarness localHarness = new TxAuthManagerHarness(); + + vm.expectRevert(ZeroAddressVerifier.selector); + localHarness.initialize(typeUrls, verifiers); + } + + function test_initAuthState_Succeeds() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); + signers[0] = signerA; + signers[1] = signerB; + + harness.initAuthState(txID, signers); + + TxAuthState.Data memory state = harness.getAuthState(txID); + assertEq(state.remaining_signers.length, 2, "Should initialize with 2 signers"); + } + + function test_initAuthState_RevertWhen_AlreadyInitialized() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = signerA; + + harness.initAuthState(txID, signers); // First time + + vm.expectRevert(abi.encodeWithSelector(ICrossError.AuthStateAlreadyInitialized.selector, txID)); + harness.initAuthState(txID, signers); // Second time + } + + function test_initAuthState_HandlesDuplicateSigners() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](3); + signers[0] = signerA; + signers[1] = signerB; + signers[2] = signerA; // Duplicate + + harness.initAuthState(txID, signers); + + TxAuthState.Data memory state = harness.getAuthState(txID); + assertEq(state.remaining_signers.length, 2, "Duplicate signers should be counted once"); + } + + function test_isCompletedAuth_ReturnsTrueWhenCompleted() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = signerA; + harness.initAuthState(txID, signers); + + harness.sign(txID, signers); + + assertTrue(harness.isCompletedAuth(txID), "Should return true when auth is completed"); + } + + function test_isCompletedAuth_ReturnsFalseWhenNotCompleted() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); + signers[0] = signerA; + signers[1] = signerB; + harness.initAuthState(txID, signers); + + AuthAccount.Data[] memory partialSigners = new AuthAccount.Data[](1); + partialSigners[0] = signerA; + harness.sign(txID, partialSigners); + + assertFalse(harness.isCompletedAuth(txID), "Should return false when auth is not completed"); + } + + function test_isCompletedAuth_ReturnsFalseWhenInitializedEmpty() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](0); + harness.initAuthState(txID, signers); + + assertTrue(harness.isCompletedAuth(txID), "Should return true if 0 signers required"); + } + + function test_isCompletedAuth_RevertWhen_NotInitialized() public { + vm.expectRevert(abi.encodeWithSelector(ICrossError.IDNotFound.selector, txID)); + harness.isCompletedAuth(txID); + } + + function test_sign_PartialSignReturnsFalse() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); + signers[0] = signerA; + signers[1] = signerB; + harness.initAuthState(txID, signers); + + AuthAccount.Data[] memory partialSigners = new AuthAccount.Data[](1); + partialSigners[0] = signerA; + + assertFalse(harness.sign(txID, partialSigners), "Should not be completed"); + } + + function test_sign_FinalSignReturnsTrue() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); + signers[0] = signerA; + signers[1] = signerB; + harness.initAuthState(txID, signers); + + AuthAccount.Data[] memory partialSigners = new AuthAccount.Data[](1); + partialSigners[0] = signerA; + assertFalse(harness.sign(txID, partialSigners), "Should not be completed"); // Sign A + + partialSigners[0] = signerB; + assertTrue(harness.sign(txID, partialSigners), "Should be completed"); // Sign B + } + + function test_sign_IgnoresUnknownSigners() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = signerA; + harness.initAuthState(txID, signers); + + AuthAccount.Data[] memory unknownSigners = new AuthAccount.Data[](2); + unknownSigners[0] = signerB; + unknownSigners[1] = signerC; + + assertFalse(harness.sign(txID, unknownSigners), "Should not be completed"); + + TxAuthState.Data memory state = harness.getAuthState(txID); + assertEq(state.remaining_signers.length, 1, "Remaining signers should not change"); + } + + function test_sign_IgnoresDuplicateSignatures() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); + signers[0] = signerA; + signers[1] = signerB; + harness.initAuthState(txID, signers); + + AuthAccount.Data[] memory partialSigners = new AuthAccount.Data[](1); + partialSigners[0] = signerA; + + assertFalse(harness.sign(txID, partialSigners), "Sign A (1st time)"); // Sign A + + TxAuthState.Data memory state = harness.getAuthState(txID); + assertEq(state.remaining_signers.length, 1, "Should have 1 remaining signer (B)"); + assertEq(state.remaining_signers[0].id, signerB.id); + + assertFalse(harness.sign(txID, partialSigners), "Sign A (2nd time)"); + + state = harness.getAuthState(txID); + assertEq(state.remaining_signers.length, 1, "Remaining signers should not change"); + } + + function test_sign_RevertWhen_NotInitialized() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = signerA; + + vm.expectRevert(abi.encodeWithSelector(ICrossError.IDNotFound.selector, txID)); + harness.sign(txID, signers); + } + + function test_sign_RevertWhen_AuthAlreadyCompleted() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = signerA; + harness.initAuthState(txID, signers); + + assertTrue(harness.sign(txID, signers), "Should be completed"); // First sign + + vm.expectRevert(abi.encodeWithSelector(ICrossError.AuthAlreadyCompleted.selector, txID)); + harness.sign(txID, signers); // Sign again + } + + function test_getAuthState_ReturnsCorrectRemainingSigners() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](3); + signers[0] = signerA; + signers[1] = signerB; + signers[2] = signerC; + harness.initAuthState(txID, signers); + + AuthAccount.Data[] memory partialSigners = new AuthAccount.Data[](1); + partialSigners[0] = signerB; + assertFalse(harness.sign(txID, partialSigners), "Should not be completed"); + + TxAuthState.Data memory state = harness.getAuthState(txID); + + assertEq(state.remaining_signers.length, 2, "Should have 2 remaining signers"); + assertEq(state.remaining_signers[0].id, signerA.id, "Signer A should remain"); + assertEq(state.remaining_signers[1].id, signerC.id, "Signer C should remain"); + } + + function test_getAuthState_RevertWhen_NotInitialized() public { + vm.expectRevert(abi.encodeWithSelector(ICrossError.IDNotFound.selector, txID)); + harness.getAuthState(txID); + } + + function test_accountKey_GeneratesUniqueKeys() public { + bytes32 keyA = harness.exposed_accountKey(signerA); + bytes32 keyB = harness.exposed_accountKey(signerB); + assertNotEq(keyA, keyB, "Different IDs should produce different keys"); + + AuthAccount.Data memory signerAAltAuth = AuthAccount.Data({id: signerA.id, auth_type: extAuthTypeValid}); + bytes32 keyAAltAuth = harness.exposed_accountKey(signerAAltAuth); + assertNotEq(keyA, keyAAltAuth, "Different auth_types should produce different keys"); + + AuthAccount.Data memory signerACopy = AuthAccount.Data({id: bytes("signerA"), auth_type: localAuthType}); + bytes32 keyACopy = harness.exposed_accountKey(signerACopy); + assertEq(keyA, keyACopy, "Identical accounts should produce the same key"); + } + + function test_accountKey_ExtensionModeIgnoresOptionValue() public { + bytes memory id = bytes("user1"); + string memory typeUrl = URL_VALID; + + GoogleProtobufAny.Data memory optionA = GoogleProtobufAny.Data({type_url: typeUrl, value: hex"aaaa"}); + GoogleProtobufAny.Data memory optionB = GoogleProtobufAny.Data({type_url: typeUrl, value: hex"bbbb"}); + + AuthAccount.Data memory accA = AuthAccount.Data({ + id: id, auth_type: AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, option: optionA}) + }); + + AuthAccount.Data memory accB = AuthAccount.Data({ + id: id, auth_type: AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_EXTENSION, option: optionB}) + }); + + bytes32 keyA = harness.exposed_accountKey(accA); + bytes32 keyB = harness.exposed_accountKey(accB); + + assertEq(keyA, keyB, "Extension mode should ignore option.value in accountKey generation"); + } + + function test_setStateFromRemainingList_HandlesDuplicatesAndReturnsRemains() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](3); + signers[0] = signerA; + signers[1] = signerB; + signers[2] = signerA; // Duplicate + + harness.exposed_setStateFromRemainingList(txID, signers); + + AuthAccount.Data[] memory remaining = harness.exposed_getRemainingSigners(txID); + + assertEq(remaining.length, 2, "getRemainingSigners should return 2 signers after deduplication"); + assertEq(remaining[0].id, signerA.id, "Signer A should be in remaining list"); + assertEq(remaining[1].id, signerB.id, "Signer B should be in remaining list"); + } + + function test_getRemainingSigners_TracksSigningProgress() public { + AuthAccount.Data[] memory allSigners = new AuthAccount.Data[](3); + allSigners[0] = signerA; + allSigners[1] = signerB; + allSigners[2] = signerC; + harness.initAuthState(txID, allSigners); + + AuthAccount.Data[] memory partialSigners = new AuthAccount.Data[](1); + partialSigners[0] = signerB; + harness.sign(txID, partialSigners); // Sign B + + AuthAccount.Data[] memory remaining = harness.exposed_getRemainingSigners(txID); + assertEq(remaining.length, 2, "getRemainingSigners should return 2 signers"); + assertEq(remaining[0].id, signerA.id, "Signer A should remain"); + assertEq(remaining[1].id, signerC.id, "Signer C should remain"); + + partialSigners[0] = signerA; + harness.sign(txID, partialSigners); // Sign A + + remaining = harness.exposed_getRemainingSigners(txID); + assertEq(remaining.length, 1, "getRemainingSigners should return 1 signer"); + assertEq(remaining[0].id, signerC.id, "Signer C should remain"); + + partialSigners[0] = signerC; + harness.sign(txID, partialSigners); // Sign C + + remaining = harness.exposed_getRemainingSigners(txID); + assertEq(remaining.length, 0, "getRemainingSigners should return 0 signers"); + } + + function test_verifySignatures_SucceedsSingleSigner() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = extSignerAValid; + + harness.verifySignatures(txID, signers); + } + + function test_verifySignatures_SucceedsMultipleSigners() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](2); + signers[0] = extSignerAValid; + signers[1] = extSignerBValid; + + harness.verifySignatures(txID, signers); + } + + function test_verifySignatures_RevertWhen_TooManySigners() public { + uint256 count = 33; + + AuthAccount.Data[] memory signers = new AuthAccount.Data[](count); + + for (uint256 i = 0; i < count; ++i) { + signers[i] = extSignerAValid; + } + + vm.expectRevert(abi.encodeWithSelector(TooManySigners.selector, count, 32)); + harness.verifySignatures(txID, signers); + } + + function test_verifySignatures_RevertWhen_AuthModeMismatch() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = signerA; + + vm.expectRevert(AuthModeMismatch.selector); + harness.verifySignatures(txID, signers); + } + + function test_verifySignatures_RevertWhen_VerifierNotFound() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = extSignerNotFound; + + vm.expectRevert(abi.encodeWithSelector(VerifierNotFound.selector, URL_NOT_FOUND)); + harness.verifySignatures(txID, signers); + } + + function test_verifySignatures_RevertWhen_StaticCallFails() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = extSignerReverting; + + vm.expectRevert(bytes("MockRevertingVerifier: Staticcall failed")); + harness.verifySignatures(txID, signers); + } + + function test_verifySignatures_RevertWhen_VerifierReturnsFalse() public { + AuthAccount.Data[] memory signers = new AuthAccount.Data[](1); + signers[0] = extSignerInvalid; + + vm.expectRevert(abi.encodeWithSelector(VerifierReturnedFalse.selector, txID, URL_INVALID)); + harness.verifySignatures(txID, signers); + } +} diff --git a/test/TxIdUtils.t.sol b/test/TxIdUtils.t.sol new file mode 100644 index 0000000..9026ab4 --- /dev/null +++ b/test/TxIdUtils.t.sol @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable func-name-mixedcase, one-contract-per-file, gas-small-strings +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import {TxIDUtils} from "../src/core/TxIDUtils.sol"; +import {MsgInitiateTx, ContractTransaction, Link, ReturnValue} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {GoogleProtobufAny as Any} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {AuthType, Account as AuthAccount} from "../src/proto/cross/core/auth/Auth.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; +import {Tx} from "../src/proto/cross/core/tx/Tx.sol"; + +contract TxIDUtilsHarness { + using TxIDUtils for MsgInitiateTx.Data; + + function exposed_computeTxId(MsgInitiateTx.Data calldata msg_) external pure returns (bytes32) { + return msg_.computeTxId(); + } +} + +contract TxIDUtilsTest is Test { + TxIDUtilsHarness private harness; + + function setUp() public { + harness = new TxIDUtilsHarness(); + } + + function test_computeTxId_SucceedsWithTypicalMsg() public view { + MsgInitiateTx.Data memory msg_ = _createBaseMsg(); + bytes32 id = harness.exposed_computeTxId(msg_); + assertNotEq(id, bytes32(0), "Computed TxID should not be zero"); + } + + function test_computeTxId_SucceedsWithMinimalMsg() public view { + MsgInitiateTx.Data memory msg_ = MsgInitiateTx.Data({ + chain_id: "", + nonce: 0, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_UNKNOWN, + contract_transactions: new ContractTransaction.Data[](0), + signers: new AuthAccount.Data[](0), + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0 + }); + + bytes32 id = harness.exposed_computeTxId(msg_); + assertNotEq(id, bytes32(0), "Minimal message should still produce a valid hash"); + } + + function test_computeTxId_ReturnsConsistentId() public view { + MsgInitiateTx.Data memory msg1 = _createBaseMsg(); + MsgInitiateTx.Data memory msg2 = _createBaseMsg(); + assertEq(harness.exposed_computeTxId(msg1), harness.exposed_computeTxId(msg2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentNonce() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.nonce = m1.nonce + 1; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentChainId() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.chain_id = "other-chain"; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentCommitProtocol() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_TPC; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentTimeoutHeight_RevisionNumber() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.timeout_height.revision_number = 1; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentTimeoutHeight_RevisionHeight() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.timeout_height.revision_height = 100; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentTimeoutTimestamp() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.timeout_timestamp = 123456789; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentRootSigners() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.signers = new AuthAccount.Data[](1); + m2.signers[0] = _createAccount("signer1"); + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentLocalSigners() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.contract_transactions[0].signers = new AuthAccount.Data[](1); + m2.contract_transactions[0].signers[0] = _createAccount("local-signer"); + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentTxArrayLength() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + + m2.contract_transactions = new ContractTransaction.Data[](2); + m2.contract_transactions[0] = m1.contract_transactions[0]; + m2.contract_transactions[1] = m1.contract_transactions[0]; + + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentCallInfo() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.contract_transactions[0].call_info = hex"deadbeef"; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentChannelAnyValue() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.contract_transactions[0].cross_chain_channel.value = hex"010203"; + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentReturnValue() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.contract_transactions[0].return_value = ReturnValue.Data(hex"ffee"); + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentLinks() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.contract_transactions[0].links = new Link.Data[](1); + m2.contract_transactions[0].links[0] = Link.Data(0); + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentSignerAuthMode() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + m1.signers = new AuthAccount.Data[](1); + m1.signers[0] = _createAccount("signer1"); + + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.signers = new AuthAccount.Data[](1); + m2.signers[0] = _createAccount("signer1"); + m2.signers[0].auth_type.mode = AuthType.AuthMode.AUTH_MODE_EXTENSION; + + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentSignerAuthOptionTypeUrl() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + m1.signers = new AuthAccount.Data[](1); + m1.signers[0] = _createAccount("signer1"); + + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.signers = new AuthAccount.Data[](1); + m2.signers[0] = _createAccount("signer1"); + m2.signers[0].auth_type.option.type_url = "/new.verifier.v1"; + + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + function test_computeTxId_ReturnsDifferentIdForDifferentSignerAuthOptionValue() public view { + MsgInitiateTx.Data memory m1 = _createBaseMsg(); + m1.signers = new AuthAccount.Data[](1); + m1.signers[0] = _createAccount("signer1"); + + MsgInitiateTx.Data memory m2 = _createBaseMsg(); + m2.signers = new AuthAccount.Data[](1); + m2.signers[0] = _createAccount("signer1"); + m2.signers[0].auth_type.option.value = hex"123456"; + + assertNotEq(harness.exposed_computeTxId(m1), harness.exposed_computeTxId(m2)); + } + + // --- Helpers --- + + function _createBaseMsg() internal pure returns (MsgInitiateTx.Data memory) { + ContractTransaction.Data[] memory txs = new ContractTransaction.Data[](1); + txs[0] = ContractTransaction.Data({ + cross_chain_channel: Any.Data("/type.url", hex"00"), + signers: new AuthAccount.Data[](0), + call_info: hex"abcd", + return_value: ReturnValue.Data(""), + links: new Link.Data[](0) + }); + + return MsgInitiateTx.Data({ + chain_id: "test-chain", + nonce: 1, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + contract_transactions: txs, + signers: new AuthAccount.Data[](0), + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0 + }); + } + + function _createAccount(string memory id) internal pure returns (AuthAccount.Data memory) { + return AuthAccount.Data({ + id: bytes(id), + auth_type: AuthType.Data({ + mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: Any.Data({type_url: "", value: hex""}) + }) + }); + } +} diff --git a/test/TxManager.t.sol b/test/TxManager.t.sol new file mode 100644 index 0000000..42581d2 --- /dev/null +++ b/test/TxManager.t.sol @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: Apache-2.0 +// solhint-disable one-contract-per-file, func-name-mixedcase, gas-small-strings, function-max-lines +pragma solidity ^0.8.20; + +import "forge-std/src/Test.sol"; +import "../src/core/TxManager.sol"; +import "../src/core/TxManagerBase.sol"; +import { + MsgInitiateTx, + MsgInitiateTxResponse, + ContractTransaction, + Link, + ReturnValue +} from "../src/proto/cross/core/initiator/Initiator.sol"; +import {ICrossError} from "../src/core/ICrossError.sol"; +import {Account as AuthAccount, AuthType} from "../src/proto/cross/core/auth/Auth.sol"; +import {Tx} from "../src/proto/cross/core/tx/Tx.sol"; +import {IbcCoreClientV1Height} from "../src/proto/ibc/core/client/v1/client.sol"; +import {CoordinatorState} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {GoogleProtobufAny} from "@hyperledger-labs/yui-ibc-solidity/contracts/proto/GoogleProtobufAny.sol"; +import {Packet} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/04-channel/IIBCChannel.sol"; +import {IIBCHandler} from "@hyperledger-labs/yui-ibc-solidity/contracts/core/25-handler/IIBCHandler.sol"; +import {IContractModule} from "../src/core/IContractModule.sol"; +import { + PacketAcknowledgementCall, + PacketData, + Acknowledgement +} from "../src/proto/cross/core/atomic/simple/AtomicSimple.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +contract DummyIBCHandler {} + +contract DummyContractModule {} + +contract TxManagerHarness is TxManager { + uint256 public runCount; + bytes32 public lastRunTxID; + uint256 public initCount; + uint256 public handlePacketCount; + uint256 public handleAckCount; + uint256 public handleTimeoutCount; + + constructor() TxManager() {} + + function getTxStatus(bytes32 txID) public view returns (MsgInitiateTxResponse.InitiateTxStatus) { + CrossStore.TxStorage storage t = _getTxStorage(); + return t.txStatus[txID]; + } + + function getTxCoordSigners(bytes32 txID) public view returns (AuthAccount.Data[] memory) { + CrossStore.TxStorage storage t = _getTxStorage(); + return t.txCoordSigners[txID]; + } + + function _runTx(bytes32 txID, MsgInitiateTx.Data calldata) internal virtual override { + ++runCount; + lastRunTxID = txID; + } + + function __initTxAtomicSimple(IIBCHandler, IContractModule) internal override { + ++initCount; + } + + function _handlePacket(Packet calldata) internal override returns (bytes memory) { + ++handlePacketCount; + return hex"1234"; // Dummy ACK + } + + function _handleAcknowledgement(Packet calldata, bytes calldata) internal override { + ++handleAckCount; + } + + function _handleTimeout(Packet calldata) internal override { + ++handleTimeoutCount; + } + + function exposed_getIBCHandler() public view returns (IIBCHandler) { + return getIBCHandler(); + } + + function exposed_getModule() public returns (IContractModule) { + Packet memory p; + return getModule(p); + } + + function setCoordinatorState(bytes32 txID, CoordinatorState.Data calldata data) public { + _saveCoordinatorState(txID, data); + } +} + +contract TxManagerTest is Test, ICrossError { + TxManagerHarness private harness; + bytes32 private txID; + MsgInitiateTx.Data private txMsg; + + DummyIBCHandler private dummyHandler; + DummyContractModule private dummyModule; + + function setUp() public { + harness = new TxManagerHarness(); + dummyHandler = new DummyIBCHandler(); + dummyModule = new DummyContractModule(); + + AuthAccount.Data[] memory signers; + ContractTransaction.Data[] memory txs; + + txMsg = MsgInitiateTx.Data({ + chain_id: "test-chain", + nonce: 1, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE, + timeout_height: IbcCoreClientV1Height.Data(0, 0), + timeout_timestamp: 0, + signers: signers, + contract_transactions: txs + }); + + txID = sha256(MsgInitiateTx.encode(txMsg)); + } + + // --- initialize --- + + function test_initialize_Succeeds() public { + harness.initialize(IIBCHandler(address(dummyHandler)), IContractModule(address(dummyModule))); + + assertEq(harness.initCount(), 1, "initialize should be called once"); + } + + function test_initialize_RevertWhen_DoubleInit() public { + harness.initialize(IIBCHandler(address(dummyHandler)), IContractModule(address(dummyModule))); + + vm.expectRevert(Initializable.InvalidInitialization.selector); + harness.initialize(IIBCHandler(address(dummyHandler)), IContractModule(address(dummyModule))); + } + + // --- handlePacket --- + + function test_handlePacket_CallsLogic() public { + harness.initialize(IIBCHandler(address(dummyHandler)), IContractModule(address(dummyModule))); + + Packet memory p; + bytes memory ack = harness.handlePacket(p); + + assertEq(harness.handlePacketCount(), 1); + assertEq(ack, hex"1234"); + } + + // --- handleAcknowledgement --- + + function test_handleAcknowledgement_CallsLogic() public { + harness.initialize(IIBCHandler(address(dummyHandler)), IContractModule(address(dummyModule))); + + Packet memory p; + bytes memory emptyAck; + harness.handleAcknowledgement(p, emptyAck); + + assertEq(harness.handleAckCount(), 1); + } + + // --- handleTimeout --- + + function test_handleTimeout_CallsLogic() public { + harness.initialize(IIBCHandler(address(dummyHandler)), IContractModule(address(dummyModule))); + + Packet memory p; + harness.handleTimeout(p); + + assertEq(harness.handleTimeoutCount(), 1); + } + + // --- getPacketAcknowledgementCall --- + + function test_getPacketAcknowledgementCall_EncodesCorrectly() public { + bytes memory ackBytes = + harness.getPacketAcknowledgementCall(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK); + + Acknowledgement.Data memory ackData = Acknowledgement.decode(ackBytes); + assertTrue(ackData.is_success); + PacketData.Data memory pd = PacketData.decode(ackData.result); + GoogleProtobufAny.Data memory any_ = GoogleProtobufAny.decode(pd.payload); + PacketAcknowledgementCall.Data memory pac = PacketAcknowledgementCall.decode(any_.value); + assertEq(uint256(pac.status), uint256(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_OK)); + + ackBytes = harness.getPacketAcknowledgementCall(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED); + ackData = Acknowledgement.decode(ackBytes); + pd = PacketData.decode(ackData.result); + any_ = GoogleProtobufAny.decode(pd.payload); + pac = PacketAcknowledgementCall.decode(any_.value); + assertEq(uint256(pac.status), uint256(PacketAcknowledgementCall.CommitStatus.COMMIT_STATUS_FAILED)); + } + + // --- isTxRecorded --- + + function test_isTxRecorded_ReturnsTrueForKnownTx() public { + harness.createTx(txID, txMsg); + assertTrue(harness.isTxRecorded(txID), "Should return true for recorded tx"); + } + + function test_isTxRecorded_ReturnsFalseForUnknownTx() public { + assertFalse(harness.isTxRecorded(txID), "Should return false for unrecorded tx"); + } + + function test_createTx_SucceedsWithNonEmptyData() public { + bytes32 deepCopytxID = keccak256("deep_copy_tx"); + + // --- 1. Setup mock data --- + GoogleProtobufAny.Data memory emptyAny = GoogleProtobufAny.Data({type_url: "", value: ""}); + AuthType.Data memory localAuthType = AuthType.Data({mode: AuthType.AuthMode.AUTH_MODE_LOCAL, option: emptyAny}); + AuthAccount.Data memory signerA = AuthAccount.Data({id: bytes("signerA"), auth_type: localAuthType}); + + // --- 2. Build a complex calldata message with nested arrays --- + // 2a. Top-level signers + AuthAccount.Data[] memory signersMem = new AuthAccount.Data[](1); + signersMem[0] = signerA; + + // 2b. Nested contract transactions + ContractTransaction.Data[] memory txsMem = new ContractTransaction.Data[](1); + Link.Data[] memory linksMem = new Link.Data[](1); + linksMem[0] = Link.Data({src_index: 123}); + + txsMem[0].signers = signersMem; // Nested signers + txsMem[0].links = linksMem; // Nested links + txsMem[0].call_info = hex"C0FFEE"; + txsMem[0].cross_chain_channel = GoogleProtobufAny.Data({type_url: "xcc_type", value: hex"01"}); + txsMem[0].return_value = ReturnValue.Data({value: bytes("RETURNVAL")}); + + // 2c. Main message + MsgInitiateTx.Data memory nonEmptyTxMsg = MsgInitiateTx.Data({ + chain_id: "test-chain-deep", + nonce: 99, + commit_protocol: Tx.CommitProtocol.COMMIT_PROTOCOL_TPC, + timeout_height: IbcCoreClientV1Height.Data(1, 101), + timeout_timestamp: 202, + signers: signersMem, + contract_transactions: txsMem + }); + + // --- 3. Execute the function under test --- + harness.createTx(deepCopytxID, nonEmptyTxMsg); + + // --- 4. Assert status (ensures coverage for non-empty paths) --- + assertTrue(harness.isTxRecorded(deepCopytxID), "Tx should be recorded"); + assertEq( + uint256(harness.getTxStatus(deepCopytxID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING), + "Status should be PENDING" + ); + + // --- 5. Verify deep copy by reading back from storage --- + AuthAccount.Data[] memory txCoordSigners = harness.getTxCoordSigners(deepCopytxID); + + assertEq(txCoordSigners.length, 1, "Nested signers length mismatch"); + assertEq(txCoordSigners[0].id, signerA.id, "Nested signer id mismatch"); + assertEq( + uint256(txCoordSigners[0].auth_type.mode), uint256(localAuthType.mode), "Nested signer auth_type mismatch" + ); + } + + function test_createTx_RevertWhen_TxAlreadyExists() public { + harness.createTx(txID, txMsg); // First time + vm.expectRevert(abi.encodeWithSelector(TxAlreadyExists.selector, txID)); + harness.createTx(txID, txMsg); // Second time + } + + //--- runTxIfCompleted --- + + function test_runTxIfCompleted_RunsTxAndSetsVerifiedStatus() public { + harness.createTx(txID, txMsg); + assertEq( + uint256(harness.getTxStatus(txID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_PENDING), + "Status should be PENDING" + ); + harness.runTxIfCompleted(txID, txMsg); + assertEq(harness.runCount(), 1, "MockTxRunner should be called once"); + assertEq(harness.lastRunTxID(), txID, "MockTxRunner should be called with correct txID"); + assertEq( + uint256(harness.getTxStatus(txID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED), + "Status should be VERIFIED" + ); + } + + function test_runTxIfCompleted_DoesNothingForUnknownTx() public { + harness.runTxIfCompleted(txID, txMsg); + assertEq(harness.runCount(), 0, "MockTxRunner should not be called"); + assertEq( + uint256(harness.getTxStatus(txID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_UNKNOWN), + "Status should remain UNKNOWN" + ); + } + + function test_runTxIfCompleted_DoesNothingIfAlreadyVerified() public { + harness.createTx(txID, txMsg); + harness.runTxIfCompleted(txID, txMsg); // First run + assertEq(harness.runCount(), 1, "MockTxRunner should be called once"); + assertEq( + uint256(harness.getTxStatus(txID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED), + "Status should be VERIFIED" + ); + harness.runTxIfCompleted(txID, txMsg); // Second run + assertEq(harness.runCount(), 1, "MockTxRunner should not be called again"); + assertEq( + uint256(harness.getTxStatus(txID)), + uint256(MsgInitiateTxResponse.InitiateTxStatus.INITIATE_TX_STATUS_VERIFIED), + "Status should be VERIFIED" + ); + } + + function test_getCoordinatorState_ReturnsCorrectState() public { + CoordinatorState.Data memory expected; + expected.commit_protocol = Tx.CommitProtocol.COMMIT_PROTOCOL_SIMPLE; + expected.phase = CoordinatorState.CoordinatorPhase.COORDINATOR_PHASE_PREPARE; + + harness.setCoordinatorState(txID, expected); + + CoordinatorState.Data memory actual = harness.getCoordinatorState(txID); + + assertEq(uint256(actual.commit_protocol), uint256(expected.commit_protocol), "Commit protocol mismatch"); + assertEq(uint256(actual.phase), uint256(expected.phase), "Phase mismatch"); + } + + function test_getCoordinatorState_RevertsIfNotFound() public { + vm.expectRevert(abi.encodeWithSelector(CoordinatorStateNotFound.selector, txID)); + harness.getCoordinatorState(txID); + } +} diff --git a/third_party/proto/ibc/core/client/v1/client.proto b/third_party/proto/ibc/core/client/v1/client.proto index 4a6f832..0501fc6 100644 --- a/third_party/proto/ibc/core/client/v1/client.proto +++ b/third_party/proto/ibc/core/client/v1/client.proto @@ -120,7 +120,7 @@ message Height { option (gogoproto.goproto_stringer) = false; // the version that the client is currently on - uint64 version_number = 1 [(gogoproto.moretags) = "yaml:\"version_number\""]; + uint64 revision_number = 1 [(gogoproto.moretags) = "yaml:\"revision_number\""]; // the height within the given version - uint64 version_height = 2 [(gogoproto.moretags) = "yaml:\"version_height\""]; + uint64 revision_height = 2 [(gogoproto.moretags) = "yaml:\"revision_height\""]; }