Skip to content

Commit

Permalink
Hyperlane fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Evgenii Akentev committed Apr 16, 2024
1 parent 57ba812 commit 7c6a94b
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 136 deletions.
4 changes: 2 additions & 2 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions src/Chainweb/VerifierPlugin/Hyperlane/Binary.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module Chainweb.VerifierPlugin.Hyperlane.Binary
, putMerkleRootMultisigIsmMetadata
, getMerkleRootMultisigIsmMetadata

, padLeft
, ethereumAddressSize
) where

Expand Down Expand Up @@ -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

Expand All @@ -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 {..}
Expand Down
43 changes: 30 additions & 13 deletions src/Chainweb/VerifierPlugin/Hyperlane/Message/After224.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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 $
Expand Down Expand Up @@ -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"
3 changes: 2 additions & 1 deletion src/Chainweb/VerifierPlugin/Hyperlane/Message/Before224.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 7c6a94b

Please sign in to comment.