ppad-bolt4-0.1.0: bench/Fixtures.hs
{-# LANGUAGE OverloadedStrings #-}
module Fixtures (
Fixtures(..)
, fixtures
) where
import Control.DeepSeq (NFData(..))
import qualified Data.ByteString as BS
import qualified Lightning.Protocol.BOLT1 as BOLT1
import Lightning.Protocol.BOLT4
data Fixtures = Fixtures {
fx_session :: !SecretKey
, fx_ad :: !BS.ByteString
, fx_route_1 :: ![Hop]
, fx_route_5 :: ![Hop]
, fx_route_20 :: ![Hop]
, fx_first_node :: !SecretKey
, fx_onion_5 :: !OnionPacket
, fx_onion_1 :: !OnionPacket
, fx_secrets_5 :: ![SharedSecret]
, fx_secret :: !SharedSecret
, fx_blinded_node :: !SecretKey
, fx_blinded_onion :: !OnionPacket
, fx_path_key :: !BOLT1.Point
, fx_path_seed :: !SecretKey
, fx_path_nodes :: ![(BOLT1.Point, BlindedHopData)]
, fx_encrypted :: !BS.ByteString
, fx_failure :: !FailureMessage
, fx_error :: !ErrorPacket
, fx_returned :: !ErrorPacket
, fx_onion_bytes :: !BS.ByteString
, fx_payload :: !HopPayload
, fx_payload_bytes :: !BS.ByteString
}
instance NFData Fixtures where
rnf (Fixtures a b c d e f g h i j k l m n o p q r s t u v) =
rnf a `seq` rnf b `seq` rnf c `seq` rnf d `seq` rnf e `seq` rnf f
`seq` rnf g `seq` rnf h `seq` rnf i `seq` rnf j `seq` rnf k
`seq` rnf l `seq` rnf m `seq` rnf n `seq` rnf o `seq` rnf p
`seq` rnf q `seq` rnf r `seq` rnf s `seq` rnf t `seq` rnf u
`seq` rnf v
demand :: String -> Maybe a -> IO a
demand msg = maybe (ioError (userError msg)) pure
right :: Show e => String -> Either e a -> IO a
right msg = either (ioError . userError . (msg ++) . (": " ++) . show) pure
fixtures :: IO Fixtures
fixtures = do
let key b = demand "secret_key" (secret_key (BS.replicate 32 b))
ad = BS.replicate 32 0x42
session <- key 0x41
nodes <- mapM key [1 .. 20]
amt <- demand "milli_satoshi" (BOLT1.milli_satoshi 100000)
scid <- demand "short_channel_id" (BOLT1.short_channel_id 800000 1 0)
ps <- demand "payment_secret" (payment_secret (BS.replicate 32 0xaa))
let fwd = empty_hop_payload
{ hp_amt_to_forward = Just amt
, hp_outgoing_cltv_value = Just 800000
, hp_short_channel_id = Just scid
}
final = empty_hop_payload
{ hp_amt_to_forward = Just amt
, hp_outgoing_cltv_value = Just 800000
, hp_payment_data = Just (PaymentData ps amt)
}
route n = [ Hop (public_key k) fwd | k <- take (n - 1) nodes ]
++ [ Hop (public_key k) final
| k <- take 1 (drop (n - 1) nodes) ]
first_node <- demand "node" (safe_head nodes)
(onion_5, secrets_5) <- right "construct" (construct session (route 5) ad)
(onion_1, _) <- right "construct" (construct session (route 1) ad)
-- a blinded route through nodes 1 to 3, entered at node 0
seed <- key 0x55
let relay = empty_blinded_hop_data
{ bhd_short_channel_id = Just scid
, bhd_payment_relay = Just (PaymentRelay 40 100 1000)
}
path_nodes = [ (public_key k, relay) | k <- take 2 (drop 1 nodes) ]
++ [ (public_key k, empty_blinded_hop_data
{ bhd_path_id = Just (BS.replicate 32 1) })
| k <- take 1 (drop 3 nodes) ]
path <- right "create_blinded_path" (create_blinded_path seed path_nodes)
hops <- case bp_hops path of
[h1, h2, h3] -> pure (h1, h2, h3)
_ -> ioError (userError "expected 3 blinded hops")
let (h1, h2, h3) = hops
bhop h pl = Hop (bh_blinded_node_id h)
pl { hp_encrypted_data = Just (bh_encrypted_data h) }
entry = Hop (public_key first_node) fwd
broute = [ entry
, Hop (bp_first_node_id path) empty_hop_payload
{ hp_encrypted_data = Just (bh_encrypted_data h1)
, hp_current_path_key = Just (bp_first_path_key path) }
, bhop h2 empty_hop_payload
, bhop h3 empty_hop_payload
{ hp_amt_to_forward = Just amt
, hp_outgoing_cltv_value = Just 800000
, hp_total_amount_msat = Just amt } ]
(bonion, _) <- right "construct" (construct session broute ad)
-- the onion received, with a path_key, by node 2
node1 <- demand "node" (safe_head (drop 1 nodes))
node2 <- demand "node" (safe_head (drop 2 nodes))
f0 <- forwarded (process first_node bonion ad Nothing)
f1 <- forwarded (process node1 (fwd_next_packet f0) ad Nothing)
b1 <- demand "blinded" (fwd_blinded f1)
-- node 4 fails a 5-hop payment
ss4 <- demand "secret" (safe_head (drop 4 secrets_5))
let failure = FailureMessage TemporaryNodeFailure BOLT1.empty_tlv_stream
err <- right "construct_error" (construct_error ss4 failure)
let returned = foldr wrap_error err (take 4 secrets_5)
payload_bytes <- right "encode_hop_payload" (encode_hop_payload final)
pure Fixtures {
fx_session = session
, fx_ad = ad
, fx_route_1 = route 1
, fx_route_5 = route 5
, fx_route_20 = route 20
, fx_first_node = first_node
, fx_onion_5 = onion_5
, fx_onion_1 = onion_1
, fx_secrets_5 = secrets_5
, fx_secret = ss4
, fx_blinded_node = node2
, fx_blinded_onion = fwd_next_packet f1
, fx_path_key = bi_next_path_key b1
, fx_path_seed = seed
, fx_path_nodes = path_nodes
, fx_encrypted = bh_encrypted_data h2
, fx_failure = failure
, fx_error = err
, fx_returned = returned
, fx_onion_bytes = encode_onion_packet onion_5
, fx_payload = final
, fx_payload_bytes = payload_bytes
}
where
safe_head xs = case xs of
x : _ -> Just x
[] -> Nothing
forwarded r = case r of
Right (Forward f) -> pure f
_ -> ioError (userError ("expected Forward: " ++ show r))