Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add hyperlane-message-id native #1335

Merged
merged 15 commits into from
Feb 13, 2024
Merged

Conversation

chessai
Copy link
Contributor

@chessai chessai commented Feb 12, 2024

Tests

Unit test, Haskell:

  • tests/HyperlaneSpec.hs
❯ cabal run test:hspec -- --match=HyperlaneSpec

HyperlaneSpec
  hyperlane
    hyperlane-message-id
      computes the correct message id [✔]

Repl test, Pact:

  • tests/pact/hyperlane-message-id.repl
cabal run test:hspec -- --match="pact tests"

PactTestsSpec
  pact tests
    ...
    tests/pact/hyperlane-message-id.repl [✔]

Gas Benchmark

Gas Benchmark Code

import Gauge.Main

benchy :: IO ()
benchy = do
  defaultMain
    [ bgroup "hyperlane"
        [ bench "0" $ whnf getHyperlaneMessageId hm0
        , bench "10" $ whnf getHyperlaneMessageId hm10
        , bench "20" $ whnf getHyperlaneMessageId hm20
        , bench "50" $ whnf getHyperlaneMessageId hm50
        , bench "100" $ whnf getHyperlaneMessageId hm100
        , bench "500" $ whnf getHyperlaneMessageId hm500
        , bench "1000" $ whnf getHyperlaneMessageId hm1000
        , bench "10000" $ whnf getHyperlaneMessageId hm10000
        ]
    ]

hm0, hm10, hm20, hm50, hm100, hm500, hm1000, hm10000 :: HyperlaneMessage
hm0 = genHM 0
hm10 = genHM 10
hm20 = genHM 20
hm50 = genHM 50
hm100 = genHM 100
hm500 = genHM 500
hm1000 = genHM 1_000
hm10000 = genHM 10_000

-- | Create a HyperlaneMessage where all bytes are 0 except for the only
--   variable length field, the TokenMessage recipient.
genHM :: Int -> HyperlaneMessage
genHM recipientSize = HyperlaneMessage
  { hmVersion = 0
  , hmNonce = 0
  , hmOriginDomain = 0
  , hmSender = BS.replicate 32 0
  , hmDestinationDomain = 0
  , hmRecipient = BS.replicate 32 0
  , hmTokenMessage = TokenMessageERC20
      { tmRecipient = Text.pack $ List.replicate recipientSize 'A'
      , tmAmount = 0
      , tmChainId = Nothing
      }
  }
{-# noinline genHM #-}
 

Gas Benchmark Results

benchmarking hyperlane/0 ... took 35.43 s, total 329090 iterations
benchmarked hyperlane/0
time                 2.876 μs   (2.770 μs .. 2.981 μs)
                     0.997 R²   (0.992 R² .. 0.999 R²)
mean                 3.051 μs   (3.030 μs .. 3.071 μs)
std dev              34.66 ns   (26.64 ns .. 46.71 ns)

benchmarking hyperlane/10 ... took 38.33 s, total 329090 iterations
benchmarked hyperlane/10
time                 2.962 μs   (2.936 μs .. 2.980 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 3.025 μs   (3.019 μs .. 3.032 μs)
std dev              10.88 ns   (7.858 ns .. 15.84 ns)

benchmarking hyperlane/20 ... took 38.35 s, total 329090 iterations
benchmarked hyperlane/20
time                 3.033 μs   (2.991 μs .. 3.080 μs)
                     1.000 R²   (0.999 R² .. 1.000 R²)
mean                 3.062 μs   (3.057 μs .. 3.070 μs)
std dev              10.53 ns   (5.386 ns .. 17.42 ns)

benchmarking hyperlane/50 ... took 37.90 s, total 313406 iterations
benchmarked hyperlane/50
time                 2.247 μs   (981.0 ns .. 3.185 μs)
                     0.713 R²   (0.249 R² .. 0.998 R²)
mean                 3.176 μs   (3.073 μs .. 3.559 μs)
std dev              303.8 ns   (33.02 ns .. 505.6 ns)
variance introduced by outliers: 28% (moderately inflated)

benchmarking hyperlane/100 ... took 38.02 s, total 298469 iterations
benchmarked hyperlane/100
time                 3.288 μs   (3.086 μs .. 3.389 μs)
                     0.996 R²   (0.986 R² .. 0.999 R²)
mean                 3.312 μs   (3.294 μs .. 3.333 μs)
std dev              32.87 ns   (21.87 ns .. 50.43 ns)

benchmarking hyperlane/500 ... took 37.08 s, total 245502 iterations
benchmarked hyperlane/500
time                 3.707 μs   (3.475 μs .. 3.928 μs)
                     0.992 R²   (0.981 R² .. 0.998 R²)
mean                 4.024 μs   (3.984 μs .. 4.065 μs)
std dev              69.26 ns   (54.88 ns .. 83.66 ns)

benchmarking hyperlane/1000 ... took 36.55 s, total 212036 iterations
benchmarked hyperlane/1000
time                 4.540 μs   (4.356 μs .. 4.699 μs)
                     0.997 R²   (0.994 R² .. 0.999 R²)
mean                 4.785 μs   (4.758 μs .. 4.824 μs)
std dev              53.55 ns   (35.82 ns .. 77.57 ns)

benchmarking hyperlane/10000 ... took 29.65 s, total 48854 iterations
benchmarked hyperlane/10000
time                 20.96 μs   (20.60 μs .. 21.37 μs)
                     0.999 R²   (0.998 R² .. 1.000 R²)
mean                 20.77 μs   (20.74 μs .. 20.83 μs)
std dev              76.68 ns   (48.73 ns .. 110.9 ns)

20240212_15h53m30s_grim

Going off of these numbers, assuming 1 milligas is 2.5ns, that means our cost is roughly 1120.8 + 0.4726 * byte_length(x), where x is the TokenMessage recipient. To avoid rounding errors due to the small cost per byte, we can cost this per 100 bytes. So ultimately, the proposed cost (in milligas) is:

1121 + 47 * (tokenMessageRecipient `div` 100)

The Milligas constant 1121 in practise cannot be included in defaultGasTable, which only contains Gas, not Milligas. We should round up here, so instead of 1 Gas, this is 2 Gas.

PR checklist:

  • Test coverage for the proposed changes
  • PR description contains example output from repl interaction or a snippet from unit test output
  • Documentation has been updated if new natives or FV properties have been added. To generate new documentation, issue cabal run tests. If they pass locally, docs are generated.
  • Any changes that could be relevant to users have been recorded in the changelog
  • In case of changes to the Pact trace output (pact -t), make sure pact-lsp is in sync.

Additionally, please justify why you should or should not do the following:

  • Confirm replay/back compat
  • Benchmark regressions
  • (For Kadena engineers) Run integration-tests against a Chainweb built with this version of Pact

src/Pact/Native.hs Show resolved Hide resolved
src/Crypto/Hash/HyperlaneMessageId.hs Outdated Show resolved Hide resolved
cabal.project Show resolved Hide resolved
cabal.project Show resolved Hide resolved
cabal.project Show resolved Hide resolved
src/Pact/Gas/Table.hs Show resolved Hide resolved
src/Pact/Gas/Table.hs Outdated Show resolved Hide resolved
src/Pact/Gas/Table.hs Show resolved Hide resolved
@chessai chessai marked this pull request as ready for review February 13, 2024 18:25
pact.cabal Outdated
@@ -80,6 +80,7 @@ library
-Wincomplete-record-updates
-Wincomplete-uni-patterns
-Wredundant-constraints
-Wno-missed-extra-shared-lib
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quoting Austin in his PR to chainweb-node:

When running Template Haskell, GHC sees that some code it loads has dependent modules that also have a dependency on the zlib shared object via an extra-libraries clause; GHC can't find or load this module, issuing a warning, but it doesn't matter because the Template Haskell code doesn't actually use zlib despite having a transitive dependency on it.

Silence this warning, as it's extremely annoying to see while working on any files that use Template Haskell for any purposes e.g. deriving lenses.

I have been getting this warning on chainweb-node and pact for a while now.

Copy link
Contributor

@edmundnoble edmundnoble left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a change in Pact.Interpreter to disable the new native until Pact 4.11, similar to other natives that are only enabled by a fork.

@chessai
Copy link
Contributor Author

chessai commented Feb 13, 2024

This needs a change in Pact.Interpreter to disable the new native until Pact 4.11, similar to other natives that are only enabled by a fork.

pact> (hyperlane-message-id 0)
<interactive>:0:0:Error: Invalid arguments, received [0] for x:object:* -> string
 at <interactive>:0:0: (hyperlane-message-id 0)
pact> (env-exec-config ['DisableVerifiers])
["DisableVerifiers"]
pact> (hyperlane-message-id 0)
<interactive>:0:0:Error: Cannot resolve hyperlane-message-id

Added

@jmcardon jmcardon dismissed edmundnoble’s stale review February 13, 2024 21:58

Addressed in latest commit

@edmundnoble edmundnoble merged commit f9f3143 into master Feb 13, 2024
7 checks passed
@edmundnoble edmundnoble deleted the chessai/native-hyperlane-message-id branch February 13, 2024 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants