module Naming.Verify
( RetireEvidence (..)
, CompleteEvidence (..)
, positiveMintPolicy
, verifyRetireEvidence
, verifyCompletion
, singleNamingToken
) where
import Data.ByteString (ByteString)
import Naming.Register (representativeName)
singleNamingToken
:: [ByteString]
-> [(ByteString, ByteString, Integer)]
-> Either String (ByteString, Integer)
singleNamingToken :: [ByteString]
-> [(ByteString, ByteString, Integer)]
-> Either String (ByteString, Integer)
singleNamingToken [ByteString]
policies [(ByteString, ByteString, Integer)]
assets =
case [(ByteString, ByteString, Integer)]
assets of
[(ByteString
policy, ByteString
name, Integer
quantity)] | ByteString
policy ByteString -> [ByteString] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ByteString]
policies -> (ByteString, Integer) -> Either String (ByteString, Integer)
forall a b. b -> Either a b
Right (ByteString
name, Integer
quantity)
[(ByteString, ByteString, Integer)]
_ -> String -> Either String (ByteString, Integer)
forall a b. a -> Either a b
Left String
"record-single-asset"
data RetireEvidence = RetireEvidence
{ RetireEvidence -> String
reRecord :: String
, RetireEvidence -> String
reRetireTx :: String
, RetireEvidence -> ByteString
reKey :: ByteString
, RetireEvidence -> ByteString
reSpelling :: ByteString
, RetireEvidence -> ByteString
reCreationHash :: ByteString
, RetireEvidence -> ByteString
reCreationHashLog :: ByteString
, RetireEvidence -> ByteString
reCurrentControl :: ByteString
, RetireEvidence -> [ByteString]
reQuorum :: [ByteString]
, RetireEvidence -> ByteString
reStatePolicy :: ByteString
, RetireEvidence -> ByteString
reToken :: ByteString
, RetireEvidence -> [(ByteString, ByteString, Integer)]
reCreationMint :: [(ByteString, ByteString, Integer)]
, RetireEvidence -> ByteString
reCustodyPolicy :: ByteString
, RetireEvidence -> ByteString
reCustodyName :: ByteString
, RetireEvidence -> Integer
reCustodyQty :: Integer
, RetireEvidence -> ByteString
reRepLog :: ByteString
, RetireEvidence -> [ByteString]
reSigners :: [ByteString]
, RetireEvidence -> [ByteString]
reWitnesses :: [ByteString]
}
deriving stock (RetireEvidence -> RetireEvidence -> Bool
(RetireEvidence -> RetireEvidence -> Bool)
-> (RetireEvidence -> RetireEvidence -> Bool) -> Eq RetireEvidence
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RetireEvidence -> RetireEvidence -> Bool
== :: RetireEvidence -> RetireEvidence -> Bool
$c/= :: RetireEvidence -> RetireEvidence -> Bool
/= :: RetireEvidence -> RetireEvidence -> Bool
Eq, Int -> RetireEvidence -> String -> String
[RetireEvidence] -> String -> String
RetireEvidence -> String
(Int -> RetireEvidence -> String -> String)
-> (RetireEvidence -> String)
-> ([RetireEvidence] -> String -> String)
-> Show RetireEvidence
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> RetireEvidence -> String -> String
showsPrec :: Int -> RetireEvidence -> String -> String
$cshow :: RetireEvidence -> String
show :: RetireEvidence -> String
$cshowList :: [RetireEvidence] -> String -> String
showList :: [RetireEvidence] -> String -> String
Show)
positiveMintPolicy
:: [(ByteString, ByteString, Integer)] -> Either String ByteString
positiveMintPolicy :: [(ByteString, ByteString, Integer)] -> Either String ByteString
positiveMintPolicy [(ByteString, ByteString, Integer)]
triples = case [ByteString
p | (ByteString
p, ByteString
_, Integer
q) <- [(ByteString, ByteString, Integer)]
triples, Integer
q Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0] of
[ByteString
p] -> ByteString -> Either String ByteString
forall a b. b -> Either a b
Right ByteString
p
[ByteString]
ps ->
String -> Either String ByteString
forall a b. a -> Either a b
Left
( String
"expected exactly one positive mint policy, found "
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([ByteString] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
ps)
)
verifyRetireEvidence :: RetireEvidence -> Either String ()
verifyRetireEvidence :: RetireEvidence -> Either String ()
verifyRetireEvidence RetireEvidence
ev = do
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"retire spelling is not the creation request key"
(RetireEvidence -> ByteString
reKey RetireEvidence
ev)
(RetireEvidence -> ByteString
reSpelling RetireEvidence
ev)
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"claim-derived control differs from public creation material"
(RetireEvidence -> ByteString
reCreationHash RetireEvidence
ev)
(RetireEvidence -> ByteString
reCreationHashLog RetireEvidence
ev)
repPolicy <- [(ByteString, ByteString, Integer)] -> Either String ByteString
positiveMintPolicy (RetireEvidence -> [(ByteString, ByteString, Integer)]
reCreationMint RetireEvidence
ev)
let repComputed = ByteString -> ByteString
representativeName (RetireEvidence -> ByteString
reSpelling RetireEvidence
ev)
unlessEq
"creation mint does not carry the recomputed rep at +1"
[(n, q) | (p, n, q) <- reCreationMint ev, p == repPolicy]
[(repComputed, 1)]
unlessEq
"custody policy is not the derived rep policy"
(reCustodyPolicy ev)
repPolicy
unlessEq
"custody name is not the recomputed rep"
(reCustodyName ev)
repComputed
unlessEq "custody quantity is not 1" (reCustodyQty ev) 1
unlessEq
"recomputed rep differs from public creation material"
repComputed
(reRepLog ev)
case reSigners ev of
[ByteString
s] -> do
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"singleton signer is not the record control"
ByteString
s
(RetireEvidence -> ByteString
reCurrentControl RetireEvidence
ev)
RetireEvidence -> [ByteString] -> Either String ()
forall {t :: * -> *} {a}.
(Foldable t, IsString a) =>
RetireEvidence -> t ByteString -> Either a ()
unlessWitnessed RetireEvidence
ev [ByteString
s]
[ByteString]
ss -> do
String -> Int -> Int -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"signer count matches neither route"
([ByteString] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
ss)
([ByteString] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (RetireEvidence -> [ByteString]
reQuorum RetireEvidence
ev))
String -> [ByteString] -> [ByteString] -> Either String ()
forall {t :: * -> *} {t :: * -> *} {a} {a}.
(Foldable t, Foldable t, Eq a) =>
a -> t a -> t a -> Either a ()
unlessSubset String
"quorum-route signer outside the quorum" [ByteString]
ss (RetireEvidence -> [ByteString]
reQuorum RetireEvidence
ev)
String -> ByteString -> [ByteString] -> Either String ()
forall {t :: * -> *} {a} {a}.
(Foldable t, Eq a) =>
a -> a -> t a -> Either a ()
unlessAbsent
String
"quorum route signed by the controller"
(RetireEvidence -> ByteString
reCurrentControl RetireEvidence
ev)
[ByteString]
ss
RetireEvidence -> [ByteString] -> Either String ()
forall {t :: * -> *} {a}.
(Foldable t, IsString a) =>
RetireEvidence -> t ByteString -> Either a ()
unlessWitnessed RetireEvidence
ev [ByteString]
ss
where
unlessEq :: a -> a -> a -> Either a ()
unlessEq a
_ a
a a
b | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessEq a
msg a
_ a
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg
unlessSubset :: a -> t a -> t a -> Either a ()
unlessSubset a
_ t a
xs t a
ys | (a -> Bool) -> t a -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (a -> t a -> Bool
forall a. Eq a => a -> t a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` t a
ys) t a
xs = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessSubset a
msg t a
_ t a
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg
unlessAbsent :: a -> a -> t a -> Either a ()
unlessAbsent a
_ a
x t a
ys | a
x a -> t a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` t a
ys = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessAbsent a
msg a
_ t a
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg
unlessWitnessed :: RetireEvidence -> t ByteString -> Either a ()
unlessWitnessed RetireEvidence
e t ByteString
ss =
a -> t ByteString -> [ByteString] -> Either a ()
forall {t :: * -> *} {t :: * -> *} {a} {a}.
(Foldable t, Foldable t, Eq a) =>
a -> t a -> t a -> Either a ()
unlessSubset
a
"expected signer has no witness bytes"
t ByteString
ss
(RetireEvidence -> [ByteString]
reWitnesses RetireEvidence
e)
data CompleteEvidence = CompleteEvidence
{ CompleteEvidence -> String
ceRetireTx :: String
, CompleteEvidence -> String
ceCompleteTx :: String
, CompleteEvidence -> String
ceCustodyTxid :: String
, CompleteEvidence -> String
ceRequestTxid :: String
, CompleteEvidence -> ByteString
ceReqKey :: ByteString
, CompleteEvidence -> Integer
ceReqEdge :: Integer
, CompleteEvidence -> ByteString
ceRepPolicy :: ByteString
, CompleteEvidence -> ByteString
ceRepName :: ByteString
, CompleteEvidence -> ByteString
ceCustodyPolicy :: ByteString
, CompleteEvidence -> ByteString
ceCustodyName :: ByteString
, CompleteEvidence -> Integer
ceCustodyQty :: Integer
, CompleteEvidence -> [(ByteString, ByteString, Integer)]
ceMint :: [(ByteString, ByteString, Integer)]
, CompleteEvidence -> Bool
ceBurnRedeemerOk :: Bool
, CompleteEvidence -> Bool
ceIsModify :: Bool
, CompleteEvidence -> Int
ceActionCount :: Int
, CompleteEvidence -> ByteString
ceRootBefore :: ByteString
, CompleteEvidence -> ByteString
ceRootAfter :: ByteString
, CompleteEvidence -> [ByteString]
ceReqSigners :: [ByteString]
, CompleteEvidence -> [ByteString]
ceWitnesses :: [ByteString]
, CompleteEvidence -> ByteString
ceFeeOwner :: ByteString
, CompleteEvidence -> [ByteString]
ceRouteKeys :: [ByteString]
}
deriving stock (CompleteEvidence -> CompleteEvidence -> Bool
(CompleteEvidence -> CompleteEvidence -> Bool)
-> (CompleteEvidence -> CompleteEvidence -> Bool)
-> Eq CompleteEvidence
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CompleteEvidence -> CompleteEvidence -> Bool
== :: CompleteEvidence -> CompleteEvidence -> Bool
$c/= :: CompleteEvidence -> CompleteEvidence -> Bool
/= :: CompleteEvidence -> CompleteEvidence -> Bool
Eq, Int -> CompleteEvidence -> String -> String
[CompleteEvidence] -> String -> String
CompleteEvidence -> String
(Int -> CompleteEvidence -> String -> String)
-> (CompleteEvidence -> String)
-> ([CompleteEvidence] -> String -> String)
-> Show CompleteEvidence
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> CompleteEvidence -> String -> String
showsPrec :: Int -> CompleteEvidence -> String -> String
$cshow :: CompleteEvidence -> String
show :: CompleteEvidence -> String
$cshowList :: [CompleteEvidence] -> String -> String
showList :: [CompleteEvidence] -> String -> String
Show)
verifyCompletion :: CompleteEvidence -> Either String ()
verifyCompletion :: CompleteEvidence -> Either String ()
verifyCompletion CompleteEvidence
ev = do
String -> String -> String -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"folded request is not the retire's own (creator mismatch)"
(CompleteEvidence -> String
ceRequestTxid CompleteEvidence
ev)
(CompleteEvidence -> String
ceCustodyTxid CompleteEvidence
ev)
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"folded request is not for the burned asset's key"
(CompleteEvidence -> ByteString
ceReqKey CompleteEvidence
ev)
(CompleteEvidence -> ByteString
ceRepName CompleteEvidence
ev)
String -> Integer -> Integer -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"folded request does not name the retirement edge"
(CompleteEvidence -> Integer
ceReqEdge CompleteEvidence
ev)
Integer
3
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"spent custody policy is not the verified rep policy"
(CompleteEvidence -> ByteString
ceCustodyPolicy CompleteEvidence
ev)
(CompleteEvidence -> ByteString
ceRepPolicy CompleteEvidence
ev)
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"spent custody name is not the verified rep"
(CompleteEvidence -> ByteString
ceCustodyName CompleteEvidence
ev)
(CompleteEvidence -> ByteString
ceRepName CompleteEvidence
ev)
String -> Integer -> Integer -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq String
"spent custody quantity is not 1" (CompleteEvidence -> Integer
ceCustodyQty CompleteEvidence
ev) Integer
1
String
-> [(ByteString, ByteString, Integer)]
-> [(ByteString, ByteString, Integer)]
-> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"completion mint is not exactly the burn"
(CompleteEvidence -> [(ByteString, ByteString, Integer)]
ceMint CompleteEvidence
ev)
[(CompleteEvidence -> ByteString
ceRepPolicy CompleteEvidence
ev, CompleteEvidence -> ByteString
ceRepName CompleteEvidence
ev, -Integer
1)]
String -> Bool -> Either String ()
forall {a}. a -> Bool -> Either a ()
unlessOk String
"mint redeemer is not the burn shape" (CompleteEvidence -> Bool
ceBurnRedeemerOk CompleteEvidence
ev)
String -> Bool -> Either String ()
forall {a}. a -> Bool -> Either a ()
unlessOk String
"state spend is not a Modify" (CompleteEvidence -> Bool
ceIsModify CompleteEvidence
ev)
String -> Int -> Int -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq String
"Modify action is not a singleton" (CompleteEvidence -> Int
ceActionCount CompleteEvidence
ev) Int
1
String -> ByteString -> ByteString -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessNeq
String
"registry root unchanged (no genuine transition)"
(CompleteEvidence -> ByteString
ceRootBefore CompleteEvidence
ev)
(CompleteEvidence -> ByteString
ceRootAfter CompleteEvidence
ev)
String -> [ByteString] -> [ByteString] -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"required signers not empty (not permissionless)"
(CompleteEvidence -> [ByteString]
ceReqSigners CompleteEvidence
ev)
[]
String -> [ByteString] -> [ByteString] -> Either String ()
forall {a} {a}. Eq a => a -> a -> a -> Either a ()
unlessEq
String
"witness is not exactly the fee owner"
(CompleteEvidence -> [ByteString]
ceWitnesses CompleteEvidence
ev)
[CompleteEvidence -> ByteString
ceFeeOwner CompleteEvidence
ev]
String -> [ByteString] -> [ByteString] -> Either String ()
forall {t :: * -> *} {t :: * -> *} {a} {a}.
(Foldable t, Foldable t, Eq a) =>
a -> t a -> t a -> Either a ()
unlessAbsent
String
"route key witnessed the completion"
(CompleteEvidence -> [ByteString]
ceWitnesses CompleteEvidence
ev)
(CompleteEvidence -> [ByteString]
ceRouteKeys CompleteEvidence
ev)
where
unlessEq :: a -> a -> a -> Either a ()
unlessEq a
_ a
a a
b | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessEq a
msg a
_ a
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg
unlessNeq :: a -> a -> a -> Either a ()
unlessNeq a
_ a
a a
b | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
b = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessNeq a
msg a
_ a
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg
unlessOk :: a -> Bool -> Either a ()
unlessOk a
_ Bool
True = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessOk a
msg Bool
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg
unlessAbsent :: a -> t a -> t a -> Either a ()
unlessAbsent a
_ t a
xs t a
ys | (a -> Bool) -> t a -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (a -> t a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` t a
ys) t a
xs = () -> Either a ()
forall a b. b -> Either a b
Right ()
unlessAbsent a
msg t a
_ t a
_ = a -> Either a ()
forall a b. a -> Either a b
Left a
msg