commit 654635bf2fde44db74c9c77679bfd03ac921eff7
parent 74af946cdd7b78d0056c78a1478f67529dc86342
Author: Jared Tobin <jared@jtobin.io>
Date: Sat, 18 Jan 2025 00:44:21 +0400
lib: clean up conversions
Diffstat:
2 files changed, 19 insertions(+), 47 deletions(-)
diff --git a/lib/Bitcoin/Prim/Script.hs b/lib/Bitcoin/Prim/Script.hs
@@ -8,7 +8,6 @@
module Bitcoin.Prim.Script where
-import Control.Monad (unless)
import Control.Monad.ST
import qualified Crypto.Hash.RIPEMD160 as RIPEMD160
import qualified Crypto.Hash.SHA256 as SHA256
@@ -20,11 +19,12 @@ import qualified Data.ByteString.Internal as BI
import qualified Data.ByteString.Builder as BSB
import qualified Data.ByteString.Unsafe as BU
import qualified Data.Char as C
-import qualified Data.Primitive.Types as PT
import qualified Data.Primitive.ByteArray as BA
-import Data.STRef
import Data.Word (Word8, Word16, Word32)
+import GHC.ForeignPtr
+import System.IO.Unsafe
+
-- max redeem script size for a P2SH output
_MAX_REDEEM_SCRIPT_SIZE :: Int
_MAX_REDEEM_SCRIPT_SIZE = 520
@@ -51,6 +51,7 @@ hex_charset :: BS.ByteString
hex_charset = "0123456789abcdef"
-- split a word8 into a pair of its high and low bits
+-- only used for show instances
hilo :: Word8 -> (Word8, Word8)
hilo b =
let hi = BU.unsafeIndex hex_charset (fi b `B.shiftR` 4)
@@ -76,16 +77,26 @@ instance Show WitnessScriptHash where
let (hi, lo) = hilo h
in C.chr (fi hi) : C.chr (fi lo) : go t
--- -- | Render a 'Script' as a base16-encoded ByteString.
--- to_base16 :: Script -> BS.ByteString
--- to_base16 (Script ba) = runST $
--- BA.copyByteArrayToPtr
+-- | Convert a 'Script' to a base16-encoded ByteString.
+to_base16 :: Script -> BS.ByteString
+to_base16 (Script ba) = B16.encode (ba_to_bs ba)
+-- | Convert a base16-encoded ByteString to a Script.
from_base16 :: BS.ByteString -> Maybe Script
from_base16 b16 = do
bs <- B16.decode b16
pure (Script (bs_to_ba bs))
+-- Convert a pinned ByteArray to a ByteString.
+ba_to_bs :: BA.ByteArray -> BS.ByteString
+ba_to_bs ba = unsafeDupablePerformIO $ do
+ let l = BA.sizeofByteArray ba
+ buf <- mallocPlainForeignPtrBytes l
+ withForeignPtr buf $ \p ->
+ BA.copyByteArrayToAddr p ba 0 l
+ pure (BI.BS buf l)
+
+-- Convert a ByteString to a pinned ByteArray.
bs_to_ba :: BS.ByteString -> BA.ByteArray
bs_to_ba bs@(BI.PS _ _ l) = runST $ do
arr <- BA.newPinnedByteArray l
@@ -98,42 +109,6 @@ bs_to_ba bs@(BI.PS _ _ l) = runST $ do
go 0
BA.unsafeFreezeByteArray arr
-
---from_base16 :: BS.ByteString -> Maybe Script
---from_base16 b16@(BI.PS _ _ b16_l)
--- | B.testBit b16_l 0 = Nothing
--- | otherwise = runST $ do
--- arr <- BA.newByteArray (b16_l `quot` 2)
--- ear <- newSTRef False
---
--- let loop j bs@(BI.PS _ _ l)
--- | l == 0 = pure ()
--- | otherwise = case BS.splitAt 2 bs of
--- (chunk, etc) -> do
--- let ws = do
--- hi <- word4 (BU.unsafeIndex chunk 0)
--- lo <- word4 (BU.unsafeIndex chunk 1)
--- pure (hi, lo)
---
--- case ws of
--- Nothing -> writeSTRef ear True
--- Just (hi, lo) -> do
--- err <- readSTRef ear
--- unless err $ do
--- let b = hi `B.shiftL` 4
--- .|. lo
--- BA.writeByteArray arr j b
--- loop (succ j) etc
---
--- loop 0 b16
---
--- err <- readSTRef ear
--- if err
--- then pure Nothing
--- else do
--- ray <- BA.unsafeFreezeByteArray arr
--- pure (Just (Script ray))
-
data Term =
OPCODE Opcode
| BYTE Word8
@@ -197,9 +172,6 @@ from_script (Script bs) = go 0 where
_ -> go (succ j)
-ba_to_bs :: BA.ByteArray -> BS.ByteString
-ba_to_bs bs = BA.foldrByteArray BS.cons mempty bs
-
to_scripthash :: Script -> Maybe ScriptHash
to_scripthash (Script bs)
| BA.sizeofByteArray bs > _MAX_REDEEM_SCRIPT_SIZE = Nothing
diff --git a/ppad-btcprim.cabal b/ppad-btcprim.cabal
@@ -27,7 +27,7 @@ library
build-depends:
base >= 4.9 && < 5
, bytestring >= 0.9 && < 0.13
- , primitive >= 0.9 && < 0.10
+ , primitive >= 0.8 && < 0.10
, ppad-base16 >= 0.1 && < 0.2
, ppad-base58 >= 0.1 && < 0.2
, ppad-bech32 >= 0.2 && < 0.3