diff --git a/CHANGELOG.md b/CHANGELOG.md index 8247aeb..fa7d323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.5.5.0] +### Added + - Added unction to decode Transparent Address in Human Readable Format -- TransparentAddress type refactored -- TransparentReceiver added to replace old TransparentAddress -- sha256 Functionmoved outside of encodeTransparentReceiver + +### Changed + +- `TransparentAddress` type refactored +- `TransparentReceiver` added to replace old `TransparentAddress` +- `sha256` Function moved outside of `encodeTransparentReceiver` ## [0.5.4.0] diff --git a/src/ZcashHaskell/Transparent.hs b/src/ZcashHaskell/Transparent.hs index 5e49ad8..6689c08 100644 --- a/src/ZcashHaskell/Transparent.hs +++ b/src/ZcashHaskell/Transparent.hs @@ -20,12 +20,12 @@ import Crypto.Hash import Crypto.Secp256k1 import qualified Data.ByteArray as BA import qualified Data.ByteString as BS -import Data.ByteString.Base58 (bitcoinAlphabet, encodeBase58, decodeBase58) +import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58) +import Data.Char (chr) import Data.HexString import qualified Data.Text as T import qualified Data.Text.Encoding as E import Data.Word -import Data.Char (chr) import Haskoin.Address (Address(..)) import qualified Haskoin.Crypto.Hash as H import Haskoin.Crypto.Keys.Extended @@ -35,8 +35,8 @@ import ZcashHaskell.Types , Scope(..) , Seed(..) , ToBytes(..) - , TransparentReceiver(..) , TransparentAddress(..) + , TransparentReceiver(..) , TransparentSpendingKey(..) , TransparentType(..) , ZcashNet(..) @@ -101,31 +101,44 @@ genTransparentReceiver i scope xprvk = do -- } decode a Transparent Address in HRF and return a TransparentAddress object decodeTransparentAddress :: BS.ByteString -> Maybe TransparentAddress decodeTransparentAddress taddress = do - if BS.length taddress < 34 + if BS.length taddress < 34 then Nothing -- Not a valid transparent address - else do - let maybeDecoded = decodeBase58 bitcoinAlphabet taddress - case maybeDecoded of - Nothing -> Nothing - Just decoded -> do + else do + let maybeDecoded = decodeBase58 bitcoinAlphabet taddress + case maybeDecoded of + Nothing -> Nothing + Just decoded -> do let digest = BS.take 22 decoded let chksum = BS.drop 22 decoded let chksumd = BS.take 4 (sha256 $ sha256 digest) - if chksum /= chksum + if chksum /= chksumd then Nothing -- Invalid address ( invalid checksum ) - else do -- build the TransparentAddress Object + else do let addressType = BS.take 2 digest let transparentReceiver = BS.drop 2 digest let fb = BS.index addressType 0 - let sb = BS.index addressType 1 + let sb = BS.index addressType 1 case fb of - 28 -> case sb of - 189 -> Just $ TransparentAddress MainNet $ TransparentReceiver P2SH (fromRawBytes digest) - 186 -> Just $ TransparentAddress TestNet $ TransparentReceiver P2SH (fromRawBytes digest) - 184 -> Just $ TransparentAddress MainNet $ TransparentReceiver P2PKH (fromRawBytes digest) - _ -> Nothing - 29 -> if sb == 37 - then Just $ TransparentAddress TestNet $ TransparentReceiver P2PKH (fromRawBytes digest) - else Nothing - _ -> Nothing + 28 -> + case sb of + 189 -> + Just $ + TransparentAddress MainNet $ + TransparentReceiver P2SH (fromRawBytes digest) + 186 -> + Just $ + TransparentAddress TestNet $ + TransparentReceiver P2SH (fromRawBytes digest) + 184 -> + Just $ + TransparentAddress MainNet $ + TransparentReceiver P2PKH (fromRawBytes digest) + _ -> Nothing + 29 -> + if sb == 37 + then Just $ + TransparentAddress TestNet $ + TransparentReceiver P2PKH (fromRawBytes digest) + else Nothing + _ -> Nothing diff --git a/test/Spec.hs b/test/Spec.hs index 5abff0a..60625e0 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -77,9 +77,9 @@ import ZcashHaskell.Types , Seed(..) , ShieldedOutput(..) , ToBytes(..) - , TransparentReceiver(..) , TransparentAddress(..) , TransparentBundle(..) + , TransparentReceiver(..) , TransparentType(..) , UnifiedAddress(..) , UnifiedFullViewingKey(..) @@ -846,22 +846,41 @@ main = do print tb show tb `shouldNotBe` "" describe "Extract Sapling Address - UA Valid" $ do - let sr = getSaplingFromUA "u14a5c4ufn9feqvxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l" + let sr = + getSaplingFromUA + "u14a5c4ufn9feqvxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l" it "Extract sapling address" $ do - case sr of - Nothing -> assertFailure "UA invalid or does not contain a Sapling receiver" + case sr of + Nothing -> + assertFailure "UA invalid or does not contain a Sapling receiver" Just t -> do - print t - t `shouldBe` "zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60" + print t + t `shouldBe` + "zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60" describe "Extract Sapling Address - UA Invalid" $ do - let sr = getSaplingFromUA "u14a5c4ufn9qfevxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l" + let sr = + getSaplingFromUA + "u14a5c4ufn9qfevxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l" it "Try to extract sapling address from invalid UA" $ do - sr `shouldBe` Nothing + sr `shouldBe` Nothing describe "Decode a Transparent Address" $ do let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e" it "Try to decode a valid Transparent Address" $ do print ta ta `shouldNotBe` Nothing + it "Encode and decode should be the same" $ do + let ua = + "u17n7hpwaujyq7ux8f9jpyymtnk5urw7pyrf60smp5mawy7jgz325hfvz3jn3zsfya8yxryf9q7ldk8nu8df0emra5wne28zq9d9nm2pu4x6qwjha565av9aze0xgujgslz74ufkj0c0cylqwjyrh9msjfh7jzal6d3qzrnhkkqy3pqm8j63y07jxj7txqeac982778rmt64f32aum94x" + case isValidUnifiedAddress ua of + Nothing -> assertFailure "Bad UA" + Just u -> do + let tAdd = + maybe + "No transparent" + (encodeTransparentReceiver (ua_net u)) $ + t_rec u + (ta_receiver <$> decodeTransparentAddress (E.encodeUtf8 tAdd)) `shouldBe` + t_rec u -- | Properties prop_PhraseLength :: Property diff --git a/zcash-haskell.cabal b/zcash-haskell.cabal index 2e0cae2..8d16f53 100644 --- a/zcash-haskell.cabal +++ b/zcash-haskell.cabal @@ -5,7 +5,7 @@ cabal-version: 3.0 -- see: https://github.com/sol/hpack name: zcash-haskell -version: 0.5.4.0 +version: 0.5.5.0 synopsis: Utilities to interact with the Zcash blockchain description: Please see the README on the repo at category: Blockchain