Add new function to decode a Transparent Address in HRF #59
4 changed files with 70 additions and 33 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -7,10 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [0.5.5.0]
|
## [0.5.5.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
- Added unction to decode Transparent Address in Human Readable Format
|
- Added unction to decode Transparent Address in Human Readable Format
|
||||||
- TransparentAddress type refactored
|
|
||||||
- TransparentReceiver added to replace old TransparentAddress
|
### Changed
|
||||||
- sha256 Functionmoved outside of encodeTransparentReceiver
|
|
||||||
|
- `TransparentAddress` type refactored
|
||||||
|
- `TransparentReceiver` added to replace old `TransparentAddress`
|
||||||
|
- `sha256` Function moved outside of `encodeTransparentReceiver`
|
||||||
|
|
||||||
## [0.5.4.0]
|
## [0.5.4.0]
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@ import Crypto.Hash
|
||||||
import Crypto.Secp256k1
|
import Crypto.Secp256k1
|
||||||
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, decodeBase58)
|
import Data.ByteString.Base58 (bitcoinAlphabet, decodeBase58, encodeBase58)
|
||||||
|
import Data.Char (chr)
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
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
|
||||||
import Data.Char (chr)
|
|
||||||
import Haskoin.Address (Address(..))
|
import Haskoin.Address (Address(..))
|
||||||
import qualified Haskoin.Crypto.Hash as H
|
import qualified Haskoin.Crypto.Hash as H
|
||||||
import Haskoin.Crypto.Keys.Extended
|
import Haskoin.Crypto.Keys.Extended
|
||||||
|
@ -35,8 +35,8 @@ import ZcashHaskell.Types
|
||||||
, Scope(..)
|
, Scope(..)
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
, ToBytes(..)
|
, ToBytes(..)
|
||||||
, TransparentReceiver(..)
|
|
||||||
, TransparentAddress(..)
|
, TransparentAddress(..)
|
||||||
|
, TransparentReceiver(..)
|
||||||
, TransparentSpendingKey(..)
|
, TransparentSpendingKey(..)
|
||||||
, TransparentType(..)
|
, TransparentType(..)
|
||||||
, ZcashNet(..)
|
, ZcashNet(..)
|
||||||
|
@ -101,31 +101,44 @@ genTransparentReceiver i scope xprvk = do
|
||||||
-- } decode a Transparent Address in HRF and return a TransparentAddress object
|
-- } decode a Transparent Address in HRF and return a TransparentAddress object
|
||||||
decodeTransparentAddress :: BS.ByteString -> Maybe TransparentAddress
|
decodeTransparentAddress :: BS.ByteString -> Maybe TransparentAddress
|
||||||
decodeTransparentAddress taddress = do
|
decodeTransparentAddress taddress = do
|
||||||
if BS.length taddress < 34
|
if BS.length taddress < 34
|
||||||
then Nothing -- Not a valid transparent address
|
then Nothing -- Not a valid transparent address
|
||||||
else do
|
else do
|
||||||
let maybeDecoded = decodeBase58 bitcoinAlphabet taddress
|
let maybeDecoded = decodeBase58 bitcoinAlphabet taddress
|
||||||
case maybeDecoded of
|
case maybeDecoded of
|
||||||
Nothing -> Nothing
|
Nothing -> Nothing
|
||||||
Just decoded -> do
|
Just decoded -> do
|
||||||
let digest = BS.take 22 decoded
|
let digest = BS.take 22 decoded
|
||||||
let chksum = BS.drop 22 decoded
|
let chksum = BS.drop 22 decoded
|
||||||
let chksumd = BS.take 4 (sha256 $ sha256 digest)
|
let chksumd = BS.take 4 (sha256 $ sha256 digest)
|
||||||
if chksum /= chksum
|
if chksum /= chksumd
|
||||||
then Nothing -- Invalid address ( invalid checksum )
|
then Nothing -- Invalid address ( invalid checksum )
|
||||||
else do
|
|
||||||
-- build the TransparentAddress Object
|
-- build the TransparentAddress Object
|
||||||
|
else do
|
||||||
let addressType = BS.take 2 digest
|
let addressType = BS.take 2 digest
|
||||||
let transparentReceiver = BS.drop 2 digest
|
let transparentReceiver = BS.drop 2 digest
|
||||||
let fb = BS.index addressType 0
|
let fb = BS.index addressType 0
|
||||||
let sb = BS.index addressType 1
|
let sb = BS.index addressType 1
|
||||||
case fb of
|
case fb of
|
||||||
28 -> case sb of
|
28 ->
|
||||||
189 -> Just $ TransparentAddress MainNet $ TransparentReceiver P2SH (fromRawBytes digest)
|
case sb of
|
||||||
186 -> Just $ TransparentAddress TestNet $ TransparentReceiver P2SH (fromRawBytes digest)
|
189 ->
|
||||||
184 -> Just $ TransparentAddress MainNet $ TransparentReceiver P2PKH (fromRawBytes digest)
|
Just $
|
||||||
_ -> Nothing
|
TransparentAddress MainNet $
|
||||||
29 -> if sb == 37
|
TransparentReceiver P2SH (fromRawBytes digest)
|
||||||
then Just $ TransparentAddress TestNet $ TransparentReceiver P2PKH (fromRawBytes digest)
|
186 ->
|
||||||
else Nothing
|
Just $
|
||||||
_ -> Nothing
|
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
|
||||||
|
|
35
test/Spec.hs
35
test/Spec.hs
|
@ -77,9 +77,9 @@ import ZcashHaskell.Types
|
||||||
, Seed(..)
|
, Seed(..)
|
||||||
, ShieldedOutput(..)
|
, ShieldedOutput(..)
|
||||||
, ToBytes(..)
|
, ToBytes(..)
|
||||||
, TransparentReceiver(..)
|
|
||||||
, TransparentAddress(..)
|
, TransparentAddress(..)
|
||||||
, TransparentBundle(..)
|
, TransparentBundle(..)
|
||||||
|
, TransparentReceiver(..)
|
||||||
, TransparentType(..)
|
, TransparentType(..)
|
||||||
, UnifiedAddress(..)
|
, UnifiedAddress(..)
|
||||||
, UnifiedFullViewingKey(..)
|
, UnifiedFullViewingKey(..)
|
||||||
|
@ -846,22 +846,41 @@ main = do
|
||||||
print tb
|
print tb
|
||||||
show tb `shouldNotBe` ""
|
show tb `shouldNotBe` ""
|
||||||
describe "Extract Sapling Address - UA Valid" $ do
|
describe "Extract Sapling Address - UA Valid" $ do
|
||||||
let sr = getSaplingFromUA "u14a5c4ufn9feqvxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l"
|
let sr =
|
||||||
|
getSaplingFromUA
|
||||||
|
"u14a5c4ufn9feqvxssnvscep29j5cse4gjpg0w3w5vjhafn74hg9k73xgnxqv6m255n23weggr6j97c8kdwvn4pkz7rz6my52z8248gjmr7knlw536tcurs5km7knqnzez4cywudt3q6shr553hurduvljfeqvfzgegenfjashslkz3y4ykhxel6mrjp9gsm9xk7k6kdxn9y84kccmv8l"
|
||||||
it "Extract sapling address" $ do
|
it "Extract sapling address" $ do
|
||||||
case sr of
|
case sr of
|
||||||
Nothing -> assertFailure "UA invalid or does not contain a Sapling receiver"
|
Nothing ->
|
||||||
|
assertFailure "UA invalid or does not contain a Sapling receiver"
|
||||||
Just t -> do
|
Just t -> do
|
||||||
print t
|
print t
|
||||||
t `shouldBe` "zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60"
|
t `shouldBe`
|
||||||
|
"zs1waxrpde36rlrjdwfhnvw030sn29lzwmvmeupd8x2uuqgypaafx7mqcy0ep8yf2xtg30n5424t60"
|
||||||
describe "Extract Sapling Address - UA Invalid" $ do
|
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
|
it "Try to extract sapling address from invalid UA" $ do
|
||||||
sr `shouldBe` Nothing
|
sr `shouldBe` Nothing
|
||||||
describe "Decode a Transparent Address" $ do
|
describe "Decode a Transparent Address" $ do
|
||||||
let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e"
|
let ta = decodeTransparentAddress "t1dMjvesbzdG41xgKaGU3HgwYJwSgbCK54e"
|
||||||
it "Try to decode a valid Transparent Address" $ do
|
it "Try to decode a valid Transparent Address" $ do
|
||||||
print ta
|
print ta
|
||||||
ta `shouldNotBe` Nothing
|
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
|
-- | Properties
|
||||||
prop_PhraseLength :: Property
|
prop_PhraseLength :: Property
|
||||||
|
|
|
@ -5,7 +5,7 @@ cabal-version: 3.0
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
|
|
||||||
name: zcash-haskell
|
name: zcash-haskell
|
||||||
version: 0.5.4.0
|
version: 0.5.5.0
|
||||||
synopsis: Utilities to interact with the Zcash blockchain
|
synopsis: Utilities to interact with the Zcash blockchain
|
||||||
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
|
description: Please see the README on the repo at <https://git.vergara.tech/Vergara_Tech/zcash-haskell#readme>
|
||||||
category: Blockchain
|
category: Blockchain
|
||||||
|
|
Loading…
Reference in a new issue