I want to write a PlutusTx validator which just checks if a transaction was signed by one of the whitelisted public keys.
This would be a first, naiive implementation:
-- | The whitelist used by 'signedByOneOfWhitelist'.
whitelist :: [PubKeyHash]
whitelist = []
-- | Check whether a transaction was signed by one of the 'whitelist' keys.
{-# INLINEABLE signedByOneOfWhitelist #-}
signedByOneOfWhitelist :: ScriptContext -> Bool
signedByOneOfWhitelist context =
any (`elem` whitelist) txInfoSignatories
where
TxInfo{txInfoSignatories} = txInfo
ScriptContext{scriptContextTxInfo = txInfo} = context
This works fine if I put this next to my validator
/ in the same module as `$$compile.
However, if I want to make this re-usable and put it into a dedicated module, say Whitelist
with the right imports import Whitelist (signedByOneOfWhitelist)
I get the following error by the plutus-tx compiler:
GHC Core to PLC plugin: E043:Error: Reference to a name which is not a local, a builtin, or an external INLINABLE function: Variable Whitelist.$s$fFoldable[]_$cfoldMap
No unfolding
Full gist for context: https://gist.github.com/ch1bo/a248087241a0a1690fba41936da45bc9
What am I doing wrong?
A workaround is to not use Foldable
by instantiating it and an explicit fold:
{-# INLINEABLE signedByOneOfWhitelist #-}
signedByOneOfWhitelist :: ScriptContext -> Bool
signedByOneOfWhitelist context =
myAny (`myElem` whitelist) txInfoSignatories
where
myAny :: (a -> Bool) -> [a] -> Bool
myAny fn = \case
[] -> False
(x : xs)
| fn x -> True
| otherwise -> myAny fn xs
myElem :: Eq a => a -> [a] -> Bool
myElem x = myAny (x ==)
TxInfo{txInfoSignatories} = txInfo
ScriptContext{scriptContextTxInfo = txInfo} = context