mirror of https://github.com/voidlizard/hbs2
Merge iv/integrate-encryption-test-dev2 into refchan-merge-2 (using imerge)
This commit is contained in:
commit
75f03b9c95
|
@ -258,7 +258,7 @@ keeyring "/path/to/new.key"
|
||||||
5. Add git remote and push
|
5. Add git remote and push
|
||||||
|
|
||||||
```
|
```
|
||||||
git add mynerepo hbs2://eq5ZFnB9HQTMTeYasYC3pSZLedcP7Zp2eDkJNdehVVk
|
git remote add mynerepo hbs2://eq5ZFnB9HQTMTeYasYC3pSZLedcP7Zp2eDkJNdehVVk
|
||||||
git push mynerepo
|
git push mynerepo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1299,3 +1299,11 @@ PR: implement-http-block-download-worker
|
||||||
PR: tcp-pex
|
PR: tcp-pex
|
||||||
branch: iv/tcp-pex_3
|
branch: iv/tcp-pex_3
|
||||||
commit: f1de7c58d5dc36dec5c318a3297733791de9a3d8
|
commit: f1de7c58d5dc36dec5c318a3297733791de9a3d8
|
||||||
|
|
||||||
|
## 2023-06-15
|
||||||
|
|
||||||
|
PR: bus-crypt
|
||||||
|
branch: iv/bus-crypt
|
||||||
|
Шифрование протокола общения нод.
|
||||||
|
Обмен асимметричными публичными ключами выполняется на стадии хэндшейка в ping/pong.
|
||||||
|
Для шифрования данных создаётся симметричный ключ по diffie-hellman.
|
||||||
|
|
|
@ -53,11 +53,13 @@ common shared-properties
|
||||||
, MultiParamTypeClasses
|
, MultiParamTypeClasses
|
||||||
, OverloadedStrings
|
, OverloadedStrings
|
||||||
, QuasiQuotes
|
, QuasiQuotes
|
||||||
|
, RecordWildCards
|
||||||
, ScopedTypeVariables
|
, ScopedTypeVariables
|
||||||
, StandaloneDeriving
|
, StandaloneDeriving
|
||||||
, TupleSections
|
, TupleSections
|
||||||
, TypeApplications
|
, TypeApplications
|
||||||
, TypeFamilies
|
, TypeFamilies
|
||||||
|
, TemplateHaskell
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,9 +72,11 @@ library
|
||||||
, HBS2.Actors.Peer.Types
|
, HBS2.Actors.Peer.Types
|
||||||
, HBS2.Base58
|
, HBS2.Base58
|
||||||
, HBS2.Clock
|
, HBS2.Clock
|
||||||
|
, HBS2.Crypto
|
||||||
, HBS2.Data.Detect
|
, HBS2.Data.Detect
|
||||||
, HBS2.Data.Types
|
, HBS2.Data.Types
|
||||||
, HBS2.Data.Types.Crypto
|
, HBS2.Data.Types.Crypto
|
||||||
|
, HBS2.Data.Types.Peer
|
||||||
, HBS2.Data.Types.Refs
|
, HBS2.Data.Types.Refs
|
||||||
, HBS2.Defaults
|
, HBS2.Defaults
|
||||||
, HBS2.Events
|
, HBS2.Events
|
||||||
|
@ -92,6 +96,8 @@ library
|
||||||
, HBS2.Net.Proto.BlockChunks
|
, HBS2.Net.Proto.BlockChunks
|
||||||
, HBS2.Net.Proto.BlockInfo
|
, HBS2.Net.Proto.BlockInfo
|
||||||
, HBS2.Net.Proto.Definition
|
, HBS2.Net.Proto.Definition
|
||||||
|
, HBS2.Net.Proto.EncryptionHandshake
|
||||||
|
, HBS2.Net.Proto.Event.PeerExpired
|
||||||
, HBS2.Net.Proto.Peer
|
, HBS2.Net.Proto.Peer
|
||||||
, HBS2.Net.Proto.PeerAnnounce
|
, HBS2.Net.Proto.PeerAnnounce
|
||||||
, HBS2.Net.Proto.PeerExchange
|
, HBS2.Net.Proto.PeerExchange
|
||||||
|
@ -151,9 +157,11 @@ library
|
||||||
, stm
|
, stm
|
||||||
, stm-chans
|
, stm-chans
|
||||||
, streaming
|
, streaming
|
||||||
|
, string-conversions
|
||||||
, suckless-conf
|
, suckless-conf
|
||||||
, temporary
|
, temporary
|
||||||
, text
|
, text
|
||||||
|
, time
|
||||||
, transformers
|
, transformers
|
||||||
, uniplate
|
, uniplate
|
||||||
, unordered-containers
|
, unordered-containers
|
||||||
|
@ -190,17 +198,21 @@ test-suite test
|
||||||
, mtl
|
, mtl
|
||||||
, prettyprinter
|
, prettyprinter
|
||||||
, QuickCheck
|
, QuickCheck
|
||||||
|
, quickcheck-instances
|
||||||
, random
|
, random
|
||||||
, safe
|
, safe
|
||||||
, serialise
|
, serialise
|
||||||
, stm
|
, stm
|
||||||
, streaming
|
, streaming
|
||||||
, tasty
|
, tasty
|
||||||
|
, tasty-quickcheck
|
||||||
, tasty-hunit
|
, tasty-hunit
|
||||||
, transformers
|
, transformers
|
||||||
, uniplate
|
, uniplate
|
||||||
, vector
|
, vector
|
||||||
|
, saltine
|
||||||
, simple-logger
|
, simple-logger
|
||||||
|
, string-conversions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,11 @@ module HBS2.Actors.Peer
|
||||||
import HBS2.Actors
|
import HBS2.Actors
|
||||||
import HBS2.Actors.Peer.Types
|
import HBS2.Actors.Peer.Types
|
||||||
import HBS2.Clock
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Types.Peer
|
||||||
import HBS2.Defaults
|
import HBS2.Defaults
|
||||||
import HBS2.Events
|
import HBS2.Events
|
||||||
import HBS2.Hash
|
import HBS2.Hash
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
import HBS2.Net.Messaging
|
import HBS2.Net.Messaging
|
||||||
import HBS2.Net.PeerLocator
|
import HBS2.Net.PeerLocator
|
||||||
import HBS2.Net.PeerLocator.Static
|
import HBS2.Net.PeerLocator.Static
|
||||||
|
@ -21,7 +23,9 @@ import HBS2.Net.Proto
|
||||||
import HBS2.Net.Proto.Sessions
|
import HBS2.Net.Proto.Sessions
|
||||||
import HBS2.Prelude.Plated
|
import HBS2.Prelude.Plated
|
||||||
import HBS2.Storage
|
import HBS2.Storage
|
||||||
|
import HBS2.System.Logger.Simple
|
||||||
|
|
||||||
|
import Control.Applicative
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
|
@ -30,18 +34,24 @@ import Data.Cache (Cache)
|
||||||
import Data.Cache qualified as Cache
|
import Data.Cache qualified as Cache
|
||||||
import Data.Dynamic
|
import Data.Dynamic
|
||||||
import Data.Foldable hiding (find)
|
import Data.Foldable hiding (find)
|
||||||
|
import Data.Map (Map)
|
||||||
import Data.Map qualified as Map
|
import Data.Map qualified as Map
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import GHC.TypeLits
|
import GHC.TypeLits
|
||||||
import Lens.Micro.Platform
|
import Lens.Micro.Platform as Lens
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import Data.HashMap.Strict qualified as HashMap
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
import Control.Concurrent.STM.TVar
|
import Control.Concurrent.STM.TVar
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
import UnliftIO (MonadUnliftIO)
|
import Data.Hashable (hash)
|
||||||
|
import UnliftIO (MonadUnliftIO(..))
|
||||||
|
import Crypto.Saltine.Core.SecretBox qualified as SBox -- Симметричное шифрование с nonce без подписи
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt -- Асимметричное шифрование без подписи
|
||||||
|
|
||||||
import Codec.Serialise (serialise, deserialiseOrFail)
|
import Codec.Serialise (serialise, deserialiseOrFail)
|
||||||
|
|
||||||
|
import Prettyprinter hiding (pipe)
|
||||||
|
-- import Debug.Trace
|
||||||
|
|
||||||
|
|
||||||
data AnyMessage enc e = AnyMessage !Integer !(Encoded e)
|
data AnyMessage enc e = AnyMessage !Integer !(Encoded e)
|
||||||
|
@ -132,8 +142,30 @@ data PeerEnv e =
|
||||||
, _envSweepers :: TVar (HashMap SKey [PeerM e IO ()])
|
, _envSweepers :: TVar (HashMap SKey [PeerM e IO ()])
|
||||||
, _envReqMsgLimit :: Cache (Peer e, Integer, Encoded e) ()
|
, _envReqMsgLimit :: Cache (Peer e, Integer, Encoded e) ()
|
||||||
, _envReqProtoLimit :: Cache (Peer e, Integer) ()
|
, _envReqProtoLimit :: Cache (Peer e, Integer) ()
|
||||||
|
, _envAsymmetricKeyPair :: AsymmKeypair (Encryption e)
|
||||||
|
, _envEncryptionKeys :: TVar (HashMap (PeerData e) (CommonSecret (Encryption e)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setEncryptionKey ::
|
||||||
|
( Hashable (PubKey 'Sign (Encryption L4Proto))
|
||||||
|
, Hashable PeerNonce
|
||||||
|
, Show (PubKey 'Sign (Encryption L4Proto))
|
||||||
|
, Show PeerNonce
|
||||||
|
, Show (CommonSecret (Encryption L4Proto))
|
||||||
|
) => PeerEnv L4Proto -> Peer L4Proto -> PeerData L4Proto -> Maybe (CommonSecret (Encryption L4Proto)) -> IO ()
|
||||||
|
setEncryptionKey penv peer pd msecret = do
|
||||||
|
atomically $ modifyTVar' (_envEncryptionKeys penv) $ Lens.at pd .~ msecret
|
||||||
|
case msecret of
|
||||||
|
Nothing -> trace $ "ENCRYPTION delete key" <+> pretty peer <+> viaShow pd
|
||||||
|
Just k -> trace $ "ENCRYPTION store key" <+> pretty peer <+> viaShow pd <+> viaShow k
|
||||||
|
|
||||||
|
getEncryptionKey ::
|
||||||
|
( Hashable (PubKey 'Sign (Encryption L4Proto))
|
||||||
|
, Hashable PeerNonce
|
||||||
|
) => PeerEnv L4Proto -> PeerData L4Proto -> IO (Maybe (CommonSecret (Encryption L4Proto)))
|
||||||
|
getEncryptionKey penv pd =
|
||||||
|
readTVarIO (_envEncryptionKeys penv) <&> preview (Lens.ix pd)
|
||||||
|
|
||||||
newtype PeerM e m a = PeerM { fromPeerM :: ReaderT (PeerEnv e) m a }
|
newtype PeerM e m a = PeerM { fromPeerM :: ReaderT (PeerEnv e) m a }
|
||||||
deriving newtype ( Functor
|
deriving newtype ( Functor
|
||||||
, Applicative
|
, Applicative
|
||||||
|
@ -264,14 +296,16 @@ instance (MonadIO m, HasProtocol e p, Hashable (Encoded e))
|
||||||
pure (not here)
|
pure (not here)
|
||||||
|
|
||||||
instance ( MonadIO m
|
instance ( MonadIO m
|
||||||
, HasProtocol e p
|
, HasProtocol e msg
|
||||||
, HasFabriq e m -- (PeerM e m)
|
, HasFabriq e m -- (PeerM e m)
|
||||||
, HasOwnPeer e m
|
, HasOwnPeer e m
|
||||||
, PeerMessaging e
|
, PeerMessaging e
|
||||||
, HasTimeLimits e p m
|
, HasTimeLimits e msg m
|
||||||
) => Request e p m where
|
, Show (Peer e)
|
||||||
request p msg = do
|
, Show msg
|
||||||
let proto = protoId @e @p (Proxy @p)
|
) => Request e msg m where
|
||||||
|
request peer_e msg = do
|
||||||
|
let proto = protoId @e @msg (Proxy @msg)
|
||||||
pipe <- getFabriq @e
|
pipe <- getFabriq @e
|
||||||
me <- ownPeer @e
|
me <- ownPeer @e
|
||||||
|
|
||||||
|
@ -280,12 +314,17 @@ instance ( MonadIO m
|
||||||
--
|
--
|
||||||
-- TODO: where to store the timeout?
|
-- TODO: where to store the timeout?
|
||||||
-- TODO: where the timeout come from?
|
-- TODO: where the timeout come from?
|
||||||
-- withTimeLimit @e @p p msg $ do
|
-- withTimeLimit @e @msg peer_e msg $ do
|
||||||
-- liftIO $ print "request!"
|
-- liftIO $ print "request!"
|
||||||
allowed <- tryLockForPeriod p msg
|
allowed <- tryLockForPeriod peer_e msg
|
||||||
|
|
||||||
|
when (not allowed) do
|
||||||
|
trace $ "REQUEST: not allowed to send" <+> viaShow msg
|
||||||
|
|
||||||
when allowed do
|
when allowed do
|
||||||
sendTo pipe (To p) (From me) (AnyMessage @(Encoded e) @e proto (encode msg))
|
sendTo pipe (To peer_e) (From me) (AnyMessage @(Encoded e) @e proto (encode msg))
|
||||||
|
-- trace $ "REQUEST: after sendTo" <+> viaShow peer_e <+> viaShow msg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
instance ( Typeable (EventHandler e p (PeerM e IO))
|
instance ( Typeable (EventHandler e p (PeerM e IO))
|
||||||
|
@ -369,6 +408,9 @@ newPeerEnv :: forall e m . ( MonadIO m
|
||||||
, Ord (Peer e)
|
, Ord (Peer e)
|
||||||
, Pretty (Peer e)
|
, Pretty (Peer e)
|
||||||
, HasNonces () m
|
, HasNonces () m
|
||||||
|
, Asymm (Encryption e)
|
||||||
|
, Hashable (PubKey 'Sign (Encryption e))
|
||||||
|
, Hashable PeerNonce
|
||||||
)
|
)
|
||||||
=> AnyStorage
|
=> AnyStorage
|
||||||
-> Fabriq e
|
-> Fabriq e
|
||||||
|
@ -376,18 +418,21 @@ newPeerEnv :: forall e m . ( MonadIO m
|
||||||
-> m (PeerEnv e)
|
-> m (PeerEnv e)
|
||||||
|
|
||||||
newPeerEnv s bus p = do
|
newPeerEnv s bus p = do
|
||||||
|
let _envSelf = p
|
||||||
pl <- AnyPeerLocator <$> newStaticPeerLocator @e mempty
|
_envPeerNonce <- newNonce @()
|
||||||
|
let _envFab = bus
|
||||||
nonce <- newNonce @()
|
let _envStorage = s
|
||||||
|
_envPeerLocator <- AnyPeerLocator <$> newStaticPeerLocator @e mempty
|
||||||
PeerEnv p nonce bus s pl <$> newPipeline defProtoPipelineSize
|
_envDeferred <- newPipeline defProtoPipelineSize
|
||||||
<*> liftIO (Cache.newCache (Just defCookieTimeout))
|
_envSessions <- liftIO (Cache.newCache (Just defCookieTimeout))
|
||||||
<*> liftIO (newTVarIO mempty)
|
_envEvents <- liftIO (newTVarIO mempty)
|
||||||
<*> liftIO (Cache.newCache (Just defCookieTimeout))
|
_envExpireTimes <- liftIO (Cache.newCache (Just defCookieTimeout))
|
||||||
<*> liftIO (newTVarIO mempty)
|
_envSweepers <- liftIO (newTVarIO mempty)
|
||||||
<*> liftIO (Cache.newCache (Just defRequestLimit))
|
_envReqMsgLimit <- liftIO (Cache.newCache (Just defRequestLimit))
|
||||||
<*> liftIO (Cache.newCache (Just defRequestLimit))
|
_envReqProtoLimit <- liftIO (Cache.newCache (Just defRequestLimit))
|
||||||
|
_envAsymmetricKeyPair <- asymmNewKeypair @(Encryption e)
|
||||||
|
_envEncryptionKeys <- liftIO (newTVarIO mempty)
|
||||||
|
pure PeerEnv {..}
|
||||||
|
|
||||||
runPeerM :: forall e m . ( MonadIO m
|
runPeerM :: forall e m . ( MonadIO m
|
||||||
, HasPeer e
|
, HasPeer e
|
||||||
|
|
|
@ -29,3 +29,6 @@ instance Pretty (AsBase58 ByteString) where
|
||||||
instance Pretty (AsBase58 LBS.ByteString) where
|
instance Pretty (AsBase58 LBS.ByteString) where
|
||||||
pretty (AsBase58 bs) = pretty $ BS8.unpack $ toBase58 (LBS.toStrict bs)
|
pretty (AsBase58 bs) = pretty $ BS8.unpack $ toBase58 (LBS.toStrict bs)
|
||||||
|
|
||||||
|
instance Show (AsBase58 ByteString) where
|
||||||
|
show (AsBase58 bs) = BS8.unpack $ toBase58 bs
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import Control.Monad.IO.Class
|
||||||
import Data.Fixed
|
import Data.Fixed
|
||||||
import Data.Int (Int64)
|
import Data.Int (Int64)
|
||||||
import Data.Proxy
|
import Data.Proxy
|
||||||
|
import Data.Time
|
||||||
import Prettyprinter
|
import Prettyprinter
|
||||||
import System.Clock
|
import System.Clock
|
||||||
import Data.Time.Clock
|
import Data.Time.Clock
|
||||||
|
@ -34,6 +35,9 @@ class IsTimeout a where
|
||||||
toTimeSpec :: Timeout a -> TimeSpec
|
toTimeSpec :: Timeout a -> TimeSpec
|
||||||
toTimeSpec x = fromNanoSecs (fromIntegral (toNanoSeconds x))
|
toTimeSpec x = fromNanoSecs (fromIntegral (toNanoSeconds x))
|
||||||
|
|
||||||
|
toNominalDiffTime :: IsTimeout t => Timeout t -> NominalDiffTime
|
||||||
|
toNominalDiffTime = fromRational . (/ (10^6)) . fromIntegral . toMicroSeconds
|
||||||
|
|
||||||
class IsTimeout a => MonadPause a m where
|
class IsTimeout a => MonadPause a m where
|
||||||
pause :: Timeout a -> m ()
|
pause :: Timeout a -> m ()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
module HBS2.Crypto where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import Crypto.Saltine.Class as SCl
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
|
import Crypto.Saltine.Internal.Box qualified as Encrypt
|
||||||
|
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
|
import Data.ByteString qualified as BS
|
||||||
|
import Data.ByteString.Lazy qualified as LBS
|
||||||
|
import Data.String.Conversions (cs)
|
||||||
|
|
||||||
|
|
||||||
|
combineNonceBS :: Encrypt.Nonce -> ByteString -> ByteString
|
||||||
|
combineNonceBS n = (SCl.encode n <>)
|
||||||
|
|
||||||
|
extractNonce :: ByteString -> Maybe (Encrypt.Nonce, ByteString)
|
||||||
|
extractNonce bs = do
|
||||||
|
let (p,bs') = BS.splitAt Encrypt.box_noncebytes bs
|
||||||
|
guard (BS.length p == Encrypt.box_noncebytes)
|
||||||
|
nonce <- SCl.decode p
|
||||||
|
pure (nonce, bs')
|
||||||
|
|
||||||
|
boxAfterNMLazy :: Encrypt.CombinedKey -> Encrypt.Nonce -> LBS.ByteString -> LBS.ByteString
|
||||||
|
boxAfterNMLazy k n = cs . combineNonceBS n . Encrypt.boxAfterNM k n . cs
|
||||||
|
|
||||||
|
boxOpenAfterNMLazy :: Encrypt.CombinedKey -> Encrypt.Nonce -> ByteString -> Maybe LBS.ByteString
|
||||||
|
boxOpenAfterNMLazy k n = fmap cs . Encrypt.boxOpenAfterNM k n
|
|
@ -1,13 +1,13 @@
|
||||||
module HBS2.Data.Types
|
module HBS2.Data.Types
|
||||||
( module HBS2.Hash
|
( module X
|
||||||
, module HBS2.Data.Types.Refs
|
|
||||||
-- , module HBS2.Data.Types.Crypto
|
-- , module HBS2.Data.Types.Crypto
|
||||||
, AsSyntax(..)
|
, AsSyntax(..)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import HBS2.Hash
|
import HBS2.Hash as X
|
||||||
import HBS2.Data.Types.Refs
|
import HBS2.Data.Types.Refs as X
|
||||||
|
import HBS2.Data.Types.Peer as X
|
||||||
-- import HBS2.Data.Types.Crypto
|
-- import HBS2.Data.Types.Crypto
|
||||||
|
|
||||||
-- import Data.Config.Suckless
|
-- import Data.Config.Suckless
|
||||||
|
|
|
@ -1,4 +1,29 @@
|
||||||
module HBS2.Data.Types.Crypto where
|
module HBS2.Data.Types.Crypto where
|
||||||
|
|
||||||
|
import Codec.Serialise
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
|
import Crypto.Saltine.Core.Sign qualified as Sign
|
||||||
|
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
|
import HBS2.Net.Proto.Types
|
||||||
|
import HBS2.Prelude
|
||||||
|
|
||||||
-- type SignPubKey = ()
|
-- type SignPubKey = ()
|
||||||
-- type EncryptPubKey = ()
|
-- type EncryptPubKey = ()
|
||||||
|
|
||||||
|
type instance PubKey 'Sign HBS2Basic = Sign.PublicKey
|
||||||
|
type instance PrivKey 'Sign HBS2Basic = Sign.SecretKey
|
||||||
|
type instance PubKey 'Encrypt HBS2Basic = Encrypt.PublicKey
|
||||||
|
type instance PrivKey 'Encrypt HBS2Basic = Encrypt.SecretKey
|
||||||
|
|
||||||
|
instance Serialise Sign.PublicKey
|
||||||
|
instance Serialise Encrypt.PublicKey
|
||||||
|
instance Serialise Sign.SecretKey
|
||||||
|
instance Serialise Encrypt.SecretKey
|
||||||
|
|
||||||
|
instance Serialise Sign.Signature
|
||||||
|
|
||||||
|
instance Signatures HBS2Basic where
|
||||||
|
type Signature HBS2Basic = Sign.Signature
|
||||||
|
makeSign = Sign.signDetached
|
||||||
|
verifySign = Sign.signVerifyDetached
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
{-# Language UndecidableInstances #-}
|
||||||
|
module HBS2.Data.Types.Peer where
|
||||||
|
|
||||||
|
import Codec.Serialise
|
||||||
|
import Data.ByteString qualified as BS
|
||||||
|
import Data.Hashable
|
||||||
|
import Lens.Micro.Platform
|
||||||
|
|
||||||
|
import HBS2.Prelude
|
||||||
|
import HBS2.Data.Types.Crypto
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
|
import HBS2.Net.Proto.Types
|
||||||
|
|
||||||
|
|
||||||
|
type PingSign e = Signature (Encryption e)
|
||||||
|
type PingNonce = BS.ByteString
|
||||||
|
|
||||||
|
data PeerData e =
|
||||||
|
PeerData
|
||||||
|
{ _peerSignKey :: PubKey 'Sign (Encryption e)
|
||||||
|
, _peerOwnNonce :: PeerNonce -- TODO: to use this field to detect if it's own peer to avoid loops
|
||||||
|
}
|
||||||
|
deriving stock (Typeable,Generic)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Eq (PubKey 'Sign (Encryption e))
|
||||||
|
, Eq PeerNonce
|
||||||
|
)
|
||||||
|
=> Eq (PeerData e)
|
||||||
|
|
||||||
|
instance
|
||||||
|
( Hashable (PubKey 'Sign (Encryption e))
|
||||||
|
, Hashable PeerNonce
|
||||||
|
)
|
||||||
|
=> Hashable (PeerData e) where
|
||||||
|
hashWithSalt s PeerData{..} = hashWithSalt s (_peerOwnNonce)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (PubKey 'Sign (Encryption e))
|
||||||
|
, Show PeerNonce
|
||||||
|
)
|
||||||
|
=> Show (PeerData e)
|
||||||
|
|
||||||
|
makeLenses 'PeerData
|
||||||
|
|
|
@ -38,6 +38,15 @@ class Signatures e where
|
||||||
makeSign :: PrivKey 'Sign e -> ByteString -> Signature e
|
makeSign :: PrivKey 'Sign e -> ByteString -> Signature e
|
||||||
verifySign :: PubKey 'Sign e -> Signature e -> ByteString -> Bool
|
verifySign :: PubKey 'Sign e -> Signature e -> ByteString -> Bool
|
||||||
|
|
||||||
|
class AsymmPubKey e ~ PubKey 'Encrypt e => Asymm e where
|
||||||
|
type family AsymmKeypair e :: Type
|
||||||
|
type family AsymmPrivKey e :: Type
|
||||||
|
type family AsymmPubKey e :: Type
|
||||||
|
type family CommonSecret e :: Type
|
||||||
|
asymmNewKeypair :: MonadIO m => m (AsymmKeypair e)
|
||||||
|
privKeyFromKeypair :: AsymmKeypair e -> AsymmPrivKey e
|
||||||
|
pubKeyFromKeypair :: AsymmKeypair e -> AsymmPubKey e
|
||||||
|
genCommonSecret :: Asymm e => AsymmPrivKey e -> AsymmPubKey e -> CommonSecret e
|
||||||
|
|
||||||
class HasCredentials s m where
|
class HasCredentials s m where
|
||||||
getCredentials :: m (PeerCredentials s)
|
getCredentials :: m (PeerCredentials s)
|
||||||
|
|
|
@ -42,6 +42,8 @@ instance Serialise (BlockAnnounceInfo e)
|
||||||
data BlockAnnounce e = BlockAnnounce PeerNonce (BlockAnnounceInfo e)
|
data BlockAnnounce e = BlockAnnounce PeerNonce (BlockAnnounceInfo e)
|
||||||
deriving stock (Generic)
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving instance (Show (Nonce ())) => Show (BlockAnnounce e)
|
||||||
|
|
||||||
instance Serialise PeerNonce => Serialise (BlockAnnounce e)
|
instance Serialise PeerNonce => Serialise (BlockAnnounce e)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,14 @@ data BlockChunksI e m =
|
||||||
|
|
||||||
|
|
||||||
data BlockChunks e = BlockChunks (Cookie e) (BlockChunksProto e)
|
data BlockChunks e = BlockChunks (Cookie e) (BlockChunksProto e)
|
||||||
deriving stock (Generic)
|
deriving stock (Generic, Show)
|
||||||
|
|
||||||
data BlockChunksProto e = BlockGetAllChunks (Hash HbSync) ChunkSize
|
data BlockChunksProto e = BlockGetAllChunks (Hash HbSync) ChunkSize
|
||||||
| BlockGetChunks (Hash HbSync) ChunkSize Word32 Word32
|
| BlockGetChunks (Hash HbSync) ChunkSize Word32 Word32
|
||||||
| BlockNoChunks
|
| BlockNoChunks
|
||||||
| BlockChunk ChunkNum ByteString
|
| BlockChunk ChunkNum ByteString
|
||||||
| BlockLost
|
| BlockLost
|
||||||
deriving stock (Generic)
|
deriving stock (Generic, Show)
|
||||||
|
|
||||||
|
|
||||||
instance HasCookie e (BlockChunks e) where
|
instance HasCookie e (BlockChunks e) where
|
||||||
|
|
|
@ -7,6 +7,7 @@ module HBS2.Net.Proto.Definition
|
||||||
where
|
where
|
||||||
|
|
||||||
import HBS2.Clock
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Types.Crypto
|
||||||
import HBS2.Defaults
|
import HBS2.Defaults
|
||||||
import HBS2.Hash
|
import HBS2.Hash
|
||||||
import HBS2.Net.Auth.Credentials
|
import HBS2.Net.Auth.Credentials
|
||||||
|
@ -14,6 +15,7 @@ import HBS2.Net.Proto
|
||||||
import HBS2.Net.Proto.BlockAnnounce
|
import HBS2.Net.Proto.BlockAnnounce
|
||||||
import HBS2.Net.Proto.BlockChunks
|
import HBS2.Net.Proto.BlockChunks
|
||||||
import HBS2.Net.Proto.BlockInfo
|
import HBS2.Net.Proto.BlockInfo
|
||||||
|
import HBS2.Net.Proto.EncryptionHandshake
|
||||||
import HBS2.Net.Proto.Peer
|
import HBS2.Net.Proto.Peer
|
||||||
import HBS2.Net.Proto.PeerAnnounce
|
import HBS2.Net.Proto.PeerAnnounce
|
||||||
import HBS2.Net.Proto.PeerExchange
|
import HBS2.Net.Proto.PeerExchange
|
||||||
|
@ -22,25 +24,21 @@ import HBS2.Net.Proto.RefLog
|
||||||
import HBS2.Net.Proto.RefChan
|
import HBS2.Net.Proto.RefChan
|
||||||
import HBS2.Prelude
|
import HBS2.Prelude
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.ByteString.Lazy (ByteString)
|
import Data.ByteString.Lazy (ByteString)
|
||||||
import Data.ByteString qualified as BS
|
import Data.ByteString qualified as BS
|
||||||
import Codec.Serialise (deserialiseOrFail,serialise)
|
import Codec.Serialise (deserialiseOrFail,serialise)
|
||||||
|
|
||||||
import Crypto.Saltine.Core.Box qualified as Crypto
|
|
||||||
import Crypto.Saltine.Class qualified as Crypto
|
import Crypto.Saltine.Class qualified as Crypto
|
||||||
import Crypto.Saltine.Core.Sign qualified as Sign
|
import Crypto.Saltine.Core.Sign qualified as Sign
|
||||||
import Crypto.Saltine.Core.Box qualified as Encrypt
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
|
|
||||||
|
import HBS2.Data.Types.Crypto
|
||||||
|
|
||||||
|
|
||||||
type instance Encryption L4Proto = HBS2Basic
|
type instance Encryption L4Proto = HBS2Basic
|
||||||
|
|
||||||
type instance PubKey 'Sign HBS2Basic = Sign.PublicKey
|
|
||||||
type instance PrivKey 'Sign HBS2Basic = Sign.SecretKey
|
|
||||||
type instance PubKey 'Encrypt HBS2Basic = Encrypt.PublicKey
|
|
||||||
type instance PrivKey 'Encrypt HBS2Basic = Encrypt.SecretKey
|
|
||||||
|
|
||||||
-- FIXME: proper-serialise-for-keys
|
-- FIXME: proper-serialise-for-keys
|
||||||
-- Возможно, нужно написать ручные инстансы Serialise
|
-- Возможно, нужно написать ручные инстансы Serialise
|
||||||
-- использовать encode/decode для каждого инстанса ниже $(c:end + 4)
|
-- использовать encode/decode для каждого инстанса ниже $(c:end + 4)
|
||||||
|
@ -48,15 +46,15 @@ type instance PrivKey 'Encrypt HBS2Basic = Encrypt.SecretKey
|
||||||
-- но возможно, будет работать и так, ведь ключи
|
-- но возможно, будет работать и так, ведь ключи
|
||||||
-- это же всего лишь байтстроки внутри.
|
-- это же всего лишь байтстроки внутри.
|
||||||
|
|
||||||
instance Serialise Sign.PublicKey
|
deserialiseCustom :: (Serialise a, MonadPlus m) => ByteString -> m a
|
||||||
instance Serialise Encrypt.PublicKey
|
deserialiseCustom = either (const mzero) pure . deserialiseOrFail
|
||||||
instance Serialise Sign.SecretKey
|
-- deserialiseCustom = either (\msg -> trace ("deserialiseCustom: " <> show msg) mzero) pure . deserialiseOrFail
|
||||||
instance Serialise Encrypt.SecretKey
|
-- deserialiseCustom = either (error . show) pure . deserialiseOrFail
|
||||||
|
|
||||||
instance HasProtocol L4Proto (BlockInfo L4Proto) where
|
instance HasProtocol L4Proto (BlockInfo L4Proto) where
|
||||||
type instance ProtocolId (BlockInfo L4Proto) = 1
|
type instance ProtocolId (BlockInfo L4Proto) = 1
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
-- FIXME: requestMinPeriod-breaks-fast-block-download
|
-- FIXME: requestMinPeriod-breaks-fast-block-download
|
||||||
|
@ -66,7 +64,7 @@ instance HasProtocol L4Proto (BlockInfo L4Proto) where
|
||||||
instance HasProtocol L4Proto (BlockChunks L4Proto) where
|
instance HasProtocol L4Proto (BlockChunks L4Proto) where
|
||||||
type instance ProtocolId (BlockChunks L4Proto) = 2
|
type instance ProtocolId (BlockChunks L4Proto) = 2
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
instance Expires (SessionKey L4Proto (BlockChunks L4Proto)) where
|
instance Expires (SessionKey L4Proto (BlockChunks L4Proto)) where
|
||||||
|
@ -75,13 +73,13 @@ instance Expires (SessionKey L4Proto (BlockChunks L4Proto)) where
|
||||||
instance HasProtocol L4Proto (BlockAnnounce L4Proto) where
|
instance HasProtocol L4Proto (BlockAnnounce L4Proto) where
|
||||||
type instance ProtocolId (BlockAnnounce L4Proto) = 3
|
type instance ProtocolId (BlockAnnounce L4Proto) = 3
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
instance HasProtocol L4Proto (PeerHandshake L4Proto) where
|
instance HasProtocol L4Proto (PeerHandshake L4Proto) where
|
||||||
type instance ProtocolId (PeerHandshake L4Proto) = 4
|
type instance ProtocolId (PeerHandshake L4Proto) = 4
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
requestPeriodLim = ReqLimPerProto 0.5
|
requestPeriodLim = ReqLimPerProto 0.5
|
||||||
|
@ -89,19 +87,19 @@ instance HasProtocol L4Proto (PeerHandshake L4Proto) where
|
||||||
instance HasProtocol L4Proto (PeerAnnounce L4Proto) where
|
instance HasProtocol L4Proto (PeerAnnounce L4Proto) where
|
||||||
type instance ProtocolId (PeerAnnounce L4Proto) = 5
|
type instance ProtocolId (PeerAnnounce L4Proto) = 5
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
instance HasProtocol L4Proto (PeerExchange L4Proto) where
|
instance HasProtocol L4Proto (PeerExchange L4Proto) where
|
||||||
type instance ProtocolId (PeerExchange L4Proto) = 6
|
type instance ProtocolId (PeerExchange L4Proto) = 6
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
instance HasProtocol L4Proto (RefLogUpdate L4Proto) where
|
instance HasProtocol L4Proto (RefLogUpdate L4Proto) where
|
||||||
type instance ProtocolId (RefLogUpdate L4Proto) = 7
|
type instance ProtocolId (RefLogUpdate L4Proto) = 7
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
-- TODO: find-out-optimal-max-safe-frequency
|
-- TODO: find-out-optimal-max-safe-frequency
|
||||||
|
@ -110,13 +108,13 @@ instance HasProtocol L4Proto (RefLogUpdate L4Proto) where
|
||||||
instance HasProtocol L4Proto (RefLogRequest L4Proto) where
|
instance HasProtocol L4Proto (RefLogRequest L4Proto) where
|
||||||
type instance ProtocolId (RefLogRequest L4Proto) = 8
|
type instance ProtocolId (RefLogRequest L4Proto) = 8
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
instance HasProtocol L4Proto (PeerMetaProto L4Proto) where
|
instance HasProtocol L4Proto (PeerMetaProto L4Proto) where
|
||||||
type instance ProtocolId (PeerMetaProto L4Proto) = 9
|
type instance ProtocolId (PeerMetaProto L4Proto) = 9
|
||||||
type instance Encoded L4Proto = ByteString
|
type instance Encoded L4Proto = ByteString
|
||||||
decode = either (const Nothing) Just . deserialiseOrFail
|
decode = deserialiseCustom
|
||||||
encode = serialise
|
encode = serialise
|
||||||
|
|
||||||
-- FIXME: real-period
|
-- FIXME: real-period
|
||||||
|
@ -153,6 +151,14 @@ instance HasProtocol L4Proto (RefChanRequest L4Proto) where
|
||||||
-- но poll у нас в минутах, и с минимальным периодом 1 минута
|
-- но poll у нас в минутах, и с минимальным периодом 1 минута
|
||||||
requestPeriodLim = ReqLimPerMessage 1
|
requestPeriodLim = ReqLimPerMessage 1
|
||||||
|
|
||||||
|
instance HasProtocol L4Proto (EncryptionHandshake L4Proto) where
|
||||||
|
type instance ProtocolId (EncryptionHandshake L4Proto) = 10
|
||||||
|
type instance Encoded L4Proto = ByteString
|
||||||
|
decode = deserialiseCustom
|
||||||
|
encode = serialise
|
||||||
|
|
||||||
|
requestPeriodLim = ReqLimPerProto 0.5
|
||||||
|
|
||||||
instance Expires (SessionKey L4Proto (BlockInfo L4Proto)) where
|
instance Expires (SessionKey L4Proto (BlockInfo L4Proto)) where
|
||||||
expiresIn _ = Just defCookieTimeoutSec
|
expiresIn _ = Just defCookieTimeoutSec
|
||||||
|
|
||||||
|
@ -171,48 +177,57 @@ instance Expires (SessionKey L4Proto (KnownPeer L4Proto)) where
|
||||||
instance Expires (SessionKey L4Proto (PeerHandshake L4Proto)) where
|
instance Expires (SessionKey L4Proto (PeerHandshake L4Proto)) where
|
||||||
expiresIn _ = Just 60
|
expiresIn _ = Just 60
|
||||||
|
|
||||||
|
instance Expires (SessionKey L4Proto (EncryptionHandshake L4Proto)) where
|
||||||
|
expiresIn _ = Just 60
|
||||||
|
|
||||||
instance Expires (EventKey L4Proto (PeerAnnounce L4Proto)) where
|
instance Expires (EventKey L4Proto (PeerAnnounce L4Proto)) where
|
||||||
expiresIn _ = Nothing
|
expiresIn _ = Nothing
|
||||||
|
|
||||||
instance Expires (EventKey L4Proto (PeerMetaProto L4Proto)) where
|
instance Expires (EventKey L4Proto (PeerMetaProto L4Proto)) where
|
||||||
expiresIn _ = Just 600
|
expiresIn _ = Just 600
|
||||||
|
|
||||||
|
-- instance Expires (EventKey L4Proto (EncryptionHandshake L4Proto)) where
|
||||||
|
-- expiresIn _ = Just 600
|
||||||
|
|
||||||
-- instance MonadIO m => HasNonces () m where
|
-- instance MonadIO m => HasNonces () m where
|
||||||
-- type instance Nonce (PeerHandshake L4Proto) = BS.ByteString
|
-- type instance Nonce (PeerHandshake L4Proto) = BS.ByteString
|
||||||
-- newNonce = do
|
-- newNonce = do
|
||||||
-- n <- liftIO ( Crypto.newNonce <&> Crypto.encode )
|
-- n <- liftIO ( Encrypt.newNonce <&> Crypto.encode )
|
||||||
-- pure $ BS.take 32 n
|
-- pure $ BS.take 32 n
|
||||||
|
|
||||||
instance MonadIO m => HasNonces (PeerHandshake L4Proto) m where
|
instance MonadIO m => HasNonces (PeerHandshake L4Proto) m where
|
||||||
type instance Nonce (PeerHandshake L4Proto) = BS.ByteString
|
type instance Nonce (PeerHandshake L4Proto) = BS.ByteString
|
||||||
newNonce = do
|
newNonce = do
|
||||||
n <- liftIO ( Crypto.newNonce <&> Crypto.encode )
|
n <- liftIO ( Encrypt.newNonce <&> Crypto.encode )
|
||||||
pure $ BS.take 32 n
|
pure $ BS.take 32 n
|
||||||
|
|
||||||
instance MonadIO m => HasNonces (PeerExchange L4Proto) m where
|
instance MonadIO m => HasNonces (PeerExchange L4Proto) m where
|
||||||
type instance Nonce (PeerExchange L4Proto) = BS.ByteString
|
type instance Nonce (PeerExchange L4Proto) = BS.ByteString
|
||||||
newNonce = do
|
newNonce = do
|
||||||
n <- liftIO ( Crypto.newNonce <&> Crypto.encode )
|
n <- liftIO ( Encrypt.newNonce <&> Crypto.encode )
|
||||||
pure $ BS.take 32 n
|
pure $ BS.take 32 n
|
||||||
|
|
||||||
instance MonadIO m => HasNonces (RefLogUpdate L4Proto) m where
|
instance MonadIO m => HasNonces (RefLogUpdate L4Proto) m where
|
||||||
type instance Nonce (RefLogUpdate L4Proto) = BS.ByteString
|
type instance Nonce (RefLogUpdate L4Proto) = BS.ByteString
|
||||||
newNonce = do
|
newNonce = do
|
||||||
n <- liftIO ( Crypto.newNonce <&> Crypto.encode )
|
n <- liftIO ( Encrypt.newNonce <&> Crypto.encode )
|
||||||
pure $ BS.take 32 n
|
pure $ BS.take 32 n
|
||||||
|
|
||||||
instance MonadIO m => HasNonces () m where
|
instance MonadIO m => HasNonces () m where
|
||||||
type instance Nonce () = BS.ByteString
|
type instance Nonce () = BS.ByteString
|
||||||
newNonce = do
|
newNonce = do
|
||||||
n <- liftIO ( Crypto.newNonce <&> Crypto.encode )
|
n <- liftIO ( Encrypt.newNonce <&> Crypto.encode )
|
||||||
pure $ BS.take 32 n
|
pure $ BS.take 32 n
|
||||||
|
|
||||||
instance Serialise Sign.Signature
|
instance Asymm HBS2Basic where
|
||||||
|
type AsymmKeypair HBS2Basic = Encrypt.Keypair
|
||||||
instance Signatures HBS2Basic where
|
type AsymmPrivKey HBS2Basic = Encrypt.SecretKey
|
||||||
type Signature HBS2Basic = Sign.Signature
|
type AsymmPubKey HBS2Basic = Encrypt.PublicKey
|
||||||
makeSign = Sign.signDetached
|
type CommonSecret HBS2Basic = Encrypt.CombinedKey
|
||||||
verifySign = Sign.signVerifyDetached
|
asymmNewKeypair = liftIO Encrypt.newKeypair
|
||||||
|
privKeyFromKeypair = Encrypt.secretKey
|
||||||
|
pubKeyFromKeypair = Encrypt.publicKey
|
||||||
|
genCommonSecret = Encrypt.beforeNM
|
||||||
|
|
||||||
instance Hashed HbSync Sign.PublicKey where
|
instance Hashed HbSync Sign.PublicKey where
|
||||||
hashObject pk = hashObject (Crypto.encode pk)
|
hashObject pk = hashObject (Crypto.encode pk)
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
{-# Language TemplateHaskell #-}
|
||||||
|
{-# Language UndecidableInstances #-}
|
||||||
|
|
||||||
|
module HBS2.Net.Proto.EncryptionHandshake where
|
||||||
|
|
||||||
|
import HBS2.Actors.Peer
|
||||||
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Types
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
|
import HBS2.Net.Proto
|
||||||
|
import HBS2.Net.Proto.Peer
|
||||||
|
import HBS2.Net.Proto.Sessions
|
||||||
|
import HBS2.Prelude.Plated
|
||||||
|
import HBS2.System.Logger.Simple
|
||||||
|
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
|
import Data.ByteString qualified as BS
|
||||||
|
import Data.String.Conversions (cs)
|
||||||
|
import Lens.Micro.Platform
|
||||||
|
|
||||||
|
instance
|
||||||
|
( Show (PubKey 'Encrypt (Encryption e))
|
||||||
|
, Show (PubKey 'Sign (Encryption e))
|
||||||
|
, Show (Nonce ())
|
||||||
|
)
|
||||||
|
=> Pretty (PeerData e) where
|
||||||
|
pretty = viaShow
|
||||||
|
|
||||||
|
data EncryptionHandshake e =
|
||||||
|
BeginEncryptionExchange (Signature (Encryption e)) (PubKey 'Encrypt (Encryption e))
|
||||||
|
| AckEncryptionExchange (Signature (Encryption e)) (PubKey 'Encrypt (Encryption e))
|
||||||
|
| ResetEncryptionKeys
|
||||||
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
sendResetEncryptionKeys :: forall e s m .
|
||||||
|
( MonadIO m
|
||||||
|
, Request e (EncryptionHandshake e) m
|
||||||
|
, e ~ L4Proto
|
||||||
|
, s ~ Encryption e
|
||||||
|
)
|
||||||
|
=> Peer e
|
||||||
|
-> m ()
|
||||||
|
|
||||||
|
sendResetEncryptionKeys peer = do
|
||||||
|
request peer (ResetEncryptionKeys @e)
|
||||||
|
|
||||||
|
sendBeginEncryptionExchange :: forall e s m .
|
||||||
|
( MonadIO m
|
||||||
|
, Request e (EncryptionHandshake e) m
|
||||||
|
, Sessions e (EncryptionHandshake e) m
|
||||||
|
-- , HasCredentials s m
|
||||||
|
, Asymm s
|
||||||
|
, Signatures s
|
||||||
|
, Serialise (PubKey 'Encrypt s)
|
||||||
|
, Pretty (Peer e)
|
||||||
|
, HasProtocol e (EncryptionHandshake e)
|
||||||
|
, e ~ L4Proto
|
||||||
|
, s ~ Encryption e
|
||||||
|
)
|
||||||
|
=> PeerCredentials s
|
||||||
|
-> PubKey 'Encrypt (Encryption e)
|
||||||
|
-> Peer e
|
||||||
|
-> m ()
|
||||||
|
|
||||||
|
sendBeginEncryptionExchange creds ourpubkey peer = do
|
||||||
|
let sign = makeSign @s (view peerSignSk creds) ((cs . serialise) ourpubkey)
|
||||||
|
request peer (BeginEncryptionExchange @e sign ourpubkey)
|
||||||
|
|
||||||
|
data EncryptionHandshakeAdapter e m s = EncryptionHandshakeAdapter
|
||||||
|
{ encHandshake_considerPeerAsymmKey :: Peer e -> Maybe Encrypt.PublicKey -> m ()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encryptionHandshakeProto :: forall e s m .
|
||||||
|
( MonadIO m
|
||||||
|
, Response e (EncryptionHandshake e) m
|
||||||
|
, Request e (EncryptionHandshake e) m
|
||||||
|
, Sessions e (KnownPeer e) m
|
||||||
|
, HasCredentials s m
|
||||||
|
, Asymm s
|
||||||
|
, Signatures s
|
||||||
|
, Sessions e (EncryptionHandshake e) m
|
||||||
|
, Serialise (PubKey 'Encrypt (Encryption e))
|
||||||
|
, s ~ Encryption e
|
||||||
|
, e ~ L4Proto
|
||||||
|
, PubKey Encrypt s ~ Encrypt.PublicKey
|
||||||
|
, Show (PubKey 'Sign s)
|
||||||
|
, Show (Nonce ())
|
||||||
|
)
|
||||||
|
=> EncryptionHandshakeAdapter e m s
|
||||||
|
-> PeerEnv e
|
||||||
|
-> EncryptionHandshake e
|
||||||
|
-> m ()
|
||||||
|
|
||||||
|
encryptionHandshakeProto EncryptionHandshakeAdapter{..} penv = \case
|
||||||
|
|
||||||
|
ResetEncryptionKeys -> do
|
||||||
|
peer <- thatPeer proto
|
||||||
|
mpeerData <- find (KnownPeerKey peer) id
|
||||||
|
-- TODO: check theirsign
|
||||||
|
trace $ "ENCRYPTION EHSP ResetEncryptionKeys from" <+> viaShow (peer, mpeerData)
|
||||||
|
|
||||||
|
-- сначала удалим у себя его прошлый ключ
|
||||||
|
encHandshake_considerPeerAsymmKey peer Nothing
|
||||||
|
|
||||||
|
creds <- getCredentials @s
|
||||||
|
let ourpubkey = pubKeyFromKeypair @s $ view envAsymmetricKeyPair penv
|
||||||
|
sendBeginEncryptionExchange @e creds ourpubkey peer
|
||||||
|
|
||||||
|
BeginEncryptionExchange theirsign theirpubkey -> do
|
||||||
|
peer <- thatPeer proto
|
||||||
|
mpeerData <- find (KnownPeerKey peer) id
|
||||||
|
-- TODO: check theirsign
|
||||||
|
|
||||||
|
trace $ "ENCRYPTION EHSP BeginEncryptionExchange from" <+> viaShow (peer, mpeerData)
|
||||||
|
|
||||||
|
-- взять свои ключи
|
||||||
|
creds <- getCredentials @s
|
||||||
|
|
||||||
|
let ourpubkey = pubKeyFromKeypair @s $ view envAsymmetricKeyPair penv
|
||||||
|
|
||||||
|
-- подписать нонс
|
||||||
|
let sign = makeSign @s (view peerSignSk creds) ((cs . serialise) ourpubkey)
|
||||||
|
|
||||||
|
-- сначала удалим у себя его прошлый ключ
|
||||||
|
encHandshake_considerPeerAsymmKey peer Nothing
|
||||||
|
|
||||||
|
-- отправить обратно свой публичный ключ
|
||||||
|
-- отправится пока ещё в плоском виде
|
||||||
|
response (AckEncryptionExchange @e sign ourpubkey)
|
||||||
|
|
||||||
|
-- Только после этого прописываем его ключ у себя
|
||||||
|
encHandshake_considerPeerAsymmKey peer (Just theirpubkey)
|
||||||
|
|
||||||
|
AckEncryptionExchange theirsign theirpubkey -> do
|
||||||
|
peer <- thatPeer proto
|
||||||
|
mpeerData <- find (KnownPeerKey peer) id
|
||||||
|
-- TODO: check theirsign
|
||||||
|
|
||||||
|
trace $ "ENCRYPTION EHSP AckEncryptionExchange from" <+> viaShow (peer, mpeerData)
|
||||||
|
|
||||||
|
-- Он уже прописал у себя наш публичный ключ и готов общаться шифрованными сообщениями
|
||||||
|
-- Прописываем его ключ у себя
|
||||||
|
encHandshake_considerPeerAsymmKey peer (Just theirpubkey)
|
||||||
|
|
||||||
|
where
|
||||||
|
proto = Proxy @(EncryptionHandshake e)
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
data PeerAsymmInfo e = PeerAsymmInfo
|
||||||
|
|
||||||
|
data instance EventKey e (PeerAsymmInfo e) = PeerAsymmInfoKey
|
||||||
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving stock instance (Eq (Peer e)) => Eq (EventKey e (PeerAsymmInfo e))
|
||||||
|
instance (Hashable (Peer e)) => Hashable (EventKey e (PeerAsymmInfo e))
|
||||||
|
|
||||||
|
data instance Event e (PeerAsymmInfo e) =
|
||||||
|
PeerAsymmPubKey (Peer e) (AsymmPubKey (Encryption e))
|
||||||
|
deriving stock (Typeable)
|
||||||
|
|
||||||
|
instance Expires (EventKey e (PeerAsymmInfo e)) where
|
||||||
|
expiresIn _ = Nothing
|
||||||
|
|
||||||
|
instance
|
||||||
|
( Serialise (PubKey 'Sign (Encryption e))
|
||||||
|
, Serialise (PubKey 'Encrypt (Encryption e))
|
||||||
|
, Serialise (Signature (Encryption e))
|
||||||
|
)
|
||||||
|
=> Serialise (EncryptionHandshake e)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (PubKey 'Encrypt (Encryption e))
|
||||||
|
, Show (Signature (Encryption e))
|
||||||
|
)
|
||||||
|
=> Show (EncryptionHandshake e)
|
||||||
|
|
||||||
|
type instance SessionData e (EncryptionHandshake e) = ()
|
||||||
|
|
||||||
|
newtype instance SessionKey e (EncryptionHandshake e) =
|
||||||
|
KnownPeerAsymmInfoKey (Peer e)
|
||||||
|
deriving stock (Generic, Typeable)
|
||||||
|
|
||||||
|
deriving instance Eq (Peer e) => Eq (SessionKey e (EncryptionHandshake e))
|
||||||
|
instance Hashable (Peer e) => Hashable (SessionKey e (EncryptionHandshake e))
|
||||||
|
|
||||||
|
data instance EventKey e (EncryptionHandshake e) =
|
||||||
|
AnyKnownPeerEncryptionHandshakeEventKey
|
||||||
|
deriving stock (Typeable, Eq,Generic)
|
|
@ -0,0 +1,35 @@
|
||||||
|
module HBS2.Net.Proto.Event.PeerExpired where
|
||||||
|
|
||||||
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Types.Peer
|
||||||
|
import HBS2.Events
|
||||||
|
import HBS2.Net.Proto
|
||||||
|
import HBS2.Net.Proto.Peer
|
||||||
|
import HBS2.Prelude.Plated
|
||||||
|
|
||||||
|
data PeerExpires = PeerExpires
|
||||||
|
|
||||||
|
data instance EventKey e PeerExpires =
|
||||||
|
PeerExpiredEventKey
|
||||||
|
deriving stock (Typeable, Eq, Generic)
|
||||||
|
|
||||||
|
data instance Event e PeerExpires =
|
||||||
|
PeerExpiredEvent (Peer e) -- (Maybe (PeerData e))
|
||||||
|
deriving stock (Typeable)
|
||||||
|
|
||||||
|
instance EventType (Event e PeerExpires) where
|
||||||
|
isPersistent = True
|
||||||
|
|
||||||
|
instance Expires (EventKey e PeerExpires) where
|
||||||
|
expiresIn _ = Nothing
|
||||||
|
|
||||||
|
instance Hashable (EventKey e PeerExpires)
|
||||||
|
|
||||||
|
--instance ( Serialise (PubKey 'Sign (Encryption e))
|
||||||
|
-- , Serialise (PubKey 'Encrypt (Encryption e))
|
||||||
|
-- , Serialise (Signature (Encryption e))
|
||||||
|
-- , Serialise PeerNonce
|
||||||
|
-- )
|
||||||
|
|
||||||
|
-- => Serialise PeerExpires
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
module HBS2.Net.Proto.Peer where
|
module HBS2.Net.Proto.Peer where
|
||||||
|
|
||||||
-- import HBS2.Base58
|
-- import HBS2.Base58
|
||||||
|
import HBS2.Actors.Peer
|
||||||
import HBS2.Data.Types
|
import HBS2.Data.Types
|
||||||
import HBS2.Events
|
import HBS2.Events
|
||||||
import HBS2.Net.Proto
|
import HBS2.Net.Proto
|
||||||
|
@ -10,33 +11,30 @@ import HBS2.Clock
|
||||||
import HBS2.Net.Proto.Sessions
|
import HBS2.Net.Proto.Sessions
|
||||||
import HBS2.Prelude.Plated
|
import HBS2.Prelude.Plated
|
||||||
import HBS2.Net.Auth.Credentials
|
import HBS2.Net.Auth.Credentials
|
||||||
|
import HBS2.System.Logger.Simple
|
||||||
|
|
||||||
-- import HBS2.System.Logger.Simple
|
import Control.Monad
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Codec.Serialise()
|
import Codec.Serialise()
|
||||||
import Data.ByteString qualified as BS
|
import Data.ByteString qualified as BS
|
||||||
import Data.Hashable
|
import Data.Hashable
|
||||||
|
import Data.String.Conversions (cs)
|
||||||
import Lens.Micro.Platform
|
import Lens.Micro.Platform
|
||||||
import Type.Reflection (someTypeRep)
|
import Type.Reflection (someTypeRep)
|
||||||
|
|
||||||
type PingSign e = Signature (Encryption e)
|
|
||||||
type PingNonce = BS.ByteString
|
|
||||||
|
|
||||||
data PeerData e =
|
|
||||||
PeerData
|
|
||||||
{ _peerSignKey :: PubKey 'Sign (Encryption e)
|
|
||||||
, _peerOwnNonce :: PeerNonce -- TODO: to use this field to detect if it's own peer to avoid loops
|
|
||||||
}
|
|
||||||
deriving stock (Typeable,Generic)
|
|
||||||
|
|
||||||
makeLenses 'PeerData
|
|
||||||
|
|
||||||
data PeerHandshake e =
|
data PeerHandshake e =
|
||||||
PeerPing PingNonce
|
PeerPing PingNonce
|
||||||
| PeerPong PingNonce (Signature (Encryption e)) (PeerData e)
|
| PeerPong PingNonce (Signature (Encryption e)) (PeerData e)
|
||||||
deriving stock (Generic)
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (PubKey 'Encrypt (Encryption e))
|
||||||
|
, Show (Signature (Encryption e))
|
||||||
|
, Show (PeerData e)
|
||||||
|
)
|
||||||
|
=> Show (PeerHandshake e)
|
||||||
|
|
||||||
newtype KnownPeer e = KnownPeer (PeerData e)
|
newtype KnownPeer e = KnownPeer (PeerData e)
|
||||||
deriving stock (Typeable,Generic)
|
deriving stock (Typeable,Generic)
|
||||||
|
|
||||||
|
@ -104,14 +102,18 @@ peerHandShakeProto :: forall e s m . ( MonadIO m
|
||||||
, EventEmitter e (PeerHandshake e) m
|
, EventEmitter e (PeerHandshake e) m
|
||||||
, EventEmitter e (ConcretePeer e) m
|
, EventEmitter e (ConcretePeer e) m
|
||||||
, HasCredentials s m
|
, HasCredentials s m
|
||||||
|
, Asymm s
|
||||||
, Signatures s
|
, Signatures s
|
||||||
|
, Serialise (PubKey 'Encrypt (Encryption e))
|
||||||
, s ~ Encryption e
|
, s ~ Encryption e
|
||||||
, e ~ L4Proto
|
, e ~ L4Proto
|
||||||
)
|
)
|
||||||
=> PeerHandshakeAdapter e m
|
=> PeerHandshakeAdapter e m
|
||||||
-> PeerHandshake e -> m ()
|
-> PeerEnv e
|
||||||
|
-> PeerHandshake e
|
||||||
|
-> m ()
|
||||||
|
|
||||||
peerHandShakeProto adapter =
|
peerHandShakeProto adapter penv =
|
||||||
\case
|
\case
|
||||||
PeerPing nonce -> do
|
PeerPing nonce -> do
|
||||||
pip <- thatPeer proto
|
pip <- thatPeer proto
|
||||||
|
@ -176,6 +178,8 @@ data instance Event e (ConcretePeer e) =
|
||||||
ConcretePeerData (Peer e) (PeerData e)
|
ConcretePeerData (Peer e) (PeerData e)
|
||||||
deriving stock (Typeable)
|
deriving stock (Typeable)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
data instance EventKey e (PeerHandshake e) =
|
data instance EventKey e (PeerHandshake e) =
|
||||||
AnyKnownPeerEventKey
|
AnyKnownPeerEventKey
|
||||||
deriving stock (Typeable, Eq,Generic)
|
deriving stock (Typeable, Eq,Generic)
|
||||||
|
@ -209,6 +213,7 @@ deriving instance Eq (Peer e) => Eq (SessionKey e (PeerHandshake e))
|
||||||
instance Hashable (Peer e) => Hashable (SessionKey e (PeerHandshake e))
|
instance Hashable (Peer e) => Hashable (SessionKey e (PeerHandshake e))
|
||||||
|
|
||||||
instance ( Serialise (PubKey 'Sign (Encryption e))
|
instance ( Serialise (PubKey 'Sign (Encryption e))
|
||||||
|
, Serialise (PubKey 'Encrypt (Encryption e))
|
||||||
, Serialise (Signature (Encryption e))
|
, Serialise (Signature (Encryption e))
|
||||||
, Serialise PeerNonce
|
, Serialise PeerNonce
|
||||||
)
|
)
|
||||||
|
@ -216,6 +221,7 @@ instance ( Serialise (PubKey 'Sign (Encryption e))
|
||||||
=> Serialise (PeerData e)
|
=> Serialise (PeerData e)
|
||||||
|
|
||||||
instance ( Serialise (PubKey 'Sign (Encryption e))
|
instance ( Serialise (PubKey 'Sign (Encryption e))
|
||||||
|
, Serialise (PubKey 'Encrypt (Encryption e))
|
||||||
, Serialise (Signature (Encryption e))
|
, Serialise (Signature (Encryption e))
|
||||||
, Serialise PeerNonce
|
, Serialise PeerNonce
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,6 +30,8 @@ newtype PeerAnnounce e =
|
||||||
PeerAnnounce PeerNonce
|
PeerAnnounce PeerNonce
|
||||||
deriving stock (Typeable, Generic)
|
deriving stock (Typeable, Generic)
|
||||||
|
|
||||||
|
deriving instance Show (Nonce ()) => Show (PeerAnnounce e)
|
||||||
|
|
||||||
|
|
||||||
peerAnnounceProto :: forall e m . ( MonadIO m
|
peerAnnounceProto :: forall e m . ( MonadIO m
|
||||||
, EventEmitter e (PeerAnnounce e) m
|
, EventEmitter e (PeerAnnounce e) m
|
||||||
|
|
|
@ -31,6 +31,11 @@ data PeerExchange e =
|
||||||
| PeerExchangePeers2 (Nonce (PeerExchange e)) [PeerAddr e]
|
| PeerExchangePeers2 (Nonce (PeerExchange e)) [PeerAddr e]
|
||||||
deriving stock (Generic, Typeable)
|
deriving stock (Generic, Typeable)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (Nonce (PeerExchange e))
|
||||||
|
, Show (PeerAddr e)
|
||||||
|
) => Show (PeerExchange e)
|
||||||
|
|
||||||
data PeerExchangePeersEv e
|
data PeerExchangePeersEv e
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +115,23 @@ peerExchangeProto pexFilt msg = do
|
||||||
|
|
||||||
case pex of
|
case pex of
|
||||||
PEX1 -> do
|
PEX1 -> do
|
||||||
|
pa <- take defPexMaxPeers <$> getAllPex1Peers
|
||||||
|
response (PeerExchangePeers @e n pa)
|
||||||
|
|
||||||
|
PEX2 -> do
|
||||||
|
pa <- take defPexMaxPeers <$> getAllPex2Peers
|
||||||
|
response (PeerExchangePeers2 @e n pa)
|
||||||
|
|
||||||
|
getAllPex1Peers :: forall e m .
|
||||||
|
( MonadIO m
|
||||||
|
, Sessions e (KnownPeer e) m
|
||||||
|
, HasPeerLocator L4Proto m
|
||||||
|
, e ~ L4Proto
|
||||||
|
)
|
||||||
|
=> m [IPAddrPort L4Proto]
|
||||||
|
getAllPex1Peers = do
|
||||||
|
pl <- getPeerLocator @e
|
||||||
|
pips <- knownPeers @e pl
|
||||||
-- TODO: tcp-peer-support-in-pex
|
-- TODO: tcp-peer-support-in-pex
|
||||||
pa' <- forM pips $ \p -> do
|
pa' <- forM pips $ \p -> do
|
||||||
auth <- find (KnownPeerKey p) id <&> isJust
|
auth <- find (KnownPeerKey p) id <&> isJust
|
||||||
|
@ -118,22 +139,23 @@ peerExchangeProto pexFilt msg = do
|
||||||
case pa of
|
case pa of
|
||||||
(L4Address UDP x) | auth -> pure [x]
|
(L4Address UDP x) | auth -> pure [x]
|
||||||
_ -> pure mempty
|
_ -> pure mempty
|
||||||
|
pure $ mconcat pa'
|
||||||
|
|
||||||
let pa = take defPexMaxPeers $ mconcat pa'
|
getAllPex2Peers :: forall e m .
|
||||||
|
( MonadIO m
|
||||||
response (PeerExchangePeers @e n pa)
|
, Sessions e (KnownPeer e) m
|
||||||
|
, HasPeerLocator L4Proto m
|
||||||
PEX2 -> do
|
, e ~ L4Proto
|
||||||
|
)
|
||||||
|
=> m [PeerAddr L4Proto]
|
||||||
|
getAllPex2Peers = do
|
||||||
|
pl <- getPeerLocator @e
|
||||||
|
pips <- knownPeers @e pl
|
||||||
pa' <- forM pips $ \p -> do
|
pa' <- forM pips $ \p -> do
|
||||||
auth <- find (KnownPeerKey p) id
|
auth <- find (KnownPeerKey p) id
|
||||||
maybe1 auth (pure mempty) ( const $ fmap L.singleton (toPeerAddr p) )
|
maybe1 auth (pure mempty) ( const $ fmap L.singleton (toPeerAddr p) )
|
||||||
|
|
||||||
-- FIXME: asap-random-shuffle-peers
|
-- FIXME: asap-random-shuffle-peers
|
||||||
let pa = take defPexMaxPeers $ mconcat pa'
|
pure $ mconcat pa'
|
||||||
|
|
||||||
response (PeerExchangePeers2 @e n pa)
|
|
||||||
|
|
||||||
|
|
||||||
newtype instance SessionKey e (PeerExchange e) =
|
newtype instance SessionKey e (PeerExchange e) =
|
||||||
PeerExchangeKey (Nonce (PeerExchange e))
|
PeerExchangeKey (Nonce (PeerExchange e))
|
||||||
|
|
|
@ -27,6 +27,10 @@ data RefLogRequest e =
|
||||||
| RefLogResponse (PubKey 'Sign (Encryption e)) (Hash HbSync)
|
| RefLogResponse (PubKey 'Sign (Encryption e)) (Hash HbSync)
|
||||||
deriving stock (Generic)
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (PubKey 'Sign (Encryption e))
|
||||||
|
) => Show (RefLogRequest e)
|
||||||
|
|
||||||
data RefLogUpdate e =
|
data RefLogUpdate e =
|
||||||
RefLogUpdate
|
RefLogUpdate
|
||||||
{ _refLogId :: PubKey 'Sign (Encryption e)
|
{ _refLogId :: PubKey 'Sign (Encryption e)
|
||||||
|
@ -36,6 +40,12 @@ data RefLogUpdate e =
|
||||||
}
|
}
|
||||||
deriving stock (Generic)
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (PubKey 'Sign (Encryption e))
|
||||||
|
, Show (Signature (Encryption e))
|
||||||
|
, Show (Nonce (RefLogUpdate e))
|
||||||
|
) => Show (RefLogUpdate e)
|
||||||
|
|
||||||
makeLenses 'RefLogUpdate
|
makeLenses 'RefLogUpdate
|
||||||
|
|
||||||
newtype RefLogUpdateI e m =
|
newtype RefLogUpdateI e m =
|
||||||
|
|
|
@ -111,7 +111,8 @@ data ReqLimPeriod = NoLimit
|
||||||
| ReqLimPerProto (Timeout 'Seconds)
|
| ReqLimPerProto (Timeout 'Seconds)
|
||||||
| ReqLimPerMessage (Timeout 'Seconds)
|
| ReqLimPerMessage (Timeout 'Seconds)
|
||||||
|
|
||||||
class (KnownNat (ProtocolId p), HasPeer e) => HasProtocol e p | p -> e where
|
class (KnownNat (ProtocolId p), HasPeer e, Show (Encoded e)
|
||||||
|
) => HasProtocol e p | p -> e where
|
||||||
type family ProtocolId p = (id :: Nat) | id -> p
|
type family ProtocolId p = (id :: Nat) | id -> p
|
||||||
type family Encoded e :: Type
|
type family Encoded e :: Type
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module HBS2.Prelude
|
module HBS2.Prelude
|
||||||
( module Data.String
|
( module Data.String
|
||||||
, module Safe
|
, module Safe
|
||||||
|
, module X
|
||||||
, MonadIO(..)
|
, MonadIO(..)
|
||||||
, void, guard, when, unless
|
, void, guard, when, unless
|
||||||
, maybe1
|
, maybe1
|
||||||
|
@ -17,6 +18,9 @@ module HBS2.Prelude
|
||||||
, Text.Text
|
, Text.Text
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Data.Typeable as X
|
||||||
|
import GHC.Generics as X (Generic)
|
||||||
|
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
import Safe
|
import Safe
|
||||||
|
|
|
@ -3,6 +3,7 @@ module Main where
|
||||||
import TestFakeMessaging
|
import TestFakeMessaging
|
||||||
import TestActors
|
import TestActors
|
||||||
-- import TestUniqProtoId
|
-- import TestUniqProtoId
|
||||||
|
import TestCrypto
|
||||||
|
|
||||||
import Test.Tasty
|
import Test.Tasty
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
|
@ -15,6 +16,7 @@ main =
|
||||||
testCase "testFakeMessaging1" testFakeMessaging1
|
testCase "testFakeMessaging1" testFakeMessaging1
|
||||||
, testCase "testActorsBasic" testActorsBasic
|
, testCase "testActorsBasic" testActorsBasic
|
||||||
-- , testCase "testUniqProtoId" testUniqProtoId
|
-- , testCase "testUniqProtoId" testUniqProtoId
|
||||||
|
, testCrypto
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
module TestCrypto where
|
||||||
|
|
||||||
|
import Test.QuickCheck.Instances.ByteString
|
||||||
|
import Test.Tasty
|
||||||
|
import Test.Tasty.QuickCheck as QC
|
||||||
|
|
||||||
|
-- import Control.Monad.Trans.Maybe
|
||||||
|
import Control.Monad
|
||||||
|
import Crypto.Saltine.Class qualified as Saltine
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
|
import Crypto.Saltine.Internal.Box qualified as Encrypt
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
|
import Data.ByteString qualified as BS
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.String.Conversions (cs)
|
||||||
|
|
||||||
|
import HBS2.Crypto
|
||||||
|
|
||||||
|
|
||||||
|
testCrypto :: TestTree
|
||||||
|
testCrypto = testGroup "testCrypto"
|
||||||
|
[ QC.testProperty "roundtripCombineExtractNonce" prop_roundtripCombineExtractNonce
|
||||||
|
, QC.testProperty "roundtripEncodingAfterNM" prop_roundtripEncodingAfterNM
|
||||||
|
]
|
||||||
|
|
||||||
|
instance Arbitrary Encrypt.Nonce where
|
||||||
|
arbitrary = Encrypt.Nonce . BS.pack <$> vectorOf Encrypt.box_noncebytes arbitrary
|
||||||
|
|
||||||
|
instance Arbitrary Encrypt.SecretKey where
|
||||||
|
arbitrary = (fromMaybe (error "Should be Just value") . Saltine.decode)
|
||||||
|
. BS.pack <$> vectorOf Encrypt.box_beforenmbytes arbitrary
|
||||||
|
|
||||||
|
instance Arbitrary Encrypt.PublicKey where
|
||||||
|
arbitrary = (fromMaybe (error "Should be Just value") . Saltine.decode)
|
||||||
|
. BS.pack <$> vectorOf Encrypt.box_beforenmbytes arbitrary
|
||||||
|
|
||||||
|
prop_roundtripCombineExtractNonce :: (Encrypt.Nonce, ByteString) -> Bool
|
||||||
|
prop_roundtripCombineExtractNonce (n, b) =
|
||||||
|
extractNonce (combineNonceBS n b) == Just (n, b)
|
||||||
|
|
||||||
|
prop_roundtripEncodingAfterNM :: (Encrypt.SecretKey, Encrypt.PublicKey, Encrypt.Nonce, ByteString) -> Bool
|
||||||
|
prop_roundtripEncodingAfterNM (sk, pk, n, b) = fromMaybe False do
|
||||||
|
let
|
||||||
|
ck = Encrypt.beforeNM sk pk
|
||||||
|
|
||||||
|
let box = boxAfterNMLazy ck n (cs b)
|
||||||
|
|
||||||
|
(n', x) <- extractNonce (cs box)
|
||||||
|
guard (n' == n)
|
||||||
|
b'' <- boxOpenAfterNMLazy ck n' x
|
||||||
|
|
||||||
|
pure (cs b'' == b)
|
|
@ -1,6 +1,7 @@
|
||||||
{-# Language AllowAmbiguousTypes #-}
|
{-# Language AllowAmbiguousTypes #-}
|
||||||
module Bootstrap where
|
module Bootstrap where
|
||||||
|
|
||||||
|
import HBS2.Data.Types.Peer
|
||||||
import HBS2.Prelude
|
import HBS2.Prelude
|
||||||
import HBS2.Net.Proto.Types
|
import HBS2.Net.Proto.Types
|
||||||
import HBS2.Net.Proto.Peer
|
import HBS2.Net.Proto.Peer
|
||||||
|
|
|
@ -17,9 +17,11 @@ import HBS2.System.Logger.Simple
|
||||||
|
|
||||||
import PeerConfig
|
import PeerConfig
|
||||||
|
|
||||||
import Control.Concurrent.STM
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
import Control.Exception
|
import Data.Maybe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
import Control.Exception
|
||||||
|
import Control.Concurrent.STM
|
||||||
import Database.SQLite.Simple
|
import Database.SQLite.Simple
|
||||||
import Database.SQLite.Simple.FromField
|
import Database.SQLite.Simple.FromField
|
||||||
import Data.Cache (Cache)
|
import Data.Cache (Cache)
|
||||||
|
@ -633,6 +635,56 @@ transactional brains action = do
|
||||||
err $ "BRAINS: " <+> viaShow e
|
err $ "BRAINS: " <+> viaShow e
|
||||||
execute_ conn [qc|ROLLBACK TO SAVEPOINT {sp}|]
|
execute_ conn [qc|ROLLBACK TO SAVEPOINT {sp}|]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
insertPeerAsymmKey :: forall e m . (e ~ L4Proto, MonadIO m)
|
||||||
|
=> BasicBrains e
|
||||||
|
-> Peer e
|
||||||
|
-> Encrypt.PublicKey
|
||||||
|
-> Encrypt.CombinedKey
|
||||||
|
-> m ()
|
||||||
|
|
||||||
|
insertPeerAsymmKey br peer hAsymmKey hSymmKey = do
|
||||||
|
insertPeerAsymmKey br peer hAsymmKey hSymmKey
|
||||||
|
insertPeerAsymmKey' br (show $ pretty peer) hAsymmKey hSymmKey
|
||||||
|
|
||||||
|
insertPeerAsymmKey' :: forall e m . (e ~ L4Proto, MonadIO m)
|
||||||
|
=> BasicBrains e
|
||||||
|
-> String
|
||||||
|
-> Encrypt.PublicKey
|
||||||
|
-> Encrypt.CombinedKey
|
||||||
|
-> m ()
|
||||||
|
|
||||||
|
insertPeerAsymmKey' br key hAsymmKey hSymmKey = do
|
||||||
|
let conn = view brainsDb br
|
||||||
|
void $ liftIO $ execute conn [qc|
|
||||||
|
INSERT INTO peer_asymmkey (peer,asymmkey,symmkey)
|
||||||
|
VALUES (?,?,?)
|
||||||
|
ON CONFLICT (peer)
|
||||||
|
DO UPDATE SET
|
||||||
|
asymmkey = excluded.asymmkey
|
||||||
|
, symmkey = excluded.symmkey
|
||||||
|
|] (key, show hAsymmKey, show hSymmKey)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
deletePeerAsymmKey :: forall e m . (e ~ L4Proto, MonadIO m)
|
||||||
|
=> BasicBrains e -> Peer e -> m ()
|
||||||
|
|
||||||
|
deletePeerAsymmKey br peer =
|
||||||
|
deletePeerAsymmKey' br (show $ pretty peer)
|
||||||
|
|
||||||
|
deletePeerAsymmKey' :: forall e m . (e ~ L4Proto, MonadIO m)
|
||||||
|
=> BasicBrains e -> String -> m ()
|
||||||
|
|
||||||
|
deletePeerAsymmKey' br key =
|
||||||
|
void $ liftIO $ execute (view brainsDb br) [qc|
|
||||||
|
DELETE FROM peer_asymmkey
|
||||||
|
WHERE peer = ?
|
||||||
|
|] (Only key)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
-- FIXME: eventually-close-db
|
-- FIXME: eventually-close-db
|
||||||
newBasicBrains :: forall e m . (Hashable (Peer e), MonadIO m)
|
newBasicBrains :: forall e m . (Hashable (Peer e), MonadIO m)
|
||||||
=> PeerConfig
|
=> PeerConfig
|
||||||
|
@ -731,6 +783,16 @@ newBasicBrains cfg = liftIO do
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
|
||||||
|
execute_ conn [qc|
|
||||||
|
create table if not exists peer_asymmkey
|
||||||
|
( peer text not null
|
||||||
|
, asymmkey text not null
|
||||||
|
, symmkey text not null
|
||||||
|
, ts DATE DEFAULT (datetime('now','localtime'))
|
||||||
|
, primary key (peer)
|
||||||
|
)
|
||||||
|
|]
|
||||||
|
|
||||||
BasicBrains <$> newTVarIO mempty
|
BasicBrains <$> newTVarIO mempty
|
||||||
<*> newTVarIO mempty
|
<*> newTVarIO mempty
|
||||||
<*> Cache.newCache (Just (toTimeSpec (30 :: Timeout 'Seconds)))
|
<*> Cache.newCache (Just (toTimeSpec (30 :: Timeout 'Seconds)))
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
module EncryptionKeys where
|
||||||
|
|
||||||
|
import HBS2.Actors.Peer
|
||||||
|
import HBS2.Base58
|
||||||
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Detect
|
||||||
|
import HBS2.Data.Types.Refs
|
||||||
|
import HBS2.Events
|
||||||
|
import HBS2.Hash
|
||||||
|
import HBS2.Merkle
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
|
import HBS2.Net.PeerLocator
|
||||||
|
import HBS2.Net.Proto
|
||||||
|
import HBS2.Net.Proto.EncryptionHandshake
|
||||||
|
import HBS2.Net.Proto.Peer
|
||||||
|
import HBS2.Net.Proto.Sessions
|
||||||
|
import HBS2.Prelude.Plated
|
||||||
|
import HBS2.Storage
|
||||||
|
import HBS2.System.Logger.Simple
|
||||||
|
|
||||||
|
import PeerConfig
|
||||||
|
import PeerTypes
|
||||||
|
|
||||||
|
import Codec.Serialise
|
||||||
|
import Control.Concurrent.Async
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
import Control.Monad
|
||||||
|
import Control.Monad.Reader
|
||||||
|
import Control.Monad.Trans.Maybe
|
||||||
|
import Data.ByteString qualified as BS
|
||||||
|
import Data.ByteString.Lazy qualified as LBS
|
||||||
|
import Data.Foldable(for_)
|
||||||
|
import Data.Function(fix)
|
||||||
|
import Data.Functor
|
||||||
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
|
import Data.HashSet (HashSet)
|
||||||
|
import Data.HashSet qualified as HashSet
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.Text qualified as Text
|
||||||
|
|
||||||
|
|
||||||
|
encryptionHandshakeWorker :: forall e m s .
|
||||||
|
( MonadIO m
|
||||||
|
, m ~ PeerM e IO
|
||||||
|
, s ~ Encryption e
|
||||||
|
, e ~ L4Proto
|
||||||
|
, HasPeerLocator e m
|
||||||
|
-- , HasPeer e
|
||||||
|
-- , HasNonces (EncryptionHandshake e) m
|
||||||
|
-- , Request e (EncryptionHandshake e) m
|
||||||
|
-- , Sessions e (EncryptionHandshake e) m
|
||||||
|
-- , Sessions e (PeerInfo e) m
|
||||||
|
-- , Sessions e (KnownPeer e) m
|
||||||
|
-- , Pretty (Peer e)
|
||||||
|
-- , HasCredentials s m
|
||||||
|
)
|
||||||
|
=> PeerConfig
|
||||||
|
-> PeerEnv e
|
||||||
|
-> PeerCredentials s
|
||||||
|
-> EncryptionHandshakeAdapter e m s
|
||||||
|
-> m ()
|
||||||
|
|
||||||
|
encryptionHandshakeWorker pconf penv creds EncryptionHandshakeAdapter{..} = do
|
||||||
|
|
||||||
|
-- e :: PeerEnv e <- ask
|
||||||
|
let ourpubkey = pubKeyFromKeypair @s $ _envAsymmetricKeyPair penv
|
||||||
|
|
||||||
|
pl <- getPeerLocator @e
|
||||||
|
|
||||||
|
forever do
|
||||||
|
liftIO $ pause @'Seconds 30
|
||||||
|
|
||||||
|
peers <- knownPeers @e pl
|
||||||
|
|
||||||
|
forM_ peers \peer -> do
|
||||||
|
-- Только если ещё не знаем ключ ноды
|
||||||
|
mpeerData <- find (KnownPeerKey peer) id
|
||||||
|
mkey <- liftIO do
|
||||||
|
join <$> forM mpeerData \peerData -> getEncryptionKey penv peerData
|
||||||
|
case mkey of
|
||||||
|
Just _ -> pure ()
|
||||||
|
Nothing -> sendBeginEncryptionExchange @e creds ourpubkey peer
|
|
@ -4,6 +4,7 @@ import HBS2.Prelude
|
||||||
import HBS2.Actors.Peer
|
import HBS2.Actors.Peer
|
||||||
import HBS2.Storage
|
import HBS2.Storage
|
||||||
import HBS2.Data.Types.Refs
|
import HBS2.Data.Types.Refs
|
||||||
|
import HBS2.Merkle (AnnMetaData)
|
||||||
import HBS2.Net.Proto.Types
|
import HBS2.Net.Proto.Types
|
||||||
import HBS2.Net.Proto.RefLog
|
import HBS2.Net.Proto.RefLog
|
||||||
import HBS2.Events
|
import HBS2.Events
|
||||||
|
@ -33,9 +34,9 @@ httpWorker :: forall e s m . ( MyPeer e
|
||||||
, s ~ Encryption e
|
, s ~ Encryption e
|
||||||
, m ~ PeerM e IO
|
, m ~ PeerM e IO
|
||||||
, e ~ L4Proto
|
, e ~ L4Proto
|
||||||
) => PeerConfig -> DownloadEnv e -> m ()
|
) => PeerConfig -> AnnMetaData -> DownloadEnv e -> m ()
|
||||||
|
|
||||||
httpWorker conf e = do
|
httpWorker conf pmeta e = do
|
||||||
|
|
||||||
sto <- getStorage
|
sto <- getStorage
|
||||||
let port' = cfgValue @PeerHttpPortKey conf <&> fromIntegral
|
let port' = cfgValue @PeerHttpPortKey conf <&> fromIntegral
|
||||||
|
@ -90,7 +91,7 @@ httpWorker conf e = do
|
||||||
status status200
|
status status200
|
||||||
|
|
||||||
get "/metadata" do
|
get "/metadata" do
|
||||||
raw $ serialise $ mkPeerMeta conf
|
raw $ serialise $ pmeta
|
||||||
|
|
||||||
put "/" do
|
put "/" do
|
||||||
-- FIXME: optional-header-based-authorization
|
-- FIXME: optional-header-based-authorization
|
||||||
|
|
|
@ -4,8 +4,11 @@ module PeerInfo where
|
||||||
|
|
||||||
import HBS2.Actors.Peer
|
import HBS2.Actors.Peer
|
||||||
import HBS2.Clock
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Types
|
||||||
import HBS2.Events
|
import HBS2.Events
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
import HBS2.Net.PeerLocator
|
import HBS2.Net.PeerLocator
|
||||||
|
import HBS2.Net.Proto.Event.PeerExpired
|
||||||
import HBS2.Net.Proto.Peer
|
import HBS2.Net.Proto.Peer
|
||||||
import HBS2.Net.Proto.PeerExchange
|
import HBS2.Net.Proto.PeerExchange
|
||||||
import HBS2.Net.Proto.Sessions
|
import HBS2.Net.Proto.Sessions
|
||||||
|
@ -145,8 +148,8 @@ peerPingLoop :: forall e m . ( HasPeerLocator e m
|
||||||
, m ~ PeerM e IO
|
, m ~ PeerM e IO
|
||||||
, e ~ L4Proto
|
, e ~ L4Proto
|
||||||
)
|
)
|
||||||
=> PeerConfig -> m ()
|
=> PeerConfig -> PeerEnv e -> m ()
|
||||||
peerPingLoop cfg = do
|
peerPingLoop cfg penv = do
|
||||||
|
|
||||||
e <- ask
|
e <- ask
|
||||||
|
|
||||||
|
@ -217,9 +220,11 @@ peerPingLoop cfg = do
|
||||||
let l = realToFrac (toNanoSecs $ now - seen) / 1e9
|
let l = realToFrac (toNanoSecs $ now - seen) / 1e9
|
||||||
-- FIXME: time-hardcode
|
-- FIXME: time-hardcode
|
||||||
when ( l > 300 ) do
|
when ( l > 300 ) do
|
||||||
|
mpeerData <- find (KnownPeerKey p) id
|
||||||
delPeers pl [p]
|
delPeers pl [p]
|
||||||
expire (PeerInfoKey p)
|
expire (PeerInfoKey p)
|
||||||
expire (KnownPeerKey p)
|
expire (KnownPeerKey p)
|
||||||
|
emit PeerExpiredEventKey (PeerExpiredEvent @e p {-mpeerData-})
|
||||||
|
|
||||||
liftIO $ mapM_ link [watch, infoLoop]
|
liftIO $ mapM_ link [watch, infoLoop]
|
||||||
|
|
||||||
|
@ -240,7 +245,6 @@ peerPingLoop cfg = do
|
||||||
pips <- knownPeers @e pl <&> (<> sas) <&> List.nub
|
pips <- knownPeers @e pl <&> (<> sas) <&> List.nub
|
||||||
|
|
||||||
for_ pips $ \p -> do
|
for_ pips $ \p -> do
|
||||||
trace $ "SEND PING TO" <+> pretty p
|
-- trace $ "SEND PING TO" <+> pretty p
|
||||||
sendPing @e p
|
sendPing @e p
|
||||||
|
-- trace $ "SENT PING TO" <+> pretty p
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,17 @@ import HBS2.Defaults
|
||||||
import HBS2.Events
|
import HBS2.Events
|
||||||
import HBS2.Hash
|
import HBS2.Hash
|
||||||
import HBS2.Data.Types.Refs
|
import HBS2.Data.Types.Refs
|
||||||
|
import HBS2.Data.Types
|
||||||
import HBS2.Net.Auth.Credentials
|
import HBS2.Net.Auth.Credentials
|
||||||
import HBS2.Net.IP.Addr
|
import HBS2.Net.IP.Addr
|
||||||
|
import HBS2.Net.Messaging
|
||||||
import HBS2.Net.Messaging.UDP
|
import HBS2.Net.Messaging.UDP
|
||||||
import HBS2.Net.Messaging.TCP
|
import HBS2.Net.Messaging.TCP
|
||||||
import HBS2.Net.PeerLocator
|
import HBS2.Net.PeerLocator
|
||||||
import HBS2.Net.Proto
|
import HBS2.Net.Proto as Proto
|
||||||
import HBS2.Net.Proto.Definition
|
import HBS2.Net.Proto.Definition
|
||||||
|
import HBS2.Net.Proto.EncryptionHandshake
|
||||||
|
import HBS2.Net.Proto.Event.PeerExpired
|
||||||
import HBS2.Net.Proto.Peer
|
import HBS2.Net.Proto.Peer
|
||||||
import HBS2.Net.Proto.PeerAnnounce
|
import HBS2.Net.Proto.PeerAnnounce
|
||||||
import HBS2.Net.Proto.PeerExchange
|
import HBS2.Net.Proto.PeerExchange
|
||||||
|
@ -45,6 +49,7 @@ import PeerInfo
|
||||||
import PeerConfig
|
import PeerConfig
|
||||||
import Bootstrap
|
import Bootstrap
|
||||||
import CheckMetrics
|
import CheckMetrics
|
||||||
|
import EncryptionKeys
|
||||||
import RefLog qualified
|
import RefLog qualified
|
||||||
import RefLog (reflogWorker)
|
import RefLog (reflogWorker)
|
||||||
import HttpWorker
|
import HttpWorker
|
||||||
|
@ -53,7 +58,7 @@ import PeerMeta
|
||||||
import CLI.RefChan
|
import CLI.RefChan
|
||||||
import RefChan
|
import RefChan
|
||||||
|
|
||||||
import Codec.Serialise
|
import Codec.Serialise as Serialise
|
||||||
-- import Control.Concurrent.Async
|
-- import Control.Concurrent.Async
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
import Control.Exception as Exception
|
import Control.Exception as Exception
|
||||||
|
@ -67,6 +72,7 @@ import Data.ByteString qualified as BS
|
||||||
import Data.Cache qualified as Cache
|
import Data.Cache qualified as Cache
|
||||||
import Data.Function
|
import Data.Function
|
||||||
import Data.List qualified as L
|
import Data.List qualified as L
|
||||||
|
import Data.Map (Map)
|
||||||
import Data.Map qualified as Map
|
import Data.Map qualified as Map
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Set qualified as Set
|
import Data.Set qualified as Set
|
||||||
|
@ -77,7 +83,7 @@ import Data.Text (Text)
|
||||||
import Data.HashSet qualified as HashSet
|
import Data.HashSet qualified as HashSet
|
||||||
import GHC.Stats
|
import GHC.Stats
|
||||||
import GHC.TypeLits
|
import GHC.TypeLits
|
||||||
import Lens.Micro.Platform
|
import Lens.Micro.Platform as Lens
|
||||||
import Network.Socket
|
import Network.Socket
|
||||||
import Options.Applicative
|
import Options.Applicative
|
||||||
import System.Directory
|
import System.Directory
|
||||||
|
@ -87,6 +93,7 @@ import System.Mem
|
||||||
import System.Metrics
|
import System.Metrics
|
||||||
import System.Posix.Process
|
import System.Posix.Process
|
||||||
import System.Environment
|
import System.Environment
|
||||||
|
import Text.InterpolatedString.Perl6 (qc)
|
||||||
|
|
||||||
import UnliftIO.Exception qualified as U
|
import UnliftIO.Exception qualified as U
|
||||||
-- import UnliftIO.STM
|
-- import UnliftIO.STM
|
||||||
|
@ -228,6 +235,7 @@ runCLI = join . customExecParser (prefs showHelpOnError) $
|
||||||
<> command "reflog" (info pRefLog (progDesc "reflog commands"))
|
<> command "reflog" (info pRefLog (progDesc "reflog commands"))
|
||||||
<> command "refchan" (info pRefChan (progDesc "refchan commands"))
|
<> command "refchan" (info pRefChan (progDesc "refchan commands"))
|
||||||
<> command "peers" (info pPeers (progDesc "show known peers"))
|
<> command "peers" (info pPeers (progDesc "show known peers"))
|
||||||
|
<> command "pexinfo" (info pPexInfo (progDesc "show pex"))
|
||||||
<> command "log" (info pLog (progDesc "set logging level"))
|
<> command "log" (info pLog (progDesc "set logging level"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -289,6 +297,10 @@ runCLI = join . customExecParser (prefs showHelpOnError) $
|
||||||
rpc <- pRpcCommon
|
rpc <- pRpcCommon
|
||||||
pure $ runRpcCommand rpc PEERS
|
pure $ runRpcCommand rpc PEERS
|
||||||
|
|
||||||
|
pPexInfo = do
|
||||||
|
rpc <- pRpcCommon
|
||||||
|
pure $ runRpcCommand rpc PEXINFO
|
||||||
|
|
||||||
onOff l =
|
onOff l =
|
||||||
hsubparser ( command "on" (info (pure (l True) ) (progDesc "on") ) )
|
hsubparser ( command "on" (info (pure (l True) ) (progDesc "on") ) )
|
||||||
<|> hsubparser ( command "off" (info (pure (l False) ) (progDesc "off") ) )
|
<|> hsubparser ( command "off" (info (pure (l False) ) (progDesc "off") ) )
|
||||||
|
@ -479,16 +491,16 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
liftIO $ print $ pretty accptAnn
|
liftIO $ print $ pretty accptAnn
|
||||||
|
|
||||||
-- FIXME: move-peerBanned-somewhere
|
-- FIXME: move-peerBanned-somewhere
|
||||||
let peerBanned p d = do
|
let peerBanned p pd = do
|
||||||
let k = view peerSignKey d
|
let k = view peerSignKey pd
|
||||||
let blacklisted = k `Set.member` blkeys
|
let blacklisted = k `Set.member` blkeys
|
||||||
let whitelisted = Set.null wlkeys || (k `Set.member` wlkeys)
|
let whitelisted = Set.null wlkeys || (k `Set.member` wlkeys)
|
||||||
pure $ blacklisted || not whitelisted
|
pure $ blacklisted || not whitelisted
|
||||||
|
|
||||||
let acceptAnnounce p d = do
|
let acceptAnnounce p pd = do
|
||||||
case accptAnn of
|
case accptAnn of
|
||||||
AcceptAnnounceAll -> pure True
|
AcceptAnnounceAll -> pure True
|
||||||
AcceptAnnounceFrom s -> pure $ view peerSignKey d `Set.member` s
|
AcceptAnnounceFrom s -> pure $ view peerSignKey pd `Set.member` s
|
||||||
|
|
||||||
rpcQ <- liftIO $ newTQueueIO @RPCCommand
|
rpcQ <- liftIO $ newTQueueIO @RPCCommand
|
||||||
|
|
||||||
|
@ -548,11 +560,42 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
void $ async $ runMessagingTCP tcpEnv
|
void $ async $ runMessagingTCP tcpEnv
|
||||||
pure $ Just tcpEnv
|
pure $ Just tcpEnv
|
||||||
|
|
||||||
proxy <- newProxyMessaging mess tcp
|
(proxy, penv) <- mdo
|
||||||
|
proxy <- newProxyMessaging mess tcp >>= \peer -> pure peer
|
||||||
|
{ _proxy_getEncryptionKey = \peer -> do
|
||||||
|
mpeerData <- withPeerM penv $ find (KnownPeerKey peer) id
|
||||||
|
mkey <- join <$> forM mpeerData \peerData -> getEncryptionKey penv peerData
|
||||||
|
case mkey of
|
||||||
|
Nothing ->
|
||||||
|
trace $ "ENCRYPTION empty getEncryptionKey"
|
||||||
|
<+> pretty peer <+> viaShow mpeerData
|
||||||
|
Just k ->
|
||||||
|
trace $ "ENCRYPTION success getEncryptionKey"
|
||||||
|
<+> pretty peer <+> viaShow mpeerData <+> viaShow k
|
||||||
|
pure mkey
|
||||||
|
|
||||||
|
, _proxy_clearEncryptionKey = \peer -> do
|
||||||
|
mpeerData <- withPeerM penv $ find (KnownPeerKey peer) id
|
||||||
|
forM_ mpeerData \peerData -> setEncryptionKey penv peer peerData Nothing
|
||||||
|
-- deletePeerAsymmKey brains peer
|
||||||
|
forM_ mpeerData \peerData ->
|
||||||
|
deletePeerAsymmKey' brains (show peerData)
|
||||||
|
|
||||||
|
, _proxy_sendResetEncryptionKeys = \peer -> withPeerM penv do
|
||||||
|
sendResetEncryptionKeys peer
|
||||||
|
|
||||||
|
, _proxy_sendBeginEncryptionExchange = \peer -> withPeerM penv do
|
||||||
|
sendBeginEncryptionExchange pc
|
||||||
|
((pubKeyFromKeypair @s . view envAsymmetricKeyPair) penv)
|
||||||
|
peer
|
||||||
|
|
||||||
|
}
|
||||||
|
penv <- newPeerEnv (AnyStorage s) (Fabriq proxy) (getOwnPeer mess)
|
||||||
|
pure (proxy, penv)
|
||||||
|
|
||||||
proxyThread <- async $ runProxyMessaging proxy
|
proxyThread <- async $ runProxyMessaging proxy
|
||||||
|
|
||||||
penv <- newPeerEnv (AnyStorage s) (Fabriq proxy) (getOwnPeer mess)
|
let peerMeta = mkPeerMeta conf penv
|
||||||
|
|
||||||
nbcache <- liftIO $ Cache.newCache (Just $ toTimeSpec ( 600 :: Timeout 'Seconds))
|
nbcache <- liftIO $ Cache.newCache (Just $ toTimeSpec ( 600 :: Timeout 'Seconds))
|
||||||
|
|
||||||
|
@ -581,8 +624,8 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
let onNoBlock (p, h) = do
|
let onNoBlock (p, h) = do
|
||||||
already <- liftIO $ Cache.lookup nbcache (p,h) <&> isJust
|
already <- liftIO $ Cache.lookup nbcache (p,h) <&> isJust
|
||||||
unless already do
|
unless already do
|
||||||
pd' <- find (KnownPeerKey p) id
|
mpde <- find (KnownPeerKey p) id
|
||||||
maybe1 pd' none $ \pd -> do
|
maybe1 mpde none $ \pd -> do
|
||||||
let pk = view peerSignKey pd
|
let pk = view peerSignKey pd
|
||||||
when (Set.member pk helpFetchKeys) do
|
when (Set.member pk helpFetchKeys) do
|
||||||
liftIO $ Cache.insert nbcache (p,h) ()
|
liftIO $ Cache.insert nbcache (p,h) ()
|
||||||
|
@ -624,6 +667,36 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
let hshakeAdapter = PeerHandshakeAdapter addNewRtt
|
let hshakeAdapter = PeerHandshakeAdapter addNewRtt
|
||||||
|
|
||||||
|
let encryptionHshakeAdapter ::
|
||||||
|
( MonadIO m
|
||||||
|
, EventEmitter e (PeerAsymmInfo e) m
|
||||||
|
) => EncryptionHandshakeAdapter L4Proto m s
|
||||||
|
encryptionHshakeAdapter = EncryptionHandshakeAdapter
|
||||||
|
{ encHandshake_considerPeerAsymmKey = \peer mpubkey -> withPeerM penv do
|
||||||
|
mpeerData <- withPeerM penv $ find (KnownPeerKey peer) id
|
||||||
|
case mpubkey of
|
||||||
|
Nothing -> do
|
||||||
|
-- trace $ "ENCRYPTION delete key" <+> pretty peer <+> viaShow mpeerData
|
||||||
|
-- deletePeerAsymmKey brains peer
|
||||||
|
forM_ mpeerData \peerData ->
|
||||||
|
deletePeerAsymmKey' brains (show peerData)
|
||||||
|
Just pk -> do
|
||||||
|
-- emit PeerAsymmInfoKey (PeerAsymmPubKey peer pk)
|
||||||
|
let symmk = genCommonSecret @s
|
||||||
|
(privKeyFromKeypair @s (view envAsymmetricKeyPair penv))
|
||||||
|
pk
|
||||||
|
case mpeerData of
|
||||||
|
Nothing -> do
|
||||||
|
-- insertPeerAsymmKey brains peer pk symmk
|
||||||
|
-- insertPeerAsymmKey' brains (show peer) pk symmk
|
||||||
|
trace $ "ENCRYPTION can not store key. No peerData"
|
||||||
|
<+> pretty peer <+> viaShow mpeerData
|
||||||
|
Just peerData -> do
|
||||||
|
liftIO $ setEncryptionKey penv peer peerData (Just symmk)
|
||||||
|
insertPeerAsymmKey' brains (show peerData) pk symmk
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
env <- ask
|
env <- ask
|
||||||
|
|
||||||
pnonce <- peerNonce @e
|
pnonce <- peerNonce @e
|
||||||
|
@ -632,29 +705,39 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
addPeers @e pl ps
|
addPeers @e pl ps
|
||||||
|
|
||||||
|
subscribe @e PeerExpiredEventKey \(PeerExpiredEvent peer {-mpeerData-}) -> liftIO do
|
||||||
|
mpeerData <- withPeerM penv $ find (KnownPeerKey peer) id
|
||||||
|
forM_ mpeerData \peerData -> setEncryptionKey penv peer peerData Nothing
|
||||||
|
-- deletePeerAsymmKey brains peer
|
||||||
|
forM_ mpeerData \peerData ->
|
||||||
|
deletePeerAsymmKey' brains (show peerData)
|
||||||
|
|
||||||
subscribe @e PeerAnnounceEventKey $ \(PeerAnnounceEvent pip nonce) -> do
|
subscribe @e PeerAnnounceEventKey $ \(PeerAnnounceEvent pip nonce) -> do
|
||||||
unless (nonce == pnonce) $ do
|
unless (nonce == pnonce) $ do
|
||||||
debug $ "Got peer announce!" <+> pretty pip
|
debug $ "Got peer announce!" <+> pretty pip
|
||||||
pd <- find (KnownPeerKey pip) id -- <&> isJust
|
mpd :: Maybe (PeerData e) <- find (KnownPeerKey pip) id
|
||||||
banned <- maybe (pure False) (peerBanned pip) pd
|
banned <- maybe (pure False) (peerBanned pip) mpd
|
||||||
let known = isJust pd && not banned
|
let known = isJust mpd && not banned
|
||||||
sendPing pip
|
sendPing pip
|
||||||
|
|
||||||
subscribe @e BlockAnnounceInfoKey $ \(BlockAnnounceEvent p bi no) -> do
|
subscribe @e BlockAnnounceInfoKey $ \(BlockAnnounceEvent p bi no) -> do
|
||||||
pa <- toPeerAddr p
|
pa <- toPeerAddr p
|
||||||
liftIO $ atomically $ writeTQueue rpcQ (CHECK no pa (view biHash bi))
|
liftIO $ atomically $ writeTQueue rpcQ (CHECK no pa (view biHash bi))
|
||||||
|
|
||||||
subscribe @e AnyKnownPeerEventKey $ \(KnownPeerEvent p d) -> do
|
subscribe @e AnyKnownPeerEventKey $ \(KnownPeerEvent p pd) -> do
|
||||||
|
|
||||||
let thatNonce = view peerOwnNonce d
|
let thatNonce = view peerOwnNonce pd
|
||||||
|
|
||||||
now <- liftIO getTimeCoarse
|
now <- liftIO getTimeCoarse
|
||||||
pinfo' <- find (PeerInfoKey p) id -- (view peerPingFailed)
|
|
||||||
maybe1 pinfo' none $ \pinfo -> do
|
-- defPeerInfo <- newPeerInfo
|
||||||
|
-- fetch True defPeerInfo (PeerInfoKey p) id >>= \pinfo -> do
|
||||||
|
|
||||||
|
find (PeerInfoKey p) id >>= mapM_ \pinfo -> do
|
||||||
liftIO $ atomically $ writeTVar (view peerPingFailed pinfo) 0
|
liftIO $ atomically $ writeTVar (view peerPingFailed pinfo) 0
|
||||||
liftIO $ atomically $ writeTVar (view peerLastWatched pinfo) now
|
liftIO $ atomically $ writeTVar (view peerLastWatched pinfo) now
|
||||||
|
|
||||||
banned <- peerBanned p d
|
banned <- peerBanned p pd
|
||||||
|
|
||||||
let doAddPeer p = do
|
let doAddPeer p = do
|
||||||
addPeers pl [p]
|
addPeers pl [p]
|
||||||
|
@ -666,7 +749,7 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
unless here do
|
unless here do
|
||||||
debug $ "Got authorized peer!" <+> pretty p
|
debug $ "Got authorized peer!" <+> pretty p
|
||||||
<+> pretty (AsBase58 (view peerSignKey d))
|
<+> pretty (AsBase58 (view peerSignKey pd))
|
||||||
request @e p (GetPeerMeta @e)
|
request @e p (GetPeerMeta @e)
|
||||||
|
|
||||||
|
|
||||||
|
@ -682,18 +765,15 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
| otherwise -> do
|
| otherwise -> do
|
||||||
|
|
||||||
update d (KnownPeerKey p) id
|
update pd (KnownPeerKey p) id
|
||||||
|
|
||||||
pd' <- knownPeers @e pl >>=
|
pdkv :: Map BS.ByteString (Peer L4Proto) <- fmap (Map.fromList . catMaybes)
|
||||||
\peers -> forM peers $ \pip -> do
|
$ knownPeers @e pl >>= mapM \pip ->
|
||||||
pd <- find (KnownPeerKey pip) (view peerOwnNonce)
|
fmap (, pip) <$> find (KnownPeerKey pip) (view peerOwnNonce)
|
||||||
pure $ (,pip) <$> pd
|
|
||||||
|
|
||||||
let pd = Map.fromList $ catMaybes pd'
|
|
||||||
|
|
||||||
let proto1 = view sockType p
|
let proto1 = view sockType p
|
||||||
|
|
||||||
case Map.lookup thatNonce pd of
|
case Map.lookup thatNonce pdkv of
|
||||||
|
|
||||||
-- TODO: prefer-local-peer-with-same-nonce-over-remote-peer
|
-- TODO: prefer-local-peer-with-same-nonce-over-remote-peer
|
||||||
-- remove remote peer
|
-- remove remote peer
|
||||||
|
@ -758,11 +838,11 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
-- peerThread "tcpWorker" (tcpWorker conf)
|
-- peerThread "tcpWorker" (tcpWorker conf)
|
||||||
|
|
||||||
peerThread "httpWorker" (httpWorker conf denv)
|
peerThread "httpWorker" (httpWorker conf peerMeta denv)
|
||||||
|
|
||||||
peerThread "checkMetrics" (checkMetrics metrics)
|
peerThread "checkMetrics" (checkMetrics metrics)
|
||||||
|
|
||||||
peerThread "peerPingLoop" (peerPingLoop @e conf)
|
peerThread "peerPingLoop" (peerPingLoop @e conf penv)
|
||||||
|
|
||||||
peerThread "knownPeersPingLoop" (knownPeersPingLoop @e conf)
|
peerThread "knownPeersPingLoop" (knownPeersPingLoop @e conf)
|
||||||
|
|
||||||
|
@ -772,6 +852,9 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
peerThread "blockDownloadLoop" (blockDownloadLoop denv)
|
peerThread "blockDownloadLoop" (blockDownloadLoop denv)
|
||||||
|
|
||||||
|
peerThread "encryptionHandshakeWorker"
|
||||||
|
(EncryptionKeys.encryptionHandshakeWorker @e conf penv pc encryptionHshakeAdapter)
|
||||||
|
|
||||||
let tcpProbeWait :: Timeout 'Seconds
|
let tcpProbeWait :: Timeout 'Seconds
|
||||||
tcpProbeWait = (fromInteger . fromMaybe 300) (cfgValue @PeerTcpProbeWaitKey conf)
|
tcpProbeWait = (fromInteger . fromMaybe 300) (cfgValue @PeerTcpProbeWaitKey conf)
|
||||||
|
|
||||||
|
@ -798,11 +881,14 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
PING pa r -> do
|
PING pa r -> do
|
||||||
debug $ "ping" <+> pretty pa
|
debug $ "ping" <+> pretty pa
|
||||||
pip <- fromPeerAddr @e pa
|
pip <- fromPeerAddr @e pa
|
||||||
subscribe (ConcretePeerKey pip) $ \(ConcretePeerData{}) -> do
|
subscribe (ConcretePeerKey pip) $ \(ConcretePeerData _ pde) -> do
|
||||||
|
|
||||||
maybe1 r (pure ()) $ \rpcPeer -> do
|
maybe1 r (pure ()) $ \rpcPeer -> do
|
||||||
pinged <- toPeerAddr pip
|
pinged <- toPeerAddr pip
|
||||||
request rpcPeer (RPCPong @e pinged)
|
request rpcPeer (RPCPong @e pinged)
|
||||||
|
-- case (view peerEncPubKey pde) of
|
||||||
|
-- Nothing -> unencrypted ping
|
||||||
|
-- Just pubkey -> encryptengd
|
||||||
|
|
||||||
sendPing pip
|
sendPing pip
|
||||||
|
|
||||||
|
@ -832,13 +918,13 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
|
|
||||||
unless (nonce == n1) do
|
unless (nonce == n1) do
|
||||||
|
|
||||||
peer <- find @e (KnownPeerKey pip) id
|
mpde <- find @e (KnownPeerKey pip) id
|
||||||
|
|
||||||
debug $ "received announce from"
|
debug $ "received announce from"
|
||||||
<+> pretty pip
|
<+> pretty pip
|
||||||
<+> pretty h
|
<+> pretty h
|
||||||
|
|
||||||
case peer of
|
case mpde of
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
sendPing @e pip
|
sendPing @e pip
|
||||||
-- TODO: enqueue-announce-from-unknown-peer?
|
-- TODO: enqueue-announce-from-unknown-peer?
|
||||||
|
@ -886,11 +972,12 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
[ makeResponse (blockSizeProto blk dontHandle onNoBlock)
|
[ makeResponse (blockSizeProto blk dontHandle onNoBlock)
|
||||||
, makeResponse (blockChunksProto adapter)
|
, makeResponse (blockChunksProto adapter)
|
||||||
, makeResponse blockAnnounceProto
|
, makeResponse blockAnnounceProto
|
||||||
, makeResponse (withCredentials @e pc . peerHandShakeProto hshakeAdapter)
|
, makeResponse (withCredentials @e pc . peerHandShakeProto hshakeAdapter penv)
|
||||||
|
, makeResponse (withCredentials @e pc . encryptionHandshakeProto encryptionHshakeAdapter penv)
|
||||||
, makeResponse (peerExchangeProto pexFilt)
|
, makeResponse (peerExchangeProto pexFilt)
|
||||||
, makeResponse (refLogUpdateProto reflogAdapter)
|
, makeResponse (refLogUpdateProto reflogAdapter)
|
||||||
, makeResponse (refLogRequestProto reflogReqAdapter)
|
, makeResponse (refLogRequestProto reflogReqAdapter)
|
||||||
, makeResponse (peerMetaProto (mkPeerMeta conf))
|
, makeResponse (peerMetaProto peerMeta)
|
||||||
, makeResponse (refChanHeadProto False refChanAdapter)
|
, makeResponse (refChanHeadProto False refChanAdapter)
|
||||||
, makeResponse (refChanUpdateProto False pc refChanAdapter)
|
, makeResponse (refChanUpdateProto False pc refChanAdapter)
|
||||||
, makeResponse (refChanRequestProto False refChanAdapter)
|
, makeResponse (refChanRequestProto False refChanAdapter)
|
||||||
|
@ -937,11 +1024,19 @@ runPeer opts = U.handle (\e -> myException e
|
||||||
let peersAction _ = do
|
let peersAction _ = do
|
||||||
who <- thatPeer (Proxy @(RPC e))
|
who <- thatPeer (Proxy @(RPC e))
|
||||||
void $ liftIO $ async $ withPeerM penv $ do
|
void $ liftIO $ async $ withPeerM penv $ do
|
||||||
forKnownPeers @e $ \p pd -> do
|
forKnownPeers @e $ \p pde -> do
|
||||||
pa <- toPeerAddr p
|
pa <- toPeerAddr p
|
||||||
let k = view peerSignKey pd
|
let k = view peerSignKey pde
|
||||||
request who (RPCPeersAnswer @e pa k)
|
request who (RPCPeersAnswer @e pa k)
|
||||||
|
|
||||||
|
let pexInfoAction :: RPC L4Proto -> ResponseM L4Proto (RpcM (ResourceT IO)) ()
|
||||||
|
pexInfoAction _ = do
|
||||||
|
who <- thatPeer (Proxy @(RPC e))
|
||||||
|
void $ liftIO $ async $ withPeerM penv $ do
|
||||||
|
-- FIXME: filter-pexinfo-entries
|
||||||
|
ps <- getAllPex2Peers
|
||||||
|
request who (RPCPexInfoAnswer @e ps)
|
||||||
|
|
||||||
let logLevelAction = \case
|
let logLevelAction = \case
|
||||||
DebugOn True -> do
|
DebugOn True -> do
|
||||||
setLogging @DEBUG debugPrefix
|
setLogging @DEBUG debugPrefix
|
||||||
|
|
|
@ -21,12 +21,16 @@ import Control.Concurrent.Async
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
|
import Control.Monad.Trans.State.Strict qualified as State
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
import Data.Foldable hiding (find)
|
import Data.Foldable hiding (find)
|
||||||
import Data.HashMap.Strict qualified as HashMap
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
|
import Data.Map.Strict qualified as Map
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
|
import Data.Set qualified as Set
|
||||||
import Data.Text qualified as Text
|
import Data.Text qualified as Text
|
||||||
import Data.Text.Encoding qualified as TE
|
import Data.Text.Encoding qualified as TE
|
||||||
|
import Data.Time
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Lens.Micro.Platform
|
import Lens.Micro.Platform
|
||||||
import Network.HTTP.Simple (getResponseBody, httpLbs, parseRequest, getResponseStatus)
|
import Network.HTTP.Simple (getResponseBody, httpLbs, parseRequest, getResponseStatus)
|
||||||
|
@ -53,14 +57,24 @@ fillPeerMeta mtcp probePeriod = do
|
||||||
debug "I'm fillPeerMeta"
|
debug "I'm fillPeerMeta"
|
||||||
pl <- getPeerLocator @e
|
pl <- getPeerLocator @e
|
||||||
|
|
||||||
pause @'Seconds 10 -- wait 'till everything calm down
|
pause @'Seconds 5 -- wait 'till everything calm down
|
||||||
|
flip State.evalStateT Map.empty $ forever do
|
||||||
|
pause @'Seconds 12
|
||||||
|
|
||||||
forever $ (>> pause probePeriod) $ do
|
ps <- knownPeers pl
|
||||||
|
now <- liftIO getCurrentTime
|
||||||
|
let pss = Set.fromList ps
|
||||||
|
psActual <- Map.filterWithKey (\k _ -> k `Set.member` pss) <$> State.get
|
||||||
|
let psNew = pss Set.\\ (Map.keysSet psActual)
|
||||||
|
let psReady = Map.keysSet . Map.filter (\t -> t < now) $ psActual
|
||||||
|
let ps' = Set.toList (psNew <> psReady)
|
||||||
|
(State.put . (<> psActual) . Map.fromList) $
|
||||||
|
(, now & addUTCTime (toNominalDiffTime probePeriod)) <$> ps'
|
||||||
|
|
||||||
ps <- knownPeers @e pl
|
when ((not . null) ps') $ lift do
|
||||||
debug $ "fillPeerMeta peers:" <+> pretty ps
|
debug $ "fillPeerMeta peers:" <+> pretty ps'
|
||||||
|
for_ ps' $ \p -> do
|
||||||
npi <- newPeerInfo
|
npi <- newPeerInfo
|
||||||
for_ ps $ \p -> do
|
|
||||||
|
|
||||||
pinfo <- fetch True npi (PeerInfoKey p) id
|
pinfo <- fetch True npi (PeerInfoKey p) id
|
||||||
mmApiAddr <- liftIO $ readTVarIO (_peerHttpApiAddress pinfo)
|
mmApiAddr <- liftIO $ readTVarIO (_peerHttpApiAddress pinfo)
|
||||||
|
|
|
@ -8,9 +8,12 @@ module PeerTypes where
|
||||||
import HBS2.Actors.Peer
|
import HBS2.Actors.Peer
|
||||||
import HBS2.Actors.Peer.Types
|
import HBS2.Actors.Peer.Types
|
||||||
import HBS2.Clock
|
import HBS2.Clock
|
||||||
|
import HBS2.Data.Types.Peer
|
||||||
import HBS2.Defaults
|
import HBS2.Defaults
|
||||||
import HBS2.Events
|
import HBS2.Events
|
||||||
import HBS2.Hash
|
import HBS2.Hash
|
||||||
|
import HBS2.Merkle (AnnMetaData)
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
import HBS2.Net.IP.Addr
|
import HBS2.Net.IP.Addr
|
||||||
import HBS2.Net.Proto
|
import HBS2.Net.Proto
|
||||||
import HBS2.Net.Proto.Peer
|
import HBS2.Net.Proto.Peer
|
||||||
|
@ -31,12 +34,15 @@ import Data.Foldable (for_)
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
|
import Control.Monad.Writer qualified as W
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
import Data.ByteString.Lazy (ByteString)
|
import Data.ByteString.Lazy (ByteString)
|
||||||
import Data.Cache (Cache)
|
import Data.Cache (Cache)
|
||||||
import Data.Cache qualified as Cache
|
import Data.Cache qualified as Cache
|
||||||
import Data.HashSet (HashSet)
|
import Data.HashSet (HashSet)
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import Data.HashMap.Strict qualified as HashMap
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
|
import Data.List qualified as L
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Lens.Micro.Platform
|
import Lens.Micro.Platform
|
||||||
import Data.Hashable
|
import Data.Hashable
|
||||||
|
@ -47,8 +53,9 @@ import Data.Text qualified as Text
|
||||||
import Data.Text.Encoding qualified as TE
|
import Data.Text.Encoding qualified as TE
|
||||||
import Data.Time.Clock (NominalDiffTime)
|
import Data.Time.Clock (NominalDiffTime)
|
||||||
import Data.Heap qualified as Heap
|
import Data.Heap qualified as Heap
|
||||||
import Data.Heap (Entry(..))
|
import Data.Heap (Heap,Entry(..))
|
||||||
-- import Data.Time.Clock
|
import Data.Time.Clock
|
||||||
|
import Data.Word
|
||||||
|
|
||||||
data PeerInfo e =
|
data PeerInfo e =
|
||||||
PeerInfo
|
PeerInfo
|
||||||
|
@ -77,23 +84,25 @@ makeLenses 'PeerInfo
|
||||||
|
|
||||||
newPeerInfo :: MonadIO m => m (PeerInfo e)
|
newPeerInfo :: MonadIO m => m (PeerInfo e)
|
||||||
newPeerInfo = liftIO do
|
newPeerInfo = liftIO do
|
||||||
PeerInfo <$> newTVarIO defBurst
|
_peerBurst <- newTVarIO defBurst
|
||||||
<*> newTVarIO Nothing
|
_peerBurstMax <- newTVarIO Nothing
|
||||||
<*> newTVarIO mempty
|
_peerBurstSet <- newTVarIO mempty
|
||||||
<*> newTVarIO 0
|
_peerErrors <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerErrorsLast <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerErrorsPerSec <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerLastWatched <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerDownloaded <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerDownloadedLast <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerPingFailed <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerDownloadedBlk <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerDownloadFail <- newTVarIO 0
|
||||||
<*> newTVarIO 0
|
_peerDownloadMiss <- newTVarIO 0
|
||||||
<*> newTVarIO []
|
_peerRTTBuffer <- newTVarIO []
|
||||||
<*> newTVarIO (Left 0)
|
-- Acts like a circular buffer.
|
||||||
<*> newTVarIO 0
|
_peerHttpApiAddress <- newTVarIO (Left 0)
|
||||||
<*> newTVarIO Nothing
|
_peerHttpDownloaded <- newTVarIO 0
|
||||||
|
_peerMeta <- newTVarIO Nothing
|
||||||
|
pure PeerInfo {..}
|
||||||
|
|
||||||
type instance SessionData e (PeerInfo e) = PeerInfo e
|
type instance SessionData e (PeerInfo e) = PeerInfo e
|
||||||
|
|
||||||
|
@ -376,8 +385,8 @@ forKnownPeers m = do
|
||||||
pl <- getPeerLocator @e
|
pl <- getPeerLocator @e
|
||||||
pips <- knownPeers @e pl
|
pips <- knownPeers @e pl
|
||||||
for_ pips $ \p -> do
|
for_ pips $ \p -> do
|
||||||
pd' <- find (KnownPeerKey p) id
|
mpde <- find (KnownPeerKey p) id
|
||||||
maybe1 pd' (pure ()) (m p)
|
maybe1 mpde (pure ()) (m p)
|
||||||
|
|
||||||
getKnownPeers :: forall e m . ( MonadIO m
|
getKnownPeers :: forall e m . ( MonadIO m
|
||||||
, HasPeerLocator e m
|
, HasPeerLocator e m
|
||||||
|
@ -394,18 +403,29 @@ getKnownPeers = do
|
||||||
maybe1 pd' (pure mempty) (const $ pure [p])
|
maybe1 pd' (pure mempty) (const $ pure [p])
|
||||||
pure $ mconcat r
|
pure $ mconcat r
|
||||||
|
|
||||||
mkPeerMeta conf = do
|
mkPeerMeta :: PeerConfig -> PeerEnv e -> AnnMetaData
|
||||||
let mHttpPort = cfgValue @PeerHttpPortKey conf <&> fromIntegral
|
mkPeerMeta conf penv = do
|
||||||
let mTcpPort =
|
let mHttpPort :: Maybe Integer
|
||||||
|
mHttpPort = cfgValue @PeerHttpPortKey conf <&> fromIntegral
|
||||||
|
let mTcpPort :: Maybe Word16
|
||||||
|
mTcpPort =
|
||||||
(
|
(
|
||||||
fmap (\(L4Address _ (IPAddrPort (_, p))) -> p)
|
fmap (\(L4Address _ (IPAddrPort (_, p))) -> p)
|
||||||
. fromStringMay @(PeerAddr L4Proto)
|
. fromStringMay @(PeerAddr L4Proto)
|
||||||
)
|
)
|
||||||
=<< cfgValue @PeerListenTCPKey conf
|
=<< cfgValue @PeerListenTCPKey conf
|
||||||
annMetaFromPeerMeta . PeerMeta . catMaybes $
|
-- let useEncryption = True -- move to config
|
||||||
[ mHttpPort <&> \p -> ("http-port", TE.encodeUtf8 . Text.pack . show $ p)
|
annMetaFromPeerMeta . PeerMeta $ W.execWriter do
|
||||||
, mTcpPort <&> \p -> ("listen-tcp", TE.encodeUtf8 . Text.pack . show $ p)
|
mHttpPort `forM` \p -> elem "http-port" (TE.encodeUtf8 . Text.pack . show $ p)
|
||||||
]
|
mTcpPort `forM` \p -> elem "listen-tcp" (TE.encodeUtf8 . Text.pack . show $ p)
|
||||||
|
-- when useEncryption do
|
||||||
|
-- elem "ekey" (TE.encodeUtf8 . Text.pack . show $
|
||||||
|
-- (Encrypt.publicKey . _envAsymmetricKeyPair) penv
|
||||||
|
-- -- mayby sign this pubkey by node key ?
|
||||||
|
-- )
|
||||||
|
|
||||||
|
where
|
||||||
|
elem k = W.tell . L.singleton . (k ,)
|
||||||
|
|
||||||
|
|
||||||
data Polling =
|
data Polling =
|
||||||
|
|
|
@ -1,26 +1,43 @@
|
||||||
{-# Language TemplateHaskell #-}
|
{-# Language TemplateHaskell #-}
|
||||||
module ProxyMessaging
|
module ProxyMessaging
|
||||||
( ProxyMessaging
|
( ProxyMessaging(..)
|
||||||
, newProxyMessaging
|
, newProxyMessaging
|
||||||
, runProxyMessaging
|
, runProxyMessaging
|
||||||
|
, sendToPlainProxyMessaging
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import HBS2.Prelude.Plated
|
import HBS2.Prelude.Plated
|
||||||
import HBS2.Net.Messaging
|
import HBS2.Net.Messaging
|
||||||
import HBS2.Clock
|
import HBS2.Clock
|
||||||
|
import HBS2.Crypto
|
||||||
|
import HBS2.Net.Auth.Credentials
|
||||||
|
import HBS2.Net.Proto.Definition ()
|
||||||
|
import HBS2.Net.Proto.Peer
|
||||||
import HBS2.Net.Proto.Types
|
import HBS2.Net.Proto.Types
|
||||||
import HBS2.Net.Messaging.UDP
|
import HBS2.Net.Messaging.UDP
|
||||||
import HBS2.Net.Messaging.TCP
|
import HBS2.Net.Messaging.TCP
|
||||||
|
|
||||||
import HBS2.System.Logger.Simple
|
import HBS2.System.Logger.Simple
|
||||||
|
|
||||||
|
import Crypto.Saltine.Class as SCl
|
||||||
|
import Crypto.Saltine.Core.Box qualified as Encrypt
|
||||||
|
|
||||||
|
import Codec.Serialise
|
||||||
|
import Control.Applicative
|
||||||
|
import Control.Arrow hiding ((<+>))
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
import Control.Concurrent.STM.TQueue
|
import Control.Concurrent.STM.TQueue
|
||||||
import Data.ByteString.Lazy (ByteString)
|
import Control.Monad.Trans.Maybe
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
|
import Data.ByteString qualified as BS
|
||||||
import Data.ByteString.Lazy qualified as LBS
|
import Data.ByteString.Lazy qualified as LBS
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.String.Conversions (cs)
|
||||||
import Data.List qualified as L
|
import Data.List qualified as L
|
||||||
import Lens.Micro.Platform
|
import Data.Map (Map)
|
||||||
|
import Data.Map qualified as Map
|
||||||
|
import Lens.Micro.Platform as Lens
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
|
||||||
-- TODO: protocol-encryption-goes-here
|
-- TODO: protocol-encryption-goes-here
|
||||||
|
@ -29,9 +46,19 @@ data ProxyMessaging =
|
||||||
ProxyMessaging
|
ProxyMessaging
|
||||||
{ _proxyUDP :: MessagingUDP
|
{ _proxyUDP :: MessagingUDP
|
||||||
, _proxyTCP :: Maybe MessagingTCP
|
, _proxyTCP :: Maybe MessagingTCP
|
||||||
, _proxyAnswers :: TQueue (From L4Proto, ByteString)
|
, _proxyAnswers :: TQueue (From L4Proto, LBS.ByteString)
|
||||||
|
|
||||||
|
, _proxy_getEncryptionKey :: Peer L4Proto -> IO (Maybe (CommonSecret (Encryption L4Proto)))
|
||||||
|
, _proxy_clearEncryptionKey :: Peer L4Proto -> IO ()
|
||||||
|
, _proxy_sendResetEncryptionKeys :: Peer L4Proto -> IO ()
|
||||||
|
, _proxy_sendBeginEncryptionExchange :: Peer L4Proto -> IO ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- 1 нода X создаёт себе Encrypt.Keypair
|
||||||
|
-- 2 подписывает из него публичный ключ ключом подписи ноды X и отправляет ноде Y
|
||||||
|
-- 3 нода Y получила Публичный ключ ноды X, создала симметричный Key,
|
||||||
|
-- зашифровала его для полученного Публичного ключа ноды X и отравила ей
|
||||||
|
|
||||||
makeLenses 'ProxyMessaging
|
makeLenses 'ProxyMessaging
|
||||||
|
|
||||||
newProxyMessaging :: forall m . MonadIO m
|
newProxyMessaging :: forall m . MonadIO m
|
||||||
|
@ -40,8 +67,16 @@ newProxyMessaging :: forall m . MonadIO m
|
||||||
-> m ProxyMessaging
|
-> m ProxyMessaging
|
||||||
|
|
||||||
newProxyMessaging u t = liftIO do
|
newProxyMessaging u t = liftIO do
|
||||||
ProxyMessaging u t
|
let _proxyUDP = u
|
||||||
<$> newTQueueIO
|
let _proxyTCP = t
|
||||||
|
_proxyAnswers <- newTQueueIO
|
||||||
|
|
||||||
|
let _proxy_getEncryptionKey = const (pure Nothing)
|
||||||
|
let _proxy_clearEncryptionKey = const (pure ())
|
||||||
|
let _proxy_sendResetEncryptionKeys = const (pure ())
|
||||||
|
let _proxy_sendBeginEncryptionExchange = const (pure ())
|
||||||
|
|
||||||
|
pure ProxyMessaging {..}
|
||||||
|
|
||||||
runProxyMessaging :: forall m . MonadIO m
|
runProxyMessaging :: forall m . MonadIO m
|
||||||
=> ProxyMessaging
|
=> ProxyMessaging
|
||||||
|
@ -66,23 +101,120 @@ runProxyMessaging env = liftIO do
|
||||||
|
|
||||||
liftIO $ mapM_ waitCatch [u,t]
|
liftIO $ mapM_ waitCatch [u,t]
|
||||||
|
|
||||||
instance Messaging ProxyMessaging L4Proto ByteString where
|
|
||||||
|
|
||||||
sendTo bus t@(To whom) f m = do
|
instance Messaging ProxyMessaging L4Proto LBS.ByteString where
|
||||||
-- sendTo (view proxyUDP bus) t f m
|
|
||||||
-- trace $ "PROXY: SEND" <+> pretty whom
|
sendTo = sendToProxyMessaging
|
||||||
|
|
||||||
|
receive = receiveFromProxyMessaging
|
||||||
|
|
||||||
|
-- receive bus _ = liftIO do
|
||||||
|
-- -- trace "PROXY: RECEIVE"
|
||||||
|
-- -- receive (view proxyUDP bus) w
|
||||||
|
-- let answ = view proxyAnswers bus
|
||||||
|
-- atomically $ do
|
||||||
|
-- r <- readTQueue answ
|
||||||
|
-- rs <- flushTQueue answ
|
||||||
|
-- pure (r:rs)
|
||||||
|
|
||||||
|
sendToPlainProxyMessaging :: (MonadIO m)
|
||||||
|
=> ProxyMessaging
|
||||||
|
-> To L4Proto
|
||||||
|
-> From L4Proto
|
||||||
|
-> LBS.ByteString
|
||||||
|
-> m ()
|
||||||
|
sendToPlainProxyMessaging bus t@(To whom) proto msg = do
|
||||||
let udp = view proxyUDP bus
|
let udp = view proxyUDP bus
|
||||||
case view sockType whom of
|
case view sockType whom of
|
||||||
UDP -> sendTo udp t f m
|
UDP -> sendTo udp t proto msg
|
||||||
TCP -> maybe1 (view proxyTCP bus) none $ \tcp -> do
|
TCP -> maybe1 (view proxyTCP bus) none $ \tcp -> do
|
||||||
sendTo tcp t f m
|
sendTo tcp t proto msg
|
||||||
|
|
||||||
receive bus _ = liftIO do
|
sendToProxyMessaging :: (MonadIO m)
|
||||||
|
=> ProxyMessaging
|
||||||
|
-> To L4Proto
|
||||||
|
-> From L4Proto
|
||||||
|
-> LBS.ByteString
|
||||||
|
-> m ()
|
||||||
|
sendToProxyMessaging bus t@(To whom) proto msg = do
|
||||||
|
-- sendTo (view proxyUDP bus) t proto msg
|
||||||
|
-- trace $ "PROXY: SEND" <+> pretty whom
|
||||||
|
mencKey <- liftIO $ _proxy_getEncryptionKey bus whom
|
||||||
|
cf <- case mencKey of
|
||||||
|
Nothing -> do
|
||||||
|
trace $ "ENCRYPTION SEND: sending plain message to" <+> pretty whom
|
||||||
|
pure id
|
||||||
|
Just k -> do
|
||||||
|
trace $ "ENCRYPTION SEND: sending encrypted message to" <+> pretty whom <+> "with key" <+> viaShow k
|
||||||
|
boxAfterNMLazy k <$> liftIO Encrypt.newNonce
|
||||||
|
sendToPlainProxyMessaging bus t proto (cf msg)
|
||||||
|
|
||||||
|
receiveFromProxyMessaging :: MonadIO m
|
||||||
|
=> ProxyMessaging -> To L4Proto -> m [(From L4Proto, LBS.ByteString)]
|
||||||
|
receiveFromProxyMessaging bus _ = liftIO do
|
||||||
-- trace "PROXY: RECEIVE"
|
-- trace "PROXY: RECEIVE"
|
||||||
-- receive (view proxyUDP bus) w
|
-- receive (view proxyUDP bus) w
|
||||||
let answ = view proxyAnswers bus
|
let answ = view proxyAnswers bus
|
||||||
atomically $ do
|
rs <- atomically $ liftM2 (:) (readTQueue answ) (flushTQueue answ)
|
||||||
r <- readTQueue answ
|
fmap catMaybes $ forM rs \(w@(From whom), msg) -> do
|
||||||
rs <- flushTQueue answ
|
fmap (w, ) <$> dfm whom msg
|
||||||
pure (r:rs)
|
|
||||||
|
|
||||||
|
-- Здесь:
|
||||||
|
-- 1. У нас есть ключ сессии и мы не смогли расшифровать -> do
|
||||||
|
-- удаляем у себя ключ
|
||||||
|
-- отправляем sendBeginEncryptionExchange
|
||||||
|
-- 2. У нас (до сих пор, даже если мы давно стартовали) нет ключа сессии -> do
|
||||||
|
-- sendResetEncryptionKeys
|
||||||
|
-- просто передаём сообщение как есть
|
||||||
|
|
||||||
|
-- В протоколе пингов:
|
||||||
|
-- 1. Если слишком долго нет ответа на ping, то удаляем у себя ключ, отправляем sendResetEncryptionKeys
|
||||||
|
-- Выполняется в PeerInfo:
|
||||||
|
-- emit PeerExpiredEventKey (PeerExpiredEvent @e p mpeerData)
|
||||||
|
|
||||||
|
where
|
||||||
|
dfm :: Peer L4Proto -> LBS.ByteString -> IO (Maybe LBS.ByteString)
|
||||||
|
dfm = \whom msg -> liftIO $ _proxy_getEncryptionKey bus whom >>= \case
|
||||||
|
|
||||||
|
Nothing -> do
|
||||||
|
trace $ "ENCRYPTION RECEIVE: we do not have a key to decode" <+> pretty whom
|
||||||
|
liftIO $ _proxy_sendBeginEncryptionExchange bus whom
|
||||||
|
pure (Just msg)
|
||||||
|
|
||||||
|
Just k -> runMaybeT $
|
||||||
|
-- А будем-ка мы просто передавать сообщение дальше как есть, если не смогли расшифровать
|
||||||
|
(<|> (do
|
||||||
|
|
||||||
|
liftIO $ _proxy_clearEncryptionKey bus whom
|
||||||
|
|
||||||
|
liftIO $ _proxy_sendResetEncryptionKeys bus whom
|
||||||
|
|
||||||
|
trace $ "ENCRYPTION RECEIVE: got plain message. clearing key of" <+> pretty whom
|
||||||
|
pure msg
|
||||||
|
)) $
|
||||||
|
do
|
||||||
|
trace $ "ENCRYPTION RECEIVE: we have a key to decode from" <+> pretty whom <+> ":" <+> viaShow k
|
||||||
|
case ((extractNonce . cs) msg) of
|
||||||
|
Nothing -> do
|
||||||
|
trace $ "ENCRYPTION RECEIVE: can not extract nonce from" <+> pretty whom <+> "message" <+> viaShow msg
|
||||||
|
fail ""
|
||||||
|
|
||||||
|
Just (nonce, msg') ->
|
||||||
|
((MaybeT . pure) (boxOpenAfterNMLazy k nonce msg')
|
||||||
|
<* (trace $ "ENCRYPTION RECEIVE: message successfully decoded from" <+> pretty whom)
|
||||||
|
)
|
||||||
|
<|>
|
||||||
|
(do
|
||||||
|
(trace $ "ENCRYPTION RECEIVE: can not decode message from" <+> pretty whom)
|
||||||
|
fail ""
|
||||||
|
|
||||||
|
-- -- Попытаться десериализовать сообщение как PeerPing или PeerPingCrypted
|
||||||
|
-- case deserialiseOrFail msg of
|
||||||
|
-- Right (_ :: PeerHandshake L4Proto) -> do
|
||||||
|
-- trace $ "ENCRYPTION RECEIVE: plain message decoded as PeerHandshake" <+> pretty whom
|
||||||
|
-- fail ""
|
||||||
|
-- Left _ -> do
|
||||||
|
-- trace $ "ENCRYPTION RECEIVE: failed" <+> pretty whom
|
||||||
|
-- mzero
|
||||||
|
|
||||||
|
)
|
||||||
|
|
|
@ -57,6 +57,7 @@ data RPCCommand =
|
||||||
| CHECK PeerNonce (PeerAddr L4Proto) (Hash HbSync)
|
| CHECK PeerNonce (PeerAddr L4Proto) (Hash HbSync)
|
||||||
| FETCH (Hash HbSync)
|
| FETCH (Hash HbSync)
|
||||||
| PEERS
|
| PEERS
|
||||||
|
| PEXINFO
|
||||||
| SETLOG SetLogging
|
| SETLOG SetLogging
|
||||||
| REFLOGUPDATE ByteString
|
| REFLOGUPDATE ByteString
|
||||||
| REFLOGFETCH (PubKey 'Sign (Encryption L4Proto))
|
| REFLOGFETCH (PubKey 'Sign (Encryption L4Proto))
|
||||||
|
@ -79,6 +80,8 @@ data RPC e =
|
||||||
| RPCFetch (Hash HbSync)
|
| RPCFetch (Hash HbSync)
|
||||||
| RPCPeers
|
| RPCPeers
|
||||||
| RPCPeersAnswer (PeerAddr e) (PubKey 'Sign (Encryption e))
|
| RPCPeersAnswer (PeerAddr e) (PubKey 'Sign (Encryption e))
|
||||||
|
| RPCPexInfo
|
||||||
|
| RPCPexInfoAnswer [PeerAddr L4Proto]
|
||||||
| RPCLogLevel SetLogging
|
| RPCLogLevel SetLogging
|
||||||
| RPCRefLogUpdate ByteString
|
| RPCRefLogUpdate ByteString
|
||||||
| RPCRefLogFetch (PubKey 'Sign (Encryption e))
|
| RPCRefLogFetch (PubKey 'Sign (Encryption e))
|
||||||
|
@ -98,6 +101,11 @@ data RPC e =
|
||||||
|
|
||||||
deriving stock (Generic)
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
deriving instance
|
||||||
|
( Show (PubKey 'Sign (Encryption e))
|
||||||
|
, Show (PeerAddr e)
|
||||||
|
) => Show (RPC e)
|
||||||
|
|
||||||
instance (Serialise (PeerAddr e), Serialise (PubKey 'Sign (Encryption e))) => Serialise (RPC e)
|
instance (Serialise (PeerAddr e), Serialise (PubKey 'Sign (Encryption e))) => Serialise (RPC e)
|
||||||
|
|
||||||
instance HasProtocol L4Proto (RPC L4Proto) where
|
instance HasProtocol L4Proto (RPC L4Proto) where
|
||||||
|
@ -127,6 +135,8 @@ data RpcAdapter e m =
|
||||||
, rpcOnFetch :: Hash HbSync -> m ()
|
, rpcOnFetch :: Hash HbSync -> m ()
|
||||||
, rpcOnPeers :: RPC e -> m ()
|
, rpcOnPeers :: RPC e -> m ()
|
||||||
, rpcOnPeersAnswer :: (PeerAddr e, PubKey 'Sign (Encryption e)) -> m ()
|
, rpcOnPeersAnswer :: (PeerAddr e, PubKey 'Sign (Encryption e)) -> m ()
|
||||||
|
, rpcOnPexInfo :: RPC e -> m ()
|
||||||
|
, rpcOnPexInfoAnswer :: [PeerAddr L4Proto] -> m ()
|
||||||
, rpcOnLogLevel :: SetLogging -> m ()
|
, rpcOnLogLevel :: SetLogging -> m ()
|
||||||
, rpcOnRefLogUpdate :: ByteString -> m ()
|
, rpcOnRefLogUpdate :: ByteString -> m ()
|
||||||
, rpcOnRefLogFetch :: PubKey 'Sign (Encryption e) -> m ()
|
, rpcOnRefLogFetch :: PubKey 'Sign (Encryption e) -> m ()
|
||||||
|
@ -194,6 +204,8 @@ rpcHandler adapter = \case
|
||||||
(RPCFetch h) -> rpcOnFetch adapter h
|
(RPCFetch h) -> rpcOnFetch adapter h
|
||||||
p@RPCPeers{} -> rpcOnPeers adapter p
|
p@RPCPeers{} -> rpcOnPeers adapter p
|
||||||
(RPCPeersAnswer pa k) -> rpcOnPeersAnswer adapter (pa,k)
|
(RPCPeersAnswer pa k) -> rpcOnPeersAnswer adapter (pa,k)
|
||||||
|
p@RPCPexInfo{} -> rpcOnPexInfo adapter p
|
||||||
|
(RPCPexInfoAnswer pa) -> rpcOnPexInfoAnswer adapter pa
|
||||||
(RPCLogLevel l) -> rpcOnLogLevel adapter l
|
(RPCLogLevel l) -> rpcOnLogLevel adapter l
|
||||||
(RPCRefLogUpdate bs) -> rpcOnRefLogUpdate adapter bs
|
(RPCRefLogUpdate bs) -> rpcOnRefLogUpdate adapter bs
|
||||||
(RPCRefLogFetch e) -> rpcOnRefLogFetch adapter e
|
(RPCRefLogFetch e) -> rpcOnRefLogFetch adapter e
|
||||||
|
|
|
@ -49,6 +49,7 @@ common common-deps
|
||||||
, stm
|
, stm
|
||||||
, streaming
|
, streaming
|
||||||
, sqlite-simple
|
, sqlite-simple
|
||||||
|
, time
|
||||||
, temporary
|
, temporary
|
||||||
, text
|
, text
|
||||||
, time
|
, time
|
||||||
|
@ -61,6 +62,7 @@ common common-deps
|
||||||
, filelock
|
, filelock
|
||||||
, ekg-core
|
, ekg-core
|
||||||
, scotty
|
, scotty
|
||||||
|
, string-conversions
|
||||||
, warp
|
, warp
|
||||||
, http-conduit
|
, http-conduit
|
||||||
, http-types
|
, http-types
|
||||||
|
@ -107,6 +109,8 @@ common shared-properties
|
||||||
, MultiParamTypeClasses
|
, MultiParamTypeClasses
|
||||||
, OverloadedStrings
|
, OverloadedStrings
|
||||||
, QuasiQuotes
|
, QuasiQuotes
|
||||||
|
, RecordWildCards
|
||||||
|
, RecursiveDo
|
||||||
, ScopedTypeVariables
|
, ScopedTypeVariables
|
||||||
, StandaloneDeriving
|
, StandaloneDeriving
|
||||||
, TupleSections
|
, TupleSections
|
||||||
|
@ -123,6 +127,7 @@ executable hbs2-peer
|
||||||
other-modules: BlockDownload
|
other-modules: BlockDownload
|
||||||
, BlockHttpDownload
|
, BlockHttpDownload
|
||||||
, DownloadQ
|
, DownloadQ
|
||||||
|
, EncryptionKeys
|
||||||
, Bootstrap
|
, Bootstrap
|
||||||
, PeerInfo
|
, PeerInfo
|
||||||
, PeerMeta
|
, PeerMeta
|
||||||
|
|
|
@ -548,6 +548,7 @@ main = join . customExecParser (prefs showHelpOnError) $
|
||||||
<> command "lref-update" (info pUpdateLRef (progDesc "updates a linear ref"))
|
<> command "lref-update" (info pUpdateLRef (progDesc "updates a linear ref"))
|
||||||
<> command "reflog" (info pReflog (progDesc "reflog commands"))
|
<> command "reflog" (info pReflog (progDesc "reflog commands"))
|
||||||
-- <> command "lref-del" (info pDelLRef (progDesc "removes a linear ref from node linear ref list"))
|
-- <> command "lref-del" (info pDelLRef (progDesc "removes a linear ref from node linear ref list"))
|
||||||
|
<> command "showpex" (info pReflog (progDesc "reflog commands"))
|
||||||
)
|
)
|
||||||
|
|
||||||
common = do
|
common = do
|
||||||
|
|
Loading…
Reference in New Issue