smcdel-1.3.0: src/SMCDEL/Examples/DiningCrypto/General.hs
module SMCDEL.Examples.DiningCrypto.General where
import Data.List
import Data.Maybe
import SMCDEL.Language
import qualified SMCDEL.Symbolic.S5 as S5_CAC
import qualified SMCDEL.Symbolic.S5_CUDD as S5_CUDD
import qualified SMCDEL.Internal.MyHaskCUDD as MyHaskCUDD
import SMCDEL.Internal.MyHaskCUDD (makeManagerZ, Manager)
import qualified Data.HasCacBDD as S5_CAC
dcScnInit :: Int -> (Bool,Bool,Bool) -> S5_CAC.KnowScene
dcScnInit payer (b1,b2,b3) = ( S5_CAC.KnS props law obs , truths ) where
props = [ P 0 -- The NSA paid
, P 1 -- Alice paid
, P 2 -- Bob paid
, P 3 -- Charlie paid
, P 4 -- shared bit of Alice and Bob
, P 5 -- shared bit of Alice and Charlie
, P 6 ] -- shared bit of Bob and Charlie
law = S5_CAC.boolBddOf $ Conj [ someonepaid, notwopaid ]
obs = [ (show (1::Int),[P 1, P 4, P 5])
, (show (2::Int),[P 2, P 4, P 6])
, (show (3::Int),[P 3, P 5, P 6]) ]
truths = [ P payer ] ++ [ P 4 | b1 ] ++ [ P 5 | b2 ] ++ [ P 6 | b3 ]
dcScn1 :: S5_CAC.KnowScene
dcScn1 = dcScnInit 1 (True,True,False)
someonepaid, notwopaid :: Form
someonepaid = Disj (map (PrpF . P) [0..3])
notwopaid = Conj [ Neg $ Conj [ PrpF $ P x, PrpF $ P y ] | x<-[0..3], y<-[(x+1)..3] ]
reveal :: Int -> Form
reveal 1 = Xor (map PrpF [P 1, P 4, P 5])
reveal 2 = Xor (map PrpF [P 2, P 4, P 6])
reveal _ = Xor (map PrpF [P 3, P 5, P 6])
dcScn2 :: S5_CAC.KnowScene
dcScn2 = update dcScn1 (Conj [reveal 1, reveal 2, reveal 3])
everyoneKnowsWhetherNSApaid :: Form
everyoneKnowsWhetherNSApaid = Conj [ Kw (show i) (PrpF $ P 0) | i <- [1..3]::[Int] ]
nobodyknowsWhoPaid :: Form
nobodyknowsWhoPaid = Conj
[ Impl (PrpF (P 1)) (Conj [Neg $ K "2" (PrpF $ P 1), Neg $ K "3" (PrpF $ P 1) ])
, Impl (PrpF (P 2)) (Conj [Neg $ K "1" (PrpF $ P 2), Neg $ K "3" (PrpF $ P 2) ])
, Impl (PrpF (P 3)) (Conj [Neg $ K "1" (PrpF $ P 3), Neg $ K "2" (PrpF $ P 3) ]) ]
dcCheckForm :: Form
dcCheckForm = PubAnnounceW (reveal 1) $ PubAnnounceW (reveal 2) $ PubAnnounceW (reveal 3) $
Conj [ everyoneKnowsWhetherNSApaid, nobodyknowsWhoPaid ]
dcValid :: Bool
dcValid = S5_CAC.validViaBdd dcStruct dcCheckForm where (dcStruct,_) = dcScn1
-- * Generalised Dining Cryptographers (with n diners and m payers)
-- Creates a disjoint form where each term has n propositions in conjunction of which m are positive and n-m are negative.
-- All terms add up to all possible combinations of n choose m, giving a general XOR where m propositions have to be positive.
genXorM :: Int -> Int -> Form
genXorM n m = Disj
[ Conj
([PrpF (P p) | p <- x]
++ [Neg (PrpF (P i)) | i <- y])
| x <- select
, let y = [0 .. n] \\ x
]
where
select = combinations m [0 .. n]
combinations :: Int -> [a] -> [[a]]
combinations k ns = filter ((k==).length) $ subsequences ns
genDcEveryoneKnowsWhetherNSApaid :: Int -> Form
genDcEveryoneKnowsWhetherNSApaid n = Conj [ Kw (show i) (PrpF $ P 0) | i <- [1..n] ]
-- XOR between shared secret bits for agent i
genDcReveal :: Int -> Int -> Int -> Form
genDcReveal n m i = Xor (map PrpF ps) where
(S5_CAC.KnS _ _ obs) = genDcKnsInit n m
ps = fromJust $ lookup (show i) obs
genDcNobodyknowsWhoPaid :: Int -> Form
genDcNobodyknowsWhoPaid n =
Conj [ Impl (PrpF (P i)) (Conj [Neg $ K (show k) (PrpF $ P i) | k <- delete i [1..n] ]) | i <- [1..n] ]
genDcCheckForm :: Int -> Int -> Form
genDcCheckForm n m =
pubAnnounceWhetherStack [ genDcReveal n m i | i<-[1..n] ] $
Conj [ genDcEveryoneKnowsWhetherNSApaid n, genDcNobodyknowsWhoPaid n ]
genDcConclusion :: Int -> Form
genDcConclusion n =
Conj [ genDcEveryoneKnowsWhetherNSApaid n, genDcNobodyknowsWhoPaid n ]
genDcValid :: Int -> Int -> Bool
genDcValid n m = S5_CAC.validViaBdd (genDcKnsInit n m) (genDcCheckForm n m)
dcProtocolCac :: Int -> Int -> S5_CAC.Bdd
dcProtocolCac n m = S5_CAC.bddOf (genDcKnsInit n m) (Conj [ genDcEveryoneKnowsWhetherNSApaid n, genDcNobodyknowsWhoPaid n ])
-- | Initial knowledge structure for General Dining Cryptographers with a complete graph.
genDcKnsInit :: Int -> Int -> S5_CAC.KnowStruct
genDcKnsInit n m = S5_CAC.KnS props law obs where
props = [ P 0 ] -- The NSA paid
++ [ (P 1) .. (P n) ] -- agent i paid
++ sharedbits
law = S5_CAC.boolBddOf $ genXorM n m
obs = [ (show i, obsfor i) | i<-[1..n] ]
sharedbitLabels = [ [k,l] | k <- [1..n], l <- [1..n], k<l ] -- n(n-1)/2 shared bits
sharedbitRel = zip sharedbitLabels [ (P $ n+1) .. ]
sharedbits = map snd sharedbitRel
obsfor i = P i : map snd (filter (\(label,_) -> i `elem` label) sharedbitRel)
dcProtocolCudd :: MyHaskCUDD.DdCtx a b c => Int -> Int -> IO (MyHaskCUDD.Dd a b c)
dcProtocolCudd n m = do
startKns <- genDcKnsInitCudd n m
return $ S5_CUDD.ddOf startKns (Conj [ genDcEveryoneKnowsWhetherNSApaid n, genDcNobodyknowsWhoPaid n ])
genDcKnsInitCudd :: MyHaskCUDD.DdCtx a b c => Int -> Int -> IO (S5_CUDD.KnowStruct a b c)
genDcKnsInitCudd n m = makeManagerZ (maximum (map fromEnum props)) >>= \mgr -> do
let law = S5_CUDD.boolDdOf mgr $ genXorM n m
return $ S5_CUDD.KnS mgr props law obs
where
sharedbitLabels = [ [k,l] | k <- [1..n], l <- [1..n], k<l ] -- n(n-1)/2 shared bits
sharedbitRel = zip sharedbitLabels [ (P $ n+1) .. ]
sharedbits = map snd sharedbitRel
props = [ P 0 ] -- The NSA paid
++ [ (P 1) .. (P n) ] -- agent i paid
++ sharedbits
obsfor i = P i : map snd (filter (\(label,_) -> i `elem` label) sharedbitRel)
obs = [ (show i, obsfor i) | i<-[1..n] ]
mgrOf :: S5_CUDD.KnowStruct a b c -> Manager
mgrOf (S5_CUDD.KnS m _ _ _) = m