bolt2

Lightning peer protocol, per BOLT #2 (docs.ppad.tech/bolt2).
git clone git://git.ppad.tech/bolt2.git
Log | Files | Refs | README | LICENSE

commit 89df0389196ed8ba5c010320ad4002741dd98771
parent e7ef9d53a92063b1c9129d2f811606795a5440cf
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat, 10 Oct 2026 14:19:38 +0400

bench: rewrite for the new API

Criterion and weigh suites over the payload codecs of representative
messages (open_channel, accept_channel2, tx_signatures,
closing_complete, update_add_htlc, update_fulfill_htlc,
commitment_signed with 0 and 483 HTLCs, revoke_and_ack,
channel_reestablish) and the message dispatcher, forcing results with
nf. Fixtures are built without partial functions.

Diffstat:
Abench/Fixtures.hs | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbench/Main.hs | 346+++++++++++++------------------------------------------------------------------
Mbench/Weight.hs | 381+++++++++----------------------------------------------------------------------
3 files changed, 224 insertions(+), 629 deletions(-)

diff --git a/bench/Fixtures.hs b/bench/Fixtures.hs @@ -0,0 +1,126 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Fixtures ( + Fixtures(..) + , fixtures + ) where + +import qualified Bitcoin.Prim.Tx as Tx +import qualified Data.ByteString as BS +import qualified Lightning.Protocol.BOLT1 as BOLT1 +import Lightning.Protocol.BOLT2 +import qualified Lightning.Protocol.BOLT9 as BOLT9 + +-- representative messages, with their encoded payloads +data Fixtures = Fixtures + { fx_open_channel :: !OpenChannel + , fx_open_channel_bytes :: !BS.ByteString + , fx_accept_channel2 :: !AcceptChannel2 + , fx_accept_channel2_bytes :: !BS.ByteString + , fx_tx_signatures :: !TxSignatures + , fx_tx_signatures_bytes :: !BS.ByteString + , fx_closing_complete :: !ClosingComplete + , fx_closing_complete_bytes :: !BS.ByteString + , fx_update_add_htlc :: !UpdateAddHtlc + , fx_update_add_htlc_bytes :: !BS.ByteString + , fx_update_add_htlc_wire :: !BS.ByteString + , fx_update_fulfill_htlc :: !UpdateFulfillHtlc + , fx_update_fulfill_htlc_bytes :: !BS.ByteString + , fx_commitment_signed :: !CommitmentSigned + , fx_commitment_signed_bytes :: !BS.ByteString + , fx_commitment_signed_483 :: !CommitmentSigned + , fx_commitment_signed_483_bytes :: !BS.ByteString + , fx_revoke_and_ack :: !RevokeAndAck + , fx_revoke_and_ack_bytes :: !BS.ByteString + , fx_channel_reestablish :: !ChannelReestablish + , fx_channel_reestablish_bytes :: !BS.ByteString + } + +ok :: Either e a -> Maybe a +ok = either (const Nothing) Just + +empty :: BOLT1.TlvStream +empty = BOLT1.empty_tlv_stream + +fixtures :: Maybe Fixtures +fixtures = do + ch <- BOLT1.chain_hash (BS.replicate 32 0x6f) + cid <- BOLT1.channel_id (BS.replicate 32 0xab) + pts <- traverse (\b -> BOLT1.point (BS.cons 0x02 (BS.replicate 32 b))) + [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77] + sig <- BOLT1.signature (BS.replicate 64 0xa1) + txid <- Tx.mkTxId (BS.replicate 32 0x7e) + spk <- script_pubkey ("\x00\x14" <> BS.replicate 20 0x88) + fund <- BOLT1.satoshi 1000000 + dust <- BOLT1.satoshi 546 + res <- BOLT1.satoshi 10000 + push <- BOLT1.milli_satoshi 0 + hmin <- BOLT1.milli_satoshi 1000 + amt <- BOLT1.milli_satoshi 100000 + fee <- BOLT1.satoshi 500 + ph <- BOLT1.payment_hash (BS.replicate 32 0x9a) + pre <- BOLT1.payment_preimage (BS.replicate 32 0x50) + sec <- BOLT1.per_commitment_secret (BS.replicate 32 0x5e) + onion <- onion_routing_packet (BS.replicate 1366 0x44) + att <- attribution_data (BS.replicate 920 0x0b) + ws <- traverse witness + [ "\x02\x47" <> BS.replicate 71 0x30 <> "\x21" + <> BS.replicate 33 0x02 + , "\x01\x40" <> BS.replicate 64 0x01 ] + ext <- BOLT1.tlv_stream [BOLT1.TlvRecord 43 (BS.replicate 16 0x2a)] + (p1, p2, p3, p4, p5, p6, p7) <- case pts of + [a, b, c, d, e, f, g] -> Just (a, b, c, d, e, f, g) + _ -> Nothing + let ctype = BOLT9.channel_type_features + (BOLT9.ChannelType BOLT9.BasicAnchors False False) + + oc = OpenChannel ch cid fund push dust maxBound res hmin 253 144 483 + p1 p2 p3 p4 p5 p6 1 (Just spk) (Just ctype) empty + ac2 = AcceptChannel2 cid fund dust maxBound hmin 3 144 483 + p1 p2 p3 p4 p5 p6 p7 (Just spk) (Just ctype) True ext + txs = TxSignatures cid txid ws empty + cc = ClosingComplete cid spk spk fee 0 (Just sig) Nothing (Just sig) + empty + add = UpdateAddHtlc cid (HtlcId 42) amt ph 800000 onion (Just p1) + empty + ful = UpdateFulfillHtlc cid (HtlcId 42) pre (Just att) Nothing empty + cs0 = CommitmentSigned cid sig [] (Just txid) empty + cs483 = CommitmentSigned cid sig (replicate 483 sig) (Just txid) + empty + raa = RevokeAndAck cid sec p1 empty + rst = ChannelReestablish cid 5 4 sec p1 (Just (NextFunding txid 1)) + empty + + oc_b <- ok (encode_open_channel oc) + ac2_b <- ok (encode_accept_channel2 ac2) + txs_b <- ok (encode_tx_signatures txs) + cc_b <- ok (encode_closing_complete cc) + add_b <- ok (encode_update_add_htlc add) + add_w <- ok (encode_message (MsgUpdateAddHtlc add)) + ful_b <- ok (encode_update_fulfill_htlc ful) + cs0_b <- ok (encode_commitment_signed cs0) + cs483_b <- ok (encode_commitment_signed cs483) + rst_b <- ok (encode_channel_reestablish rst) + pure Fixtures + { fx_open_channel = oc + , fx_open_channel_bytes = oc_b + , fx_accept_channel2 = ac2 + , fx_accept_channel2_bytes = ac2_b + , fx_tx_signatures = txs + , fx_tx_signatures_bytes = txs_b + , fx_closing_complete = cc + , fx_closing_complete_bytes = cc_b + , fx_update_add_htlc = add + , fx_update_add_htlc_bytes = add_b + , fx_update_add_htlc_wire = add_w + , fx_update_fulfill_htlc = ful + , fx_update_fulfill_htlc_bytes = ful_b + , fx_commitment_signed = cs0 + , fx_commitment_signed_bytes = cs0_b + , fx_commitment_signed_483 = cs483 + , fx_commitment_signed_483_bytes = cs483_b + , fx_revoke_and_ack = raa + , fx_revoke_and_ack_bytes = encode_revoke_and_ack raa + , fx_channel_reestablish = rst + , fx_channel_reestablish_bytes = rst_b + } diff --git a/bench/Main.hs b/bench/Main.hs @@ -1,301 +1,65 @@ -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE OverloadedStrings #-} - --- | --- Module: Main --- Copyright: (c) 2025 Jared Tobin --- License: MIT --- Maintainer: Jared Tobin <jared@ppad.tech> --- --- Criterion timing benchmarks for BOLT #2 message codecs. - module Main where import Criterion.Main -import qualified Data.ByteString as BS -import Lightning.Protocol.BOLT1 (TlvStream, unsafeTlvStream) +import Fixtures import Lightning.Protocol.BOLT2 --- Test data construction ------------------------------------------------------ - --- | 32 zero bytes for channel IDs, chain hashes, etc. -zeroBytes32 :: BS.ByteString -zeroBytes32 = BS.replicate 32 0x00 -{-# NOINLINE zeroBytes32 #-} - --- | 33-byte compressed public key (02 prefix + 32 zero bytes). -testPoint :: Point -testPoint = case point (BS.cons 0x02 zeroBytes32) of - Just p -> p - Nothing -> error "testPoint: invalid" -{-# NOINLINE testPoint #-} - --- | 64-byte signature. -testSignature :: Signature -testSignature = case signature (BS.replicate 64 0x01) of - Just s -> s - Nothing -> error "testSignature: invalid" -{-# NOINLINE testSignature #-} - --- | 32-byte channel ID. -testChannelId :: ChannelId -testChannelId = case channelId zeroBytes32 of - Just c -> c - Nothing -> error "testChannelId: invalid" -{-# NOINLINE testChannelId #-} - --- | 32-byte chain hash. -testChainHash :: ChainHash -testChainHash = case chainHash zeroBytes32 of - Just h -> h - Nothing -> error "testChainHash: invalid" -{-# NOINLINE testChainHash #-} - --- | 32-byte txid. -testTxId :: TxId -testTxId = case mkTxId zeroBytes32 of - Just t -> t - Nothing -> error "testTxId: invalid" -{-# NOINLINE testTxId #-} - --- | 32-byte payment hash. -testPaymentHash :: PaymentHash -testPaymentHash = case paymentHash zeroBytes32 of - Just h -> h - Nothing -> error "testPaymentHash: invalid" -{-# NOINLINE testPaymentHash #-} - --- | 1366-byte onion packet. -testOnionPacket :: OnionPacket -testOnionPacket = case onionPacket (BS.replicate 1366 0x00) of - Just o -> o - Nothing -> error "testOnionPacket: invalid" -{-# NOINLINE testOnionPacket #-} - --- | Empty TLV stream. -emptyTlvs :: TlvStream -emptyTlvs = unsafeTlvStream [] -{-# NOINLINE emptyTlvs #-} - --- V1 messages ----------------------------------------------------------------- - --- | Test OpenChannel message. -testOpenChannel :: OpenChannel -testOpenChannel = OpenChannel - { openChannelChainHash = testChainHash - , openChannelTempChannelId = testChannelId - , openChannelFundingSatoshi = Satoshi 1000000 - , openChannelPushMsat = MilliSatoshi 0 - , openChannelDustLimitSatoshi = Satoshi 546 - , openChannelMaxHtlcValueInFlight = MilliSatoshi 1000000000 - , openChannelChannelReserveSat = Satoshi 10000 - , openChannelHtlcMinimumMsat = MilliSatoshi 1000 - , openChannelFeeratePerKw = 250 - , openChannelToSelfDelay = 144 - , openChannelMaxAcceptedHtlcs = 30 - , openChannelFundingPubkey = testPoint - , openChannelRevocationBasepoint = testPoint - , openChannelPaymentBasepoint = testPoint - , openChannelDelayedPaymentBase = testPoint - , openChannelHtlcBasepoint = testPoint - , openChannelFirstPerCommitPoint = testPoint - , openChannelChannelFlags = 0x00 - , openChannelTlvs = emptyTlvs - } -{-# NOINLINE testOpenChannel #-} - --- | Encoded OpenChannel for decode benchmarks. -encodedOpenChannel :: BS.ByteString -encodedOpenChannel = encodeOpenChannel testOpenChannel -{-# NOINLINE encodedOpenChannel #-} - --- V2 messages ----------------------------------------------------------------- - --- | Test OpenChannel2 message. -testOpenChannel2 :: OpenChannel2 -testOpenChannel2 = OpenChannel2 - { openChannel2ChainHash = testChainHash - , openChannel2TempChannelId = testChannelId - , openChannel2FundingFeeratePerkw = 2500 - , openChannel2CommitFeeratePerkw = 250 - , openChannel2FundingSatoshi = Satoshi 1000000 - , openChannel2DustLimitSatoshi = Satoshi 546 - , openChannel2MaxHtlcValueInFlight = MilliSatoshi 1000000000 - , openChannel2HtlcMinimumMsat = MilliSatoshi 1000 - , openChannel2ToSelfDelay = 144 - , openChannel2MaxAcceptedHtlcs = 30 - , openChannel2Locktime = 0 - , openChannel2FundingPubkey = testPoint - , openChannel2RevocationBasepoint = testPoint - , openChannel2PaymentBasepoint = testPoint - , openChannel2DelayedPaymentBase = testPoint - , openChannel2HtlcBasepoint = testPoint - , openChannel2FirstPerCommitPoint = testPoint - , openChannel2SecondPerCommitPoint = testPoint - , openChannel2ChannelFlags = 0x00 - , openChannel2Tlvs = emptyTlvs - } -{-# NOINLINE testOpenChannel2 #-} - --- | Encoded OpenChannel2 for decode benchmarks. -encodedOpenChannel2 :: BS.ByteString -encodedOpenChannel2 = encodeOpenChannel2 testOpenChannel2 -{-# NOINLINE encodedOpenChannel2 #-} - --- | Test witness data (simulated P2WPKH signature + pubkey). -testWitness :: Witness -testWitness = Witness (BS.replicate 107 0xab) -{-# NOINLINE testWitness #-} - --- | TxSignatures with multiple witnesses. -testTxSignatures :: TxSignatures -testTxSignatures = TxSignatures - { txSignaturesChannelId = testChannelId - , txSignaturesTxid = testTxId - , txSignaturesWitnesses = replicate 5 testWitness - } -{-# NOINLINE testTxSignatures #-} - --- | Encoded TxSignatures for decode benchmarks. -encodedTxSignatures :: BS.ByteString -encodedTxSignatures = case encodeTxSignatures testTxSignatures of - Right bs -> bs - Left e -> error $ "encodedTxSignatures: " ++ show e -{-# NOINLINE encodedTxSignatures #-} - --- Close messages -------------------------------------------------------------- - --- | Test ClosingSigned message. -testClosingSigned :: ClosingSigned -testClosingSigned = ClosingSigned - { closingSignedChannelId = testChannelId - , closingSignedFeeSatoshi = Satoshi 1000 - , closingSignedSignature = testSignature - , closingSignedTlvs = emptyTlvs - } -{-# NOINLINE testClosingSigned #-} - --- | Encoded ClosingSigned for decode benchmarks. -encodedClosingSigned :: BS.ByteString -encodedClosingSigned = encodeClosingSigned testClosingSigned -{-# NOINLINE encodedClosingSigned #-} - --- Normal operation messages --------------------------------------------------- - --- | Test UpdateAddHtlc message. -testUpdateAddHtlc :: UpdateAddHtlc -testUpdateAddHtlc = UpdateAddHtlc - { updateAddHtlcChannelId = testChannelId - , updateAddHtlcId = htlcId 0 - , updateAddHtlcAmountMsat = MilliSatoshi 10000000 - , updateAddHtlcPaymentHash = testPaymentHash - , updateAddHtlcCltvExpiry = 800000 - , updateAddHtlcOnionPacket = testOnionPacket - , updateAddHtlcTlvs = emptyTlvs - } -{-# NOINLINE testUpdateAddHtlc #-} - --- | Encoded UpdateAddHtlc for decode benchmarks. -encodedUpdateAddHtlc :: BS.ByteString -encodedUpdateAddHtlc = encodeUpdateAddHtlc testUpdateAddHtlc -{-# NOINLINE encodedUpdateAddHtlc #-} - --- | Test CommitmentSigned message with HTLC signatures (10 sigs). -testCommitmentSigned :: CommitmentSigned -testCommitmentSigned = CommitmentSigned - { commitmentSignedChannelId = testChannelId - , commitmentSignedSignature = testSignature - , commitmentSignedHtlcSignatures = replicate 10 testSignature - } -{-# NOINLINE testCommitmentSigned #-} - --- | Encoded CommitmentSigned for decode benchmarks. -encodedCommitmentSigned :: BS.ByteString -encodedCommitmentSigned = case encodeCommitmentSigned testCommitmentSigned of - Right bs -> bs - Left e -> error $ "encodedCommitmentSigned: " ++ show e -{-# NOINLINE encodedCommitmentSigned #-} - --- | Test CommitmentSigned with many HTLC signatures (100 sigs). -testCommitmentSignedLarge :: CommitmentSigned -testCommitmentSignedLarge = CommitmentSigned - { commitmentSignedChannelId = testChannelId - , commitmentSignedSignature = testSignature - , commitmentSignedHtlcSignatures = replicate 100 testSignature - } -{-# NOINLINE testCommitmentSignedLarge #-} - --- | Encoded large CommitmentSigned for decode benchmarks. -encodedCommitmentSignedLarge :: BS.ByteString -encodedCommitmentSignedLarge = - case encodeCommitmentSigned testCommitmentSignedLarge of - Right bs -> bs - Left e -> error $ "encodedCommitmentSignedLarge: " ++ show e -{-# NOINLINE encodedCommitmentSignedLarge #-} - --- | Test CommitmentSigned with max HTLC signatures (483 sigs). -testCommitmentSignedMax :: CommitmentSigned -testCommitmentSignedMax = CommitmentSigned - { commitmentSignedChannelId = testChannelId - , commitmentSignedSignature = testSignature - , commitmentSignedHtlcSignatures = replicate 483 testSignature - } -{-# NOINLINE testCommitmentSignedMax #-} - --- | Encoded max CommitmentSigned for decode benchmarks. -encodedCommitmentSignedMax :: BS.ByteString -encodedCommitmentSignedMax = - case encodeCommitmentSigned testCommitmentSignedMax of - Right bs -> bs - Left e -> error $ "encodedCommitmentSignedMax: " ++ show e -{-# NOINLINE encodedCommitmentSignedMax #-} - --- Benchmark groups ------------------------------------------------------------ - main :: IO () -main = defaultMain - [ bgroup "v1" - [ bgroup "open_channel" - [ bench "encode" $ nf encodeOpenChannel testOpenChannel - , bench "decode" $ nf decodeOpenChannel encodedOpenChannel - ] +main = case fixtures of + Nothing -> fail "invalid fixtures" + Just fx -> defaultMain [ + bgroup "open_channel" [ + bench "encode" $ nf encode_open_channel (fx_open_channel fx) + , bench "decode" $ nf decode_open_channel (fx_open_channel_bytes fx) + ] + , bgroup "accept_channel2" [ + bench "encode" $ nf encode_accept_channel2 (fx_accept_channel2 fx) + , bench "decode" $ + nf decode_accept_channel2 (fx_accept_channel2_bytes fx) + ] + , bgroup "tx_signatures" [ + bench "encode" $ nf encode_tx_signatures (fx_tx_signatures fx) + , bench "decode" $ nf decode_tx_signatures (fx_tx_signatures_bytes fx) + ] + , bgroup "closing_complete" [ + bench "encode" $ nf encode_closing_complete (fx_closing_complete fx) + , bench "decode" $ + nf decode_closing_complete (fx_closing_complete_bytes fx) + ] + , bgroup "update_add_htlc" [ + bench "encode" $ nf encode_update_add_htlc (fx_update_add_htlc fx) + , bench "decode" $ + nf decode_update_add_htlc (fx_update_add_htlc_bytes fx) + , bench "encode_message" $ + nf encode_message (MsgUpdateAddHtlc (fx_update_add_htlc fx)) + , bench "decode_message" $ + nf decode_message (fx_update_add_htlc_wire fx) + ] + , bgroup "update_fulfill_htlc" [ + bench "encode" $ + nf encode_update_fulfill_htlc (fx_update_fulfill_htlc fx) + , bench "decode" $ + nf decode_update_fulfill_htlc (fx_update_fulfill_htlc_bytes fx) ] - , bgroup "v2" - [ bgroup "open_channel2" - [ bench "encode" $ nf encodeOpenChannel2 testOpenChannel2 - , bench "decode" $ nf decodeOpenChannel2 encodedOpenChannel2 - ] - , bgroup "tx_signatures" - [ bench "encode" $ nf encodeTxSignatures testTxSignatures - , bench "decode" $ nf decodeTxSignatures encodedTxSignatures - ] + , bgroup "commitment_signed" [ + bench "encode (0 htlcs)" $ + nf encode_commitment_signed (fx_commitment_signed fx) + , bench "decode (0 htlcs)" $ + nf decode_commitment_signed (fx_commitment_signed_bytes fx) + , bench "encode (483 htlcs)" $ + nf encode_commitment_signed (fx_commitment_signed_483 fx) + , bench "decode (483 htlcs)" $ + nf decode_commitment_signed (fx_commitment_signed_483_bytes fx) ] - , bgroup "close" - [ bgroup "closing_signed" - [ bench "encode" $ nf encodeClosingSigned testClosingSigned - , bench "decode" $ nf decodeClosingSigned encodedClosingSigned - ] + , bgroup "revoke_and_ack" [ + bench "encode" $ nf encode_revoke_and_ack (fx_revoke_and_ack fx) + , bench "decode" $ + nf decode_revoke_and_ack (fx_revoke_and_ack_bytes fx) ] - , bgroup "normal" - [ bgroup "update_add_htlc" - [ bench "encode" $ nf encodeUpdateAddHtlc testUpdateAddHtlc - , bench "decode" $ nf decodeUpdateAddHtlc encodedUpdateAddHtlc - ] - , bgroup "commitment_signed" - [ bench "encode" $ nf encodeCommitmentSigned testCommitmentSigned - , bench "decode" $ nf decodeCommitmentSigned encodedCommitmentSigned - ] - , bgroup "commitment_signed_100" - [ bench "encode" $ - nf encodeCommitmentSigned testCommitmentSignedLarge - , bench "decode" $ - nf decodeCommitmentSigned encodedCommitmentSignedLarge - ] - , bgroup "commitment_signed_483" - [ bench "encode" $ - nf encodeCommitmentSigned testCommitmentSignedMax - , bench "decode" $ - nf decodeCommitmentSigned encodedCommitmentSignedMax - ] + , bgroup "channel_reestablish" [ + bench "encode" $ + nf encode_channel_reestablish (fx_channel_reestablish fx) + , bench "decode" $ + nf decode_channel_reestablish (fx_channel_reestablish_bytes fx) ] - ] + ] diff --git a/bench/Weight.hs b/bench/Weight.hs @@ -1,344 +1,49 @@ -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE OverloadedStrings #-} - --- | --- Module: Main --- Copyright: (c) 2025 Jared Tobin --- License: MIT --- Maintainer: Jared Tobin <jared@ppad.tech> --- --- Weigh allocation benchmarks for BOLT #2 message codecs. - module Main where -import qualified Data.ByteString as BS -import Lightning.Protocol.BOLT1 (TlvStream, unsafeTlvStream) +import Fixtures import Lightning.Protocol.BOLT2 import Weigh --- | Wrapper for encoding functions that return Either. -forceEncode :: Either EncodeError BS.ByteString -> BS.ByteString -forceEncode (Right bs) = bs -forceEncode (Left e) = error $ "forceEncode: " ++ show e -{-# INLINE forceEncode #-} - --- Test data construction ------------------------------------------------------ - --- | 32 zero bytes for channel IDs, chain hashes, etc. -zeroBytes32 :: BS.ByteString -zeroBytes32 = BS.replicate 32 0x00 -{-# NOINLINE zeroBytes32 #-} - --- | 33-byte compressed public key (02 prefix + 32 zero bytes). -testPoint :: Point -testPoint = case point (BS.cons 0x02 zeroBytes32) of - Just p -> p - Nothing -> error "testPoint: invalid" -{-# NOINLINE testPoint #-} - --- | 64-byte signature. -testSignature :: Signature -testSignature = case signature (BS.replicate 64 0x01) of - Just s -> s - Nothing -> error "testSignature: invalid" -{-# NOINLINE testSignature #-} - --- | 32-byte channel ID. -testChannelId :: ChannelId -testChannelId = case channelId zeroBytes32 of - Just c -> c - Nothing -> error "testChannelId: invalid" -{-# NOINLINE testChannelId #-} - --- | 32-byte chain hash. -testChainHash :: ChainHash -testChainHash = case chainHash zeroBytes32 of - Just h -> h - Nothing -> error "testChainHash: invalid" -{-# NOINLINE testChainHash #-} - --- | 32-byte txid. -testTxId :: TxId -testTxId = case mkTxId zeroBytes32 of - Just t -> t - Nothing -> error "testTxId: invalid" -{-# NOINLINE testTxId #-} - --- | 32-byte payment hash. -testPaymentHash :: PaymentHash -testPaymentHash = case paymentHash zeroBytes32 of - Just h -> h - Nothing -> error "testPaymentHash: invalid" -{-# NOINLINE testPaymentHash #-} - --- | 1366-byte onion packet. -testOnionPacket :: OnionPacket -testOnionPacket = case onionPacket (BS.replicate 1366 0x00) of - Just o -> o - Nothing -> error "testOnionPacket: invalid" -{-# NOINLINE testOnionPacket #-} - --- | Empty TLV stream. -emptyTlvs :: TlvStream -emptyTlvs = unsafeTlvStream [] -{-# NOINLINE emptyTlvs #-} - --- Message constructors -------------------------------------------------------- - --- | Construct OpenChannel message. -mkOpenChannel :: ChainHash -> ChannelId -> Point -> TlvStream -> OpenChannel -mkOpenChannel !ch !cid !pt !tlvs = OpenChannel - { openChannelChainHash = ch - , openChannelTempChannelId = cid - , openChannelFundingSatoshi = Satoshi 1000000 - , openChannelPushMsat = MilliSatoshi 0 - , openChannelDustLimitSatoshi = Satoshi 546 - , openChannelMaxHtlcValueInFlight = MilliSatoshi 1000000000 - , openChannelChannelReserveSat = Satoshi 10000 - , openChannelHtlcMinimumMsat = MilliSatoshi 1000 - , openChannelFeeratePerKw = 250 - , openChannelToSelfDelay = 144 - , openChannelMaxAcceptedHtlcs = 30 - , openChannelFundingPubkey = pt - , openChannelRevocationBasepoint = pt - , openChannelPaymentBasepoint = pt - , openChannelDelayedPaymentBase = pt - , openChannelHtlcBasepoint = pt - , openChannelFirstPerCommitPoint = pt - , openChannelChannelFlags = 0x00 - , openChannelTlvs = tlvs - } - --- | Construct OpenChannel2 message. -mkOpenChannel2 :: ChainHash -> ChannelId -> Point -> TlvStream -> OpenChannel2 -mkOpenChannel2 !ch !cid !pt !tlvs = OpenChannel2 - { openChannel2ChainHash = ch - , openChannel2TempChannelId = cid - , openChannel2FundingFeeratePerkw = 2500 - , openChannel2CommitFeeratePerkw = 250 - , openChannel2FundingSatoshi = Satoshi 1000000 - , openChannel2DustLimitSatoshi = Satoshi 546 - , openChannel2MaxHtlcValueInFlight = MilliSatoshi 1000000000 - , openChannel2HtlcMinimumMsat = MilliSatoshi 1000 - , openChannel2ToSelfDelay = 144 - , openChannel2MaxAcceptedHtlcs = 30 - , openChannel2Locktime = 0 - , openChannel2FundingPubkey = pt - , openChannel2RevocationBasepoint = pt - , openChannel2PaymentBasepoint = pt - , openChannel2DelayedPaymentBase = pt - , openChannel2HtlcBasepoint = pt - , openChannel2FirstPerCommitPoint = pt - , openChannel2SecondPerCommitPoint = pt - , openChannel2ChannelFlags = 0x00 - , openChannel2Tlvs = tlvs - } - --- | Construct TxSignatures message. -mkTxSignatures :: ChannelId -> TxId -> [Witness] -> TxSignatures -mkTxSignatures !cid !tid !ws = TxSignatures - { txSignaturesChannelId = cid - , txSignaturesTxid = tid - , txSignaturesWitnesses = ws - } - --- | Construct ClosingSigned message. -mkClosingSigned :: ChannelId -> Signature -> TlvStream -> ClosingSigned -mkClosingSigned !cid !sig !tlvs = ClosingSigned - { closingSignedChannelId = cid - , closingSignedFeeSatoshi = Satoshi 1000 - , closingSignedSignature = sig - , closingSignedTlvs = tlvs - } - --- | Construct UpdateAddHtlc message. -mkUpdateAddHtlc - :: ChannelId -> PaymentHash -> OnionPacket -> TlvStream -> UpdateAddHtlc -mkUpdateAddHtlc !cid !ph !onion !tlvs = UpdateAddHtlc - { updateAddHtlcChannelId = cid - , updateAddHtlcId = htlcId 0 - , updateAddHtlcAmountMsat = MilliSatoshi 10000000 - , updateAddHtlcPaymentHash = ph - , updateAddHtlcCltvExpiry = 800000 - , updateAddHtlcOnionPacket = onion - , updateAddHtlcTlvs = tlvs - } - --- | Construct CommitmentSigned message. -mkCommitmentSigned :: ChannelId -> Signature -> [Signature] -> CommitmentSigned -mkCommitmentSigned !cid !sig !htlcSigs = CommitmentSigned - { commitmentSignedChannelId = cid - , commitmentSignedSignature = sig - , commitmentSignedHtlcSignatures = htlcSigs - } - --- Pre-constructed messages ---------------------------------------------------- - --- | Test OpenChannel message. -testOpenChannel :: OpenChannel -testOpenChannel = - mkOpenChannel testChainHash testChannelId testPoint emptyTlvs -{-# NOINLINE testOpenChannel #-} - --- | Encoded OpenChannel for decode benchmarks. -encodedOpenChannel :: BS.ByteString -encodedOpenChannel = encodeOpenChannel testOpenChannel -{-# NOINLINE encodedOpenChannel #-} - --- | Test OpenChannel2 message. -testOpenChannel2 :: OpenChannel2 -testOpenChannel2 = - mkOpenChannel2 testChainHash testChannelId testPoint emptyTlvs -{-# NOINLINE testOpenChannel2 #-} - --- | Encoded OpenChannel2 for decode benchmarks. -encodedOpenChannel2 :: BS.ByteString -encodedOpenChannel2 = encodeOpenChannel2 testOpenChannel2 -{-# NOINLINE encodedOpenChannel2 #-} - --- | Test witness data. -testWitness :: Witness -testWitness = Witness (BS.replicate 107 0xab) -{-# NOINLINE testWitness #-} - --- | Multiple witnesses for TxSignatures. -testWitnesses :: [Witness] -testWitnesses = replicate 5 testWitness -{-# NOINLINE testWitnesses #-} - --- | Test TxSignatures message. -testTxSignatures :: TxSignatures -testTxSignatures = mkTxSignatures testChannelId testTxId testWitnesses -{-# NOINLINE testTxSignatures #-} - --- | Encoded TxSignatures for decode benchmarks. -encodedTxSignatures :: BS.ByteString -encodedTxSignatures = case encodeTxSignatures testTxSignatures of - Right bs -> bs - Left e -> error $ "encodedTxSignatures: " ++ show e -{-# NOINLINE encodedTxSignatures #-} - --- | Test ClosingSigned message. -testClosingSigned :: ClosingSigned -testClosingSigned = mkClosingSigned testChannelId testSignature emptyTlvs -{-# NOINLINE testClosingSigned #-} - --- | Encoded ClosingSigned for decode benchmarks. -encodedClosingSigned :: BS.ByteString -encodedClosingSigned = encodeClosingSigned testClosingSigned -{-# NOINLINE encodedClosingSigned #-} - --- | Test UpdateAddHtlc message. -testUpdateAddHtlc :: UpdateAddHtlc -testUpdateAddHtlc = - mkUpdateAddHtlc testChannelId testPaymentHash testOnionPacket emptyTlvs -{-# NOINLINE testUpdateAddHtlc #-} - --- | Encoded UpdateAddHtlc for decode benchmarks. -encodedUpdateAddHtlc :: BS.ByteString -encodedUpdateAddHtlc = encodeUpdateAddHtlc testUpdateAddHtlc -{-# NOINLINE encodedUpdateAddHtlc #-} - --- | HTLC signatures for CommitmentSigned. -testHtlcSigs :: [Signature] -testHtlcSigs = replicate 10 testSignature -{-# NOINLINE testHtlcSigs #-} - --- | Test CommitmentSigned message. -testCommitmentSigned :: CommitmentSigned -testCommitmentSigned = - mkCommitmentSigned testChannelId testSignature testHtlcSigs -{-# NOINLINE testCommitmentSigned #-} - --- | Encoded CommitmentSigned for decode benchmarks. -encodedCommitmentSigned :: BS.ByteString -encodedCommitmentSigned = case encodeCommitmentSigned testCommitmentSigned of - Right bs -> bs - Left e -> error $ "encodedCommitmentSigned: " ++ show e -{-# NOINLINE encodedCommitmentSigned #-} - --- | Large HTLC signatures for CommitmentSigned (100). -testHtlcSigsLarge :: [Signature] -testHtlcSigsLarge = replicate 100 testSignature -{-# NOINLINE testHtlcSigsLarge #-} - --- | Test CommitmentSigned message (100 sigs). -testCommitmentSignedLarge :: CommitmentSigned -testCommitmentSignedLarge = - mkCommitmentSigned testChannelId testSignature testHtlcSigsLarge -{-# NOINLINE testCommitmentSignedLarge #-} - --- | Encoded large CommitmentSigned for decode benchmarks. -encodedCommitmentSignedLarge :: BS.ByteString -encodedCommitmentSignedLarge = - case encodeCommitmentSigned testCommitmentSignedLarge of - Right bs -> bs - Left e -> error $ "encodedCommitmentSignedLarge: " ++ show e -{-# NOINLINE encodedCommitmentSignedLarge #-} - --- | Max HTLC signatures for CommitmentSigned (483). -testHtlcSigsMax :: [Signature] -testHtlcSigsMax = replicate 483 testSignature -{-# NOINLINE testHtlcSigsMax #-} - --- | Test CommitmentSigned message (483 sigs). -testCommitmentSignedMax :: CommitmentSigned -testCommitmentSignedMax = - mkCommitmentSigned testChannelId testSignature testHtlcSigsMax -{-# NOINLINE testCommitmentSignedMax #-} - --- | Encoded max CommitmentSigned for decode benchmarks. -encodedCommitmentSignedMax :: BS.ByteString -encodedCommitmentSignedMax = - case encodeCommitmentSigned testCommitmentSignedMax of - Right bs -> bs - Left e -> error $ "encodedCommitmentSignedMax: " ++ show e -{-# NOINLINE encodedCommitmentSignedMax #-} - --- Weigh benchmarks ------------------------------------------------------------ - main :: IO () -main = mainWith $ do - -- V1 message construction and encoding - wgroup "v1/open_channel" $ do - func "construct" (mkOpenChannel testChainHash testChannelId testPoint) - emptyTlvs - func "encode" encodeOpenChannel testOpenChannel - func "decode" decodeOpenChannel encodedOpenChannel - - -- V2 message construction and encoding - wgroup "v2/open_channel2" $ do - func "construct" (mkOpenChannel2 testChainHash testChannelId testPoint) - emptyTlvs - func "encode" encodeOpenChannel2 testOpenChannel2 - func "decode" decodeOpenChannel2 encodedOpenChannel2 - - wgroup "v2/tx_signatures" $ do - func "construct" (mkTxSignatures testChannelId testTxId) testWitnesses - func "encode" (forceEncode . encodeTxSignatures) testTxSignatures - func "decode" decodeTxSignatures encodedTxSignatures - - -- Close messages - wgroup "close/closing_signed" $ do - func "construct" (mkClosingSigned testChannelId testSignature) emptyTlvs - func "encode" encodeClosingSigned testClosingSigned - func "decode" decodeClosingSigned encodedClosingSigned - - -- Normal operation (hot paths) - wgroup "normal/update_add_htlc" $ do - func "construct" - (mkUpdateAddHtlc testChannelId testPaymentHash testOnionPacket) emptyTlvs - func "encode" encodeUpdateAddHtlc testUpdateAddHtlc - func "decode" decodeUpdateAddHtlc encodedUpdateAddHtlc - - wgroup "normal/commitment_signed" $ do - func "construct" (mkCommitmentSigned testChannelId testSignature) - testHtlcSigs - func "encode" (forceEncode . encodeCommitmentSigned) testCommitmentSigned - func "decode" decodeCommitmentSigned encodedCommitmentSigned - - wgroup "normal/commitment_signed_100" $ do - func "decode" decodeCommitmentSigned encodedCommitmentSignedLarge - - wgroup "normal/commitment_signed_483" $ do - func "decode" decodeCommitmentSigned encodedCommitmentSignedMax +main = case fixtures of + Nothing -> fail "invalid fixtures" + Just fx -> mainWith $ do + func "baseline (weigh overhead)" (+ (1 :: Int)) 1 + wgroup "open_channel" $ do + func "encode" encode_open_channel (fx_open_channel fx) + func "decode" decode_open_channel (fx_open_channel_bytes fx) + wgroup "accept_channel2" $ do + func "encode" encode_accept_channel2 (fx_accept_channel2 fx) + func "decode" decode_accept_channel2 (fx_accept_channel2_bytes fx) + wgroup "tx_signatures" $ do + func "encode" encode_tx_signatures (fx_tx_signatures fx) + func "decode" decode_tx_signatures (fx_tx_signatures_bytes fx) + wgroup "closing_complete" $ do + func "encode" encode_closing_complete (fx_closing_complete fx) + func "decode" decode_closing_complete (fx_closing_complete_bytes fx) + wgroup "update_add_htlc" $ do + func "encode" encode_update_add_htlc (fx_update_add_htlc fx) + func "decode" decode_update_add_htlc (fx_update_add_htlc_bytes fx) + func "encode_message" encode_message + (MsgUpdateAddHtlc (fx_update_add_htlc fx)) + func "decode_message" decode_message (fx_update_add_htlc_wire fx) + wgroup "update_fulfill_htlc" $ do + func "encode" encode_update_fulfill_htlc (fx_update_fulfill_htlc fx) + func "decode" decode_update_fulfill_htlc + (fx_update_fulfill_htlc_bytes fx) + wgroup "commitment_signed" $ do + func "encode (0 htlcs)" encode_commitment_signed + (fx_commitment_signed fx) + func "decode (0 htlcs)" decode_commitment_signed + (fx_commitment_signed_bytes fx) + func "encode (483 htlcs)" encode_commitment_signed + (fx_commitment_signed_483 fx) + func "decode (483 htlcs)" decode_commitment_signed + (fx_commitment_signed_483_bytes fx) + wgroup "revoke_and_ack" $ do + func "encode" encode_revoke_and_ack (fx_revoke_and_ack fx) + func "decode" decode_revoke_and_ack (fx_revoke_and_ack_bytes fx) + wgroup "channel_reestablish" $ do + func "encode" encode_channel_reestablish (fx_channel_reestablish fx) + func "decode" decode_channel_reestablish + (fx_channel_reestablish_bytes fx)