packages feed

bitcoin-tx 0.11.0 → 0.12.0

raw patch · 4 files changed

+42/−17 lines, 4 filesdep +cryptohashdep +hexstringdep −base16-bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: cryptohash, hexstring

Dependencies removed: base16-bytestring

API changes (from Hackage documentation)

+ Data.Bitcoin.Transaction: transactionId :: Transaction -> HexString
- Data.Bitcoin.Transaction: decode :: ByteString -> Transaction
+ Data.Bitcoin.Transaction: decode :: HexString -> Transaction
- Data.Bitcoin.Transaction: encode :: Transaction -> ByteString
+ Data.Bitcoin.Transaction: encode :: Transaction -> HexString

Files

bitcoin-tx.cabal view
@@ -1,6 +1,6 @@ name: bitcoin-tx
 category: Network, Finance
-version: 0.11.0
+version: 0.12.0
 license: MIT
 license-file: LICENSE
 copyright: (c) 2015 Leon Mergen
@@ -31,9 +31,11 @@ 
   build-depends:       base                     >= 4.3          && < 5
                      , bytestring
-                     , base16-bytestring
                      , binary
+                     , hexstring
 
+                     , cryptohash
+
                      , bitcoin-script
 
 test-suite test-suite
@@ -51,6 +53,7 @@                      , hspec
 
                      , bytestring
+                     , hexstring
 
                      , bitcoin-tx
                      , bitcoin-script
src/Data/Bitcoin/Transaction.hs view
@@ -1,23 +1,36 @@ module Data.Bitcoin.Transaction ( decode
                                 , encode
+                                , transactionId
                                 , Transaction (..)
                                 , TransactionIn (..)
-                                , TransactionOut (..) )where
+                                , TransactionOut (..)) where
 
-import qualified Data.ByteString.Lazy as BSL
-import qualified Data.ByteString.Base16.Lazy as BS16L
+import qualified Data.Binary                    as B (encode)
 
-import qualified Data.Binary     as B ( decode
-                                      , encode )
+import qualified Data.ByteString                as BS (reverse)
+import qualified Data.ByteString.Lazy           as BSL (toStrict)
 
-import Data.Bitcoin.Transaction.Types
+import qualified Crypto.Hash.SHA256             as Sha256
+import qualified Data.HexString                 as HS
 
+import           Data.Bitcoin.Transaction.Types
+
 -- | Decodes a hex representation of a transaction into a 'Transaction' object.
-decode :: BSL.ByteString -> Transaction
-decode =
-  B.decode . fst . BS16L.decode
+decode :: HS.HexString -- ^ The hexadecimal representation of the transaction
+       -> Transaction  -- ^ The decoded 'Transaction' object
+decode = HS.toBinary
 
 -- | Encodes a 'Transaction' object into a hex representation.
-encode :: Transaction -> BSL.ByteString
-encode =
-  BS16L.encode . B.encode
+encode :: Transaction  -- ^ The 'Transaction' we would like to encode to hex
+       -> HS.HexString -- ^ The hexadecimal representation of the transaction
+encode = HS.fromBinary
+
+-- | Calculates the transaction id of a 'Transaction' as a 'HS.HexString' so it
+--   can be used in RPC interfaces.
+transactionId :: Transaction -> HS.HexString
+transactionId =
+      -- Bitcoin uses a "double sha256", also known as sha256d as its hash algo
+  let sha256d = Sha256.hash . Sha256.hash
+      bytes   = BSL.toStrict . B.encode
+
+  in HS.fromBytes . BS.reverse . sha256d . bytes
src/Data/Bitcoin/Transaction/Types.hs view
@@ -63,7 +63,6 @@                    | TxnMultisig   -- ^ JSON of "multisig" received.
     deriving ( Show, Read, Ord, Eq )
 
-
 data TransactionHash = TransactionHash Integer
     deriving ( Show, Read, Eq )
 
test/Data/Bitcoin/TransactionSpec.hs view
@@ -2,14 +2,16 @@ 
 import           Data.Bitcoin.Script            (Script (..))
 import           Data.Bitcoin.Transaction
-import qualified Data.ByteString.Lazy.Char8     as BSL8 (pack)
+import qualified Data.ByteString.Char8          as BS8 (pack)
 
+import qualified Data.HexString as HS (hexString)
+
 import           Test.Hspec
 
 spec :: Spec
 spec = do
   describe "when parsing a specific transaction" $ do
-    let hex = BSL8.pack "0100000002f327e86da3e66bd20e1129b1fb36d07056f0b9a117199e759396526b8f3a20780000000049483045022100fce442ec52aa2792efc27fd3ad0eaf7fa69f097fdcefab017ea56d1799b10b2102207a6ae3eb61e11ffaba0453f173d1792f1b7bb8e7422ea945101d68535c4b474801fffffffff0ede03d75050f20801d50358829ae02c058e8677d2cc74df51f738285013c26000000006b483045022100b77f935ff366a6f3c2fdeb83589c790265d43b3d2cf5e5f0047da56c36de75f40220707ceda75d8dcf2ccaebc506f7293c3dcb910554560763d7659fb202f8ec324b012102240d7d3c7aad57b68aa0178f4c56f997d1bfab2ded3c2f9427686017c603a6d6ffffffff02f028d6dc010000001976a914ffb035781c3c69e076d48b60c3d38592e7ce06a788ac00ca9a3b000000001976a914fa5139067622fd7e1e722a05c17c2bb7d5fd6df088ac00000000"
+    let hex = HS.hexString $ BS8.pack "0100000002f327e86da3e66bd20e1129b1fb36d07056f0b9a117199e759396526b8f3a20780000000049483045022100fce442ec52aa2792efc27fd3ad0eaf7fa69f097fdcefab017ea56d1799b10b2102207a6ae3eb61e11ffaba0453f173d1792f1b7bb8e7422ea945101d68535c4b474801fffffffff0ede03d75050f20801d50358829ae02c058e8677d2cc74df51f738285013c26000000006b483045022100b77f935ff366a6f3c2fdeb83589c790265d43b3d2cf5e5f0047da56c36de75f40220707ceda75d8dcf2ccaebc506f7293c3dcb910554560763d7659fb202f8ec324b012102240d7d3c7aad57b68aa0178f4c56f997d1bfab2ded3c2f9427686017c603a6d6ffffffff02f028d6dc010000001976a914ffb035781c3c69e076d48b60c3d38592e7ce06a788ac00ca9a3b000000001976a914fa5139067622fd7e1e722a05c17c2bb7d5fd6df088ac00000000"
 
     it "encoding a decoding a transaction results in the original hex" $
       (encode . decode) hex `shouldBe` hex
@@ -20,3 +22,11 @@       case decoded of
        (Transaction 1 [(TransactionIn _ _ 4294967295), (TransactionIn _ _ 4294967295)] [(TransactionOut 7999990000 (Script _)), (TransactionOut 1000000000 (Script _))] 0) -> return ()
        _                               -> expectationFailure ("Result does not match expected: " ++ show decoded)
+
+  describe "when generating a transaction id" $ do
+    -- This test case is taken from the information provided at:
+    --   http://bitcoin.stackexchange.com/questions/32765/how-do-i-calculate-the-txid-of-this-raw-transaction
+    let hex = HS.hexString $ BS8.pack "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d014dffffffff0100f2052a01000000434104e70a02f5af48a1989bf630d92523c9d14c45c75f7d1b998e962bff6ff9995fc5bdb44f1793b37495d80324acba7c8f537caaf8432b8d47987313060cc82d8a93ac00000000"
+
+    it "succesfully calculates a transaction id" $ do
+      (transactionId . decode) hex `shouldBe` (HS.hexString $ BS8.pack "2d05f0c9c3e1c226e63b5fac240137687544cf631cd616fd34fd188fc9020866")