Compare commits
No commits in common. "4f20160c36c60f3df5a3d24c8e3711320e8cead2" and "30c3827cab1a55d5972245fb382a8c4ad9add999" have entirely different histories.
4f20160c36
...
30c3827cab
9 changed files with 155 additions and 227 deletions
|
@ -10,4 +10,4 @@ source-repository-package
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git
|
location: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git
|
||||||
tag: 39d8da7b11a80269454c2f134a5c834e0f3cb9a7
|
tag: fd1ddce73c0ad18a2a4509a299c6e93f8c6c383d
|
||||||
|
|
|
@ -99,7 +99,7 @@ constraints: any.Cabal ==3.8.1.0,
|
||||||
hashable +integer-gmp -random-initial-seed,
|
hashable +integer-gmp -random-initial-seed,
|
||||||
any.haskell-lexer ==1.1.1,
|
any.haskell-lexer ==1.1.1,
|
||||||
any.haskoin-core ==1.0.4,
|
any.haskoin-core ==1.0.4,
|
||||||
any.hexstring ==0.12.1.0,
|
any.hexstring ==0.12.0,
|
||||||
any.hourglass ==0.2.12,
|
any.hourglass ==0.2.12,
|
||||||
any.hsc2hs ==0.68.10,
|
any.hsc2hs ==0.68.10,
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
|
|
|
@ -641,7 +641,7 @@ pub extern "C" fn rust_wrapper_sapling_spendingkey(
|
||||||
let extsk_bytes = extsk.to_bytes().to_vec();
|
let extsk_bytes = extsk.to_bytes().to_vec();
|
||||||
marshall_to_haskell_var(&extsk_bytes, out, out_len, RW);
|
marshall_to_haskell_var(&extsk_bytes, out, out_len, RW);
|
||||||
} else {
|
} else {
|
||||||
let child_sk = extsk.derive_child(ChildIndex::from_index(ix + (1 << 31)));
|
let child_sk = extsk.derive_child(ChildIndex::from_index(ix));
|
||||||
marshall_to_haskell_var(&child_sk.to_bytes().to_vec(), out, out_len, RW);
|
marshall_to_haskell_var(&child_sk.to_bytes().to_vec(), out, out_len, RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -655,29 +655,16 @@ pub extern "C" fn rust_wrapper_sapling_paymentaddress(
|
||||||
out_len: &mut usize
|
out_len: &mut usize
|
||||||
){
|
){
|
||||||
let extspk: Vec<u8> = marshall_from_haskell_var(extspk, extspk_len, RW);
|
let extspk: Vec<u8> = marshall_from_haskell_var(extspk, extspk_len, RW);
|
||||||
if div_ix == 0 {
|
let expsk = ExpandedSpendingKey::from_spending_key(&extspk);
|
||||||
let sp_key = ExtendedSpendingKey::from_bytes(&extspk);
|
let fvk = SaplingFullViewingKey::from_expanded_spending_key(&expsk);
|
||||||
match sp_key {
|
let dk = DiversifierKey::master(&extspk);
|
||||||
Ok(sp_key_x) => {
|
let result = sapling_find_address(&fvk, &dk, DiversifierIndex::from(div_ix));
|
||||||
let (def_div, def_address) = sp_key_x.default_address();
|
match result {
|
||||||
marshall_to_haskell_var(&def_address.to_bytes().to_vec(), out, out_len, RW);
|
Some((_d, p_address)) => {
|
||||||
},
|
marshall_to_haskell_var(&p_address.to_bytes().to_vec(), out, out_len, RW);
|
||||||
Err(_e) => {
|
},
|
||||||
marshall_to_haskell_var(&vec![0], out, out_len, RW);
|
None => {
|
||||||
}
|
marshall_to_haskell_var(&vec![0], out, out_len, RW);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let expsk = ExpandedSpendingKey::from_spending_key(&extspk);
|
|
||||||
let fvk = SaplingFullViewingKey::from_expanded_spending_key(&expsk);
|
|
||||||
let dk = DiversifierKey::master(&extspk);
|
|
||||||
let result = sapling_find_address(&fvk, &dk, DiversifierIndex::from(div_ix));
|
|
||||||
match result {
|
|
||||||
Some((_d, p_address)) => {
|
|
||||||
marshall_to_haskell_var(&p_address.to_bytes().to_vec(), out, out_len, RW);
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
marshall_to_haskell_var(&vec![0], out, out_len, RW);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import C.Zcash
|
||||||
)
|
)
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Char8 as C
|
import qualified Data.ByteString.Char8 as C
|
||||||
import Data.HexString (fromRawBytes, toBytes)
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
import Data.Word
|
import Data.Word
|
||||||
|
@ -84,9 +83,9 @@ isValidUnifiedAddress str =
|
||||||
then Just (raw_s x)
|
then Just (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 whichNet (raw_t x)
|
||||||
else if not (BS.null (raw_to x))
|
else if not (BS.null (raw_to x))
|
||||||
then Just $ TransparentAddress P2SH (fromRawBytes $ raw_to x)
|
then Just $ TransparentAddress P2SH whichNet (raw_to x)
|
||||||
else Nothing)
|
else Nothing)
|
||||||
|
|
||||||
-- | Encode a 'UnifiedAddress' per [ZIP-316](https://zips.z.cash/zip-0316)
|
-- | Encode a 'UnifiedAddress' per [ZIP-316](https://zips.z.cash/zip-0316)
|
||||||
|
@ -103,8 +102,8 @@ encodeUnifiedAddress ua = encodeBech32m (E.encodeUtf8 hr) b
|
||||||
Nothing -> BS.empty
|
Nothing -> BS.empty
|
||||||
Just t ->
|
Just t ->
|
||||||
case ta_type t of
|
case ta_type t of
|
||||||
P2SH -> packReceiver 0x01 $ Just $ toBytes $ ta_bytes t
|
P2SH -> packReceiver 0x01 $ Just $ ta_bytes t
|
||||||
P2PKH -> packReceiver 0x00 $ Just $ toBytes $ ta_bytes t
|
P2PKH -> packReceiver 0x00 $ Just $ ta_bytes t
|
||||||
sReceiver = packReceiver 0x02 $ s_rec ua
|
sReceiver = packReceiver 0x02 $ s_rec ua
|
||||||
oReceiver = packReceiver 0x03 $ o_rec ua
|
oReceiver = packReceiver 0x03 $ o_rec ua
|
||||||
padding = E.encodeUtf8 $ T.justifyLeft 16 '\NUL' hr
|
padding = E.encodeUtf8 $ T.justifyLeft 16 '\NUL' hr
|
||||||
|
|
|
@ -106,15 +106,15 @@ genSaplingSpendingKey seed i = do
|
||||||
(rustWrapperSaplingSpendingkey seed (fromIntegral i))
|
(rustWrapperSaplingSpendingkey seed (fromIntegral i))
|
||||||
|
|
||||||
-- | Attempts to generate a sapling Payment Address using an ExtendedSpendingKey and a Diversifier Index
|
-- | Attempts to generate a sapling Payment Address using an ExtendedSpendingKey and a Diversifier Index
|
||||||
genSaplingPaymentAddress :: Int -> SaplingSpendingKey -> Maybe SaplingReceiver
|
genSaplingPaymentAddress :: SaplingSpendingKey -> Int -> Maybe SaplingReceiver
|
||||||
genSaplingPaymentAddress i extspk =
|
genSaplingPaymentAddress extspk i =
|
||||||
if BS.length res == 43
|
if BS.length res == 43
|
||||||
then Just res
|
then Just res
|
||||||
else Nothing
|
else Nothing
|
||||||
where
|
where
|
||||||
res =
|
res =
|
||||||
withPureBorshVarBuffer
|
withPureBorshVarBuffer
|
||||||
(rustWrapperSaplingPaymentAddress extspk (fromIntegral (i * 111)))
|
(rustWrapperSaplingPaymentAddress extspk (fromIntegral i))
|
||||||
|
|
||||||
-- | Generate an internal Sapling address
|
-- | Generate an internal Sapling address
|
||||||
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingInternalReceiver
|
genSaplingInternalAddress :: SaplingSpendingKey -> Maybe SaplingInternalReceiver
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
--
|
--
|
||||||
module ZcashHaskell.Transparent where
|
module ZcashHaskell.Transparent where
|
||||||
|
|
||||||
import Control.Exception (throwIO)
|
|
||||||
import Crypto.Hash
|
import Crypto.Hash
|
||||||
import qualified Data.ByteArray as BA
|
import qualified Data.ByteArray as BA
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.ByteString.Base58 (bitcoinAlphabet, encodeBase58)
|
import Data.ByteString.Base58 (bitcoinAlphabet, encodeBase58)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
|
import Data.Word
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
( TransparentAddress(..)
|
( TransparentAddress(..)
|
||||||
, TransparentType(..)
|
, TransparentType(..)
|
||||||
|
@ -29,17 +29,13 @@ import ZcashHaskell.Types
|
||||||
, getTransparentPrefix
|
, getTransparentPrefix
|
||||||
)
|
)
|
||||||
|
|
||||||
import Crypto.Secp256k1
|
|
||||||
import Data.HexString
|
|
||||||
import Data.Word
|
|
||||||
import Haskoin.Address (Address(..))
|
|
||||||
import qualified Haskoin.Crypto.Hash as H
|
|
||||||
import Haskoin.Crypto.Keys.Extended
|
import Haskoin.Crypto.Keys.Extended
|
||||||
|
import Data.Word
|
||||||
|
import Crypto.Secp256k1
|
||||||
|
|
||||||
encodeTransparent :: ZcashNet -> TransparentAddress -> T.Text
|
encodeTransparent :: TransparentAddress -> T.Text
|
||||||
encodeTransparent zNet t =
|
encodeTransparent t =
|
||||||
encodeTransparent' (getTransparentPrefix zNet (ta_type t)) $
|
encodeTransparent' (getTransparentPrefix (ta_net t) (ta_type t)) $ ta_bytes t
|
||||||
toBytes $ ta_bytes t
|
|
||||||
where
|
where
|
||||||
encodeTransparent' :: (Word8, Word8) -> BS.ByteString -> T.Text
|
encodeTransparent' :: (Word8, Word8) -> BS.ByteString -> T.Text
|
||||||
encodeTransparent' (a, b) h =
|
encodeTransparent' (a, b) h =
|
||||||
|
@ -51,22 +47,17 @@ encodeTransparent zNet t =
|
||||||
checksum = sha256 $ sha256 digest
|
checksum = sha256 $ sha256 digest
|
||||||
|
|
||||||
-- | Attempts to generate an Extended Private Key from a known HDSeed.
|
-- | Attempts to generate an Extended Private Key from a known HDSeed.
|
||||||
genTransparentPrvKey :: BS.ByteString -> XPrvKey
|
genTransparentPrvKey ::
|
||||||
|
BS.ByteString -> XPrvKey
|
||||||
genTransparentPrvKey hdseed = do
|
genTransparentPrvKey hdseed = do
|
||||||
makeXPrvKey hdseed
|
makeXPrvKey hdseed
|
||||||
|
|
||||||
-- | Attempts to obtain an Extended Public Key from a known Extended Private Key
|
-- | Attempts to obtain an Extended Public Key from a known Extended Private Key
|
||||||
genTransparentPubKey :: XPrvKey -> IO XPubKey
|
genTransparentPubKey ::
|
||||||
|
XPrvKey -> IO XPubKey
|
||||||
genTransparentPubKey xpvk = do
|
genTransparentPubKey xpvk = do
|
||||||
ioCtx <- createContext
|
ioCtx <- createContext
|
||||||
let xpubk = deriveXPubKey ioCtx xpvk
|
let xpubk = deriveXPubKey ioCtx xpvk
|
||||||
return xpubk
|
return xpubk
|
||||||
|
|
||||||
|
|
||||||
genTransparentReceiver :: XPubKey -> IO TransparentAddress
|
|
||||||
genTransparentReceiver xpubk = do
|
|
||||||
ioCtx <- createContext
|
|
||||||
let x = xPubAddr ioCtx xpubk
|
|
||||||
case x of
|
|
||||||
PubKeyAddress k -> return $ TransparentAddress P2PKH $ fromBinary k
|
|
||||||
ScriptAddress j -> return $ TransparentAddress P2SH $ fromBinary j
|
|
||||||
_anyOtherKind -> throwIO $ userError "Unsupported transparent address type"
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ import qualified Data.Text.Encoding as E
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import qualified GHC.Generics as GHC
|
import qualified GHC.Generics as GHC
|
||||||
import qualified Generics.SOP as SOP
|
import qualified Generics.SOP as SOP
|
||||||
import Haskoin.Address (Address)
|
|
||||||
|
|
||||||
-- * General
|
-- * General
|
||||||
--
|
--
|
||||||
|
@ -46,6 +45,21 @@ type Seed = C.ByteString
|
||||||
-- | A mnemonic phrase used to derive seeds
|
-- | A mnemonic phrase used to derive seeds
|
||||||
type Phrase = BS.ByteString
|
type Phrase = BS.ByteString
|
||||||
|
|
||||||
|
-- | A spending key for Sapling
|
||||||
|
type SaplingSpendingKey = BS.ByteString
|
||||||
|
|
||||||
|
-- | A spending key for Orchard
|
||||||
|
type OrchardSpendingKey = BS.ByteString
|
||||||
|
|
||||||
|
-- | A Sapling receiver
|
||||||
|
type SaplingReceiver = BS.ByteString
|
||||||
|
|
||||||
|
-- | A Sapling internal receiver
|
||||||
|
type SaplingInternalReceiver = BS.ByteString
|
||||||
|
|
||||||
|
-- | An Orchard receiver
|
||||||
|
type OrchardReceiver = BS.ByteString
|
||||||
|
|
||||||
-- | Type to represent data after Bech32 decoding
|
-- | Type to represent data after Bech32 decoding
|
||||||
data RawData = RawData
|
data RawData = RawData
|
||||||
{ hrp :: !BS.ByteString -- ^ Human-readable part of the Bech32 encoding
|
{ hrp :: !BS.ByteString -- ^ Human-readable part of the Bech32 encoding
|
||||||
|
@ -236,19 +250,11 @@ data TransparentType
|
||||||
-- | Type to represent a transparent Zcash addresses
|
-- | Type to represent a transparent Zcash addresses
|
||||||
data TransparentAddress = TransparentAddress
|
data TransparentAddress = TransparentAddress
|
||||||
{ ta_type :: !TransparentType
|
{ ta_type :: !TransparentType
|
||||||
, ta_bytes :: !HexString
|
, ta_net :: !ZcashNet
|
||||||
|
, ta_bytes :: !BS.ByteString
|
||||||
} deriving (Eq, Prelude.Show, Read)
|
} deriving (Eq, Prelude.Show, Read)
|
||||||
|
|
||||||
-- * Sapling
|
-- * Sapling
|
||||||
-- | A spending key for Sapling
|
|
||||||
type SaplingSpendingKey = BS.ByteString
|
|
||||||
|
|
||||||
-- | A Sapling receiver
|
|
||||||
type SaplingReceiver = BS.ByteString
|
|
||||||
|
|
||||||
-- | 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
|
||||||
|
@ -274,12 +280,6 @@ instance FromJSON ShieldedOutput where
|
||||||
pure $ ShieldedOutput cv cmu ephKey encText outText p
|
pure $ ShieldedOutput cv cmu ephKey encText outText p
|
||||||
|
|
||||||
-- * Orchard
|
-- * Orchard
|
||||||
-- | A spending key for Orchard
|
|
||||||
type OrchardSpendingKey = BS.ByteString
|
|
||||||
|
|
||||||
-- | An Orchard receiver
|
|
||||||
type OrchardReceiver = BS.ByteString
|
|
||||||
|
|
||||||
-- | Type to represent a Unified Address
|
-- | Type to represent a Unified Address
|
||||||
data UnifiedAddress = UnifiedAddress
|
data UnifiedAddress = UnifiedAddress
|
||||||
{ ua_net :: !ZcashNet
|
{ ua_net :: !ZcashNet
|
||||||
|
|
251
test/Spec.hs
251
test/Spec.hs
|
@ -66,7 +66,6 @@ import ZcashHaskell.Types
|
||||||
, ShieldedOutput(..)
|
, ShieldedOutput(..)
|
||||||
, UnifiedAddress(..)
|
, UnifiedAddress(..)
|
||||||
, UnifiedFullViewingKey(..)
|
, UnifiedFullViewingKey(..)
|
||||||
, ZcashNet(..)
|
|
||||||
, decodeHexText
|
, decodeHexText
|
||||||
, getValue
|
, getValue
|
||||||
)
|
)
|
||||||
|
@ -471,116 +470,18 @@ main = do
|
||||||
describe "Wallet seed phrase" $ do
|
describe "Wallet seed phrase" $ do
|
||||||
prop "Generated phrases are valid" $ again prop_PhraseLength
|
prop "Generated phrases are valid" $ again prop_PhraseLength
|
||||||
prop "Derived seeds are valid" $ again prop_SeedLength
|
prop "Derived seeds are valid" $ again prop_SeedLength
|
||||||
describe "Transparent Private and Public Key Generation" $ do
|
|
||||||
it "Obtain a transparent extended private key from HDSeed" $ do
|
|
||||||
let hdseed =
|
|
||||||
[ 206
|
|
||||||
, 61
|
|
||||||
, 120
|
|
||||||
, 38
|
|
||||||
, 206
|
|
||||||
, 40
|
|
||||||
, 201
|
|
||||||
, 62
|
|
||||||
, 83
|
|
||||||
, 175
|
|
||||||
, 151
|
|
||||||
, 131
|
|
||||||
, 218
|
|
||||||
, 141
|
|
||||||
, 206
|
|
||||||
, 254
|
|
||||||
, 28
|
|
||||||
, 244
|
|
||||||
, 172
|
|
||||||
, 213
|
|
||||||
, 128
|
|
||||||
, 248
|
|
||||||
, 156
|
|
||||||
, 45
|
|
||||||
, 204
|
|
||||||
, 44
|
|
||||||
, 169
|
|
||||||
, 3
|
|
||||||
, 162
|
|
||||||
, 188
|
|
||||||
, 16
|
|
||||||
, 173
|
|
||||||
, 192
|
|
||||||
, 164
|
|
||||||
, 96
|
|
||||||
, 148
|
|
||||||
, 91
|
|
||||||
, 52
|
|
||||||
, 244
|
|
||||||
, 83
|
|
||||||
, 149
|
|
||||||
, 169
|
|
||||||
, 82
|
|
||||||
, 196
|
|
||||||
, 199
|
|
||||||
, 53
|
|
||||||
, 177
|
|
||||||
, 170
|
|
||||||
, 1
|
|
||||||
, 6
|
|
||||||
, 0
|
|
||||||
, 120
|
|
||||||
, 170
|
|
||||||
, 2
|
|
||||||
, 238
|
|
||||||
, 219
|
|
||||||
, 241
|
|
||||||
, 243
|
|
||||||
, 172
|
|
||||||
, 178
|
|
||||||
, 104
|
|
||||||
, 81
|
|
||||||
, 159
|
|
||||||
, 144
|
|
||||||
] :: [Word8]
|
|
||||||
let xtpvk = genTransparentPrvKey (BS.pack hdseed)
|
|
||||||
let testpvk =
|
|
||||||
XPrvKey
|
|
||||||
0
|
|
||||||
"0000000000"
|
|
||||||
0
|
|
||||||
"fb5b9b89d3e9dfdebeaabd15de8fbc7e9a140b7f2de2b4034c2573425d39aceb"
|
|
||||||
"46aa0cd24a6e05709591426a4e682dd5406de4e75a39c0f410ee790403880943"
|
|
||||||
xtpvk `shouldBe` testpvk
|
|
||||||
it "Obtain a transparent extended public key from private key" $ do
|
|
||||||
let testpvk =
|
|
||||||
XPrvKey
|
|
||||||
0
|
|
||||||
"0000000000"
|
|
||||||
0
|
|
||||||
"fb5b9b89d3e9dfdebeaabd15de8fbc7e9a140b7f2de2b4034c2573425d39aceb"
|
|
||||||
"46aa0cd24a6e05709591426a4e682dd5406de4e75a39c0f410ee790403880943"
|
|
||||||
let testpbk =
|
|
||||||
XPubKey
|
|
||||||
0
|
|
||||||
"00000000"
|
|
||||||
0
|
|
||||||
"fb5b9b89d3e9dfdebeaabd15de8fbc7e9a140b7f2de2b4034c2573425d39aceb"
|
|
||||||
"279bda9c704f6da479cedb12c7cf773b3a348569dc1cfa6002526bad67674fd737b84a2bdb1199ecab1c9fed1b9a38aba5ba19259c1510d733a2376118515cd8"
|
|
||||||
let xtpubkIO = genTransparentPubKey testpvk
|
|
||||||
xtpubk <- xtpubkIO
|
|
||||||
---print $ show xtpubk
|
|
||||||
xtpubk `shouldBe` testpbk
|
|
||||||
before getSeed $
|
before getSeed $
|
||||||
describe "Optimized spending key tests" $ do
|
describe "Optimized spending key tests" $ do
|
||||||
it "Sapling spending keys are valid" $ \s ->
|
it "Sapling spending keys are valid" $ \s ->
|
||||||
property $ prop_SaplingSpendingKey s
|
property $ prop_SaplingSpendingKey s
|
||||||
it "Sapling receivers are valid" $ \s ->
|
it "Sapling receivers are valid" $ \s ->
|
||||||
property $ prop_SaplingReceiver s
|
property $ prop_SaplingReceiver s
|
||||||
it "Sapling receivers are distinct" $ \s ->
|
it "Sapling receivers are not the same" $ \s ->
|
||||||
property $ prop_SaplingRecRepeated s
|
property $ prop_SaplingRecRepeated s
|
||||||
it "Orchard spending keys are valid" $ \s ->
|
it "Orchard spending keys are valid" $ \s ->
|
||||||
property $ prop_OrchardSpendingKey s
|
property $ prop_OrchardSpendingKey s
|
||||||
it "Orchard receivers are valid" $ \s ->
|
it "Orchard receivers are valid" $ \s ->
|
||||||
property $ prop_OrchardReceiver s
|
property $ prop_OrchardReceiver s
|
||||||
it "Orchard receivers are distinct" $ \s ->
|
|
||||||
property $ prop_OrchardRecRepeated s
|
|
||||||
describe "Address tests" $ do
|
describe "Address tests" $ do
|
||||||
it "Encode transparent" $ do
|
it "Encode transparent" $ do
|
||||||
let ua =
|
let ua =
|
||||||
|
@ -588,48 +489,104 @@ main = do
|
||||||
let msg =
|
let msg =
|
||||||
case isValidUnifiedAddress ua of
|
case isValidUnifiedAddress ua of
|
||||||
Nothing -> "Bad UA"
|
Nothing -> "Bad UA"
|
||||||
Just u ->
|
Just u -> maybe "No transparent" encodeTransparent $ t_rec u
|
||||||
maybe "No transparent" (encodeTransparent (ua_net u)) $
|
|
||||||
t_rec u
|
|
||||||
msg `shouldBe` "t1LPWuQnjCRH7JAeEErSXKixcUteLJRJjKD"
|
msg `shouldBe` "t1LPWuQnjCRH7JAeEErSXKixcUteLJRJjKD"
|
||||||
it "Recover UA from YWallet" $
|
describe "Transparent Private and Public Key Generation" $ do
|
||||||
ioProperty $ do
|
it "Obtain a transparent extended private key from HDSeed" $ do
|
||||||
let p =
|
let hdseed =
|
||||||
"security expect junk hour people bind law hub between topic wink cliff spirit scissors auction idle figure option wide useful swift prison cushion round"
|
[ 206
|
||||||
let targetUA =
|
, 61
|
||||||
isValidUnifiedAddress
|
, 120
|
||||||
"u1qsylqauvnhw8tsfe3cldcsj3mjrfqzgaf3mt8yzlkjuvsf5wzj223yvrt8q66qukfqcc80x3z0mk6ym6pm2f0hukzkp6t4wj78h85t6kfr2u9mqsfhdd73g3sc7ezy2ut3rtq5jmejatwv4xqqd6l8tt9fycer8kdw0gz6e607nkssqsc7kd7nk2yfz2hpvpqhdg39wxalpjzhe34j7"
|
, 38
|
||||||
let s = getWalletSeed p
|
, 206
|
||||||
case s of
|
, 40
|
||||||
Nothing -> return $ expectationFailure "Failed to generate seed"
|
, 201
|
||||||
Just s' -> do
|
, 62
|
||||||
let oK = genOrchardSpendingKey s' MainNetCoin 0
|
, 83
|
||||||
let sK = genSaplingSpendingKey s' 0
|
, 175
|
||||||
let tK = genTransparentPrvKey s'
|
, 151
|
||||||
let oR = genOrchardReceiver 0 =<< oK
|
, 131
|
||||||
let sR = genSaplingPaymentAddress 0 =<< sK
|
, 218
|
||||||
tR <- genTransparentReceiver =<< genTransparentPubKey tK
|
, 141
|
||||||
let newUA = UnifiedAddress MainNet oR sR $ Just tR
|
, 206
|
||||||
return $ Just newUA `shouldBe` targetUA
|
, 254
|
||||||
it "Recover UA from Zingo" $
|
, 28
|
||||||
ioProperty $ do
|
, 244
|
||||||
let p =
|
, 172
|
||||||
"cloth swing left trap random tornado have great onion element until make shy dad success art tuition canvas thunder apple decade elegant struggle invest"
|
, 213
|
||||||
let targetUA =
|
, 128
|
||||||
isValidUnifiedAddress
|
, 248
|
||||||
"u1trd8cvc6265ywwj4mmvuznsye5ghe2dhhn3zy8kcuyg4vx3svskw9r2dedp5hu6m740vylkqc34t4w9eqkl9fyu5uyzn3af72jg235440ke6tu5cf994eq85n97x69x9824hqejmwz3d8qqthtesrd6gerjupdymldhl9xccejjwfj0dhh9mt4rw4kytp325twlutsxd20rfqhzxu3m"
|
, 156
|
||||||
let s = getWalletSeed p
|
, 45
|
||||||
case s of
|
, 204
|
||||||
Nothing -> return $ expectationFailure "Failed to generate seed"
|
, 44
|
||||||
Just s' -> do
|
, 169
|
||||||
let oK = genOrchardSpendingKey s' MainNetCoin 0
|
, 3
|
||||||
let sK = genSaplingSpendingKey s' 0
|
, 162
|
||||||
let tK = genTransparentPrvKey s'
|
, 188
|
||||||
let oR = genOrchardReceiver 0 =<< oK
|
, 16
|
||||||
let sR = genSaplingPaymentAddress 0 =<< sK
|
, 173
|
||||||
tR <- genTransparentReceiver =<< genTransparentPubKey tK
|
, 192
|
||||||
let newUA = UnifiedAddress MainNet oR sR $ Just tR
|
, 164
|
||||||
return $ Just newUA `shouldBe` targetUA
|
, 96
|
||||||
|
, 148
|
||||||
|
, 91
|
||||||
|
, 52
|
||||||
|
, 244
|
||||||
|
, 83
|
||||||
|
, 149
|
||||||
|
, 169
|
||||||
|
, 82
|
||||||
|
, 196
|
||||||
|
, 199
|
||||||
|
, 53
|
||||||
|
, 177
|
||||||
|
, 170
|
||||||
|
, 1
|
||||||
|
, 6
|
||||||
|
, 0
|
||||||
|
, 120
|
||||||
|
, 170
|
||||||
|
, 2
|
||||||
|
, 238
|
||||||
|
, 219
|
||||||
|
, 241
|
||||||
|
, 243
|
||||||
|
, 172
|
||||||
|
, 178
|
||||||
|
, 104
|
||||||
|
, 81
|
||||||
|
, 159
|
||||||
|
, 144
|
||||||
|
] :: [Word8]
|
||||||
|
let xtpvk = genTransparentPrvKey (BS.pack hdseed)
|
||||||
|
let testpvk =
|
||||||
|
XPrvKey
|
||||||
|
0
|
||||||
|
"0000000000"
|
||||||
|
0
|
||||||
|
"fb5b9b89d3e9dfdebeaabd15de8fbc7e9a140b7f2de2b4034c2573425d39aceb"
|
||||||
|
"46aa0cd24a6e05709591426a4e682dd5406de4e75a39c0f410ee790403880943"
|
||||||
|
xtpvk `shouldBe` testpvk
|
||||||
|
it "Obtain a transparent extended public key from private key" $ do
|
||||||
|
let testpvk =
|
||||||
|
XPrvKey
|
||||||
|
0
|
||||||
|
"0000000000"
|
||||||
|
0
|
||||||
|
"fb5b9b89d3e9dfdebeaabd15de8fbc7e9a140b7f2de2b4034c2573425d39aceb"
|
||||||
|
"46aa0cd24a6e05709591426a4e682dd5406de4e75a39c0f410ee790403880943"
|
||||||
|
let testpbk =
|
||||||
|
XPubKey
|
||||||
|
0
|
||||||
|
"00000000"
|
||||||
|
0
|
||||||
|
"fb5b9b89d3e9dfdebeaabd15de8fbc7e9a140b7f2de2b4034c2573425d39aceb"
|
||||||
|
"279bda9c704f6da479cedb12c7cf773b3a348569dc1cfa6002526bad67674fd737b84a2bdb1199ecab1c9fed1b9a38aba5ba19259c1510d733a2376118515cd8"
|
||||||
|
let xtpubkIO = genTransparentPubKey testpvk
|
||||||
|
xtpubk <- xtpubkIO
|
||||||
|
---print $ show xtpubk
|
||||||
|
xtpubk `shouldBe` testpbk
|
||||||
|
|
||||||
-- | Properties
|
-- | Properties
|
||||||
prop_PhraseLength :: Property
|
prop_PhraseLength :: Property
|
||||||
|
@ -660,19 +617,13 @@ prop_SaplingSpendingKey s (NonNegative i) =
|
||||||
|
|
||||||
prop_SaplingReceiver :: Seed -> NonNegative Int -> NonNegative Int -> Property
|
prop_SaplingReceiver :: Seed -> NonNegative Int -> NonNegative Int -> Property
|
||||||
prop_SaplingReceiver s (NonNegative i) (NonNegative j) =
|
prop_SaplingReceiver s (NonNegative i) (NonNegative j) =
|
||||||
genSaplingPaymentAddress i (fromMaybe "" $ genSaplingSpendingKey s j) =/=
|
genSaplingPaymentAddress (fromMaybe "" $ genSaplingSpendingKey s j) i =/=
|
||||||
Nothing
|
Nothing
|
||||||
|
|
||||||
prop_SaplingRecRepeated :: Seed -> NonNegative Int -> Property
|
prop_SaplingRecRepeated :: Seed -> NonNegative Int -> Property
|
||||||
prop_SaplingRecRepeated s (NonNegative i) =
|
prop_SaplingRecRepeated s (NonNegative i) =
|
||||||
genSaplingPaymentAddress i (fromMaybe "" $ genSaplingSpendingKey s 1) =/=
|
genSaplingPaymentAddress (fromMaybe "" $ genSaplingSpendingKey s 1) i =/=
|
||||||
genSaplingPaymentAddress (i + 1) (fromMaybe "" $ genSaplingSpendingKey s 1)
|
genSaplingPaymentAddress (fromMaybe "" $ genSaplingSpendingKey s 1) (i + 1)
|
||||||
|
|
||||||
prop_OrchardRecRepeated ::
|
|
||||||
Seed -> CoinType -> NonNegative Int -> NonNegative Int -> Property
|
|
||||||
prop_OrchardRecRepeated s c (NonNegative i) (NonNegative j) =
|
|
||||||
genOrchardReceiver j (fromMaybe "" $ genOrchardSpendingKey s c i) =/=
|
|
||||||
genOrchardReceiver (j + 1) (fromMaybe "" $ genOrchardSpendingKey s c i)
|
|
||||||
|
|
||||||
-- | Generators
|
-- | Generators
|
||||||
genOrcArgs :: Gen (CoinType, Int, Int)
|
genOrcArgs :: Gen (CoinType, Int, Int)
|
||||||
|
|
|
@ -51,7 +51,7 @@ library
|
||||||
, cryptonite
|
, cryptonite
|
||||||
, foreign-rust
|
, foreign-rust
|
||||||
, generics-sop
|
, generics-sop
|
||||||
, hexstring >=0.12.1
|
, hexstring >=0.12
|
||||||
, http-conduit
|
, http-conduit
|
||||||
, memory
|
, memory
|
||||||
, text
|
, text
|
||||||
|
@ -72,7 +72,7 @@ test-suite zcash-haskell-test
|
||||||
, base >=4.7 && <5
|
, base >=4.7 && <5
|
||||||
, bytestring
|
, bytestring
|
||||||
, haskoin-core
|
, haskoin-core
|
||||||
, hexstring >= 0.12.1
|
, hexstring
|
||||||
, hspec
|
, hspec
|
||||||
, QuickCheck
|
, QuickCheck
|
||||||
, quickcheck-transformer
|
, quickcheck-transformer
|
||||||
|
|
Loading…
Reference in a new issue