-
Notifications
You must be signed in to change notification settings - Fork 214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add goldens for singleAddressFromKey #433
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE OverloadedLabels #-} | ||
{-# LANGUAGE RankNTypes #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
{-# LANGUAGE TypeApplications #-} | ||
|
||
module Cardano.Wallet.Jormungandr.BinarySpec (spec) where | ||
|
@@ -25,11 +26,18 @@ import Cardano.Wallet.Jormungandr.Binary | |
, singleAddressFromKey | ||
) | ||
import Cardano.Wallet.Jormungandr.Compatibility | ||
( genesis ) | ||
( Jormungandr, genesis ) | ||
import Cardano.Wallet.Jormungandr.Environment | ||
( Network (..) ) | ||
import Cardano.Wallet.Primitive.Types | ||
( Address (..), Coin (..), Hash (..), SlotId (..), Tx (..), TxOut (..) ) | ||
( Address (..) | ||
, Coin (..) | ||
, EncodeAddress (..) | ||
, Hash (..) | ||
, SlotId (..) | ||
, Tx (..) | ||
, TxOut (..) | ||
) | ||
import Control.Exception | ||
( evaluate ) | ||
import Data.ByteArray.Encoding | ||
|
@@ -44,11 +52,15 @@ import Data.Proxy | |
( Proxy (..) ) | ||
import Data.Quantity | ||
( Quantity (..) ) | ||
import Data.Text | ||
( Text ) | ||
import Test.Hspec | ||
( Spec, anyErrorCall, describe, it, runIO, shouldBe, shouldThrow ) | ||
|
||
import qualified Codec.Binary.Bech32 as Bech32 | ||
import qualified Data.ByteString as BS | ||
import qualified Data.ByteString.Lazy as BL | ||
import qualified Data.Text as T | ||
|
||
{-# ANN spec ("HLint: ignore Use head" :: String) #-} | ||
spec :: Spec | ||
|
@@ -90,8 +102,59 @@ spec = do | |
it "throws when length (key) != 32" $ | ||
evaluate (singleAddressFromKey (Proxy @'Mainnet) (XPub "\148" cc)) | ||
`shouldThrow` anyErrorCall | ||
describe "keyToAddress is consistent with jcli" $ do | ||
-- The goldens have been verified with jcli as follows: | ||
-- $ jcli key generate --type=Ed25519 | jcli key to-public | ||
-- ed25519_pk1yv0er3wlzvcauqj470tesdlcwy4dll9w7cvsvn4q30678gh44tnsxdh75c | ||
-- $ jcli address single ed25519_pk1yv0er3wlzvcauqj470tesdlcwy4dll9w7cvsvn4q30678gh44tnsxdh75c --testing | ||
-- ta1sv33lyw9mufnrhsz2hea0xphlpcj4hlu4mmpjpjw5z9ltcaz7k4wwywkd6j | ||
-- $ jcli address single ed25519_pk1yv0er3wlzvcauqj470tesdlcwy4dll9w7cvsvn4q30678gh44tnsxdh75c | ||
-- ca1qv33lyw9mufnrhsz2hea0xphlpcj4hlu4mmpjpjw5z9ltcaz7k4ww0xfchg | ||
|
||
bech32KeyToAddrGolden | ||
"ed25519_pk1yv0er3wlzvcauqj470tesdlcwy4dll9w7cvsvn4q30678gh44tnsxdh75c" | ||
"ta1sv33lyw9mufnrhsz2hea0xphlpcj4hlu4mmpjpjw5z9ltcaz7k4wwywkd6j" | ||
"ca1qv33lyw9mufnrhsz2hea0xphlpcj4hlu4mmpjpjw5z9ltcaz7k4ww0xfchg" | ||
|
||
bech32KeyToAddrGolden | ||
"ed25519_pk1gf85kgfspqzgz9mvmral4e8zatg6d64ep3gk223fla09parjm7zqf4xy3n" | ||
"ta1sdpy7jepxqyqfqghdnv0h7hyut4drfh2hyx9zef298l4u585wt0cgmkm96t" | ||
"ca1qdpy7jepxqyqfqghdnv0h7hyut4drfh2hyx9zef298l4u585wt0cgs7ysh3" | ||
|
||
bech32KeyToAddrGolden | ||
"ed25519_pk16cwyfh3jy6ls8ypfpen8pk55d3ufkp9793xc96u32rl83uuv89nsxsnnhg" | ||
"ta1s0tpc3x7xgnt7qus9y8xvux6j3k83xcyhckymqhtj9g0u78n3sukwk7ku9u" | ||
"ca1q0tpc3x7xgnt7qus9y8xvux6j3k83xcyhckymqhtj9g0u78n3sukwakffgx" | ||
|
||
bech32KeyToAddrGolden | ||
:: Text | ||
-- ^ public key ("ed25519_pk...") | ||
-> Text | ||
-- ^ corresponding testnet address ("ta...") | ||
-> Text | ||
-- ^ corresponding mainnet address ("ca...") | ||
-> Spec | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reasoning for using
|
||
bech32KeyToAddrGolden key testnetAddr mainnetAddr = it msg $ do | ||
let xpub = XPub decodeBech32Key cc | ||
encodeAddress (Proxy @(Jormungandr 'Testnet)) | ||
(singleAddressFromKey (Proxy @'Testnet) xpub) `shouldBe` testnetAddr | ||
encodeAddress (Proxy @(Jormungandr 'Mainnet)) | ||
(singleAddressFromKey (Proxy @'Mainnet) xpub) `shouldBe` mainnetAddr | ||
|
||
where | ||
cc = ChainCode "<ChainCode is not used by singleAddressToKey>" | ||
msg = T.unpack key ++ " generates correct testnet and mainnet addresses" | ||
decodeBech32Key :: ByteString | ||
decodeBech32Key = | ||
let | ||
(hrp', dp) = either (error . show) id (Bech32.decodeLenient key) | ||
hrp = T.unpack $ Bech32.humanReadablePartToText hrp' | ||
in | ||
if hrp == "ed25519_pk" | ||
then maybe (error "invalid bech32") id (Bech32.dataPartToBytes dp) | ||
else error $ "failed to decode key: " ++ hrp ++ " is not ed25519_pk" | ||
|
||
cc :: ChainCode | ||
cc = ChainCode "<ChainCode shouldn't be used by keyToAddress>" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that these looks quite redundant with: Or am I missing something 🤔 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :s #435 |
||
|
||
genesisHeader :: BlockHeader | ||
genesisHeader = BlockHeader | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A caveat is that it is unreadable if you don't know of the meaning of the human readable parts.
A benefit from passing in
Text
directly is thatbech32KeyToAddrGolden
has more control, and can output the key in bech32 format despite there being no encodeBech32Key.Maybe we should add
encode/decodeBech32Key
inAddressDerivation
… 🤔There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make things more readable without impeding too much on the flexibility, you may use a record type and use record fields at the call-site 👍