{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
module Lightning.Protocol.BOLT7.Validate (
ValidationError(..)
, validateChannelAnnouncement
, validateNodeAnnouncement
, validateChannelUpdate
, validateQueryChannelRange
, validateReplyChannelRange
) where
import Control.DeepSeq (NFData)
import Data.Word (Word32, Word64)
import GHC.Generics (Generic)
import Lightning.Protocol.BOLT7.Codec (decodeShortChannelIdList)
import Lightning.Protocol.BOLT7.Messages
import Lightning.Protocol.BOLT7.Types
data ValidationError
= ValidateNodeIdOrdering
| ValidateUnknownEvenFeature
| ValidateHtlcAmounts
| ValidateBlockOverflow
| ValidateScidNotAscending
deriving (ValidationError -> ValidationError -> Bool
(ValidationError -> ValidationError -> Bool)
-> (ValidationError -> ValidationError -> Bool)
-> Eq ValidationError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ValidationError -> ValidationError -> Bool
== :: ValidationError -> ValidationError -> Bool
$c/= :: ValidationError -> ValidationError -> Bool
/= :: ValidationError -> ValidationError -> Bool
Eq, Int -> ValidationError -> ShowS
[ValidationError] -> ShowS
ValidationError -> String
(Int -> ValidationError -> ShowS)
-> (ValidationError -> String)
-> ([ValidationError] -> ShowS)
-> Show ValidationError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ValidationError -> ShowS
showsPrec :: Int -> ValidationError -> ShowS
$cshow :: ValidationError -> String
show :: ValidationError -> String
$cshowList :: [ValidationError] -> ShowS
showList :: [ValidationError] -> ShowS
Show, (forall x. ValidationError -> Rep ValidationError x)
-> (forall x. Rep ValidationError x -> ValidationError)
-> Generic ValidationError
forall x. Rep ValidationError x -> ValidationError
forall x. ValidationError -> Rep ValidationError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ValidationError -> Rep ValidationError x
from :: forall x. ValidationError -> Rep ValidationError x
$cto :: forall x. Rep ValidationError x -> ValidationError
to :: forall x. Rep ValidationError x -> ValidationError
Generic)
instance NFData ValidationError
validateChannelAnnouncement :: ChannelAnnouncement
-> Either ValidationError ()
validateChannelAnnouncement :: ChannelAnnouncement -> Either ValidationError ()
validateChannelAnnouncement ChannelAnnouncement
msg = do
let nid1 :: NodeId
nid1 = ChannelAnnouncement -> NodeId
channelAnnNodeId1 ChannelAnnouncement
msg
nid2 :: NodeId
nid2 = ChannelAnnouncement -> NodeId
channelAnnNodeId2 ChannelAnnouncement
msg
if NodeId
nid1 NodeId -> NodeId -> Bool
forall a. Ord a => a -> a -> Bool
>= NodeId
nid2
then ValidationError -> Either ValidationError ()
forall a b. a -> Either a b
Left ValidationError
ValidateNodeIdOrdering
else () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
FeatureBits -> Either ValidationError ()
validateFeatureBits (ChannelAnnouncement -> FeatureBits
channelAnnFeatures ChannelAnnouncement
msg)
validateNodeAnnouncement :: NodeAnnouncement -> Either ValidationError ()
validateNodeAnnouncement :: NodeAnnouncement -> Either ValidationError ()
validateNodeAnnouncement NodeAnnouncement
msg = do
FeatureBits -> Either ValidationError ()
validateFeatureBits (NodeAnnouncement -> FeatureBits
nodeAnnFeatures NodeAnnouncement
msg)
validateChannelUpdate :: ChannelUpdate -> Either ValidationError ()
validateChannelUpdate :: ChannelUpdate -> Either ValidationError ()
validateChannelUpdate ChannelUpdate
msg = do
case ChannelUpdate -> Maybe HtlcMaximumMsat
chanUpdateHtlcMaxMsat ChannelUpdate
msg of
Maybe HtlcMaximumMsat
Nothing -> () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
Just HtlcMaximumMsat
htlcMax ->
let htlcMin :: HtlcMinimumMsat
htlcMin = ChannelUpdate -> HtlcMinimumMsat
chanUpdateHtlcMinMsat ChannelUpdate
msg
in if HtlcMinimumMsat -> Word64
getHtlcMinimumMsat HtlcMinimumMsat
htlcMin Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> HtlcMaximumMsat -> Word64
getHtlcMaximumMsat HtlcMaximumMsat
htlcMax
then ValidationError -> Either ValidationError ()
forall a b. a -> Either a b
Left ValidationError
ValidateHtlcAmounts
else () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
validateQueryChannelRange :: QueryChannelRange -> Either ValidationError ()
validateQueryChannelRange :: QueryChannelRange -> Either ValidationError ()
validateQueryChannelRange QueryChannelRange
msg = do
let first :: Word64
first = Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (QueryChannelRange -> Word32
queryRangeFirstBlock QueryChannelRange
msg) :: Word64
num :: Word64
num = Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (QueryChannelRange -> Word32
queryRangeNumBlocks QueryChannelRange
msg) :: Word64
if Word64
first Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
num Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
forall a. Bounded a => a
maxBound :: Word32)
then ValidationError -> Either ValidationError ()
forall a b. a -> Either a b
Left ValidationError
ValidateBlockOverflow
else () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
validateReplyChannelRange :: ReplyChannelRange -> Either ValidationError ()
validateReplyChannelRange :: ReplyChannelRange -> Either ValidationError ()
validateReplyChannelRange ReplyChannelRange
msg =
case ByteString -> Either DecodeError [ShortChannelId]
decodeShortChannelIdList (ReplyChannelRange -> ByteString
replyRangeData ReplyChannelRange
msg) of
Left DecodeError
_ -> () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
Right [ShortChannelId]
scids -> [ShortChannelId] -> Either ValidationError ()
checkAscending [ShortChannelId]
scids
where
checkAscending :: [ShortChannelId] -> Either ValidationError ()
checkAscending [] = () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
checkAscending [ShortChannelId
_] = () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()
checkAscending (ShortChannelId
a:ShortChannelId
b:[ShortChannelId]
rest)
| ShortChannelId -> ByteString
getShortChannelId ShortChannelId
a ByteString -> ByteString -> Bool
forall a. Ord a => a -> a -> Bool
< ShortChannelId -> ByteString
getShortChannelId ShortChannelId
b = [ShortChannelId] -> Either ValidationError ()
checkAscending (ShortChannelId
bShortChannelId -> [ShortChannelId] -> [ShortChannelId]
forall a. a -> [a] -> [a]
:[ShortChannelId]
rest)
| Bool
otherwise = ValidationError -> Either ValidationError ()
forall a b. a -> Either a b
Left ValidationError
ValidateScidNotAscending
validateFeatureBits :: FeatureBits -> Either ValidationError ()
validateFeatureBits :: FeatureBits -> Either ValidationError ()
validateFeatureBits FeatureBits
_features = () -> Either ValidationError ()
forall a b. b -> Either a b
Right ()