Improve type safety for Orchard
This commit is contained in:
parent
d2619123c0
commit
4cc4c37960
4 changed files with 35 additions and 16 deletions
|
@ -41,7 +41,7 @@ genOrchardSpendingKey ::
|
||||||
genOrchardSpendingKey s coinType accountId =
|
genOrchardSpendingKey s coinType accountId =
|
||||||
if BS.length k /= 32
|
if BS.length k /= 32
|
||||||
then Nothing
|
then Nothing
|
||||||
else Just k
|
else Just $ OrchardSpendingKey k
|
||||||
where
|
where
|
||||||
k =
|
k =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
|
@ -56,11 +56,14 @@ genOrchardReceiver ::
|
||||||
genOrchardReceiver i scope osk =
|
genOrchardReceiver i scope osk =
|
||||||
if BS.length k /= 43
|
if BS.length k /= 43
|
||||||
then Nothing
|
then Nothing
|
||||||
else Just k
|
else Just $ OrchardReceiver k
|
||||||
where
|
where
|
||||||
k =
|
k =
|
||||||
withPureBorshVarBuffer $
|
withPureBorshVarBuffer $
|
||||||
rustWrapperGenOrchardReceiver osk (fromIntegral i) (scope == External)
|
rustWrapperGenOrchardReceiver
|
||||||
|
(getBytes osk)
|
||||||
|
(fromIntegral i)
|
||||||
|
(scope == External)
|
||||||
|
|
||||||
-- | Checks if given bytestring is a valid encoded unified address
|
-- | Checks if given bytestring is a valid encoded unified address
|
||||||
isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress
|
isValidUnifiedAddress :: BS.ByteString -> Maybe UnifiedAddress
|
||||||
|
@ -79,10 +82,10 @@ isValidUnifiedAddress str =
|
||||||
UnifiedAddress
|
UnifiedAddress
|
||||||
whichNet
|
whichNet
|
||||||
(if BS.length (raw_o x) == 43
|
(if BS.length (raw_o x) == 43
|
||||||
then Just (raw_o x)
|
then Just $ OrchardReceiver (raw_o x)
|
||||||
else Nothing)
|
else Nothing)
|
||||||
(if BS.length (raw_s x) == 43
|
(if BS.length (raw_s x) == 43
|
||||||
then Just (SaplingReceiver $ raw_s x)
|
then Just $ SaplingReceiver (raw_s x)
|
||||||
else Nothing)
|
else Nothing)
|
||||||
(if not (BS.null (raw_t x))
|
(if not (BS.null (raw_t x))
|
||||||
then Just $ TransparentAddress P2PKH (fromRawBytes $ raw_t x)
|
then Just $ TransparentAddress P2PKH (fromRawBytes $ raw_t x)
|
||||||
|
@ -107,7 +110,7 @@ encodeUnifiedAddress ua = encodeBech32m (E.encodeUtf8 hr) b
|
||||||
P2SH -> packReceiver 0x01 $ Just $ toBytes $ ta_bytes t
|
P2SH -> packReceiver 0x01 $ Just $ toBytes $ ta_bytes t
|
||||||
P2PKH -> packReceiver 0x00 $ Just $ toBytes $ ta_bytes t
|
P2PKH -> packReceiver 0x00 $ Just $ toBytes $ ta_bytes t
|
||||||
sReceiver = packReceiver 0x02 $ getBytes <$> s_rec ua
|
sReceiver = packReceiver 0x02 $ getBytes <$> s_rec ua
|
||||||
oReceiver = packReceiver 0x03 $ o_rec ua
|
oReceiver = packReceiver 0x03 $ getBytes <$> o_rec ua
|
||||||
padding = E.encodeUtf8 $ T.justifyLeft 16 '\NUL' hr
|
padding = E.encodeUtf8 $ T.justifyLeft 16 '\NUL' hr
|
||||||
packReceiver :: Word8 -> Maybe BS.ByteString -> BS.ByteString
|
packReceiver :: Word8 -> Maybe BS.ByteString -> BS.ByteString
|
||||||
packReceiver typeCode receiver' =
|
packReceiver typeCode receiver' =
|
||||||
|
|
|
@ -40,7 +40,6 @@ import ZcashHaskell.Types
|
||||||
, DecodedNote(..)
|
, DecodedNote(..)
|
||||||
, RawData(..)
|
, RawData(..)
|
||||||
, RawTxResponse(..)
|
, RawTxResponse(..)
|
||||||
, SaplingInternalReceiver
|
|
||||||
, SaplingReceiver(..)
|
, SaplingReceiver(..)
|
||||||
, SaplingSpendingKey(..)
|
, SaplingSpendingKey(..)
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
|
@ -124,5 +123,5 @@ genSaplingPaymentAddress i extspk =
|
||||||
(fromIntegral (i * 111)))
|
(fromIntegral (i * 111)))
|
||||||
|
|
||||||
-- | Generate an internal Sapling address
|
-- | Generate an internal Sapling address
|
||||||
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingInternalReceiver
|
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingReceiver
|
||||||
genSaplingInternalAddress sk = undefined
|
genSaplingInternalAddress sk = undefined
|
||||||
|
|
|
@ -279,9 +279,6 @@ newtype SaplingReceiver =
|
||||||
instance ToBytes SaplingReceiver where
|
instance ToBytes SaplingReceiver where
|
||||||
getBytes (SaplingReceiver s) = s
|
getBytes (SaplingReceiver s) = s
|
||||||
|
|
||||||
-- | A Sapling internal receiver
|
|
||||||
type SaplingInternalReceiver = BS.ByteString
|
|
||||||
|
|
||||||
-- | Type to represent a Sapling Shielded Output as provided by the @getrawtransaction@ RPC method of @zcashd@.
|
-- | Type to represent a Sapling Shielded Output as provided by the @getrawtransaction@ RPC method of @zcashd@.
|
||||||
data ShieldedOutput = ShieldedOutput
|
data ShieldedOutput = ShieldedOutput
|
||||||
{ s_cv :: !HexString -- ^ Value commitment to the input note
|
{ s_cv :: !HexString -- ^ Value commitment to the input note
|
||||||
|
@ -308,10 +305,20 @@ instance FromJSON ShieldedOutput where
|
||||||
|
|
||||||
-- * Orchard
|
-- * Orchard
|
||||||
-- | A spending key for Orchard
|
-- | A spending key for Orchard
|
||||||
type OrchardSpendingKey = BS.ByteString
|
newtype OrchardSpendingKey =
|
||||||
|
OrchardSpendingKey BS.ByteString
|
||||||
|
deriving stock (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
instance ToBytes OrchardSpendingKey where
|
||||||
|
getBytes (OrchardSpendingKey o) = o
|
||||||
|
|
||||||
-- | An Orchard receiver
|
-- | An Orchard receiver
|
||||||
type OrchardReceiver = BS.ByteString
|
newtype OrchardReceiver =
|
||||||
|
OrchardReceiver BS.ByteString
|
||||||
|
deriving stock (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
|
instance ToBytes OrchardReceiver where
|
||||||
|
getBytes (OrchardReceiver o) = o
|
||||||
|
|
||||||
-- | Type to represent a Unified Address
|
-- | Type to represent a Unified Address
|
||||||
data UnifiedAddress = UnifiedAddress
|
data UnifiedAddress = UnifiedAddress
|
||||||
|
|
16
test/Spec.hs
16
test/Spec.hs
|
@ -57,6 +57,7 @@ import ZcashHaskell.Types
|
||||||
, CoinType
|
, CoinType
|
||||||
, DecodedNote(..)
|
, DecodedNote(..)
|
||||||
, OrchardAction(..)
|
, OrchardAction(..)
|
||||||
|
, OrchardSpendingKey(..)
|
||||||
, Phrase(..)
|
, Phrase(..)
|
||||||
, RawData(..)
|
, RawData(..)
|
||||||
, RawTxResponse(..)
|
, RawTxResponse(..)
|
||||||
|
@ -565,7 +566,10 @@ prop_OrchardSpendingKey s c (NonNegative i) =
|
||||||
prop_OrchardReceiver ::
|
prop_OrchardReceiver ::
|
||||||
Seed -> CoinType -> NonNegative Int -> NonNegative Int -> Scope -> Property
|
Seed -> CoinType -> NonNegative Int -> NonNegative Int -> Scope -> Property
|
||||||
prop_OrchardReceiver s c (NonNegative i) (NonNegative j) scope =
|
prop_OrchardReceiver s c (NonNegative i) (NonNegative j) scope =
|
||||||
genOrchardReceiver j scope (fromMaybe "" $ genOrchardSpendingKey s c i) =/=
|
genOrchardReceiver
|
||||||
|
j
|
||||||
|
scope
|
||||||
|
(fromMaybe (OrchardSpendingKey "") $ genOrchardSpendingKey s c i) =/=
|
||||||
Nothing
|
Nothing
|
||||||
|
|
||||||
prop_SaplingSpendingKey :: Seed -> CoinType -> NonNegative Int -> Property
|
prop_SaplingSpendingKey :: Seed -> CoinType -> NonNegative Int -> Property
|
||||||
|
@ -592,8 +596,14 @@ prop_SaplingRecRepeated s c (NonNegative i) =
|
||||||
prop_OrchardRecRepeated ::
|
prop_OrchardRecRepeated ::
|
||||||
Seed -> CoinType -> NonNegative Int -> NonNegative Int -> Scope -> Property
|
Seed -> CoinType -> NonNegative Int -> NonNegative Int -> Scope -> Property
|
||||||
prop_OrchardRecRepeated s c (NonNegative i) (NonNegative j) scope =
|
prop_OrchardRecRepeated s c (NonNegative i) (NonNegative j) scope =
|
||||||
genOrchardReceiver j scope (fromMaybe "" $ genOrchardSpendingKey s c i) =/=
|
genOrchardReceiver
|
||||||
genOrchardReceiver (j + 1) scope (fromMaybe "" $ genOrchardSpendingKey s c i)
|
j
|
||||||
|
scope
|
||||||
|
(fromMaybe (OrchardSpendingKey "") $ genOrchardSpendingKey s c i) =/=
|
||||||
|
genOrchardReceiver
|
||||||
|
(j + 1)
|
||||||
|
scope
|
||||||
|
(fromMaybe (OrchardSpendingKey "") $ genOrchardSpendingKey s c i)
|
||||||
|
|
||||||
prop_TransparentSpendingKey :: Seed -> NonNegative Int -> Property
|
prop_TransparentSpendingKey :: Seed -> NonNegative Int -> Property
|
||||||
prop_TransparentSpendingKey s (NonNegative i) =
|
prop_TransparentSpendingKey s (NonNegative i) =
|
||||||
|
|
Loading…
Reference in a new issue