From 7c6a94b08f1956cd1993003d78c7f11636275447 Mon Sep 17 00:00:00 2001 From: Evgenii Akentev Date: Mon, 8 Apr 2024 13:16:55 +0400 Subject: [PATCH] Hyperlane fixes --- cabal.project | 4 +- .../VerifierPlugin/Hyperlane/Binary.hs | 9 +- .../Hyperlane/Message/After224.hs | 43 ++-- .../Hyperlane/Message/Before224.hs | 3 +- .../Transaction/Message/After224.hs | 208 ++++++++---------- .../Transaction/Message/Before224.hs | 5 +- 6 files changed, 136 insertions(+), 136 deletions(-) diff --git a/cabal.project b/cabal.project index 931f547ab7..c21ce463aa 100644 --- a/cabal.project +++ b/cabal.project @@ -71,8 +71,8 @@ package yet-another-logger source-repository-package type: git location: https://github.com/kadena-io/pact.git - tag: 85301eff5b66d2733d4213f16271d91128689d4b - --sha256: sha256-3ARA5apBLK+urukjLZjOZF9dP1lDN5E1dkFC58sTcBE= + tag: c6efe69fcafefc01b34d738c8a64bac5efea7b8a + --sha256: sha256-wTTeg8N4LPEy0pS2suY5OCDtlVMB0WQVFz2Dkrx4ea0= source-repository-package type: git diff --git a/src/Chainweb/VerifierPlugin/Hyperlane/Binary.hs b/src/Chainweb/VerifierPlugin/Hyperlane/Binary.hs index 0182368253..e968d3c90b 100644 --- a/src/Chainweb/VerifierPlugin/Hyperlane/Binary.hs +++ b/src/Chainweb/VerifierPlugin/Hyperlane/Binary.hs @@ -18,6 +18,7 @@ module Chainweb.VerifierPlugin.Hyperlane.Binary , putMerkleRootMultisigIsmMetadata , getMerkleRootMultisigIsmMetadata + , padLeft , ethereumAddressSize ) where @@ -48,9 +49,9 @@ putHyperlaneMessage (HyperlaneMessage {..}) = do putWord8 hmVersion putWord32be hmNonce putWord32be hmOriginDomain - putRawByteString (padLeft hmSender) + putRawByteString hmSender putWord32be hmDestinationDomain - putRawByteString (padLeft hmRecipient) + putRawByteString hmRecipient putRawByteString hmMessageBody @@ -59,9 +60,9 @@ getHyperlaneMessage = do hmVersion <- getWord8 hmNonce <- getWord32be hmOriginDomain <- getWord32be - hmSender <- BS.takeEnd ethereumAddressSize <$> getByteString 32 + hmSender <- getByteString 32 hmDestinationDomain <- getWord32be - hmRecipient <- BS.dropWhile (== 0) <$> getByteString 32 + hmRecipient <- getByteString 32 hmMessageBody <- BL.toStrict <$> getRemainingLazyByteString return $ HyperlaneMessage {..} diff --git a/src/Chainweb/VerifierPlugin/Hyperlane/Message/After224.hs b/src/Chainweb/VerifierPlugin/Hyperlane/Message/After224.hs index 497d9ba170..d4dc953dbb 100644 --- a/src/Chainweb/VerifierPlugin/Hyperlane/Message/After224.hs +++ b/src/Chainweb/VerifierPlugin/Hyperlane/Message/After224.hs @@ -16,14 +16,15 @@ module Chainweb.VerifierPlugin.Hyperlane.Message.After224 (runPlugin) where import Control.Error -import Control.Monad (unless) +import Control.Monad (unless, when) import Control.Monad.Except import Control.Monad.ST -import qualified Data.Text.Encoding as Text +import Data.Traversable (forM) import qualified Data.Vector as V import qualified Data.Set as Set import qualified Data.Map.Strict as M +import Data.List (foldl') import Data.STRef import Ethereum.Misc hiding (Word256) @@ -50,9 +51,13 @@ runPlugin proof caps gasRef = do [cap] -> return cap _ -> throwError $ VerifierError "Expected one capability." - (capMessageId, capMessage, capSigners) <- case _scArgs of - [mid, mb, sigs] -> return (mid, mb, sigs) - _ -> throwError $ VerifierError $ "Incorrect number of capability arguments. Expected: messageId, message, signers." + (capMessageId, capMessage, capSigners, capThreshold) <- case _scArgs of + [mid, mb, PList sigs, PLiteral (LInteger threshold)] -> do + parsedSigners <- forM sigs $ \case + (PLiteral (LString v)) -> pure v + _ -> throwError $ VerifierError "Only string signers are supported" + return (mid, mb, parsedSigners, fromIntegral threshold) + _ -> throwError $ VerifierError $ "Incorrect number of capability arguments. Expected: messageId, message, signers, threshold." -- extract proof object values (hyperlaneMessageBase64, metadataBase64) <- case proof of @@ -87,8 +92,8 @@ runPlugin proof caps gasRef = do hmNoncePactValue = PLiteral $ LInteger $ fromIntegral hmNonce hmOriginDomainPactValue = PLiteral $ LInteger $ fromIntegral hmOriginDomain hmDestinationDomainPactValue = PLiteral $ LInteger $ fromIntegral hmDestinationDomain - hmSenderPactValue = PLiteral $ LString $ encodeHex hmSender - hmRecipientPactValue = PLiteral $ LString $ Text.decodeUtf8 hmRecipient + hmSenderPactValue = PLiteral $ LString $ encodeB64UrlNoPaddingText hmSender + hmRecipientPactValue = PLiteral $ LString $ encodeB64UrlNoPaddingText hmRecipient hmMessageBodyPactValue = PLiteral $ LString $ encodeB64UrlNoPaddingText hmMessageBody hmMessagePactValue = PObject . ObjectMap . M.fromList $ @@ -129,10 +134,22 @@ runPlugin proof caps gasRef = do putRawByteString mrmimSignedCheckpointMessageId addresses <- catMaybes <$> mapM (\sig -> chargeGas gasRef 16250 >> recoverAddress digest sig) mrmimSignatures - let addressesVals = PList $ V.fromList $ map (PLiteral . LString . encodeHex) addresses + let addressesHex = map encodeHex addresses - -- Note, that we check the signers for the full equality including their order and amount. - -- Hyperlane's ISM uses a threshold and inclusion check. - unless (addressesVals == capSigners) $ - throwError $ VerifierError $ - "Signers don't match. Expected: " <> sshow addressesVals <> " but got " <> sshow capSigners + when (length addressesHex < capThreshold) $ + throwError $ VerifierError $ "The number of recovered addresses from the signatures is less than threshold: " <> sshow capThreshold + + -- Requires that m-of-n validators verify a merkle root, and verifies a merkle proof of message against that root. + -- + -- The signature addresses and validator addresses should be in the same order. + -- + -- The original algorithm in hyperlane. + -- https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/v3/solidity/contracts/isms/multisig/AbstractMultisigIsm.sol#L67 + let + verificationAddresses = take capThreshold addressesHex + verifyStep (_, vals) signer = case V.elemIndex signer vals of + Just i -> let newV = V.drop (i + 1) vals in (True, newV) + Nothing -> (False, V.empty) + verified = fst $ foldl' verifyStep (True, capSigners) verificationAddresses + + unless verified $ throwError $ VerifierError "Verification failed" diff --git a/src/Chainweb/VerifierPlugin/Hyperlane/Message/Before224.hs b/src/Chainweb/VerifierPlugin/Hyperlane/Message/Before224.hs index 8d246efe59..193f0acccb 100644 --- a/src/Chainweb/VerifierPlugin/Hyperlane/Message/Before224.hs +++ b/src/Chainweb/VerifierPlugin/Hyperlane/Message/Before224.hs @@ -20,6 +20,7 @@ import Control.Monad (unless) import Control.Monad.Except import Control.Monad.ST +import qualified Data.ByteString as BS import qualified Data.Text.Encoding as Text import qualified Data.Vector as V import qualified Data.Set as Set @@ -72,7 +73,7 @@ runPlugin proof caps gasRef = do runGetS getMessageIdMultisigIsmMetadata metadata -- validate recipient - let hmRecipientPactValue = PLiteral $ LString $ Text.decodeUtf8 hmRecipient + let hmRecipientPactValue = PLiteral $ LString $ Text.decodeUtf8 $ BS.dropWhile (== 0) hmRecipient unless (hmRecipientPactValue == capRecipient) $ throwError $ VerifierError $ "Recipients don't match. Expected: " <> sshow hmRecipientPactValue <> " but got " <> sshow capRecipient diff --git a/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/After224.hs b/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/After224.hs index 5bc28d58c4..c14ee48502 100644 --- a/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/After224.hs +++ b/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/After224.hs @@ -42,11 +42,13 @@ import Chainweb.Test.Pact.VerifierPluginTest.Transaction.Utils tests :: TestTree tests = testGroup "After224" [ test generousConfig getGasModel "verifySuccess" hyperlaneVerifySuccess + , test generousConfig getGasModel "verifyMoreValidatorsSuccess" hyperlaneVerifyMoreValidatorsSuccess , test generousConfig getGasModel "verifyEmptyRecoveredSignaturesSuccess" hyperlaneVerifyEmptyRecoveredSignaturesSuccess , test generousConfig getGasModel "verifyWrongSignersFailure" hyperlaneVerifyWrongSignersFailure , test generousConfig getGasModel "verifyNotEnoughRecoveredSignaturesFailure" hyperlaneVerifyNotEnoughRecoveredSignaturesFailure , test generousConfig getGasModel "verifyNotEnoughCapabilitySignaturesFailure" hyperlaneVerifyNotEnoughCapabilitySignaturesFailure , test generousConfig getGasModel "verifyIncorretProofFailure" hyperlaneVerifyMerkleIncorrectProofFailure + , test generousConfig getGasModel "verifyFailureNotEnoughSignaturesToPassThreshold" hyperlaneVerifyFailureNotEnoughSignaturesToPassThreshold ] where -- This is way more than what is used in production, but during testing @@ -81,12 +83,15 @@ hyperlaneMessageBase64 = encodeB64UrlNoPaddingText $ runPutS $ putHyperlaneMessa { hmVersion = 3 , hmNonce = 0 , hmOriginDomain = 31337 - , hmSender = decodeHexUnsafe "0x7fa9385be102ac3eac297483dd6233d62b3e1496" + , hmSender = either (error . show) id $ decodeB64UrlNoPaddingText "AAAAAAAAAAAAAAAAf6k4W-ECrD6sKXSD3WIz1is-FJY" , hmDestinationDomain = 626 - , hmRecipient = "6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV" + , hmRecipient = either (error . show) id $ decodeB64UrlNoPaddingText "AAAAAAAAAADpgrOqkM0BOY-FQnNzkDXuYlsVcf50GRU" , hmMessageBody = either (error . show) id $ decodeB64UrlNoPaddingText hyperlaneTokenMessageBase64 } +hyperlaneMessageId :: T.Text +hyperlaneMessageId = encodeHex $ keccak256ByteString $ either (error . show) id $ decodeB64UrlNoPaddingText $ hyperlaneMessageBase64 + -- | Hyperlane test MerkleTree Metadata encoded in base64 -- Test data was generated using the following test in the hyperlane codebase -- https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/b14f997810ebd7dbdff2ac6622a149ae77010ae3/solidity/test/isms/MultisigIsm.t.sol#L35 @@ -95,7 +100,7 @@ mkHyperlaneMerkleTreeMetadataBase64 proof signatures = encodeB64UrlNoPaddingText MerkleRootMultisigIsmMetadata { mrmimOriginMerkleTreeAddress = decodeHexUnsafe "0x2e234dae75c793f67a35089c9d99245e1c58470b" , mrmimMessageIdIndex = 0 - , mrmimSignedCheckpointMessageId = decodeHexUnsafe "0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae" + , mrmimSignedCheckpointMessageId = decodeHexUnsafe hyperlaneMessageId , mrmimMerkleProof = proof , mrmimSignedCheckpointIndex = 0 , mrmimSignatures = signatures @@ -110,9 +115,15 @@ hyperlaneMerkleTreeIncorrectProof <> "\x19" <> B.drop 32 hyperlaneMerkleTreeCorrectProof +validSigner :: T.Text +validSigner = "0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e" + +validSignature :: T.Text +validSignature = "0xfabe80dd5bf4440e5e7fbc3cdf12325df9c00beb1281c5ddf12e77177046790c49f531ccebb29ba9c9664a581ed1870873850e0cf0c231b779e21f48a1d0dcea1b" + -- | Deploys a contract with a valid signer -deployContractWithValidSigner :: PactTxTest -deployContractWithValidSigner = +deployContractWith :: [T.Text] -> Integer -> T.Text -> PactTxTest +deployContractWith signers threshold moduleHash = PactTxTest (buildBasicGas 70000 $ mkExec' $ mconcat @@ -128,11 +139,13 @@ deployContractWithValidSigner = , " messageBody:string" , ")" , "(defcap G () true)" - , "(defcap K (messageId:string message:object{hyperlane_message} signers:[string])" + , "(defcap K (messageId:string message:object{hyperlane_message} signers:[string] threshold:integer)" , " (enforce-verifier 'hyperlane_v3_message)" - , " (enforce (= messageId \"0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae\") \"invalid messageId\")" - , " (enforce (= signers [\"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"]) \"invalid signers\")" - , " (enforce (= (at \"recipient\" message) \"6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV\") \"invalid recipient\")" + , " (enforce (= messageId \"" <> hyperlaneMessageId <> "\") \"invalid messageId\")" + , " (enforce (= messageId (hyperlane-message-id message)) \"invalid calculated messageId\")" + , " (enforce (= signers [" <> (T.intercalate "," $ map (\s -> "\"" <> s <> "\"") signers) <> "]) \"invalid signers\")" + , " (enforce (= (at \"sender\" message) \"AAAAAAAAAAAAAAAAf6k4W-ECrD6sKXSD3WIz1is-FJY\") \"invalid sender\")" + , " (enforce (= (at \"recipient\" message) \"AAAAAAAAAADpgrOqkM0BOY-FQnNzkDXuYlsVcf50GRU\") \"invalid recipient\")" , " (bind (hyperlane-decode-token-message (at \"messageBody\" message)) " , " { \"amount\" := amount, " , " \"chainId\" := chain-id, " @@ -142,77 +155,28 @@ deployContractWithValidSigner = , " )" , ")" , "(defun x () (with-capability (K " - , "\"0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae\"" + , "\"" <> hyperlaneMessageId <> "\"" , " {" , " \"version\": 3," , " \"nonce\": 0," , " \"originDomain\": 31337," - , " \"sender\": \"0x7fa9385be102ac3eac297483dd6233d62b3e1496\"," + , " \"sender\": \"AAAAAAAAAAAAAAAAf6k4W-ECrD6sKXSD3WIz1is-FJY\"," , " \"destinationDomain\": 626," - , " \"recipient\": \"6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV\"," + , " \"recipient\": \"AAAAAAAAAADpgrOqkM0BOY-FQnNzkDXuYlsVcf50GRU\"," , " \"messageBody\": \"" <> hyperlaneTokenMessageBase64 <> "\"" , "}" - , " [\"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"]" + , " [" <> (T.intercalate "," $ map (\s -> "\"" <> s <> "\"") signers) <> "]" + , " " <> sshow threshold , ")" , " \"succeeded\")))" ]) (assertTxSuccess "Should deploy module" - (pString "Loaded module free.m, hash lJnbz74rDJQFwjIeA2ZdK0WmXJTScxGUGem-nre4TV4")) - --- | Deploys a contract with an invalid signer -deployContractWithInvalidSigner :: PactTxTest -deployContractWithInvalidSigner = - PactTxTest - (buildBasicGas 70000 - $ mkExec' $ mconcat - [ "(namespace 'free)" - , "(module m G" - , "(defschema hyperlane_message" - , " version:integer" - , " nonce:integer" - , " originDomain:integer" - , " destinationDomain:integer" - , " sender:string" - , " recipient:string" - , " messageBody:string" - , ")" - , "(defcap G () true)" - , "(defcap K (messageId:string message:object{hyperlane_message} signers:[string])" - , " (enforce-verifier 'hyperlane_v3_message)" - , " (enforce (= messageId \"0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae\") \"invalid messageId\")" - , " (enforce (= signers [\"wrongValidator\"]) \"invalid signers\")" - , " (enforce (= (at \"recipient\" message) \"6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV\") \"invalid recipient\")" - , " (bind (hyperlane-decode-token-message (at \"messageBody\" message)) " - , " { \"amount\" := amount, " - , " \"chainId\" := chain-id, " - , " \"recipient\" := recipient-guard }" - , " (enforce (= amount 0.000000000000000123) \"invalid amount\")" - , " (enforce (= (create-principal recipient-guard) \"k:da1a339bd82d2c2e9180626a00dc043275deb3ababb27b5738abf6b9dcee8db6\") \"invalid recipient guard\")" - , " )" - , ")" - , "(defun x () (with-capability (K " - , "\"0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae\"" - , " {" - , " \"version\": 3," - , " \"nonce\": 0," - , " \"originDomain\": 31337," - , " \"sender\": \"0x7fa9385be102ac3eac297483dd6233d62b3e1496\"," - , " \"destinationDomain\": 626," - , " \"recipient\": \"6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV\"," - , " \"messageBody\": \"" <> hyperlaneTokenMessageBase64 <> "\"" - , "}" - , " []" - , ")" - , " \"succeeded\")))" - ]) - (assertTxSuccess - "Should deploy module" - (pString "Loaded module free.m, hash Yq0Z121-F0lVinDfjCtIwUZLZjz0ffIShYZfsO75WFk")) + (pString $ "Loaded module free.m, hash " <> moduleHash)) -- | Calls '(free.m.x)' from 'deployContractWithValidSigner' -mkMerkleMetadataCallWithGas :: GasLimit -> B.ByteString -> [T.Text] -> [T.Text] -> MempoolCmdBuilder -mkMerkleMetadataCallWithGas gas merkleProof signatures signersText = buildBasic' +mkMerkleMetadataCallWithGas :: GasLimit -> B.ByteString -> [T.Text] -> [T.Text] -> Integer -> MempoolCmdBuilder +mkMerkleMetadataCallWithGas gas merkleProof signatures signersText threshold = buildBasic' (set cbGasLimit gas . set cbVerifiers [Verifier (VerifierName "hyperlane_v3_message") @@ -226,39 +190,51 @@ mkMerkleMetadataCallWithGas gas merkleProof signatures signersText = buildBasic' [cap]]) (mkExec' "(free.m.x)") where - messageId = pString "0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae" + messageId = pString hyperlaneMessageId message = PObject . ObjectMap . M.fromList $ [ ("version", PLiteral $ LInteger 3) , ("nonce", PLiteral $ LInteger 0) , ("originDomain", PLiteral $ LInteger 31337) , ("destinationDomain", PLiteral $ LInteger 626) - , ("sender", pString "0x7fa9385be102ac3eac297483dd6233d62b3e1496") - , ("recipient", pString "6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV") + , ("sender", pString "AAAAAAAAAAAAAAAAf6k4W-ECrD6sKXSD3WIz1is-FJY") + , ("recipient", pString "AAAAAAAAAADpgrOqkM0BOY-FQnNzkDXuYlsVcf50GRU") , ("messageBody", pString hyperlaneTokenMessageBase64) ] signers = PList $ V.fromList $ map pString signersText cap = SigCapability (QualifiedName (ModuleName "m" (Just (NamespaceName "free"))) "K" def) - [messageId, message, signers] + [messageId, message, signers, pInteger threshold] -mkMerkleMetadataCall :: B.ByteString -> [T.Text] -> [T.Text] -> MempoolCmdBuilder +mkMerkleMetadataCall :: B.ByteString -> [T.Text] -> [T.Text] -> Integer -> MempoolCmdBuilder mkMerkleMetadataCall = mkMerkleMetadataCallWithGas 20000 hyperlaneVerifySuccess :: PactTestM () hyperlaneVerifySuccess = do runToHeight 127 + let threshold = 1 runBlockTest - [ deployContractWithValidSigner + [ deployContractWith [validSigner] threshold "F3KIO7h4MVOFqR19l9qSPP91WcVOIYX7ULeXc8nJXC0" , checkVerifierNotInTx "hyperlane_v3_message" - , PactTxTest (mkMerkleMetadataCall - hyperlaneMerkleTreeCorrectProof - ["0xb3df841e9e3036f0858b0376280ef6692be293b53da3fba3384c82d6ca86704619cd7700147e3439fb66a985bdb310a4273204a0b5e5337deec0f00dfc8a5a171c"] - ["0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e"] - ) + , PactTxTest (mkMerkleMetadataCall hyperlaneMerkleTreeCorrectProof [validSignature] [validSigner] threshold) (\cr -> liftIO $ do assertTxSuccess "should have succeeded" (pString "succeeded") cr - assertEqual "gas should have been charged" 16578 (_crGas cr)) + assertEqual "gas should have been charged" 16588 (_crGas cr)) + ] + +hyperlaneVerifyMoreValidatorsSuccess :: PactTestM () +hyperlaneVerifyMoreValidatorsSuccess = do + runToHeight 127 + + let threshold = 1 + let signers = ["wrongSigner", validSigner] + runBlockTest + [ deployContractWith signers threshold "2OeafidyAc6BpsQdrLCVewhByLyQa2nI3FoFxPGu0IM" + , checkVerifierNotInTx "hyperlane_v3_message" + , PactTxTest (mkMerkleMetadataCall hyperlaneMerkleTreeCorrectProof [validSignature] signers threshold) + (\cr -> liftIO $ do + assertTxSuccess "should have succeeded" (pString "succeeded") cr + assertEqual "gas should have been charged" 16588 (_crGas cr)) ] hyperlaneVerifyEmptyRecoveredSignaturesSuccess :: PactTestM () @@ -272,30 +248,30 @@ hyperlaneVerifyEmptyRecoveredSignaturesSuccess = do [ "(namespace 'free)" , "(module m G" , "(defcap G () true)" - , "(defcap K (messageId:string message signers:[string])" + , "(defcap K (messageId:string message signers:[string] threshold:integer)" , " (enforce-verifier 'hyperlane_v3_message)" , " (enforce (= signers []) \"invalid signers\")" , ")" , "(defun x () (with-capability (K " - , "\"0x6f370c453c86ad681e936741683cceca8f13c46f2a49b1c9f8c6a23b5bb97aae\"" + , "\"" <> hyperlaneMessageId <> "\"" , " {" , " \"version\": 3," , " \"nonce\": 0," , " \"originDomain\": 31337," - , " \"sender\": \"0x7fa9385be102ac3eac297483dd6233d62b3e1496\"," + , " \"sender\": \"AAAAAAAAAAAAAAAAf6k4W-ECrD6sKXSD3WIz1is-FJY\"," , " \"destinationDomain\": 626," - , " \"recipient\": \"6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV\"," + , " \"recipient\": \"AAAAAAAAAADpgrOqkM0BOY-FQnNzkDXuYlsVcf50GRU\"," , " \"messageBody\": \"" <> hyperlaneTokenMessageBase64 <> "\"" , "}" - , " []" + , " [] 0" , ")" , " \"succeeded\")))" ]) (assertTxSuccess "Should deploy module" - (pString "Loaded module free.m, hash dOUmd1arhUC2DGhDP1dLGad_JBXpLsvMhs98wP_ovJo")) + (pString "Loaded module free.m, hash kP1ToC2qen8p66JBmCawN_tBA_Sg_fX-KlbQ5ik9hIg")) , checkVerifierNotInTx "hyperlane_v3_message" - , PactTxTest (mkMerkleMetadataCall hyperlaneMerkleTreeCorrectProof [] []) + , PactTxTest (mkMerkleMetadataCall hyperlaneMerkleTreeCorrectProof [] [] 0) (\cr -> liftIO $ do assertTxSuccess "should have succeeded" (pString "succeeded") cr assertEqual "gas should have been charged" 299 (_crGas cr)) @@ -305,16 +281,13 @@ hyperlaneVerifyWrongSignersFailure :: PactTestM () hyperlaneVerifyWrongSignersFailure = do runToHeight 127 + let threshold = 1 runBlockTest - [ deployContractWithInvalidSigner + [ deployContractWith ["wrongSigner"] threshold "Dj6xzrxfmjAuclsGnqIv-Uzg65z9EtQnH4nT6ziSFIA" , checkVerifierNotInTx "hyperlane_v3_message" - , PactTxTest (mkMerkleMetadataCall - hyperlaneMerkleTreeCorrectProof - ["0xb3df841e9e3036f0858b0376280ef6692be293b53da3fba3384c82d6ca86704619cd7700147e3439fb66a985bdb310a4273204a0b5e5337deec0f00dfc8a5a171c"] - ["wrongValidator"]) + , PactTxTest (mkMerkleMetadataCall hyperlaneMerkleTreeCorrectProof [validSignature] ["wrongSigner"] threshold) (\cr -> liftIO $ do - let errMsg = "Tx verifier error: Signers don't match. Expected: PList [PLiteral (LString {_lString = \"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"})] but got PList [PLiteral (LString {_lString = \"wrongValidator\"})]" - assertTxFailure "should have failed with signers don't match" errMsg cr + assertTxFailure "Verification should fail" "Tx verifier error: Verification failed" cr assertEqual "gas should have been charged" 20000 (_crGas cr)) ] @@ -322,14 +295,14 @@ hyperlaneVerifyNotEnoughRecoveredSignaturesFailure :: PactTestM () hyperlaneVerifyNotEnoughRecoveredSignaturesFailure = do runToHeight 127 + let threshold = 1 runBlockTest - [ deployContractWithInvalidSigner + [ deployContractWith ["wrongSigner"] threshold "Dj6xzrxfmjAuclsGnqIv-Uzg65z9EtQnH4nT6ziSFIA" , checkVerifierNotInTx "hyperlane_v3_message" , PactTxTest (mkMerkleMetadataCall - hyperlaneMerkleTreeCorrectProof [] ["wrongValidator"]) + hyperlaneMerkleTreeCorrectProof [] [] threshold) (\cr -> liftIO $ do - let errMsg = "Tx verifier error: Signers don't match. Expected: PList [] but got PList [PLiteral (LString {_lString = \"wrongValidator\"})]" - assertTxFailure "should have failed with signers don't match" errMsg cr + assertTxFailure "Verification should fail with not enough recovered addresses" "Tx verifier error: The number of recovered addresses from the signatures is less than threshold: 1" cr assertEqual "gas should have been charged" 20000 (_crGas cr)) ] @@ -337,19 +310,13 @@ hyperlaneVerifyNotEnoughCapabilitySignaturesFailure :: PactTestM () hyperlaneVerifyNotEnoughCapabilitySignaturesFailure = do runToHeight 127 + let threshold = 2 runBlockTest - [ deployContractWithValidSigner + [ deployContractWith [validSigner] threshold "vdb8pICE6ZpC5OOr2RCMUK9JTh3d3aRU5LpGLopIOhE" , checkVerifierNotInTx "hyperlane_v3_message" - , PactTxTest (mkMerkleMetadataCallWithGas 40000 - hyperlaneMerkleTreeCorrectProof - [ "0xb3df841e9e3036f0858b0376280ef6692be293b53da3fba3384c82d6ca86704619cd7700147e3439fb66a985bdb310a4273204a0b5e5337deec0f00dfc8a5a171c" - , "0xb3df841e9e3036f0858b0376280ef6692be293b53da3fba3384c82d6ca86704619cd7700147e3439fb66a985bdb310a4273204a0b5e5337deec0f00dfc8a5a171c" - ] - ["0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e"] - ) + , PactTxTest (mkMerkleMetadataCallWithGas 40000 hyperlaneMerkleTreeCorrectProof [validSignature, validSignature] [validSigner] threshold) (\cr -> liftIO $ do - let errMsg = "Tx verifier error: Signers don't match. Expected: PList [PLiteral (LString {_lString = \"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"}),PLiteral (LString {_lString = \"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"})] but got PList [PLiteral (LString {_lString = \"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"})]" - assertTxFailure "should have failed with signers don't match" errMsg cr + assertTxFailure "Verification should fail" "Tx verifier error: Verification failed" cr assertEqual "gas should have been charged" 40000 (_crGas cr)) ] @@ -357,16 +324,29 @@ hyperlaneVerifyMerkleIncorrectProofFailure :: PactTestM () hyperlaneVerifyMerkleIncorrectProofFailure = do runToHeight 127 + let threshold = 1 runBlockTest - [ deployContractWithValidSigner + [ deployContractWith [validSigner] threshold "F3KIO7h4MVOFqR19l9qSPP91WcVOIYX7ULeXc8nJXC0" , checkVerifierNotInTx "hyperlane_v3_message" - , PactTxTest (mkMerkleMetadataCall - hyperlaneMerkleTreeIncorrectProof - ["0xb3df841e9e3036f0858b0376280ef6692be293b53da3fba3384c82d6ca86704619cd7700147e3439fb66a985bdb310a4273204a0b5e5337deec0f00dfc8a5a171c"] - ["0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e"] - ) + , PactTxTest (mkMerkleMetadataCall hyperlaneMerkleTreeIncorrectProof [validSignature] [validSigner] threshold) (\cr -> liftIO $ do - let errMsg = "Tx verifier error: Signers don't match. Expected: PList [PLiteral (LString {_lString = \"0x6d49eb3534b546856da70706a745038e4f0fd88a\"})] but got PList [PLiteral (LString {_lString = \"0x4bd34992e0994e9d3c53c1ccfe5c2e38d907338e\"})]" - assertTxFailure "should have failed with signers don't match" errMsg cr + assertTxFailure "Verification should fail" "Tx verifier error: Verification failed" cr assertEqual "gas should have been charged" 20000 (_crGas cr)) ] + +-- | We pass 2 signatures, 1st one matches to the correct validator, +-- but there is no second valid validator for the 2nd signature, and the verification fails. +hyperlaneVerifyFailureNotEnoughSignaturesToPassThreshold :: PactTestM () +hyperlaneVerifyFailureNotEnoughSignaturesToPassThreshold = do + runToHeight 127 + + let threshold = 2 + let signers = ["wrongSigner", validSigner, "wrongSigner"] + runBlockTest + [ deployContractWith [validSigner] threshold "vdb8pICE6ZpC5OOr2RCMUK9JTh3d3aRU5LpGLopIOhE" + , checkVerifierNotInTx "hyperlane_v3_message" + , PactTxTest (mkMerkleMetadataCallWithGas 40000 hyperlaneMerkleTreeCorrectProof [validSignature, validSignature] signers threshold) + (\cr -> liftIO $ do + assertTxFailure "Verification should fail" "Tx verifier error: Verification failed" cr + assertEqual "gas should have been charged" 40000 (_crGas cr)) + ] diff --git a/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/Before224.hs b/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/Before224.hs index 3c33ac0aca..626cbe5eca 100644 --- a/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/Before224.hs +++ b/test/Chainweb/Test/Pact/VerifierPluginTest/Transaction/Message/Before224.hs @@ -84,12 +84,13 @@ hyperlaneMessageBase64 = encodeB64UrlNoPaddingText $ runPutS $ putHyperlaneMessa { hmVersion = 3 , hmNonce = 0 , hmOriginDomain = 31337 - , hmSender = decodeHexUnsafe "0x7fa9385be102ac3eac297483dd6233d62b3e1496" + , hmSender = padLeft $ decodeHexUnsafe "0x7fa9385be102ac3eac297483dd6233d62b3e1496" , hmDestinationDomain = 626 - , hmRecipient = "6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV" + , hmRecipient = padLeft $ "6YKzqpDNATmPhUJzc5A17mJbFXH-dBkV" , hmMessageBody = either (error . show) id $ decodeB64UrlNoPaddingText hyperlaneTokenMessageBase64 } + -- ========================================================= -- -- MessageId metadata tests