@@ -45,24 +45,36 @@ module Bitcoin.Address (
45
45
46
46
import Bitcoin.Address.Base58
47
47
import Bitcoin.Address.Bech32
48
- import Bitcoin.Crypto
49
- import Bitcoin.Data
50
- import Bitcoin.Keys.Common
51
- import Bitcoin.Script
52
- import Bitcoin.Util
53
- import Control.Applicative
48
+ import Bitcoin.Crypto (Hash160 , Hash256 , addressHash , addressHashL , sha256 )
49
+ import Bitcoin.Data (Network (.. ))
50
+ import Bitcoin.Keys.Common (PubKeyI )
51
+ import Bitcoin.Script (
52
+ Script ,
53
+ ScriptInput (.. ),
54
+ ScriptOutput (.. ),
55
+ SimpleInput (SpendPKHash ),
56
+ decodeOutput ,
57
+ decodeOutputBS ,
58
+ encodeOutput ,
59
+ encodeOutputBS ,
60
+ toP2WSH ,
61
+ )
62
+ import Bitcoin.Util (eitherToMaybe , encodeHex , maybeToEither )
63
+ import qualified Bitcoin.Util as U
64
+ import Control.Applicative ((<|>) )
54
65
import Control.Arrow (second )
55
- import Control.DeepSeq
56
- import Control.Monad
57
- import Data.Binary (Binary (.. ))
66
+ import Control.DeepSeq (NFData )
67
+ import Control.Monad ((<=<) )
68
+ import Data.Binary (Binary (.. ), Get , Put )
69
+ import qualified Data.Binary as Bin
70
+ import Data.Binary.Get (runGet )
71
+ import qualified Data.Binary.Get as Get
72
+ import Data.Binary.Put (runPut )
73
+ import qualified Data.Binary.Put as Put
58
74
import Data.ByteString (ByteString )
59
- import qualified Data.ByteString as B
60
- import Data.Bytes.Get
61
- import Data.Bytes.Put
62
- import Data.Bytes.Serial
63
- import Data.Hashable
64
- import Data.Maybe
65
- import Data.Serialize (Serialize (.. ))
75
+ import qualified Data.ByteString as BS
76
+ import qualified Data.ByteString.Lazy as BSL
77
+ import Data.Hashable (Hashable )
66
78
import Data.Text (Text )
67
79
import qualified Data.Text as T
68
80
import Data.Word (Word8 )
@@ -100,50 +112,41 @@ data Address
100
112
(Eq , Ord , Generic , Show , Read , Hashable , NFData )
101
113
102
114
103
- instance Serial Address where
104
- serialize (PubKeyAddress k) = do
105
- putWord8 0x00
106
- serialize k
107
- serialize (ScriptAddress s) = do
108
- putWord8 0x01
109
- serialize s
110
- serialize (WitnessPubKeyAddress h) = do
111
- putWord8 0x02
112
- serialize h
113
- serialize (WitnessScriptAddress s) = do
114
- putWord8 0x03
115
- serialize s
116
- serialize (WitnessAddress v d) = do
117
- putWord8 0x04
118
- putWord8 v
119
- putWord64be (fromIntegral (B. length d))
120
- putByteString d
121
-
122
-
123
- deserialize =
124
- getWord8 >>= \ case
125
- 0x00 -> PubKeyAddress <$> deserialize
126
- 0x01 -> ScriptAddress <$> deserialize
127
- 0x02 -> WitnessPubKeyAddress <$> deserialize
128
- 0x03 -> WitnessScriptAddress <$> deserialize
115
+ instance Binary Address where
116
+ put = \ case
117
+ PubKeyAddress k -> do
118
+ Put. putWord8 0x00
119
+ put k
120
+ ScriptAddress s -> do
121
+ Put. putWord8 0x01
122
+ put s
123
+ WitnessPubKeyAddress h -> do
124
+ Put. putWord8 0x02
125
+ put h
126
+ WitnessScriptAddress s -> do
127
+ Put. putWord8 0x03
128
+ put s
129
+ WitnessAddress v d -> do
130
+ Put. putWord8 0x04
131
+ Put. putWord8 v
132
+ Put. putWord64be (fromIntegral (BS. length d))
133
+ Put. putByteString d
134
+
135
+
136
+ get =
137
+ Get. getWord8 >>= \ case
138
+ 0x00 -> PubKeyAddress <$> get
139
+ 0x01 -> ScriptAddress <$> get
140
+ 0x02 -> WitnessPubKeyAddress <$> get
141
+ 0x03 -> WitnessScriptAddress <$> get
129
142
0x04 ->
130
143
WitnessAddress
131
- <$> getWord8
132
- <*> (getByteString . fromIntegral =<< getWord64be)
144
+ <$> Get. getWord8
145
+ <*> (Get. getByteString . fromIntegral =<< Get. getWord64be)
133
146
b ->
134
147
fail . T. unpack $
135
148
" Could not decode address type byte: "
136
- <> encodeHex (B. singleton b)
137
-
138
-
139
- instance Serialize Address where
140
- put = serialize
141
- get = deserialize
142
-
143
-
144
- instance Binary Address where
145
- put = serialize
146
- get = deserialize
149
+ <> encodeHex (BS. singleton b)
147
150
148
151
149
152
-- | 'Address' pays to a public key hash.
@@ -178,17 +181,17 @@ isWitnessAddress _ = False
178
181
-- | Convert address to human-readable string. Uses 'Base58', or 'Bech32'
179
182
-- depending on network.
180
183
addrToText :: Network -> Address -> Maybe Text
181
- addrToText net a@ PubKeyAddress {} = Just . encodeBase58Check . runPutS $ base58put net a
182
- addrToText net a@ ScriptAddress {} = Just . encodeBase58Check . runPutS $ base58put net a
184
+ addrToText net a@ PubKeyAddress {} = Just . encodeBase58Check . Put. runPut $ base58put net a
185
+ addrToText net a@ ScriptAddress {} = Just . encodeBase58Check . Put. runPut $ base58put net a
183
186
addrToText net WitnessPubKeyAddress {getAddrHash160 = h} = do
184
187
hrp <- getBech32Prefix net
185
- segwitEncode hrp 0 ( B. unpack (runPutS $ serialize h))
188
+ segwitEncode hrp 0 . BSL. unpack $ Bin. encode h
186
189
addrToText net WitnessScriptAddress {getAddrHash256 = h} = do
187
190
hrp <- getBech32Prefix net
188
- segwitEncode hrp 0 ( B. unpack (runPutS $ serialize h))
191
+ segwitEncode hrp 0 . BSL. unpack $ Bin. encode h
189
192
addrToText net WitnessAddress {getAddrVersion = v, getAddrData = d} = do
190
193
hrp <- getBech32Prefix net
191
- segwitEncode hrp v (B . unpack d)
194
+ segwitEncode hrp v (BS . unpack d)
192
195
193
196
194
197
-- | Parse 'Base58', or 'Bech32' address, depending on network.
@@ -200,24 +203,24 @@ textToAddr net txt =
200
203
bech32ToAddr :: Network -> Text -> Maybe Address
201
204
bech32ToAddr net txt = do
202
205
hrp <- getBech32Prefix net
203
- (ver, bs) <- second B . pack <$> segwitDecode hrp txt
206
+ (ver, bs) <- second BS . pack <$> segwitDecode hrp txt
204
207
case ver of
205
- 0 -> case B .length bs of
206
- 20 -> WitnessPubKeyAddress <$> eitherToMaybe (runGetS deserialize bs)
207
- 32 -> WitnessScriptAddress <$> eitherToMaybe (runGetS deserialize bs)
208
+ 0 -> case BS .length bs of
209
+ 20 -> WitnessPubKeyAddress <$> ( eitherToMaybe . U. decode . BSL. fromStrict) bs
210
+ 32 -> WitnessScriptAddress <$> ( eitherToMaybe . U. decode . BSL. fromStrict) bs
208
211
_ -> Nothing
209
212
_ -> Just $ WitnessAddress ver bs
210
213
211
214
212
215
base58ToAddr :: Network -> Text -> Maybe Address
213
216
base58ToAddr net txt =
214
- eitherToMaybe . runGetS (base58get net) =<< decodeBase58Check txt
217
+ eitherToMaybe . U. runGet (base58get net) =<< decodeBase58Check txt
215
218
216
219
217
- base58get :: MonadGet m => Network -> m Address
220
+ base58get :: Network -> Get Address
218
221
base58get net = do
219
- pfx <- getWord8
220
- addr <- deserialize
222
+ pfx <- Get. getWord8
223
+ addr <- get
221
224
f pfx addr
222
225
where
223
226
f x a
@@ -226,19 +229,19 @@ base58get net = do
226
229
| otherwise = fail " Does not recognize address prefix"
227
230
228
231
229
- base58put :: MonadPut m => Network -> Address -> m ()
232
+ base58put :: Network -> Address -> Put
230
233
base58put net (PubKeyAddress h) = do
231
- putWord8 (getAddrPrefix net)
232
- serialize h
234
+ Put. putWord8 (getAddrPrefix net)
235
+ put h
233
236
base58put net (ScriptAddress h) = do
234
- putWord8 (getScriptPrefix net)
235
- serialize h
237
+ Put. putWord8 (getScriptPrefix net)
238
+ put h
236
239
base58put _ _ = error " Cannot serialize this address as Base58"
237
240
238
241
239
242
-- | Obtain a standard pay-to-public-key-hash address from a public key.
240
243
pubKeyAddr :: PubKeyI -> Address
241
- pubKeyAddr = PubKeyAddress . addressHash . runPutS . serialize
244
+ pubKeyAddr = PubKeyAddress . addressHashL . Bin. encode
242
245
243
246
244
247
-- | Obtain a standard pay-to-public-key-hash (P2PKH) address from a 'Hash160'.
@@ -249,7 +252,7 @@ p2pkhAddr = PubKeyAddress
249
252
-- | Obtain a SegWit pay-to-witness-public-key-hash (P2WPKH) address from a
250
253
-- public key.
251
254
pubKeyWitnessAddr :: PubKeyI -> Address
252
- pubKeyWitnessAddr = WitnessPubKeyAddress . addressHash . runPutS . serialize
255
+ pubKeyWitnessAddr = WitnessPubKeyAddress . addressHashL . Bin. encode
253
256
254
257
255
258
-- | Obtain a backwards-compatible SegWit P2SH-P2WPKH address from a public key.
@@ -259,9 +262,8 @@ pubKeyCompatWitnessAddr =
259
262
. addressHash
260
263
. encodeOutputBS
261
264
. PayWitnessPKHash
262
- . addressHash
263
- . runPutS
264
- . serialize
265
+ . addressHashL
266
+ . Bin. encode
265
267
266
268
267
269
-- | Obtain a SegWit pay-to-witness-public-key-hash (P2WPKH) address from a
@@ -316,7 +318,7 @@ addressToScript = encodeOutput . addressToOutput
316
318
317
319
-- | Encode address as output script in 'ByteString' form.
318
320
addressToScriptBS :: Address -> ByteString
319
- addressToScriptBS = runPutS . serialize . addressToScript
321
+ addressToScriptBS = U. encodeS . addressToScript
320
322
321
323
322
324
-- | Decode an output script into an 'Address' if it has such representation.
0 commit comments